When automating rsync transfers via cron jobs, we often encounter authentication hurdles. The key issue lies in properly passing credentials to the rsync daemon without interactive prompts. Let's examine why your current approach might fail.
#!/bin/bash
USER=name
RSYNC_PASSWORD=pass
DEST="myhost::mymodule"
/usr/bin/rsync -rltvvv . $DEST
The main problem in your script is that environment variables need to be exported to be visible to child processes (like rsync). A simple assignment like USER=name
only sets the variable for the current shell session.
Here's the corrected version:
#!/bin/bash
export RSYNC_PASSWORD="your_password"
export USER="your_username" # or LOGNAME
DEST="myhost::mymodule"
/usr/bin/rsync -rltvvv --no-blocking-io . "$DEST"
While exporting passwords works, it's not the most secure method. Here are three better approaches:
1. Using SSH Keys Instead
For SSH-based transfers (not daemon mode):
#!/bin/bash
/usr/bin/rsync -rltvv -e "ssh -i /path/to/private_key" . user@host:/path/
2. Rsync Secret File Method
Create a secrets file (e.g., /etc/rsync.secrets):
username:password
Then use it in your script:
#!/bin/bash
/usr/bin/rsync -rltvv --password-file=/etc/rsync.secrets . user@host::module
3. Temporary Environment with env
For one-time commands without permanent export:
#!/bin/bash
env RSYNC_PASSWORD="pass" /usr/bin/rsync -rltvv . user@host::module
When encountering "@ERROR: auth failed on module", check:
- File permissions on /etc/rsyncd.secrets (should be 600)
- Correct username/password in rsyncd.conf
- Hosts allow/deny rules in rsyncd.conf
- Time synchronization between servers
Here's a robust implementation with error handling:
#!/bin/bash
# Configuration
SYNC_USER="syncuser"
SYNC_PASS="correct-horse-battery-staple"
REMOTE_HOST="backup.example.com"
MODULE="data_backup"
LOG_FILE="/var/log/rsync_backup.log"
# Temporary credential handling
export RSYNC_PASSWORD="$SYNC_PASS"
trap 'unset RSYNC_PASSWORD' EXIT
# Execute sync with error checking
if ! /usr/bin/rsync -az --no-blocking-io --delete \
--log-file="$LOG_FILE" \
--timeout=300 \
--contimeout=30 \
. "${SYNC_USER}@${REMOTE_HOST}::${MODULE}"; then
echo "[$(date)] Rsync failed" >> "$LOG_FILE"
exit 1
fi
When working with rsync daemon authentication, there are several key points to understand about the authentication mechanism:
- Rsync daemon uses a separate authentication system from SSH
- Module access is controlled through the
secrets file
defined in rsyncd.conf - Environment variables must be set before the rsync command executes
The issue in your script stems from how environment variables are being set. Here's the proper implementation:
#!/bin/bash
export RSYNC_PASSWORD="your_secure_password"
DEST="myuser@myhost::mymodule"
/usr/bin/rsync -avz --progress . "$DEST"
Key improvements:
- Using
export
makes the variable available to child processes - The username is included in the destination string
- Simplified flags while maintaining verbosity with
--progress
While the above works, storing passwords in scripts is risky. Here are better approaches:
Option 1: Using SSH Keys Instead
#!/bin/bash
DEST="myuser@myhost:/path/to/destination"
/usr/bin/rsync -avz -e "ssh -i /path/to/private_key" . "$DEST"
Option 2: Using a Password File with Restricted Permissions
#!/bin/bash
RSYNC_PASSWORD_FILE="/etc/rsync/password"
DEST="myuser@myhost::mymodule"
/usr/bin/rsync -avz --password-file="$RSYNC_PASSWORD_FILE" . "$DEST"
Then create the password file:
sudo mkdir -p /etc/rsync
echo "your_secure_password" | sudo tee /etc/rsync/password
sudo chmod 600 /etc/rsync/password
If you're still encountering problems, check these aspects:
- Verify rsyncd.conf has
secrets file = /path/to/secrets
properly configured - Ensure the secrets file has correct permissions (chmod 600)
- Check that the username in your script matches an entry in the secrets file
- Test connectivity first with
telnet myhost 873
Here's a robust implementation suitable for production environments:
#!/bin/bash
# Set variables
RSYNC_USER="myuser"
RSYNC_HOST="myhost"
RSYNC_MODULE="mymodule"
LOG_FILE="/var/log/rsync_$(date +%Y%m%d).log"
# Execute rsync with error handling
if /usr/bin/rsync -avz --delete --progress \
--password-file=/etc/rsync/password \
. "${RSYNC_USER}@${RSYNC_HOST}::${RSYNC_MODULE}" >> "$LOG_FILE" 2>&1
then
echo "Rsync completed successfully at $(date)" >> "$LOG_FILE"
else
echo "Rsync failed with exit code $? at $(date)" >> "$LOG_FILE"
exit 1
fi
This script includes logging, error handling, and follows security best practices while maintaining the original functionality.