Most Samba guides treat a share as a block of text in smb.conf, and on Fedora that assumption breaks on the first write. A Samba share on Fedora is the agreement of four separate layers: firewalld has to let port 445 through, Samba has to know the user in its own password database, Linux permissions have to allow the mapped user, and SELinux has to see a label it lets smbd write to. The first two fail loudly, with an unreachable host or NT_STATUS_LOGON_FAILURE, but the last two both hand the client the same NT_STATUS_ACCESS_DENIED.
We built a team share on a Fedora server, mounted it permanently on a Fedora client with systemd automount and opened it from a Mac, and the one failure we hit is the instructive part: listing the share worked, a local write as the same user worked, and only the remote write was refused. The sections below walk through how each layer makes its decision, then the fix and the encryption setting worth turning on. The behavior described here was checked against Samba 4.25 on Fedora 45 in October 2026.
How smbd decides whether a write succeeds
Every file operation from a client passes the same checkpoints in a fixed order, and knowing the order is what makes an access error readable. A failure at an early step usually produces a clear message, while the last two steps both surface as a plain access denied:
- firewalld accepts the TCP connection to port 445, or rejects it.
- smbd authenticates the user against its own database (
tdbsam), not against/etc/shadow. - The share’s
valid usersline decides whether that user may connect to this share at all. - smbd switches to the user’s Linux UID and groups, so ordinary file permissions apply.
- SELinux checks whether the
smbd_tdomain may touch the file’s label.
Steps 4 and 5 are where Fedora differs from guides written for distributions without SELinux, because a directory can pass the permission check and still fail the label check. That is also why the same share works without this step on Ubuntu 26.04, which runs smbd unconfined unless you install and enforce the optional AppArmor profiles, and needs the same extra step on AlmaLinux and Oracle Linux. We’ll set up each layer in that order, so each one can be confirmed before the next one depends on it.
What the Samba packages give you
The server needs the samba package for smbd, samba-client for testing, and policycoreutils-python-utils for the semanage command used later. Our server started from the Fedora Cloud image, which ships without firewalld, so it got that too; on Fedora Server it’s already running:
sudo dnf -y install samba samba-client firewalld policycoreutils-python-utils
sudo systemctl enable --now firewalld smb
Only smb needs to run. The nmb service handles NetBIOS names and browsing, which clients connecting by DNS name or IP address don’t use, and it stayed inactive throughout our tests. smbd listens on 445 for SMB and on 139 for the older NetBIOS session transport:
sudo ss -tlnp | grep -E ":445|:139"
Both ports are open on IPv4 and IPv6, so smbd itself is ready before any share exists. Nothing in this output says a client can reach them yet, which is the next layer:
LISTEN 0 50 0.0.0.0:445 0.0.0.0:* users:(("smbd",pid=1323,fd=29))
LISTEN 0 50 0.0.0.0:139 0.0.0.0:* users:(("smbd",pid=1323,fd=30))
LISTEN 0 50 [::]:445 [::]:* users:(("smbd",pid=1323,fd=27))
LISTEN 0 50 [::]:139 [::]:* users:(("smbd",pid=1323,fd=28))
Listening is not the same as reachable. firewalld’s samba service covers both ports, and it isn’t open in the default zone until you add it (the firewalld guide for Fedora explains zones if your server uses a different one):
sudo firewall-cmd --permanent --add-service=samba
sudo firewall-cmd --reload
sudo firewall-cmd --info-service=samba | head -3
The service opens the two TCP ports smbd uses and includes the samba-client service for the NetBIOS UDP ports, so you do not need to open anything one by one. Opening it in the zone your server’s interface sits in is what matters:
samba
ports: 139/tcp 445/tcp
protocols:
Fedora’s default smb.conf already defines [homes] and two printer shares, which is why a client lists more shares than the one you create. The [homes] share only works after you also turn on the samba_enable_home_dirs SELinux boolean, which is off by default; we leave it alone and build a dedicated share instead.
Why the share directory gets its own group
Step 4 of the checklist means smbd writes as whichever Linux user logged in, so a share used by several people needs a group that owns the directory and a setgid bit that keeps new files in that group. Without the setgid bit, each file would get its creator’s primary group, and the next colleague couldn’t edit it. Create the group, add each user, and give the directory mode 2770:
sudo groupadd smbshare
sudo usermod -aG smbshare gedion
sudo mkdir -p /srv/samba/shared
sudo chgrp smbshare /srv/samba/shared
sudo chmod 2770 /srv/samba/shared
ls -ldZ /srv/samba/shared
The s in the group permissions is the setgid bit. Look at the SELinux label too, because it is the one layer this setup hasn’t touched yet, and it is the one an ls -l without -Z never shows:
drwxrws---. 1 root smbshare unconfined_u:object_r:var_t:s0 0 Oct 20 12:28 /srv/samba/shared
A directory created under /srv inherits var_t, a generic label that SELinux doesn’t associate with Samba. We kept it that way on purpose for the first test, so the failure it causes is visible.
What the share definition controls
The share stanza names the path, restricts it to the group with valid users = @smbshare, and sets the modes Samba applies to new files and directories, which keeps them group-writable. That valid users line is layer 3 of the checklist, so a user who authenticates but is not in the group gets refused before Linux permissions are even consulted. Keeping the group check in both places is deliberate, because a later chmod mistake on the directory then still leaves outsiders out. Open the main configuration file:
sudo vim /etc/samba/smb.conf
Add the share at the end of the file. A mask can only remove permission bits, so the setgid bit on new folders comes from the kernel, which copies it from the setgid parent; a folder we created over SMB came out as drwxrws--- owned by group smbshare:
[shared]
comment = Team share
path = /srv/samba/shared
valid users = @smbshare
read only = no
browseable = yes
create mask = 0660
directory mask = 2770
Validate the file before restarting anything. testparm parses the whole configuration and prints the effective share, and warns about any parameter name it doesn’t recognize, so a typo shows up before smbd silently ignores it:
testparm -s 2>&1 | sed -n "/\[shared\]/,\$p"
testparm -s 2>&1 | head -3
browseable = yes is the default, so it disappears from the share, and the directory mask gains a leading zero. The GnuTLS line in the header is informational, not an error:
[shared]
comment = Team share
create mask = 0660
directory mask = 02770
path = /srv/samba/shared
read only = No
valid users = @smbshare
Load smb config files from /etc/samba/smb.conf
Loaded services file OK.
Weak crypto is allowed by GnuTLS (e.g. NTLM as a compatibility fallback)
Why Samba keeps its own passwords
SMB authentication uses NTLM or Kerberos exchanges that need a hash format /etc/shadow does not store, so Samba keeps a separate database. A Linux account with a perfectly good login password cannot connect until it also has a Samba password. Add one for each user; smbpasswd prompts twice:
sudo smbpasswd -a gedion
sudo pdbedit -L
sudo systemctl restart smb
pdbedit -L lists the accounts in that database with their UID. Each entry must match an existing Linux user, because step 4 switches to that UID, and Samba has no account to switch to otherwise:
gedion:1001:fedora Cloud User
The two passwords are independent from here on. Changing the Linux one with passwd leaves the Samba one untouched, which is a common reason for a share that “suddenly” rejects a user after a password rotation.
What SELinux does to an unlabeled share
With the first four layers in place, we connected from the Fedora client. Testing from a second machine matters here, because smbclient //localhost/shared on the server never crosses the firewall, and a plain touch there runs in your shell’s SELinux context instead of smbd_t, so either can pass while every real client fails. Install the client tools there, then list the shares and try a listing and an upload in one session:
sudo dnf -y install samba-client cifs-utils
smbclient -L //10.0.1.50 -U gedion
smbclient //10.0.1.50/shared -U gedion -c "ls; put /etc/hostname hello.txt"
Authentication worked and the listing worked, so layers 1 to 3 were fine, and reading a directory is something SELinux allows smbd on many labels. Creating a file is where the failure appeared:
. D 0 Tue Oct 20 12:28:45 2026
.. D 0 Tue Oct 20 12:28:45 2026
20865024 blocks of size 1024. 19179380 blocks available
NT_STATUS_ACCESS_DENIED opening remote file \hello.txt
Writing the same directory locally as the same user succeeded with sudo -u gedion touch, which rules out layer 4. That leaves SELinux, and the denial is in the audit records the moment the upload fails. Search them for smbd’s process name:
sudo journalctl _TRANSPORT=audit --since "-20 min" --no-pager | grep -m1 smbd
The record names the denied operation (create), the domain doing it (smbd_t), the label it hit (var_t) and permissive=0, meaning SELinux enforced it. The client address appears in the process name, shown here as 10.0.1.51:
Oct 20 12:29:09 node-a audit[1657]: AVC avc: denied { create } for pid=1657 comm="smbd[10.0.1.51]" name="hello.txt" scontext=system_u:system_r:smbd_t:s0 tcontext=system_u:object_r:var_t:s0 tclass=file permissive=0
The fix is a label, not a boolean. Register a file-context rule for the whole tree so the label survives a relabel, then apply it with restorecon:
sudo semanage fcontext -a -t samba_share_t "/srv/samba(/.*)?"
sudo restorecon -Rv /srv/samba
restorecon reports each relabeled path. Because the rule is now in the policy, a full filesystem relabel later sets the same type instead of reverting it to var_t:
Relabeled /srv/samba from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:samba_share_t:s0
Relabeled /srv/samba/shared from unconfined_u:object_r:var_t:s0 to unconfined_u:object_r:samba_share_t:s0
The same upload from the client now works, and on the server the new file shows each layer doing its job: the uploader as owner, smbshare as group from the setgid bit, mode 660 from the create mask, and the inherited samba_share_t label:
-rw-rw----. 1 gedion smbshare system_u:object_r:samba_share_t:s0 7 Oct 20 12:30 hello.txt
The whole fix, from the audit record to the relabeled file, fits on one screen of the server:

You’ll also find the samba_export_all_rw boolean recommended for this error. It works by letting smbd write to almost every file on the system, which is a much bigger change than labeling one directory, so keep it for the rare case where the data has to stay under a label another service needs. The SELinux survival guide for Fedora covers semanage fcontext in more detail.
How the client mounts the share at boot
A permanent mount should keep the password out of /etc/fstab, which every user can read, and should not hold up boot when the server is unreachable. A root-only credentials file solves the first problem, and x-systemd.automount solves the second by mounting on first access instead of during boot. Create the credentials file on the client:
sudo vim /etc/samba-shared.cred
Put the Samba username and password in it, one per line. These are the Samba credentials from smbpasswd, not the Linux login, which is easy to mix up when they differ:
username=gedion
password=YourSambaPassword
Lock it down, create the mount point and add the fstab entry. The uid and gid options decide which local user owns the files on the client, because the CIFS client does not map server UIDs by default:
sudo chmod 600 /etc/samba-shared.cred
sudo mkdir -p /mnt/shared
echo "//10.0.1.50/shared /mnt/shared cifs credentials=/etc/samba-shared.cred,uid=$(id -u),gid=$(id -g),_netdev,x-systemd.automount 0 0" | sudo tee -a /etc/fstab
sudo systemctl daemon-reload
sudo systemctl start mnt-shared.automount
ls -l /mnt/shared
We rebooted the client to test it (journalctl --list-boots showed the new boot), and findmnt showed only the autofs trigger until the first ls, then the CIFS mount stacked on top of it:
TARGET SOURCE FSTYPE
/mnt/shared systemd-1 autofs
/mnt/shared //10.0.1.50/shared cifs
The kernel client negotiated SMB 3.1.1 (vers=3.1.1 in the mount options) with no version pinned. Files on the mount appear as -rwxr-xr-x owned by the local user, even though the server stores them as -rw-rw----; the client synthesizes those modes from the mount options, and the server’s permissions are still what decides each write.
What a Mac sees on the same share
We mounted the share from macOS with mount_smbfs, wrote a file, and asked smbutil what had been negotiated. In Finder, the same connection is Go, Connect to Server and smb://10.0.1.50/shared:
mkdir -p ~/smbmnt
mount_smbfs "//[email protected]/shared" ~/smbmnt
smbutil statshares -m ~/smbmnt | grep -E "SMB_VERSION|SMB_ENCRYPT|SIGNING|SERVER_NAME"
The Mac also landed on SMB 3.1.1 and advertised all four AES ciphers, so it can meet whatever encryption level the server asks for:
SERVER_NAME 10.0.1.50
SMB_VERSION SMB_3.1.1
SMB_ENCRYPT_ALGORITHMS AES_128_CCM_ENABLED
SMB_ENCRYPT_ALGORITHMS AES_128_GCM_ENABLED
SMB_ENCRYPT_ALGORITHMS AES_256_CCM_ENABLED
SMB_ENCRYPT_ALGORITHMS AES_256_GCM_ENABLED
SIGNING_SUPPORTED TRUE
The file the Mac wrote arrived on the server as -rw-rw----. gedion smbshare, the same as the Linux client’s, because ownership and modes come from the server side of the checklist, not from the client.
Why encryption is off until you ask for it
Samba’s defaults on Fedora already refuse the oldest protocols and the weakest authentication, but they do not encrypt traffic. testparm -sv prints every effective value, so filter it to the settings that matter here:
testparm -sv 2>/dev/null | grep -E "^\s*(server min protocol|server max protocol|server smb encrypt|server signing|ntlm auth) "
On a share with no encryption setting yet, the values were:
ntlm auth = ntlmv2-only
server max protocol = SMB3
server min protocol = SMB2_02
server signing = default
server smb encrypt = default
With default, encryption is negotiated only if the client asks, and our first smbstatus showed the Fedora client’s session signed but unencrypted. To make the server insist on it for this share, open the configuration again:
sudo vim /etc/samba/smb.conf
Add one line to the [shared] stanza; testparm reports it under its canonical name, server smb encrypt:
smb encrypt = required
Reload smbd so new connections pick it up:
sudo smbcontrol smbd reload-config
sudo smbstatus -S
In our test the Fedora client’s session came back encrypted within seconds of the reload, with no action on the client, and it stayed that way after a later client reboot, when the automount reconnected with AES-128-GCM:
Service pid Machine Connected at Encryption Signing
---------------------------------------------------------------------------------------------
IPC$ 3641 10.0.1.51 Tue Oct 20 12:46:41 PM 2026 UTC - -
shared 3641 10.0.1.51 Tue Oct 20 12:46:41 PM 2026 UTC AES-128-GCM AES-128-CMAC
Clients that can’t encrypt are refused on a required share, so check old printers, scanners and NAS backup jobs before you set it on a share they use. Both of our clients connected without any change on their side: the Fedora mount needed no new options, and the Mac reported SMB_CURR_ENCRYPT_ALGORITHM AES-128-GCM and ENCRYPTION_REQUIRED TRUE for the share.
Common misconceptions about Samba on Fedora
Most Samba problems on Fedora come from carrying over an assumption that was true somewhere else. These are the ones our lab disproved:
- “My Linux password logs in to Samba.” It doesn’t;
smbpasswd -acreates a separate password that you have to rotate separately. - “Access denied means wrong permissions.” On Fedora it is just as often the SELinux label, and the audit record names the exact operation and label that failed.
- “chmod 777 will fix it.” It changes layer 4 only; a
var_tdirectory stays unwritable to smbd at any mode. - “You need nmb running.” Clients that connect by DNS name or IP address only need smbd on 445; nmb serves NetBIOS names and browsing, and SMB1 is off anyway, which is why
smbclient -LprintedSMB1 disabled -- no workgroup available. - “Client file modes are the server’s modes.” A CIFS mount shows modes built from its mount options; the server still enforces its own.
If you hold on to one model from all this, make it the five checkpoints in order. When a share misbehaves, find the first checkpoint that fails instead of changing settings at random. The Fedora hardening guide covers the firewall and SELinux side of the server beyond Samba.