netshare-mounter
CLI utility that configures SMB/CIFS shares as systemd mount units — so they mount on
boot, wait for the network, and are managed with systemctl and journalctl rather than
fstab. It installs cifs-utils if missing, writes a per-mount credentials file at mode
600, and validates before mounting.
Quick usage lives in USAGE.md; each command also has a man page under
man/.
Building
Section titled “Building”The executable is generated by Bashly from src/:
cd packages/debian-ubuntu/scripts/netshare-mounterbashly generate # needs Ruby + `gem install bashly`sudo cp netshare-mounter /usr/local/bin/Without Ruby, generate through Docker:
docker run --rm --user $(id -u):$(id -g) --volume "$PWD:/app" dannyben/bashly generate# Windows (Git Bash): docker run --rm --volume "/${PWD}:/app" dannyben/bashly generateCommands
Section titled “Commands”sudo netshare-mounter mount //192.168.1.29/plex_storage /mnt/plex_storagenetshare-mounter status /mnt/plex_storagesudo netshare-mounter unmount /mnt/plex_storagemount <share> <mountpoint>
Section titled “mount <share> <mountpoint>”Credentials are prompted for when not passed.
| Option | Default |
|---|---|
-u, --username | prompt |
-p, --password | prompt |
-d, --domain | none |
--uid / --gid | 1000 / 1000 |
--file-mode / --dir-mode | 0644 / 0755 |
--cifs-version | 3.0 (1.0, 2.0, 2.1, 3.0, 3.1.1) |
-c, --credentials-file | ~/.netshare-mounter/<unit-name>.credentials |
--auto-install | install cifs-utils without prompting |
--enable-only | enable for next boot without mounting now |
unmount <mountpoint>
Section titled “unmount <mountpoint>”| Option | Effect |
|---|---|
-k, --keep-credentials | Leave the credentials file in place |
-m, --keep-mountpoint | Leave the mount point directory |
-f, --force | umount -f even if busy |
--purge | Remove credentials, mount point and unit without prompting |
status [mountpoint]
Section titled “status [mountpoint]”Shows all CIFS mounts when the mount point is omitted. -v adds the systemd unit detail;
-j emits JSON (… --json | jq -r '.active').
validate <share>
Section titled “validate <share>”-c, --check-connectivity tests reachability of the SMB server;
--check-credentials <file> checks that file’s permissions.
How it works
Section titled “How it works”Each mount gets its own credentials file, named after the unit —
/mnt/plex_storage → ~/.netshare-mounter/mnt-plex_storage.credentials, stored in the
invoking user’s home even under sudo. --credentials-file overrides that when several
mounts should share one. Files are written 600, never logged, and shredded on removal.
The generated unit:
[Unit]Description=Mount SMB Share: //192.168.1.29/plex_storageAfter=network-online.targetWants=network-online.targetRequiresMountsFor=/mnt
[Mount]What=//192.168.1.29/plex_storageWhere=/mnt/plex_storageType=cifsOptions=credentials=…,uid=1000,gid=1000,file_mode=0644,dir_mode=0755,vers=3.0,rwTimeoutSec=30
[Install]WantedBy=multi-user.targetsystemd derives the unit name from the path — /mnt/plex_storage must be
mnt-plex_storage.mount, and spaces in mount paths are not allowed at all.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Check |
|---|---|
Permission denied | Credentials. Test by hand: sudo mount -t cifs //server/share /mnt/test -o credentials=<file> |
Connection timed out | netshare-mounter validate //server/share --check-connectivity, then nc -zv server 445 |
| Unit fails to start | systemctl status mnt-<name>.mount, journalctl -xeu mnt-<name>.mount |
| Busy during unmount | lsof /mnt/<name> or fuser -vm /mnt/<name>, then unmount --force |
| Wrong credentials permissions | validate <share> --check-credentials <file>, or chmod 600 it |
| Mount fails on an old server | Lower --cifs-version to 2.0 or 1.0; modern servers want 3.0/3.1.1 |
For Active Directory, pass the domain both ways:
--username 'DOMAIN\\user' --domain DOMAIN.
Project structure
Section titled “Project structure”netshare-mounter/├── src/│ ├── bashly.yml # command definitions│ ├── {mount,unmount,status,validate}_command.sh│ └── lib/{helpers,systemd,credentials}.sh├── netshare-mounter # generated — do not edit├── USAGE.md└── man/, docs/ # generated man pagesEdit src/, never the generated executable, and keep shellcheck clean.