Samba File Server: Shares, Permissions and Access Control
At a glance#
- Purpose: Build and administer a standalone Samba file server providing Windows-compatible shared folders to Linux and Windows clients.
- Applies to: Samba 4.x on RHEL-family and Ubuntu/Debian, in standalone (non-domain) mode.
- Risk: Medium — misconfigured permissions can expose confidential data to everyone on the network.
- Time: 1–2 hours for a first build; 15 minutes per additional share.
Overview#
Samba implements the SMB/CIFS protocol, letting Linux serve shared folders that Windows machines mount as network drives. This article covers standalone mode, where Samba keeps its own user database rather than joining a directory service.
The thing that catches people out is that two independent permission layers apply, and access is granted only where both agree:
Client → Share-level permissions (smb.conf) → Filesystem permissions (POSIX/ACL) → FileA share marked writeable in smb.conf still fails if the underlying directory is read-only to that user. Most "Samba permissions" tickets are actually filesystem permission problems.
Before you start#
- Root or
sudoaccess. - A decision on where share data will live — a dedicated filesystem or LVM volume is strongly preferred over
/homeor/. - A list of groups and who belongs to them.
- TCP 445 reachable from clients.
Warning: Never expose Samba to the internet. SMB has a long history of serious vulnerabilities and is a primary ransomware propagation path. Restrict TCP 445 to internal networks at the firewall.
Installation#
# RHEL / Rocky / AlmaLinux
sudo dnf install -y samba samba-client samba-common
# Ubuntu / Debian
sudo apt update && sudo apt install -y samba smbclientsudo systemctl enable --now smb nmb # RHEL
sudo systemctl enable --now smbd nmbd # UbuntuPreparing storage and groups#
1. Create the share directory#
sudo mkdir -p /srv/shares/finance
sudo mkdir -p /srv/shares/public2. Create groups that mirror access requirements#
sudo groupadd finance
sudo groupadd staff3. Set filesystem ownership and permissions#
This is the layer that actually enforces access:
# finance: only the finance group, nothing for others
sudo chown root:finance /srv/shares/finance
sudo chmod 2770 /srv/shares/finance
# public: all staff can read and write
sudo chown root:staff /srv/shares/public
sudo chmod 2775 /srv/shares/publicThe leading 2 sets setgid, so every file created inside inherits the directory's group. Without it, files belong to the creator's primary group and colleagues cannot open them — the single most common cause of "I can see the folder but not the file".
Full detail in Linux File Permissions, Ownership and ACLs.
Creating Samba users#
Samba keeps its own password database. A Linux account must exist first, then be added to Samba:
# Linux account with no shell login - file access only
sudo useradd -M -s /sbin/nologin jsmith
sudo usermod -aG finance,staff jsmith
# add to the Samba password database
sudo smbpasswd -a jsmith# list Samba users
sudo pdbedit -L -v
# disable / enable
sudo smbpasswd -d jsmith
sudo smbpasswd -e jsmith
# remove
sudo smbpasswd -x jsmithNote: -M -s /sbin/nologin creates an account that can access shares but cannot log into the server itself. File-server users should never get a shell.
Configuring shares#
sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.bak-$(date +%F)
sudo nano /etc/samba/smb.conf[global]
workgroup = WORKGROUP
server string = Samba File Server
netbios name = FILESRV
security = user
map to guest = never
# restrict to the internal network
hosts allow = 192.168.10.0/24 127.0.0.1
hosts deny = 0.0.0.0/0
interfaces = lo eth0
bind interfaces only = yes
# require modern, encrypted SMB only
server min protocol = SMB2_10
client min protocol = SMB2_10
smb encrypt = desired
log file = /var/log/samba/log.%m
max log size = 5000
logging = file
[finance]
comment = Finance department
path = /srv/shares/finance
browseable = no
writable = yes
valid users = @finance
create mask = 0660
directory mask = 2770
force group = finance
[public]
comment = Shared staff area
path = /srv/shares/public
browseable = yes
writable = yes
valid users = @staff
create mask = 0664
directory mask = 2775
force group = staffKey directives:
| Directive | Purpose |
|---|---|
valid users = @group | Only members of that group may connect. @ denotes a group. |
browseable = no | Hides the share from network browsing. It is still reachable by exact path — obscurity, not security. |
create mask / directory mask | Maximum permissions on newly created files and folders. |
force group | Files are created owned by this group regardless of the user's primary group. |
map to guest = never | Refuses anonymous access outright. |
server min protocol = SMB2_10 | Disables SMB1, which is obsolete and dangerous. |
Warning: Never enable SMB1 (NT1). It is the protocol WannaCry spread over. If an old device "needs" SMB1, replace the device.
Applying and testing configuration#
Always validate before restarting:
sudo testparmtestparm reports syntax errors and prints the effective configuration with defaults filled in.
sudo systemctl restart smb nmb # RHEL
sudo systemctl restart smbd nmbd # UbuntuFirewall and SELinux#
# firewalld
sudo firewall-cmd --permanent --add-service=samba
sudo firewall-cmd --reload
# ufw - restrict to the LAN
sudo ufw allow from 192.168.10.0/24 to any port 445 proto tcpOn RHEL-family systems SELinux blocks Samba from serving arbitrary paths until the context is set:
sudo setsebool -P samba_export_all_rw on
sudo semanage fcontext -a -t samba_share_t "/srv/shares(/.*)?"
sudo restorecon -Rv /srv/sharesNote: If a share is visible but every file access is denied on RHEL, check SELinux before anything else. sudo ausearch -m avc -ts recent will show the denials.
Connecting from clients#
Windows — File Explorer address bar:
\\192.168.10.50\financeMap as a drive: This PC → Map network drive, tick Connect using different credentials.
Linux — one-off mount:
sudo mkdir -p /mnt/finance
sudo mount -t cifs //192.168.10.50/finance /mnt/finance \
-o username=jsmith,uid=$(id -u),gid=$(id -g),vers=3.0Persistent mount with credentials kept out of fstab:
sudo nano /etc/samba/credentials-financeusername=jsmith
password=REPLACE_MEsudo chmod 600 /etc/samba/credentials-finance# /etc/fstab
//192.168.10.50/finance /mnt/finance cifs credentials=/etc/samba/credentials-finance,uid=1000,gid=1000,vers=3.0,_netdev,nofail 0 0sudo mount -aWarning: nofail matters. Without it, a server that cannot reach the file share will hang during boot waiting for the mount.
Verification#
# config valid
sudo testparm -s
# services running
sudo systemctl status smb nmb
# listening on 445
sudo ss -tulpn | grep 445
# list shares as a user - the real test
smbclient -L //localhost -U jsmith
# connect and write
smbclient //localhost/finance -U jsmithInside smbclient, confirm both directions work:
smb: \> ls
smb: \> put /etc/hostname test.txt
smb: \> del test.txt
smb: \> quitThen verify access control actually holds by testing with a user who should not have access:
smbclient //localhost/finance -U someoneelseThat must fail. A share that everyone can reach is worse than no share.
Finally, confirm the setgid inheritance works:
sudo -u jsmith touch /srv/shares/finance/inherit-test
ls -l /srv/shares/finance/inherit-test # group should be 'finance'
sudo rm /srv/shares/finance/inherit-testRollback#
sudo cp /etc/samba/smb.conf.bak-YYYY-MM-DD /etc/samba/smb.conf
sudo testparm
sudo systemctl restart smb nmbIf a permission change broke access, filesystem permissions can be reset with:
sudo chown -R root:finance /srv/shares/finance
sudo find /srv/shares/finance -type d -exec chmod 2770 {} \;
sudo find /srv/shares/finance -type f -exec chmod 660 {} \;Troubleshooting#
| Symptom | Cause and fix |
|---|---|
NT_STATUS_LOGON_FAILURE | Samba password not set. Run sudo smbpasswd -a user. A Linux password is not enough. |
NT_STATUS_ACCESS_DENIED on a share the user should reach | Filesystem permissions, not Samba. Test with sudo -u user ls /srv/shares/x. |
| Share visible, all files denied (RHEL) | SELinux context missing. Run the semanage/restorecon steps. |
| Files created but colleagues cannot open them | setgid missing on the directory. chmod 2770. |
NT_STATUS_BAD_NETWORK_NAME | Share name typo, or the path does not exist. |
| Windows will not connect at all | Client has SMB1 disabled and the server offers only SMB1, or vice versa. Confirm server min protocol. |
| Windows caches old credentials | cmdkey /list, then cmdkey /delete:192.168.10.50. |
| Cannot see the server when browsing the network | Normal on modern Windows — browsing is unreliable. Use the full \\ip\share path. |
| Very slow transfers | Check smb encrypt overhead, duplex mismatch, and disk I/O on the server. |
| Boot hangs after adding an fstab entry | Missing _netdev,nofail. Add both. |
Related#
- Linux File Permissions, Ownership and ACLs
- Linux User and Group Management
- Linux Firewall Configuration: firewalld and UFW
- [Windows-to-Linux Rsync Sync for Nextcloud (via SSH)](Windows-to-Linux%20Rsync%20Sync%20for%20Nextcloud%20(via%20SSH%20240bf62b1b5380d3884acbf2c61e2d55.md)