SMB automount using systemd

Hi - I saw there were repeating questions on how to mount external drives over SMB.

I documented in detail what I did under Bazzite and a bottleneck I had with SELinux. Happy to get feedback on what I could have differently, better, or easier.

Bazzite SMB automount

Make sure that you replace whatever is in “<>” with your own data.

Setup authentication configuration file

Generate a file that defines the login data to mount the volume. The file will be called credentials located at /var/home/<username>/.smb/credentials. Make sure you first generate the folder mkdir /var/home/<username>/.smb.

username=<username>
password=<password>
  • Ensure the credentials file is readable only by the owner: chmod u=rw,go= /var/home/<username>/.smb/credentials
  • Create a mount folder on your local machine: mkdir /var/home/<username>/retrodeck
  • Create a file called var-home-<username>-retrodeck.mount located at /etc/systemd/system. sudo touch /etc/systemd/system/var-home-<username>-retrodeck.mount.

Create mount unit

[Unit]
Description=Mount SMB Retrodeck Share
# A human-readable description of this mount unit.

# Ensures the network is available before trying to mount.
Requires=network-online.target
# This unit will only start if 'network-online.target' is available.
After=network-online.target systemd-resolved.service
# Waits until network and DNS resolution are ready.
Wants=network-online.target systemd-resolved.service
# Suggests that these services should be running, but does not fail if they aren't.

[Mount]
# Defines what to mount and where.

# The network share (SMB/CIFS) that will be mounted.
What=//<yourRemoteServerIP>/<yourRemoteFolder>
# Replace with actual IP and share name, e.g., //192.168.1.100/retrodeck.

# Local mount point where the share will be attached.
Where=/var/home/<username>/retrodeck
# Replace <username> and <retrodeck> with actual values. Make sure that it matches with the folder you create as mount folder.

# Specifies the filesystem type.
Type=cifs
# This is necessary for mounting a Windows SMB/CIFS share.

# Mount options:
Options=rw,uid=1000,gid=1000,nofail,credentials=/var/home/<username>/.smb/credentials,vers=3.0
# `rw`          → Read/write access.
# `uid=1000`    → Ensures that the mounted files are owned by user ID 1000 (your main user).
# `gid=1000`    → Ensures group ownership by group ID 1000.
# `nofail`      → Prevents boot failure if the SMB share is unavailable.
# `credentials=/var/home/<username>/.smb/credentials` → Specifies the file storing the SMB username & password.
# `vers=3.0`    → Forces SMB version 3.0 for security and performance.

# Sets a timeout to stop trying if the mount hangs.
TimeoutSec=30
# If the mount attempt takes longer than 30 seconds, it will give up.

[Install]
# Ensures this mount is activated at boot.
WantedBy=multi-user.target
# Mounts the share when the system reaches multi-user mode (normal operation).

Set mount unit file permissions

  • Make sure you have set the correct permissions and ownership for systemd mount files.
  • Correct Owner and Group: sudo chown root:root /etc/systemd/system/var-home-<username>-retrodeck.mount
  • Correct File Permissions: sudo chmod u=rw,g=r,o=r /etc/systemd/system/var-home-<username>-retrodeck.mount (u=rw → User (root) gets read & write; g=r → Group (root) gets read-only.; o=r → Others get read-only)

Fixing SELinux Denial (under Bazzite)

By default Systemd is being denied access to the mount unit file due to SELinux policies.

Check Current SELinux Mode

Run:

getenforce
  • If it returns Enforcing, SELinux is actively blocking access.
  • If it returns Permissive, it logs issues but doesn’t enforce them.

Relabel the Mount Unit File

Since the file is in /etc/systemd/system/, it should have the correct SELinux label. To fix it:

sudo restorecon -v /etc/systemd/system/var-home-<username>-retrodeck.mount

Now reload Systemd, enable Auto-Start, and start the SMB mount immediately

  • Reload Systemd to recognize New or modified units: sudo systemctl daemon-reload
    • Forces systemd to reload all unit files (services, mounts, timers, etc.).
    • Necessary when adding, modifying, or deleting .mount files, since systemd does not automatically detect changes.
    • Without this, systemd might not recognize new or modified units, leading to errors when enabling or starting them.
  • Enable the mount to Auto-Start at boot: sudo systemctl enable var-home-<username>-retrodeck.mount
    • Creates a symbolic link in /etc/systemd/system/multi-user.target.wants/ pointing to your mount file.
    • Ensures that systemd automatically mounts the SMB share every time the system boots.
    • This does not immediately mount it—it just sets it up for future boots.
  • Start (mount) the SMB share immediately: sudo systemctl start var-home-<username>-retrodeck.mount
    • Manually triggers the mounting of the SMB share right now, without waiting for a reboot.
    • If successful, the mount point (/var/home/<username>/retrodeck) should now show the contents of the SMB share.
    • If there are errors (e.g., wrong credentials, network issues), it will fail, but logs can be checked using journalctl -xe.

Thank you for this very detailed description. For me only one question is left and Iḿ not sure how to deal with it. I have set SELinux to “Permissve” as default now, is it supposed to stay this way and will it break automounting my NAS folder if I reset it to “Enforcing” ? Tyvm

Thanks for the guide.
I mounted all my SMB folders into /var/mnt/nas and it works perfect.
Note: if your SMB folder contains a space symbol, just enter it into Where: (inside .mount file) without any restrictions (I used nano for editing)

Thank you for your step by step guide. It looked easy to follow but I failed to mount my NAS SMB share…After bazzite going to sleep, it was impossible to login. Hard drive kept on turning and authentification failed. I had to reboot on Win11 :thinking: .

What user name and password should I use? I assumed it was my NAS’s…

I followed this exactly, but I keep getting:

var-home-sarreq-tha-dump.mount - Mount SMB tha-dump Share 
     Loaded: bad-setting (Reason: Unit var-home-sarreq-tha-dump.mount has a bad unit file setting.) 
     Active: inactive (dead) 
      Where: /var/home/sarreq/Tha-Dump 
       What: //THE-DUMP/Tha-Dump/

Jun 20 20:44:55 WastePaperBin systemd[1]: var-home-sarreq-tha-dump.mount: Where= setting doesn't match unit name. Refusing.

firstly, what constitutes the Unit name? is it the .mount file’s filename? what am I missing?

my .mount file:

[Unit]
Description=Mount SMB Tha-Dump Share
# A human-readable description of this mount unit.

# Ensures the network is available before trying to mount.
Requires=network-online.target
# This unit will only start if 'network-online.target' is available.
After=network-online.target systemd-resolved.service
# Waits until network and DNS resolution are ready.
Wants=network-online.target systemd-resolved.service
# Suggests that these services should be running, but does not fail if they aren't.

[Mount]
# Defines what to mount and where.

# The network share (SMB/CIFS) that will be mounted.
What=//THE-DUMP/Tha-Dump/
# Replace with actual IP and share name, e.g., //192.168.1.100/retrodeck.

:face_with_raised_eyebrow: ############ I tried using the IP address, and still get the same problem

# Local mount point where the share will be attached.
Where=/var/home/sarreq/Tha-Dump/
# Replace <username> and <retrodeck> with actual values. Make sure that it matches with the folder you create as mount folder.

# Specifies the filesystem type.
Type=cifs
# This is necessary for mounting a Windows SMB/CIFS share.

# Mount options:
Options=rw,uid=1000,gid=1000,nofail,credentials=/var/home/sarreq/.smb/credentials,vers=3.0
# `rw`          → Read/write access.
# `uid=1000`    → Ensures that the mounted files are owned by user ID 1000 (your main user).
# `gid=1000`    → Ensures group ownership by group ID 1000.
# `nofail`      → Prevents boot failure if the SMB share is unavailable.
# `credentials=/var/home/<username>/.smb/credentials` → Specifies the file storing the SMB username & password.
# `vers=3.0`    → Forces SMB version 3.0 for security and performance.

# Sets a timeout to stop trying if the mount hangs.
TimeoutSec=30
# If the mount attempt takes longer than 30 seconds, it will give up.

[Install]
# Ensures this mount is activated at boot.
WantedBy=multi-user.target
# Mounts the share when the system reaches multi-user mode (normal operation).

The answer is provided here:

systemd has strict unit file naming restrictions for mounts.

In short, rename your mount point /var/home/sarreq/Tha-Dump to something simpler and without a dash - like /var/home/sarreq/thadump. In that case, your unit file must be named var-home-sarreq-thadump.mount.

Alternatively, leave the mount point as is but rename your unit file to var-home-sarreq-Tha\x2dDump.mount… yeah, the dash pretty much screws everything up.

OK, that fixes the unit name error, but now I’m getting the error:

Can't start the unit var-home-sarreq-thadump.mount, because: Failed

I’ve already set SELinux to permissive.

the unitfile as it is now:

[Unit]
Description=Mount SMB Tha-Dump Share
# A human-readable description of this mount unit.

# Ensures the network is available before trying to mount.
Requires=network-online.target

# This unit will only start if 'network-online.target' is available.
After=network-online.target systemd-resolved.service

# Waits until network and DNS resolution are ready.
Wants=network-online.target systemd-resolved.service

# Suggests that these services should be running, but does not fail if they aren't.

[Mount]
# Defines what to mount and where.
# The network share (SMB/CIFS) that will be mounted.
What=//THE-DUMP/Tha-Dump/
# Replace with actual IP and share name, e.g., //192.168.1.100/retrodeck.

# Local mount point where the share will be attached.
Where=/var/home/sarreq/thadump/
# Replace <username> and <retrodeck> with actual values. Make sure that it matches with the folder you create as mount folder.

# Specifies the filesystem type.
Type=cifs
# This is necessary for mounting a Windows SMB/CIFS share.

# Mount options:
Options=rw,uid=1000,gid=1000,nofail,credentials=/var/home/sarreq/.smb/credentials,vers=3.0
# `rw`          → Read/write access.
# `uid=1000`    → Ensures that the mounted files are owned by user ID 1000 (your main user).
# `gid=1000`    → Ensures group ownership by group ID 1000.
# `nofail`      → Prevents boot failure if the SMB share is unavailable.
# `credentials=/var/home/<username>/.smb/credentials` → Specifies the file storing the SMB username & password.
# `vers=3.0`    → Forces SMB version 3.0 for security and performance.

# Sets a timeout to stop trying if the mount hangs.
TimeoutSec=30
# If the mount attempt takes longer than 30 seconds, it will give up.

[Install]
# Ensures this mount is activated at boot.
WantedBy=multi-user.target
# Mounts the share when the system reaches multi-user mode (normal operation).

And what does this command say?

sudo journalctl -u var-home-sarreq-thadump.mount

sorry, got busy with other things.

this confuses me entirely.

Jun 23 18:56:15 WastePaperBin systemd[1]: Mounting var-home-sarreq-thadump.mount - Mount SMB Tha-Dump Share...
Jun 23 18:56:15 WastePaperBin mount[18335]: Mounting cifs URL not implemented yet. Attempt to mount smb://THE-DUMP/Tha-Dump/
Jun 23 18:56:15 WastePaperBin systemd[1]: var-home-sarreq-thadump.mount: Mount process exited, code=exited, status=1/FAILURE
Jun 23 18:56:15 WastePaperBin systemd[1]: var-home-sarreq-thadump.mount: Failed with result 'exit-code'.
Jun 23 18:56:15 WastePaperBin systemd[1]: Failed to mount var-home-sarreq-thadump.mount - Mount SMB Tha-Dump Share.

and changing it to the IP gives this:

Jun 29 05:41:29 WastePaperBin systemd[1]: Mounting var-home-sarreq-thadump.mount - Mount SMB Tha-Dump Share...
Jun 29 05:41:34 WastePaperBin mount[1527]: mount error: could not resolve address for THE-DUMP: Unknown error
Jun 29 05:41:34 WastePaperBin systemd[1]: var-home-sarreq-thadump.mount: Mount process exited, code=exited, status=1/FAILURE
Jun 29 05:41:34 WastePaperBin systemd[1]: var-home-sarreq-thadump.mount: Failed with result 'exit-code'.
Jun 29 05:41:34 WastePaperBin systemd[1]: Failed to mount var-home-sarreq-thadump.mount - Mount SMB Tha-Dump Share.

Can you show both versions of your var-home-sarreq-thadump.mount unit file?

Literally, the only difference is the IP address over the SMB URL

[Unit]
Description=Mount SMB Tha-Dump Share
# A human-readable description of this mount unit.

# Ensures the network is available before trying to mount.
Requires=network-online.target

# This unit will only start if 'network-online.target' is available.
After=network-online.target systemd-resolved.service

# Waits until network and DNS resolution are ready.
Wants=network-online.target systemd-resolved.service

# Suggests that these services should be running, but does not fail if they aren't.

[Mount]
# Defines what to mount and where.
# The network share (SMB/CIFS) that will be mounted.
What=//THE-DUMP/Tha-Dump/
# Replace with actual IP and share name, e.g., //192.168.1.100/retrodeck.

# Local mount point where the share will be attached.
Where=/var/home/sarreq/thadump/
# Replace <username> and <retrodeck> with actual values. Make sure that it matches with the folder you create as mount folder.

# Specifies the filesystem type.
Type=cifs
# This is necessary for mounting a Windows SMB/CIFS share.

# Mount options:
Options=rw,uid=1000,gid=1000,nofail,credentials=/var/home/sarreq/.smb/credentials,vers=3.0
# `rw`          → Read/write access.
# `uid=1000`    → Ensures that the mounted files are owned by user ID 1000 (your main user).
# `gid=1000`    → Ensures group ownership by group ID 1000.
# `nofail`      → Prevents boot failure if the SMB share is unavailable.
# `credentials=/var/home/<username>/.smb/credentials` → Specifies the file storing the SMB username & password.
# `vers=3.0`    → Forces SMB version 3.0 for security and performance.

# Sets a timeout to stop trying if the mount hangs.
TimeoutSec=30
# If the mount attempt takes longer than 30 seconds, it will give up.

[Install]
# Ensures this mount is activated at boot.
WantedBy=multi-user.target
# Mounts the share when the system reaches multi-user mode (normal operation).

[Unit]
Description=Mount SMB Tha-Dump Share
# A human-readable description of this mount unit.

# Ensures the network is available before trying to mount.
Requires=network-online.target

# This unit will only start if 'network-online.target' is available.
After=network-online.target systemd-resolved.service

# Waits until network and DNS resolution are ready.
Wants=network-online.target systemd-resolved.service

# Suggests that these services should be running, but does not fail if they aren't.

[Mount]
# Defines what to mount and where.
# The network share (SMB/CIFS) that will be mounted.
What=//192.168.1.161/Tha-Dump/
# Replace with actual IP and share name, e.g., //192.168.1.100/retrodeck.

# Local mount point where the share will be attached.
Where=/var/home/sarreq/thadump/
# Replace <username> and <retrodeck> with actual values. Make sure that it matches with the folder you create as mount folder.

# Specifies the filesystem type.
Type=cifs
# This is necessary for mounting a Windows SMB/CIFS share.

# Mount options:
Options=rw,uid=1000,gid=1000,nofail,credentials=/var/home/sarreq/.smb/credentials,vers=3.0
# `rw`          → Read/write access.
# `uid=1000`    → Ensures that the mounted files are owned by user ID 1000 (your main user).
# `gid=1000`    → Ensures group ownership by group ID 1000.
# `nofail`      → Prevents boot failure if the SMB share is unavailable.
# `credentials=/var/home/<username>/.smb/credentials` → Specifies the file storing the SMB username & password.
# `vers=3.0`    → Forces SMB version 3.0 for security and performance.

# Sets a timeout to stop trying if the mount hangs.
TimeoutSec=30
# If the mount attempt takes longer than 30 seconds, it will give up.

[Install]
# Ensures this mount is activated at boot.
WantedBy=multi-user.target
# Mounts the share when the system reaches multi-user mode (normal operation).

alternatively, is there a way to install SMB4K? I’ve never had a problem with that.

Are you doing:

sudo systemctl daemon-reload

after each change in the mount unit file?

Both of your errors show things that are not found in the unit files so they seem as not being related at all.

Hey all, new Bazzite and Linux in general user here. Tried to follow the instructions in the guide, but unfortunately it isn’t working for me. This is what shows up when I use journalctl -xe, I have no clue what any of this means, it’s a little bit extremely out of my depth. Does anybody know what the important things are here that it’s telling me to fix?

A stop job for unit user-runtime-dir@0.service has begun execution. 
░░  
░░ The job identifier is 18225. 
Aug 26 22:10:17 WIN-7VHBMNAQCPV.localdomain systemd\[1\]: run-user-0.mount: Deactivated successfully. 
░░ Subject: Unit succeeded 
░░ Defined-By: systemd 
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel 
░░  
░░ The unit run-user-0.mount has successfully entered the 'dead' state. 
Aug 26 22:10:17 WIN-7VHBMNAQCPV.localdomain systemd\[1\]: user-runtime-dir@0.service: Deactivated successfully. 
░░ Subject: Unit succeeded 
░░ Defined-By: systemd 
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel 
░░  
░░ The unit user-runtime-dir@0.service has successfully entered the 'dead' state. 
Aug 26 22:10:17 WIN-7VHBMNAQCPV.localdomain systemd\[1\]: Stopped user-runtime-dir@0.service - User Runtime Directory /run/user/0. 
░░ Subject: A stop job for unit user-runtime-dir@0.service has finished 
░░ Defined-By: systemd 
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel 
░░  
░░ A stop job for unit user-runtime-dir@0.service has finished. 
░░  
░░ The job identifier is 18225 and the job result is done. 
Aug 26 22:10:17 WIN-7VHBMNAQCPV.localdomain audit\[1\]: SERVICE_STOP pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=user-runtime-dir@0 comm=> 
Aug 26 22:10:17 WIN-7VHBMNAQCPV.localdomain systemd\[1\]: Removed slice user-0.slice - User Slice of UID 0. 
░░ Subject: A stop job for unit user-0.slice has finished 
░░ Defined-By: systemd 
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel 
░░  
░░ A stop job for unit user-0.slice has finished. 
░░  
░░ The job identifier is 18227 and the job result is done. 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain systemd\[1\]: Starting rpm-ostreed.service - rpm-ostree System Management Daemon... 
░░ Subject: A start job for unit rpm-ostreed.service has begun execution 
░░ Defined-By: systemd 
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel 
░░  
░░ A start job for unit rpm-ostreed.service has begun execution. 
░░  
░░ The job identifier is 18229. 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain rpm-ostree\[8944\]: Reading config file '/etc/rpm-ostreed.conf' 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain rpm-ostree\[8944\]: In idle state; will auto-exit in 63 seconds 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain systemd\[1\]: Started rpm-ostreed.service - rpm-ostree System Management Daemon. 
░░ Subject: A start job for unit rpm-ostreed.service has finished successfully 
░░ Defined-By: systemd 
░░ Support: https://lists.freedesktop.org/mailman/listinfo/systemd-devel 
░░  
░░ A start job for unit rpm-ostreed.service has finished successfully. 
░░  
░░ The job identifier is 18229. 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain audit\[1\]: SERVICE_START pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=rpm-ostreed comm="syste> 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain rpm-ostree\[8944\]: Allowing active client :1.262 (uid 1000) 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain rpm-ostree\[8944\]: client(id:cli dbus:1.262 unit:app-org.kde.konsole-6069.scope uid:1000) added; new total=1 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain rpm-ostree\[8944\]: client(id:cli dbus:1.262 unit:app-org.kde.konsole-6069.scope uid:1000) vanished; remaining=0 
Aug 26 22:10:18 WIN-7VHBMNAQCPV.localdomain rpm-ostree\[8944\]: In idle state; will auto-exit in 61 seconds

Welcome - and sorry the log dump is confusing. journalctl -xe is “the end of the journal around the last interesting event”, not “the error for my NAS mount”. What you pasted is a root user session (user-runtime-dir@0) shutting down and rpm-ostree starting. That is unrelated to SMB.

We need the mount unit’s status, not -xe.

Replace USERNAME and FOLDER with the values you actually used (in the guide that was retrodeck).

# who you are (uid should match the uid= in Options=)
id
#the unit systemd thinks it has
systemctl list-units --type=mount --all | grep -i home
# this is the useful log
systemctl status var-home-USERNAME-FOLDER.mount --no-pager
journalctl -u var-home-USERNAME-FOLDER.mount --no-pager -n 50

Paste those two outputs here (status + -u log), plus:

  1. the filename of the unit under /etc/systemd/system/
  2. the Where= and What= lines from that file

A few things that bite people following this guide (also later in this thread):

  • Unit name must match Where=. Path /var/home/bob/nas → file var-home-bob-nas.mount. A hyphen in the folder name is special; systemd wants \x2d in the filename, or you pick a folder without -. Easiest: mkdir ~/nas and var-home-USERNAME-nas.mount.
  • No trailing slash on Where= (use /var/home/USERNAME/nas, not …/nas/).
  • What= is //IP/sharename, not smb://.... Prefer the NAS IPv4 over a hostname. After each edit: sudo systemctl daemon-reload.
  • Credentials are the NAS SMB user, not your Bazzite login. File mode 600, then sudo restorecon -v on the .mount file. Leave SELinux Enforcing; Permissive is only for debugging, not the fix.

Quick sanity check that the share itself works (before systemd):

sudo mount -t cifs //NAS_IP/SHARE /var/home/USERNAME/FOLDER
-o credentials=/var/home/USERNAME/.smb/credentials,uid=$(id -u),gid=$(id -g),vers=3.0
ls /var/home/USERNAME/FOLDER
sudo umount /var/home/USERNAME/FOLDER

If that mount fails, the unit cannot work either (wrong IP, share name, or password). If it succeeds, the unit file/name is the remaining problem.

Happy to look at the systemctl status / journalctl -u output once you have it.