NAS Mount

This role manages CIFS/SMB network share mounting from NAS devices.

ARA Ansible Bash Centreon DNS Debian Docker NAS

NAS Mount Role

Overview

This role manages CIFS/SMB network share mounting from NAS devices. It installs cifs-utils, creates mount point directories, generates secure credential files, mounts network shares with proper ownership (UID/GID), adds entries to /etc/fstab for persistence across reboots, and supports both mounting and unmounting operations for multiple NAS devices.

Purpose

  • Automated NAS Mounting: Mount network shares via CIFS/SMB protocol
  • Dual NAS Support: Mount multiple NAS devices (Synology DS418, Proxmox OMV)
  • Secure Credentials: Store passwords in separate credential files
  • Persistent Mounts: Automatic mounting via /etc/fstab
  • Ownership Control: Configure UID/GID for file access
  • State Management: Mount or unmount shares on demand
  • Backup Storage: Provides storage for backup roles

Requirements

  • Ansible 2.9 or higher
  • Collection: ansible.posix (for mount module)
  • NAS devices accessible via network
  • CIFS/SMB shares configured on NAS
  • NAS user accounts with appropriate permissions
  • Ansible Vault for storing NAS passwords
  • Proper sudo/root permissions on target host

What is CIFS/SMB?

CIFS (Common Internet File System) and SMB (Server Message Block) are network file sharing protocols that:

  • Allow mounting remote file systems over network
  • Provide file and print sharing
  • Support authentication and permissions
  • Compatible with Windows, Linux, NAS devices

Common use cases:

  • Mounting Windows shares on Linux
  • Accessing NAS storage (Synology, QNAP, etc.)
  • Network backup storage
  • Shared file access across systems

Role Variables

Required Variables

VariableRequiredDescription
nas_mount_mountsYesList of NAS mount configurations
vault_nas_mount_*_passwordYesNAS passwords in Ansible Vault

Optional Variables

VariableDefaultDescription
nas_mount_uid1001User ID for mount ownership
nas_mount_gid1001Group ID for mount ownership
nas_mount_statemountedMount state (mounted/unmounted)

Variable Details

nas_mount_mounts

List of NAS mounts to configure.

Structure:

nas_mount_mounts:
  - name: nas_identifier
    server: nas_ip_address
    share: /share_path
    mount_point: /local/mount/point
    user: nas_username
    password: "{{ vault_password }}"
    domain: WORKGROUP

Default configuration:

nas_mount_mounts:
  - name: synology-ds418
    server: "{{ hostvars['synology-ds418']['ip_vlan12'] }}"
    share: "/Backups"
    mount_point: "/mnt/synology-ds418"
    user: "backupuser"
    password: "{{ vault_nas_mount_synology_ds418_backup_password }}"
    domain: "WORKGROUP"

  - name: prxmx-omv
    server: "{{ hostvars['prxmx-omv']['ip_vlan12'] }}"
    share: "/Backups"
    mount_point: "/mnt/prxmx-omv"
    user: "backupuser"
    password: "{{ vault_nas_mount_prxmx_omv_backup_password }}"
    domain: "WORKGROUP"

Field descriptions:

FieldRequiredDescription
nameYesUnique identifier for this mount
serverYesNAS IP address or hostname
shareYesShare path on NAS (e.g., /Backups)
mount_pointYesLocal directory to mount share
userYesCIFS/SMB username for authentication
passwordYesPassword (from vault)
domainYesWindows domain or workgroup

Custom example:

nas_mount_mounts:
  - name: qnap-storage
    server: "192.168.x.x"
    share: "/Media"
    mount_point: "/mnt/qnap/media"
    user: "mediauser"
    password: "{{ vault_qnap_media_password }}"
    domain: "WORKGROUP"

  - name: windows-server
    server: "192.168.x.x"
    share: "/SharedFiles"
    mount_point: "/mnt/winserver"
    user: "domain\\username"
    password: "{{ vault_winserver_password }}"
    domain: "COMPANY"

nas_mount_uid and nas_mount_gid

User and Group IDs for mount ownership. Files on mounted shares appear owned by this UID/GID.

Default:

nas_mount_uid: 1001
nas_mount_gid: 1001

How to find UID/GID:

# For user 'backupuser'
id backupuser
# Output: uid=1001(backupuser) gid=1001(backupuser) groups=1001(backupuser)

Example for different user:

nas_mount_uid: 1000  # Standard user UID
nas_mount_gid: 1000  # Standard user GID

nas_mount_state

Control whether shares should be mounted or unmounted.

Values:

  • mounted: Mount shares and add to /etc/fstab
  • unmounted: Unmount shares, remove from /etc/fstab, cleanup

Default: mounted

Unmounting example:

nas_mount_state: unmounted

Dependencies

This role requires:

  • Collection: ansible.posix (for mount module)
  • Package: cifs-utils (installed by role)
  • NAS devices accessible on network
  • Ansible Vault for storing passwords

Example Playbook

Basic Usage

---
- name: Mount NAS Shares
  hosts: backup_server
  become: true

  roles:
    - nas_mount

Mount Custom NAS

---
- name: Mount QNAP Storage
  hosts: media_server
  become: true

  vars:
    nas_mount_mounts:
      - name: qnap-media
        server: "192.168.x.x"
        share: "/Media"
        mount_point: "/mnt/qnap"
        user: "mediauser"
        password: "{{ vault_qnap_password }}"
        domain: "WORKGROUP"

    nas_mount_uid: 1000
    nas_mount_gid: 1000

  roles:
    - nas_mount

Unmount All Shares

---
- name: Unmount NAS Shares
  hosts: backup_server
  become: true

  vars:
    nas_mount_state: unmounted

  roles:
    - nas_mount

With Custom Ownership

---
- name: Mount NAS with Custom UID/GID
  hosts: backup_server
  become: true

  vars:
    nas_mount_uid: 1002  # User 'mediauser'
    nas_mount_gid: 1002  # Group 'mediauser'

  roles:
    - nas_mount

What This Role Does

When nas_mount_state = mounted

  1. Installs cifs-utils package

    • Required for CIFS/SMB mounting
    • Provides mount.cifs helper
  2. For each NAS in nas_mount_mounts:

    • Creates mount point directory (e.g., /mnt/synology-ds418)
    • Creates credentials file (/etc/nas_creds_{name}) with mode 0600
    • Mounts the share using ansible.posix.mount
    • Adds to /etc/fstab for persistent mounting

When nas_mount_state = unmounted

  1. For each NAS in nas_mount_mounts:
    • Unmounts the share
    • Removes mount point directory
    • Deletes credentials file
    • Removes from /etc/fstab

Credential Files

Format

Role creates credential files at /etc/nas_creds_{name}:

username=backupuser
password=secret_password
domain=WORKGROUP

Security

  • Location: /etc/nas_creds_synology-ds418
  • Permissions: 0600 (owner read/write only)
  • Ownership: root:root
  • Purpose: Avoid passwords in /etc/fstab

Why Separate Credentials Files?

Security benefits:

  • Passwords not visible in mount output
  • Passwords not in /etc/fstab (world-readable by default)
  • Each mount can have different credentials
  • Easy to rotate passwords (update file, remount)

/etc/fstab Entry

Role adds entries to /etc/fstab:

//192.168.x.x/Backups /mnt/synology-ds418 cifs credentials=/etc/nas_creds_synology-ds418,uid=1001,gid=1001 0 0
//192.168.x.x/Backups /mnt/prxmx-omv cifs credentials=/etc/nas_creds_prxmx-omv,uid=1001,gid=1001 0 0

Field explanation:

  • Device: //server/share (UNC path)
  • Mount point: /mnt/synology-ds418
  • Type: cifs (CIFS/SMB filesystem)
  • Options: credentials=...,uid=...,gid=...
  • Dump: 0 (don’t backup with dump)
  • Pass: 0 (don’t fsck at boot)

Mount Options

The role uses these mount options:

OptionValueDescription
credentials/etc/nas_creds_{name}Path to credentials file
uid1001 (configurable)User ID for file ownership
gid1001 (configurable)Group ID for file ownership

Additional options (not used by role but can be added):

OptionDescription
vers=3.0Force SMB version 3.0
roRead-only mount
noserverinoDon’t trust server inode numbers
nopermDon’t check permissions
file_mode=0644Set file permissions
dir_mode=0755Set directory permissions

Custom mount options example:

# In mount.yml, modify opts parameter:
opts: "credentials=/etc/nas_creds_{{ nas.name }},uid={{ nas_mount_uid }},gid={{ nas_mount_gid }},vers=3.0,noperm"

UID/GID Ownership

Why UID/GID Matters

CIFS mounts don’t preserve Linux ownership from NAS. Instead, all files appear owned by specified UID/GID.

Example:

nas_mount_uid: 1001  # User 'backupuser'
nas_mount_gid: 1001  # Group 'backupuser'

Result:

ls -la /mnt/synology-ds418/
# All files show: -rw-r--r-- 1 backupuser backupuser

Finding Correct UID/GID

# Check user's UID/GID
id username

# Example output:
# uid=1001(backupuser) gid=1001(backupuser) groups=1001(backupuser)

# Use these values in role variables

Common UID/GID Values

UserTypical UIDTypical GID
root00
First user10001000
Second user10011001
Service account999-1000999-1000

Verifying Mounts

Check Mounted Shares

# List all mounts
mount | grep cifs

# Should show:
# //192.168.x.x/Backups on /mnt/synology-ds418 type cifs (...)
# //192.168.x.x/Backups on /mnt/prxmx-omv type cifs (...)

# Check specific mount
df -h /mnt/synology-ds418

# List files
ls -la /mnt/synology-ds418/

Check /etc/fstab

# View fstab entries
grep cifs /etc/fstab

# Should show mount configurations

Check Credentials Files

# List credential files
ls -l /etc/nas_creds_*

# Should show:
# -rw------- 1 root root /etc/nas_creds_synology-ds418
# -rw------- 1 root root /etc/nas_creds_prxmx-omv

# View credentials (as root)
cat /etc/nas_creds_synology-ds418

Test Read/Write

# Test read
ls /mnt/synology-ds418/

# Test write (as user with UID matching mount)
touch /mnt/synology-ds418/test_file.txt

# Test as different user
sudo -u backupuser touch /mnt/synology-ds418/test_file.txt

Security Considerations

  • Credential Files: Protected with mode 0600 (root only)
  • Passwords in Vault: Never in plaintext in playbooks
  • No Logging: Tasks marked with no_log: true to prevent password exposure
  • Root Ownership: Credential files owned by root:root
  • fstab Security: Passwords not in /etc/fstab (uses credentials files)
  • Network Security: CIFS traffic is not encrypted (consider VPN for remote access)
  • NAS Permissions: Configure appropriate ACLs on NAS side

Tags

This role does not define any tags. Use playbook-level tags if needed:

- hosts: backup_server
  roles:
    - nas_mount
  tags:
    - nas
    - mount
    - storage
    - backup

Notes

  • Role uses /etc/fstab for persistent mounts (survives reboots)
  • Credentials stored in separate files (not in fstab)
  • Supports multiple NAS devices simultaneously
  • Mount options include UID/GID for ownership
  • Role is idempotent (safe to run multiple times)
  • Unmount state removes all traces (directories, credentials, fstab entries)
  • CIFS protocol requires cifs-utils package

Troubleshooting

”mount error(13): Permission denied”

Cause: Invalid credentials or insufficient permissions on NAS

Solution:

# Verify credentials
cat /etc/nas_creds_synology-ds418

# Test credentials manually
smbclient //nas-ip/Backups -U username

# Check NAS permissions for user
# (verify user has access to share on NAS)

# Check credentials file exists and is readable by root
ls -l /etc/nas_creds_synology-ds418

“mount error(112): Host is down”

Cause: NAS not reachable or wrong IP

Solution:

# Test network connectivity
ping nas-ip

# Check if NAS is powered on
# Verify IP address is correct

# Test SMB port
telnet nas-ip 445
# Should connect

# Check DNS resolution
nslookup nas-hostname

“mount error(115): Operation now in progress”

Cause: Network timeout or firewall blocking

Solution:

# Check firewall allows SMB (port 445)
# On NAS and client

# Increase timeout (in mount options):
opts: "credentials=...,uid=...,gid=...,_netdev,timeo=30"

# Check network stability
ping -c 100 nas-ip

“mount.cifs: command not found”

Cause: cifs-utils not installed

Solution:

# Install manually
dnf install cifs-utils  # RedHat
apt install cifs-utils  # Debian

# Re-run role (should install automatically)
ansible-playbook site.yml --tags nas

Permission denied when writing to mount

Cause: UID/GID mismatch

Solution:

# Check current user UID
id username

# Check mount UID
mount | grep cifs
# Look for uid=XXXX in options

# If mismatch, update role variables:
nas_mount_uid: correct_uid
nas_mount_gid: correct_gid

# Re-run role
ansible-playbook site.yml --tags nas

Mount exists but shows empty

Cause: Mount overlaying existing directory with files

Solution:

# Unmount to see original directory
umount /mnt/synology-ds418

# Check what was hidden
ls /mnt/synology-ds418/

# Remove files if needed, remount
mount /mnt/synology-ds418

Stale mount after NAS reboot

Cause: Connection broken, mount not refreshed

Solution:

# Lazy unmount (force)
umount -l /mnt/synology-ds418

# Remount
mount /mnt/synology-ds418

# Or restart autofs if using it
systemctl restart autofs

Testing After Role Execution

Verify Packages Installed

# Check cifs-utils installed
rpm -q cifs-utils  # RedHat
dpkg -l cifs-utils  # Debian

Verify Mounts Active

# List CIFS mounts
mount -t cifs

# Check with df
df -h -t cifs

# Should show both NAS mounts

Test File Operations

# As user with matching UID
ls /mnt/synology-ds418/
touch /mnt/synology-ds418/test_file.txt
echo "test content" > /mnt/synology-ds418/test_file.txt
cat /mnt/synology-ds418/test_file.txt
rm /mnt/synology-ds418/test_file.txt

Verify Persistence

# Reboot system
reboot

# After reboot, check mounts
mount | grep cifs

# Should be automatically mounted via /etc/fstab

Performance Considerations

  • Network Speed: Limited by network bandwidth (1 Gbps typical)
  • Latency: Higher than local storage (network round-trip)
  • Concurrent Access: May be slower with many simultaneous users
  • NAS Performance: Depends on NAS hardware (CPU, RAM, disk speed)

Tips for better performance:

  • Use Gigabit or 10 Gigabit network
  • Minimize network hops (direct connection preferred)
  • Use SSD storage on NAS
  • Consider SMB version 3.0 for multichannel support

Best Practices

  1. Store passwords in Ansible Vault (never plaintext)
  2. Use descriptive mount names (matches NAS device name)
  3. Configure appropriate UID/GID (matches backup user)
  4. Test mounts after changes (verify read/write access)
  5. Monitor mount status (check for stale mounts)
  6. Document share purposes (backup, media, etc.)
  7. Use network redundancy (dual NAS for critical backups)
  8. Regular connectivity checks (monitor NAS availability)
  9. Backup credential files (part of system backup)
  10. Review NAS permissions (least privilege principle)

Unmounting NAS Shares

To cleanly remove NAS mounts:

---
- name: Unmount NAS Shares
  hosts: backup_server
  become: true

  vars:
    nas_mount_state: unmounted

  roles:
    - nas_mount

What this does:

  1. Unmounts all shares
  2. Removes mount point directories
  3. Deletes credential files
  4. Removes /etc/fstab entries

Clean system state - no traces of mounts remain.

This role is often used with:

  • nas_mount_systemd: Alternative using systemd mount units
  • docker_data_backup: Backup Docker data to NAS
  • ansible_code_backup: Backup Ansible code to NAS
  • centreon_clapi_backup: Backup Centreon config to NAS

Alternative: Manual Mount

If you prefer manual mounting:

# Install cifs-utils
dnf install cifs-utils

# Create mount point
mkdir /mnt/nas

# Create credentials file
cat > /etc/nas_creds << EOF
username=nasuser
password=naspassword
domain=WORKGROUP
EOF
chmod 600 /etc/nas_creds

# Mount manually
mount -t cifs //nas-ip/ShareName /mnt/nas -o credentials=/etc/nas_creds,uid=1001,gid=1001

# Add to /etc/fstab for persistence
echo "//nas-ip/ShareName /mnt/nas cifs credentials=/etc/nas_creds,uid=1001,gid=1001 0 0" >> /etc/fstab

License

MIT

Author

Created for homelab infrastructure management.