Configure network-attached storage backup with NFS and encryption

Intermediate 45 min May 10, 2026 604 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up an encrypted NFS backup server with automated backup scripts and performance monitoring. Configure LUKS encryption, NFS exports, and centralized backup management for secure enterprise storage.

Prerequisites

  • Root access to server
  • Secondary storage device or partition
  • Network connectivity between server and clients
  • At least 4GB free space for backup operations

What this solves

Network-attached storage (NAS) backup systems provide centralized, scalable backup solutions for multiple servers and workstations. This tutorial configures an NFS server with LUKS encryption to secure backup data at rest, automated backup scripts for scheduled operations, and monitoring tools to track backup performance and security events.

Step-by-step configuration

Update system and install required packages

Start by updating your system and installing NFS server components, encryption tools, and monitoring utilities.

sudo apt update && sudo apt upgrade -y
sudo apt install -y nfs-kernel-server nfs-common cryptsetup rsync cron-apt smartmontools
sudo dnf update -y
sudo dnf install -y nfs-utils cryptsetup rsync smartmontools

Create and encrypt backup storage partition

Set up LUKS encryption on your backup storage device. Replace /dev/sdb1 with your actual backup partition.

Warning: This will destroy all data on the specified partition. Ensure you have backups of any important data.
sudo cryptsetup luksFormat /dev/sdb1
sudo cryptsetup luksOpen /dev/sdb1 backup_encrypted
sudo mkfs.ext4 /dev/mapper/backup_encrypted

Configure automatic decryption on boot

Create a keyfile and configure automatic mounting to avoid manual password entry on system restart.

sudo mkdir -p /etc/luks-keys
sudo dd if=/dev/urandom of=/etc/luks-keys/backup.key bs=1024 count=4
sudo chmod 400 /etc/luks-keys/backup.key
sudo cryptsetup luksAddKey /dev/sdb1 /etc/luks-keys/backup.key

Configure crypttab for automatic decryption:

backup_encrypted /dev/sdb1 /etc/luks-keys/backup.key luks

Create mount point and configure fstab

Set up the mount point and configure automatic mounting on boot.

sudo mkdir -p /srv/nfs/backup
sudo mount /dev/mapper/backup_encrypted /srv/nfs/backup

Add the mount to fstab for persistence:

/dev/mapper/backup_encrypted /srv/nfs/backup ext4 defaults,noatime 0 2

Configure NFS server exports

Set up NFS exports with proper security options and access controls.

sudo mkdir -p /srv/nfs/backup/clients
sudo chown -R nobody:nogroup /srv/nfs/backup
sudo chmod -R 755 /srv/nfs/backup

Configure NFS exports with security restrictions:

/srv/nfs/backup 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash,secure)
/srv/nfs/backup/clients 192.168.1.0/24(rw,sync,no_subtree_check,root_squash,secure)
Note: Replace 192.168.1.0/24 with your actual network range. The secure option requires connections from ports below 1024.

Start and enable NFS services

Enable and start the NFS server services for persistent operation.

sudo systemctl enable --now nfs-kernel-server
sudo systemctl enable --now nfs-common
sudo exportfs -arv
sudo systemctl enable --now nfs-server
sudo systemctl enable --now rpcbind
sudo exportfs -arv

Configure firewall rules

Open required ports for NFS communication while maintaining security.

sudo ufw allow from 192.168.1.0/24 to any port nfs
sudo ufw allow from 192.168.1.0/24 to any port 2049
sudo ufw allow from 192.168.1.0/24 to any port 111
sudo firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=192.168.1.0/24 service name=nfs accept"
sudo firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=192.168.1.0/24 port port=2049 protocol=tcp accept"
sudo firewall-cmd --permanent --add-rich-rule="rule family=ipv4 source address=192.168.1.0/24 port port=111 protocol=tcp accept"
sudo firewall-cmd --reload

Create automated backup script

Develop a comprehensive backup script with encryption, compression, and logging capabilities.

#!/bin/bash

# NFS Backup Script with Encryption
# Configuration
BACKUP_SOURCE="/home /etc /var/www"
BACKUP_DEST="/srv/nfs/backup/daily"
LOG_FILE="/var/log/nfs-backup.log"
RETENTION_DAYS=30
ENCRYPTION_KEY="/etc/backup-encryption.key"
DATE=$(date +%Y-%m-%d_%H-%M-%S)

# Create encryption key if it doesn't exist
if [ ! -f "$ENCRYPTION_KEY" ]; then
    openssl rand -base64 32 > "$ENCRYPTION_KEY"
    chmod 600 "$ENCRYPTION_KEY"
fi

# Logging function
log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# Start backup
log_message "Starting backup process"
mkdir -p "$BACKUP_DEST"

# Perform rsync backup with compression
for source in $BACKUP_SOURCE; do
    if [ -d "$source" ]; then
        log_message "Backing up $source"
        rsync -avz --delete "$source" "$BACKUP_DEST/" 2>&1 | tee -a "$LOG_FILE"
    fi
done

# Create encrypted archive
log_message "Creating encrypted archive"
tar -czf - "$BACKUP_DEST" | openssl enc -aes-256-cbc -salt -pass file:"$ENCRYPTION_KEY" > "$BACKUP_DEST/../backup_$DATE.tar.gz.enc"

# Cleanup old backups
log_message "Cleaning up old backups"
find "$BACKUP_DEST/../" -name "backup_*.tar.gz.enc" -mtime +$RETENTION_DAYS -delete

# Verify backup integrity
if [ -f "$BACKUP_DEST/../backup_$DATE.tar.gz.enc" ]; then
    log_message "Backup completed successfully: backup_$DATE.tar.gz.enc"
else
    log_message "ERROR: Backup failed - encrypted archive not created"
    exit 1
fi

log_message "Backup process completed"

Make the script executable:

sudo chmod 755 /usr/local/bin/nfs-backup.sh
sudo chown root:root /usr/local/bin/nfs-backup.sh

Configure scheduled backups with cron

Set up automated backup scheduling with proper logging and error handling.

sudo crontab -e

Add the following cron entries:

# Daily backup at 2 AM
0 2 * * * /usr/local/bin/nfs-backup.sh

# Weekly backup verification at 3 AM on Sundays
0 3 * * 0 /usr/local/bin/verify-backups.sh

# Monthly cleanup at 4 AM on the 1st
0 4 1 * * find /srv/nfs/backup -type f -mtime +90 -delete

Create backup verification script

Implement automated backup integrity checking and monitoring.

#!/bin/bash

# Backup Verification Script
BACKUP_DIR="/srv/nfs/backup"
LOG_FILE="/var/log/backup-verification.log"
ENCRYPTION_KEY="/etc/backup-encryption.key"
ALERT_EMAIL="admin@example.com"

log_message() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

# Check disk space
DISK_USAGE=$(df "$BACKUP_DIR" | awk 'NR==2 {print $5}' | sed 's/%//')
if [ "$DISK_USAGE" -gt 85 ]; then
    log_message "WARNING: Backup disk usage is ${DISK_USAGE}%"
    echo "Backup disk usage critical: ${DISK_USAGE}%" | mail -s "NFS Backup Alert" "$ALERT_EMAIL"
fi

# Verify latest encrypted backup
LATEST_BACKUP=$(find "$BACKUP_DIR" -name "backup_*.tar.gz.enc" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)

if [ -f "$LATEST_BACKUP" ]; then
    log_message "Verifying backup: $LATEST_BACKUP"
    if openssl enc -aes-256-cbc -d -salt -pass file:"$ENCRYPTION_KEY" -in "$LATEST_BACKUP" | tar -tzf - > /dev/null 2>&1; then
        log_message "Backup verification successful"
    else
        log_message "ERROR: Backup verification failed"
        echo "Backup verification failed for $LATEST_BACKUP" | mail -s "NFS Backup Error" "$ALERT_EMAIL"
    fi
else
    log_message "ERROR: No backup files found"
fi

# Check NFS service status
if ! systemctl is-active --quiet nfs-kernel-server 2>/dev/null && ! systemctl is-active --quiet nfs-server 2>/dev/null; then
    log_message "ERROR: NFS server is not running"
    echo "NFS server is down" | mail -s "NFS Server Alert" "$ALERT_EMAIL"
fi

Make the verification script executable:

sudo chmod 755 /usr/local/bin/verify-backups.sh

Configure NFS performance monitoring

Set up monitoring for NFS performance metrics and security events.

[Unit]
Description=NFS Performance Monitor
After=nfs-kernel-server.service

[Service]
Type=forking
ExecStart=/usr/local/bin/nfs-monitor.sh
Restart=always
RestartSec=60
User=root

[Install]
WantedBy=multi-user.target

Create the monitoring script:

#!/bin/bash

# NFS Performance Monitoring Script
LOG_FILE="/var/log/nfs-performance.log"
MONITOR_INTERVAL=300  # 5 minutes

log_metric() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "$LOG_FILE"
}

while true; do
    # Monitor NFS connections
    ACTIVE_CONNECTIONS=$(netstat -an | grep :2049 | grep ESTABLISHED | wc -l)
    log_metric "Active NFS connections: $ACTIVE_CONNECTIONS"
    
    # Monitor disk I/O
    DISK_IO=$(iostat -x 1 1 | awk '/sdb/ {print "Read: " $4 " Write: " $5}')
    log_metric "Backup disk I/O - $DISK_IO"
    
    # Monitor backup mount status
    if mountpoint -q /srv/nfs/backup; then
        log_metric "Backup mount: OK"
    else
        log_metric "ERROR: Backup mount failed"
    fi
    
    # Check encryption status
    if cryptsetup status backup_encrypted > /dev/null 2>&1; then
        log_metric "Encryption: Active"
    else
        log_metric "ERROR: Encryption not active"
    fi
    
    sleep $MONITOR_INTERVAL
done

Enable the monitoring service:

sudo chmod 755 /usr/local/bin/nfs-monitor.sh
sudo systemctl enable --now nfs-monitor.service

Configure client connections

Install NFS client packages

On client machines, install NFS client tools to connect to your backup server.

sudo apt install -y nfs-common
sudo dnf install -y nfs-utils

Mount NFS backup share

Configure client machines to mount the NFS backup share.

sudo mkdir -p /mnt/backup
sudo mount -t nfs 192.168.1.100:/srv/nfs/backup/clients /mnt/backup

For persistent mounting, add to fstab:

192.168.1.100:/srv/nfs/backup/clients /mnt/backup nfs defaults,_netdev 0 0

Verify your setup

Test your NFS backup configuration and verify all components are working correctly.

# Check NFS server status
sudo systemctl status nfs-kernel-server  # Ubuntu/Debian
sudo systemctl status nfs-server         # AlmaLinux/Rocky

# Verify NFS exports
sudo exportfs -v

# Test NFS connectivity from server
showmount -e localhost

# Check encryption status
sudo cryptsetup status backup_encrypted

# Verify backup mount
df -h /srv/nfs/backup

# Test backup script
sudo /usr/local/bin/nfs-backup.sh

# Check backup logs
sudo tail -f /var/log/nfs-backup.log

# Verify client connection (from client machine)
mount | grep nfs
touch /mnt/backup/test-file.txt

Performance optimization

Optimize NFS server settings

Configure NFS server parameters for better performance with backup workloads.

RPCNFSDCOUNT=16
RPCNFSDPRIORITY=0
RPCMOUNTDOPTS="--manage-gids"
NEED_SVCGSSD=no
RPCSVCGSSDOPTS=""

For systems that need monitoring integration, you might want to configure advanced htop monitoring with custom scripts and alerting to track NFS performance metrics.

Configure network buffer optimization

Optimize network settings for large file transfers typical in backup operations.

net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 65536 67108864
net.core.netdev_max_backlog = 5000

Apply the settings:

sudo sysctl -p /etc/sysctl.d/99-nfs-performance.conf

Security hardening

Configure backup rotation and retention

Implement secure backup rotation with proper cleanup and archival policies.

#!/bin/bash

# Backup Rotation Script
BACKUP_DIR="/srv/nfs/backup"
ARCHIVE_DIR="/srv/nfs/backup/archive"
DAILY_RETENTION=7
WEEKLY_RETENTION=4
MONTHLY_RETENTION=12

# Create archive directory
mkdir -p "$ARCHIVE_DIR"/{daily,weekly,monthly}

# Rotate daily backups
find "$BACKUP_DIR" -name "backup_*.tar.gz.enc" -mtime +$DAILY_RETENTION -exec mv {} "$ARCHIVE_DIR/daily/" \;

# Create weekly archive (every Sunday)
if [ $(date +%u) -eq 7 ]; then
    LATEST_DAILY=$(find "$ARCHIVE_DIR/daily" -name "backup_*.tar.gz.enc" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)
    if [ -f "$LATEST_DAILY" ]; then
        cp "$LATEST_DAILY" "$ARCHIVE_DIR/weekly/weekly_$(date +%Y-%m-%d).tar.gz.enc"
    fi
fi

# Create monthly archive (1st of month)
if [ $(date +%d) -eq 01 ]; then
    LATEST_WEEKLY=$(find "$ARCHIVE_DIR/weekly" -name "weekly_*.tar.gz.enc" -type f -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)
    if [ -f "$LATEST_WEEKLY" ]; then
        cp "$LATEST_WEEKLY" "$ARCHIVE_DIR/monthly/monthly_$(date +%Y-%m).tar.gz.enc"
    fi
fi

# Cleanup old archives
find "$ARCHIVE_DIR/daily" -name "backup_*.tar.gz.enc" -mtime +30 -delete
find "$ARCHIVE_DIR/weekly" -name "weekly_*.tar.gz.enc" -mtime +120 -delete
find "$ARCHIVE_DIR/monthly" -name "monthly_*.tar.gz.enc" -mtime +365 -delete

Implement access logging

Enable comprehensive logging for security auditing and troubleshooting.

# NFS logging configuration
kern.* /var/log/nfs-kernel.log
daemon.* /var/log/nfs-daemon.log

# Separate NFS client access logs
:msg, contains, "nfs" /var/log/nfs-access.log
& stop

Restart rsyslog to apply changes:

sudo systemctl restart rsyslog

Common issues

Symptom Cause Fix
Mount fails with "Permission denied" Firewall blocking NFS ports Check firewall rules: sudo ufw status or firewall-cmd --list-all
"Stale file handle" errors NFS server restart or network issues Unmount and remount: sudo umount /mnt/backup && sudo mount /mnt/backup
Backup script fails with encryption error Missing or corrupted encryption key Recreate encryption key: sudo openssl rand -base64 32 > /etc/backup-encryption.key
Poor backup performance Network buffer sizes too small Apply network optimization settings and restart NFS services
LUKS device won't auto-mount Incorrect /etc/crypttab configuration Verify crypttab syntax and key file permissions: chmod 400 /etc/luks-keys/backup.key
NFS exports not visible Export table not refreshed Refresh exports: sudo exportfs -arv

Next steps

Running this in production?

Want this handled for you? Setting up encrypted NFS backup once is straightforward. Keeping it monitored, securing encryption keys, managing retention policies and ensuring backups are restorable across environments is the harder part. See how we run infrastructure like this for European SaaS and e-commerce teams.

Automated install script

Run this to automate the entire setup

Prefere não gerir isto sozinho?

Gerimos a infraestrutura de empresas que dependem do tempo de atividade. Totalmente gerida, com um contacto fixo que conhece o seu ambiente.

Tem um contacto fixo que conhece o seu ambiente

Roterdão 07:24 · acessível por mensagem, sem formulário de tickets