A state-based SMB/CIFS mount controller for Linux that manages network shares based on reachability.
It is designed to prevent desktop freezes, reduce mount instability, and provide predictable control over SMB mounts across multiple servers.
AI was use a lot here, I'm mostly just sharing this because I like it myself.
This tool replaces traditional automount approaches (such as autofs in desktop environments) with a deterministic state system:
- Shares are mounted only after the server is confirmed online (up to 3 trys by default)
- Shares are unmounted only after the server is confirmed offline (up to 3 trys by default)
- Supports multiple SMB servers in parallel
- Designed for use with systemd (but can be easly replaced, it just needs to run in root on startup)
- Multi-server SMB/CIFS support
- Parallel mount and unmount execution
- Stateful online/offline detection using counters
- Configurable retry thresholds
- Lazy unmount to avoid "device busy" issues
- Optional staggered execution delays (by default 0.1 seconds)
- Does not interfere after stabilization (hands control back to user)
- Systemd integration included (can be skipped)
- Non-blocking design to avoid file manager freezes
Each server is monitored independently.
- If the server responds on port 445, an ONLINE counter increases
- All configured shares for that server are mounted
- If mount succeeds, the counter continues counting up until COUNT_MAX is reached, then stops trying (allows manual control)
- If mount fails, it will retry up to COUNT_MAX times
- If the server is unreachable, an OFFLINE counter increases
- All shares are unmounted using lazy unmount
- If unmount succeeds, the counter continues counting up until COUNT_MAX is reached, then stops trying (allows manual control)
- If unmount fails, it will retry up to COUNT_MAX times
After either action completes, the system stops acting until state changes again.
Paste the following in a terminal and press enter
bash -c '
curl -fsSL https://codeberg.org/marvin1099/smb-mount-controller/raw/branch/main/smb-controller-installer.sh -o smb-controller-installer.sh \
|| { echo "Download failed"; exit 1; }
chmod +x smb-controller-installer.sh || { echo "chmod failed"; exit 1; }
echo "Downloaded to $(realpath smb-controller-installer.sh)"
IFS= read -rp "Read installer? (y/n) " ans; ans=${ans,,}
[[ "$ans" == y* ]] && less smb-controller-installer.sh
IFS= read -rp "Keep installer on exit? (y/n) " anw; anw=${anw,,}
IFS= read -rp "Run installer? (y/n) " ans; ans=${ans,,}
[[ "$ans" == y* ]] && ./smb-controller-installer.sh || NO=1
[[ "$anw" == y* ]] && echo "Keeping installer" \
|| { rm ./smb-controller-installer.sh && echo "Removed installer" || echo "Failed to remove installer"; }
[[ -n "$NO" ]] && { echo "Cancelled"; exit 1; } || echo "Installer ran successfully"
'
As alternative to quick start the project is available in the AUR:
yay -S smb-mount-controller-gitor
paru -S smb-mount-controller-gitThis will install behave like:
./smb-controller-installer.sh -iYou still need to edit the config manually, so it works on your system
The project includes an interactive installer that supports both guided and non-interactive modes.
Run:
./smb-controller-installer.shThis will:
-
Offer you options to:
- Read the script
- Install
- Uninstall
- Cancel (exit)
-
On Install selection:
- Install the controller script
- Offer configuration options (example or empty config)
- Open the config in an editor (can be disabled with -c flag)
- Optionally install and enable systemd service
-
On Uninstall:
- Stops and disables systemd service (if present)
- Removes installed binaries and service files
- Keeps the config file
The installer supports flags for automation:
./smb-controller-installer.sh -iBehavior:
- Installs controller
- Downloads systemd service automatically (no activation or start)
- Uses existing config if present, otherwise installs default
- Skips all prompts
- Does not open editor (you still need to edit manually, so it works on your system)
./smb-controller-installer.sh -i -lUse -l to use files from the script's directory instead of downloading. Useful for offline installation or custom builds.
./smb-controller-installer.sh -i -nUse -n to skip systemd service file creation. Useful for systems without systemd or custom setups.
./smb-controller-installer.sh -i -cUse -c to open the config file in an editor during non-interactive install. In interactive mode, this option disables the automatic config editor prompt.
./smb-controller-installer.sh -i -aUse -a to enable and start the systemd service immediately (requires -i without -n).
./smb-controller-installer.sh -r
# or
./smb-controller-installer.sh -uBehavior:
- Stops and disables systemd service (if present)
- Removes installed binaries and service files
- Does not prompt for confirmation
- Keeps config file
./smb-controller-installer.sh -r -nUse -n to skip systemd service removal.
./smb-controller-installer.sh -i -sUse -s to view the script with less before proceeding.
./smb-controller-installer.sh -hShows full help with all available options and examples.
Configuration is defined in:
/etc/smb-controller.conf
Config edit is needed, as the config will likely never match your setup.
- GLOBAL SETTINGS: timing, mount options, base path
- SERVERS: list of SMB servers with credentials
- PATHS: mapping of mount points to servers and remote paths
Example (also in example-smb-controller.conf):
# =========================
# GLOBAL SETTINGS
# =========================
# smb-mount-controller config v1
# Base directory for all mount points (use absolute path)
# This is only used in the config, so can be replaced if need be
BASEMNT="/srv/M"
# Timeout in seconds for each port check (server reachability test)
CHECK_TIMEOUT=1
# Number of attempts to mount/unmount on state change
# After this many attempts, the script stops trying and allows manual control
# Example output: "[SMB-media] OFFLINE 3/3" means no more auto-unmount attempts
COUNT_MAX=3
# Wait time in seconds between full server checks
SLEEP=5
# Delay in seconds between each share mount/unmount action
# (prevents load spikes when mounting many shares at once)
SPAWN_DELAY=0.1
# Delay in seconds between processing each server
# (light throttling to reduce CPU usage)
SERVER_DELAY=0.1
# Mount options for CIFS shares
# Examples: uid=root (owner), gid=smbmount (group for access),
# file_mode/dir_mode (permissions), soft (non-blocking)
MOUNT_OPTIONS="uid=root,gid=smbmount,file_mode=0770,dir_mode=0770,soft"
# =========================
# SERVERS
# =========================
# Define SMB servers to monitor
# FORMAT: name:ip:credentials_file
# name: friendly identifier (used in PATHS)
# ip: IP address or hostname of the server
# credentials: path to credentials file (see smb-controller.sh for format)
SERVERS=(
"media-server:192.168.50.10:/etc/samba/media-smb-credentials"
"backup-node:192.168.50.11:/etc/samba/backup-smb-credentials"
)
# =========================
# PATHS
# =========================
# Define mount points for each server
# FORMAT: label:mountpoint:remote_path:server_name
# label: descriptive name (used in logs)
# mountpoint: local directory to mount to (use ${BASEMNT} for global base)
# remote_path: path on the SMB server to mount
# server_name: name from SERVERS array to connect to
PATHS=(
"mediaHome:${BASEMNT}/mediaHome:/home:media-server"
"mediaData:${BASEMNT}/mediaData:/mnt:media-server"
"mediaUSB:${BASEMNT}/mediaUSB:/usbs:media-server"
"backupHome:${BASEMNT}/backupHome:/home:backup-node"
"backupData:${BASEMNT}/backupData:/mnt:backup-node"
"backupUSB:${BASEMNT}/backupUSB:/usbs:backup-node"
)- Linux system with some sort of backround service
- cifs-utils
- netcat (nc)
- bash 4+
The controller runs as a systemd service for continuous operation (if secected).
Example behavior:
- Starts on boot (if enabled)
- Automatically recovers after restart
- Runs continuously in background
This project is designed with the following priorities:
- Avoid blocking filesystem operations
- Prevent file manager freezes (especially KDE Dolphin)
- Keep user control over mounts
- Avoid constant mount/unmount loops
- Be predictable and state-driven rather than event-driven
- Uses lazy unmount (
umount -l) to prevent blocking on busy mounts - Designed for trusted LAN environments
- Not intended as a security boundary mechanism