This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Samba Configuration (smb.conf)
Relevant source files
Purpose and Scope
This document provides a complete reference for the smb.conf file, which configures the Samba server running inside the docker-sshfs container. The configuration establishes the SMB/CIFS protocol bridge that makes remote SSH filesystems accessible to macOS Finder through guest-authenticated network shares.
For information about FUSE configuration that enables Samba to access SSHFS mounts, see FUSE Configuration. For details about SSHFS mount options that work with this configuration, see SSHFS Mount Options. For the broader security model, see Security Model.
Sources : smb.conf:1-20
Configuration File Structure
The smb.conf file contains two distinct sections that control different aspects of the Samba server:
| Section | Lines | Purpose |
|---|---|---|
[global] | smb.conf:1-8 | Server-wide settings including security model, protocol versions, and network identity |
[SSHFS Share] | smb.conf:10-19 | Share-specific settings for the /samba-share directory including permissions and user mapping |
Sources : smb.conf:1-20
Global Configuration Section
The [global] section at smb.conf:1-8 defines server-wide behavior for the Samba daemon. These settings apply to all shares and control how the server identifies itself on the network and handles client connections.
graph LR
subgraph "Configuration"
workgroup["workgroup = WORKGROUP\nLine 2"]
netbios["netbios name = sambaserver\nLine 6"]
serverstring["server string = Samba Server %v\nLine 5"]
end
subgraph "macOS Finder Discovery"
BrowseList["Network Browser\nShows: sambaserver"]
ConnectionDialog["Connection Dialog\nWorkgroup: WORKGROUP"]
end
subgraph "SMB Protocol"
NetBIOS["NetBIOS Name Resolution\nPort 139"]
DirectTCP["Direct TCP/IP\nPort 445"]
end
workgroup --> ConnectionDialog
netbios --> BrowseList
netbios --> NetBIOS
netbios --> DirectTCP
serverstring --> BrowseList
Network Identity Settings
| Directive | Value | Line | Purpose |
|---|---|---|---|
workgroup | WORKGROUP | smb.conf2 | Sets Windows workgroup name; matches default macOS SMB client expectations |
netbios name | sambaserver | smb.conf6 | Defines the server's NetBIOS identity for network browsing and name resolution |
server string | Samba Server %v | smb.conf5 | Human-readable description displayed in network browsers; %v expands to Samba version |
Sources : smb.conf:2-6
Security and Authentication Model
The security configuration at smb.conf:3-4 implements a guest-only access model that eliminates password requirements while maintaining consistent file ownership:
graph TB
subgraph "Configuration Directives"
security["security = user\nLine 3"]
mapguest["map to guest = bad user\nLine 4"]
end
subgraph "Client Connection Flow"
MacOSClient["macOS Finder Client\nConnect as Guest"]
BadPassword["Any Username\nInvalid/No Password"]
end
subgraph "Authentication Processing"
UserCheck["Samba Authentication Check"]
GuestMap["Map to Guest Account"]
ForceUserApply["Apply force user = sshuser"]
end
subgraph "Resulting Access"
SSHUserAccess["All Operations as sshuser\nUID 1000, GID 1000"]
FilesystemOps["Filesystem Operations\nVia /samba-share symlink"]
end
security --> UserCheck
mapguest --> GuestMap
MacOSClient --> BadPassword
BadPassword --> UserCheck
UserCheck -->|User doesn't exist| GuestMap
GuestMap --> ForceUserApply
ForceUserApply --> SSHUserAccess
SSHUserAccess --> FilesystemOps
| Directive | Value | Line | Behavior |
|---|---|---|---|
security | user | smb.conf3 | Requires user-level authentication (not share-level); enables per-user access control but overridden by map to guest |
map to guest | bad user | smb.conf4 | Converts any connection with an invalid username into a guest connection; effectively disables password authentication |
The bad user mapping combined with guest only = yes in the share definition creates a passwordless authentication flow where any connection attempt succeeds as guest access, then force user ensures all operations execute as sshuser.
Sources : smb.conf:3-4
Protocol Version Enforcement
Lines smb.conf:7-8 enforce minimum SMB protocol versions, eliminating support for the deprecated SMB1 protocol:
graph LR
subgraph "Protocol Configuration"
ClientMin["client min protocol = SMB2\nLine 7"]
ServerMin["server min protocol = SMB2\nLine 8"]
end
subgraph "Supported Protocols"
SMB2["SMB 2.0\n✓ Supported"]
SMB21["SMB 2.1\n✓ Supported"]
SMB3["SMB 3.x\n✓ Supported"]
end
subgraph "Rejected Protocols"
SMB1["SMB 1.0 / CIFS\n✗ Rejected"]
end
ClientMin --> SMB2
ServerMin --> SMB2
ClientMin --> SMB21
ServerMin --> SMB21
ClientMin --> SMB3
ServerMin --> SMB3
ClientMin -.->|Blocks| SMB1
ServerMin -.->|Blocks| SMB1
subgraph "Security Benefits"
NoSMB1Vulns["Eliminates SMB1\nSecurity Vulnerabilities"]
end
SMB1 --> NoSMB1Vulns
| Directive | Value | Line | Effect |
|---|---|---|---|
client min protocol | SMB2 | smb.conf7 | Prevents Samba from acting as client using SMB1 (not directly relevant for this server-only use case) |
server min protocol | SMB2 | smb.conf8 | Rejects client connections attempting to use SMB1; enforces modern protocol versions |
Modern macOS versions default to SMB2+ for new connections, making this configuration transparent for most users while preventing potential SMB1-related security issues.
Sources : smb.conf:7-8
Share Configuration Section
The [SSHFS Share] section at smb.conf:10-19 defines the actual network share that macOS clients connect to. This configuration establishes the critical link between the Samba server and the SSHFS-mounted filesystem.
graph TB
subgraph "Share Configuration"
ShareName["[SSHFS Share]\nLine 10"]
Path["path = /samba-share\nLine 11"]
Browseable["browseable = yes\nLine 16"]
end
subgraph "Filesystem Structure"
SambaShareDir["/samba-share Directory\nchmod 777\nCreated by Dockerfile"]
SymLink["/samba-share/remote\nSymbolic Link"]
RemoteMount["/remote Mount Point\nSSHFS Target"]
end
subgraph "macOS Access"
FinderBrowser["Finder Network Browser\nShows: SSHFS Share"]
MountPoint["Mounted Volume\nsmb://container-ip/SSHFS Share"]
end
ShareName --> Path
Path --> SambaShareDir
Browseable --> FinderBrowser
SambaShareDir --> SymLink
SymLink -.->|Links to| RemoteMount
FinderBrowser --> MountPoint
MountPoint --> SambaShareDir
Share Path and Visibility
| Directive | Value | Line | Purpose |
|---|---|---|---|
| Share name | SSHFS Share | smb.conf10 | Display name shown in macOS Finder network browser; spaces are preserved in SMB share names |
path | /samba-share | smb.conf11 | Root directory served by this share; contains the symbolic link to /remote SSHFS mount point |
browseable | yes | smb.conf16 | Makes share visible in network browsing; allows discovery without knowing share name in advance |
The share name SSHFS Share (with space) appears verbatim in macOS Finder. The directory at /samba-share must exist with appropriate permissions (set to 777 by the Dockerfile) before Samba starts.
Sources : smb.conf:10-16
Write Access Configuration
The configuration at smb.conf:12-18 enables full read-write access with permissive file creation masks:
| Directive | Value | Line | Effect |
|---|---|---|---|
writable | yes | smb.conf12 | Enables write operations (create, modify, delete); opposite of read only |
read only | no | smb.conf15 | Explicitly disables read-only mode; redundant with writable = yes but included for clarity |
create mask | 0777 | smb.conf17 | Sets permission mask for newly created files to full access (owner/group/other all have rwx) |
directory mask | 0777 | smb.conf18 | Sets permission mask for newly created directories to full access |
The 0777 masks are unusually permissive but necessary for this use case because:
- The
force userdirective causes all operations to run assshuser - SSHFS mount options set
uid=1000,gid=1000matchingsshuser - Files created must be accessible regardless of how they're accessed (via SMB or direct container shell)
Sources : smb.conf:12-18
Guest Access Enforcement
Lines smb.conf:13-14 enforce guest-only access at the share level, complementing the global map to guest setting:
graph TB
subgraph "Global Settings"
GlobalSecurity["security = user\nLine 3"]
MapGuest["map to guest = bad user\nLine 4"]
end
subgraph "Share Settings"
GuestOK["guest ok = yes\nLine 13"]
GuestOnly["guest only = yes\nLine 14"]
end
subgraph "Connection Attempts"
ValidUser["Valid Username\n+ Correct Password"]
InvalidUser["Invalid Username\n+ Any Password"]
Guest["Explicit Guest Connection"]
end
subgraph "Authentication Result"
AllGuest["All Connections\nAuthenticated as Guest"]
end
GlobalSecurity --> MapGuest
MapGuest --> GuestOK
GuestOnly --> AllGuest
ValidUser --> MapGuest
InvalidUser --> MapGuest
Guest --> GuestOK
MapGuest --> AllGuest
GuestOK --> AllGuest
| Directive | Value | Line | Behavior |
|---|---|---|---|
guest ok | yes | smb.conf13 | Allows guest connections to this share; permits access without valid credentials |
guest only | yes | smb.conf14 | Forces all connections to use guest access even if valid credentials are provided; prevents authenticated access |
The combination of guest ok = yes and guest only = yes creates a mandatory guest access policy. Even if a user provides valid credentials, Samba ignores them and processes the connection as guest. This works in conjunction with force user to ensure consistent identity.
Sources : smb.conf:13-14
User Identity Mapping
The force user directive at smb.conf19 is the critical configuration that ensures filesystem operations have correct ownership:
graph TB
subgraph "Configuration Chain"
GuestAuth["Guest Authentication\nLines 13-14"]
ForceUser["force user = sshuser\nLine 19"]
SSHUserAccount["sshuser Account\nUID 1000, GID 1000"]
end
subgraph "SSHFS Mount"
MountOptions["sshfs -o uid=1000,gid=1000\nMount Options"]
RemoteMount["/remote Mount Point\nOwned by UID 1000"]
end
subgraph "Filesystem Operations"
SambaWrite["SMB Write Request\nfrom macOS"]
ActualWrite["Filesystem Write\nas sshuser UID 1000"]
SSHFSWrite["SSHFS Operation\nto Remote Server"]
end
subgraph "Permission Matching"
UIDMatch["UID 1000 = UID 1000\nWrite Permission Granted"]
end
GuestAuth --> ForceUser
ForceUser --> SSHUserAccount
SSHUserAccount --> ActualWrite
MountOptions --> RemoteMount
RemoteMount --> UIDMatch
ActualWrite --> UIDMatch
SambaWrite --> ActualWrite
ActualWrite --> SSHFSWrite
| Directive | Value | Line | Purpose |
|---|---|---|---|
force user | sshuser | smb.conf19 | Overrides the authenticated user identity; all filesystem operations execute as sshuser regardless of client credentials |
Why This Matters : Without force user = sshuser, writes would fail because:
- Guest connections typically map to the
nobodyuser - The
/remoteSSHFS mount is owned bysshuser(UID 1000) due to mount options - FUSE by default only allows the mounting user to access mounted filesystems
- Even with
allow_other, write permissions depend on matching UIDs
The force user directive ensures that Samba's effective UID matches the SSHFS mount's ownership, enabling write access through the protocol bridge.
Sources : smb.conf19
graph TB
subgraph "smb.conf Configuration"
direction TB
Global["[global] Section"]
Share["[SSHFS Share] Section"]
MapGuest["map to guest = bad user"]
ForceUser["force user = sshuser"]
Path["path = /samba-share"]
MinProtocol["server min protocol = SMB2"]
CreateMask["create mask = 0777"]
end
subgraph "Dockerfile Setup"
SSHUserCreate["RUN useradd -m -u 1000 sshuser"]
SambaShareMkdir["RUN mkdir -p /samba-share"]
SambaShareChmod["RUN chmod 777 /samba-share"]
SymlinkCreate["RUN ln -s /remote /samba-share/remote"]
end
subgraph "FUSE Configuration"
AllowOther["user_allow_other\nin /etc/fuse.conf"]
end
subgraph "Runtime Operations"
SSHFSMount["sshfs -o allow_other,uid=1000,gid=1000"]
SmbdProcess["smbd -F -S"]
MacOSConnection["macOS Finder\nSMB Connection"]
end
subgraph "Filesystem Access"
SambaRead["Read Operations\nvia /samba-share"]
SambaWrite["Write Operations\nas sshuser UID 1000"]
FUSEAccess["FUSE Mount Access\nallow_other enables"]
end
%% Configuration dependencies
ForceUser -.->|Requires user exists| SSHUserCreate
Path -.->|Requires directory| SambaShareMkdir
CreateMask -.->|Directory must be writable| SambaShareChmod
Path -.->|Contains symlink| SymlinkCreate
%% Runtime flow
Global --> SmbdProcess
Share --> SmbdProcess
MinProtocol --> MacOSConnection
MapGuest --> MacOSConnection
SSHFSMount --> FUSEAccess
AllowOther --> FUSEAccess
SmbdProcess --> SambaRead
SmbdProcess --> SambaWrite
FUSEAccess --> SambaRead
FUSEAccess --> SambaWrite
%% Critical path
ForceUser --> SambaWrite
SSHFSMount -.->|UID must match| SambaWrite
Configuration Integration Map
This diagram shows how smb.conf directives integrate with other system components:
Sources : smb.conf:1-20
Security Implications
The smb.conf configuration implements a convenience-over-security model appropriate for local development but not production environments:
Security Trade-offs Table
| Configuration Choice | Security Impact | Rationale |
|---|---|---|
map to guest = bad user | ❌ No authentication required | Eliminates password friction for local development; container ports bound to 127.0.0.1 limits exposure |
guest only = yes | ❌ Valid credentials ignored | Ensures consistent behavior; prevents confusion when credentials are provided but unused |
create mask = 0777 | ❌ World-writable files | Required for UID/GID consistency across SMB and direct container access |
directory mask = 0777 | ❌ World-writable directories | Prevents permission issues when accessing via different methods |
force user = sshuser | ⚠️ Single user identity | Enables write access through SSHFS mount; loses audit trail of actual user |
server min protocol = SMB2 | ✅ Blocks SMB1 vulnerabilities | Modern protocol enforcement reduces attack surface |
| Ports bound to 127.0.0.1 | ✅ Localhost-only access | Prevents external network exposure despite guest access (requires Docker run configuration) |
Mitigating Factors
The security model is acceptable for local development because:
- Network isolation : Docker
runcommand binds ports to127.0.0.1, preventing LAN access - Temporary containers : Development containers are typically short-lived and frequently rebuilt
- Single-user context : Developer's workstation is single-user; no multi-tenant concerns
- Controlled environment : User has root access to host system anyway; container provides convenience not security boundary
Production Considerations
For production use, this configuration would require modifications:
- Implement user authentication (remove
map to guest) - Use restrictive create masks (0644 for files, 0755 for directories)
- Configure per-user
force userbased on authenticated identity - Enable SMB signing and encryption
- Use certificate-based authentication for SMB3+
Sources : smb.conf:3-19
graph TB
subgraph "Required Alignments"
direction TB
Alignment1["force user = sshuser\n↕\nuseradd -u 1000 sshuser\n↕\nsshfs -o uid=1000"]
Alignment2["path = /samba-share\n↕\nmkdir -p /samba-share\n↕\nln -s /remote /samba-share/remote"]
Alignment3["create mask = 0777\n↕\nchmod 777 /samba-share\n↕\nsshfs -o allow_other"]
Alignment4["guest ok = yes\n↕\nmap to guest = bad user\n↕\nmacOS Connect as Guest"]
end
subgraph "Failure Modes"
direction TB
Failure1["UID Mismatch\n→ Permission denied on write"]
Failure2["Missing Directory\n→ smbd fails to start"]
Failure3["Permission Conflict\n→ FUSE denies Samba access"]
Failure4["Auth Mismatch\n→ Connection rejected"]
end
Alignment1 -.->|If misaligned| Failure1
Alignment2 -.->|If misaligned| Failure2
Alignment3 -.->|If misaligned| Failure3
Alignment4 -.->|If misaligned| Failure4
Critical Configuration Dependencies
Certain smb.conf settings must align with other system configurations or functionality breaks:
Dependency Matrix
| smb.conf Setting | Must Match | Location | Verification Command |
|---|---|---|---|
force user = sshuser | User account with UID 1000 | Dockerfile | id sshuser should show uid=1000 |
force user = sshuser | SSHFS mount uid=1000 | Mount command | `mount |
path = /samba-share | Existing directory | Dockerfile | ls -ld /samba-share should exist with 777 |
path = /samba-share | Contains symlink to /remote | Dockerfile | ls -l /samba-share/remote should show symlink |
create mask = 0777 | Directory permissions 777 | Dockerfile | stat -c %a /samba-share should return 777 |
guest ok = yes | map to guest = bad user in [global] | smb.conf4 | Both directives must be present |
server min protocol = SMB2 | macOS SMB client version | macOS 10.11+ | Modern macOS defaults to SMB2+ |
Sources : smb.conf:1-20
sequenceDiagram
participant smbd as smbd Process
participant config as smb.conf
participant fs as Filesystem
participant client as macOS Client
participant mount as SSHFS Mount
Note over smbd: Container starts
smbd->>config: Parse /etc/samba/smb.conf
smbd->>fs: Verify /samba-share exists
fs-->>smbd: Directory found (777 permissions)
smbd->>smbd: Bind ports 139, 445
smbd->>smbd: Enable SMB2+ only
Note over smbd: Ready to accept connections
client->>smbd: SMB connection request
smbd->>config: Check [global] security settings
config-->>smbd: map to guest = bad user
smbd->>smbd: Authenticate as guest
client->>smbd: Browse shares
smbd->>config: Read [SSHFS Share] section
config-->>smbd: browseable = yes
smbd-->>client: Return share list: SSHFS Share
client->>smbd: Mount "SSHFS Share"
smbd->>config: Get path directive
config-->>smbd: path = /samba-share
smbd->>config: Get force user directive
config-->>smbd: force user = sshuser
smbd->>fs: Access /samba-share as sshuser
fs-->>smbd: Access granted (UID 1000)
smbd-->>client: Mount success
client->>smbd: Write file request
smbd->>config: Check writable setting
config-->>smbd: writable = yes
smbd->>config: Get create mask
config-->>smbd: create mask = 0777
smbd->>fs: Create file as sshuser (0777)
fs->>mount: Write propagates to SSHFS
mount-->>fs: Write complete
fs-->>smbd: File created
smbd-->>client: Write success
Runtime Behavior
When the Samba daemon starts with this configuration, it produces the following behavior:
Sources : smb.conf:1-20
graph TB
subgraph "Layer 3: Remote Server"
RemoteFS["Remote Filesystem\nSSH Server"]
end
subgraph "Layer 2: Docker Container"
direction TB
SSHFS["SSHFS Client\nuid=1000,gid=1000\nallow_other"]
RemoteMount["/remote Mount Point\nFUSE Filesystem"]
Symlink["/samba-share/remote\nSymbolic Link"]
SambaDir["/samba-share\nRoot Directory\nchmod 777"]
SmbConf["smb.conf\nConfiguration File"]
Smbd["smbd Daemon\nServing /samba-share"]
end
subgraph "Layer 1: macOS Host"
Finder["macOS Finder\nSMB Client"]
end
%% Connections
RemoteFS -->|SSH Protocol| SSHFS
SSHFS -->|Mounts to| RemoteMount
RemoteMount -.->|Linked by| Symlink
Symlink -->|Points to| SambaDir
SambaDir -->|Contains| Symlink
SmbConf -->|Configures| Smbd
SmbConf -.->|Defines path = /samba-share| SambaDir
SmbConf -.->|Defines force user = sshuser| SSHFS
Smbd -->|Serves| SambaDir
Finder -->|SMB Protocol| Smbd
style SmbConf fill:#fff4e1
Relationship to System Architecture
The smb.conf file sits at a critical integration point in the three-tier architecture:
The configuration file's path directive connects Samba to the filesystem layer, while force user ensures UID alignment with SSHFS mount ownership. Without correct smb.conf settings, the protocol bridge fails even if SSHFS and Samba are both operational.
Sources : smb.conf:11-19