Replace the FTPS-based deployment approach with rsync over SSH for more reliable and efficient mirroring of the Hugo site. This change addresses issues with the previous approach and provides true mirror behavior. Key changes: - Replace lftp with rsync for file synchronization - Add --delete flag for true mirror behavior (removes stale remote files) - Simplify authentication to use SSH keys only (no password needed) - Update all documentation and OpenSpec artifacts - Add .envrc to gitignore for direnv users Environment variables: - SSH_USER: SSH username (required) - SSH_HOST: server hostname (required) - SSH_PORT: SSH port (optional, defaults to 22) - REMOTE_ROOT: remote directory path (optional, defaults to /httpsdocs) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
161 lines
3.8 KiB
Bash
Executable File
161 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#
|
|
# Rsync Deployment Script for markusgraf.ch
|
|
#
|
|
# This script deploys the Hugo-built static site to the production server
|
|
# via rsync over SSH, mirroring the content (including deletions).
|
|
#
|
|
# Prerequisites:
|
|
# - Hugo site must be built (public/ directory exists)
|
|
# - SSH access to the server must be configured
|
|
# - SSH_USER, SSH_HOST environment variables must be set
|
|
#
|
|
# Usage:
|
|
# export SSH_USER='your-username'
|
|
# export SSH_HOST='your-server.com'
|
|
# export SSH_PORT='22' # optional, defaults to 22
|
|
# export REMOTE_ROOT='/httpsdocs' # optional, defaults to /httpsdocs
|
|
# ./scripts/deploy.sh
|
|
#
|
|
# Server Details:
|
|
# - Default Target Directory: /httpsdocs
|
|
# - Default Port: 22
|
|
# - Source Directory: public/
|
|
#
|
|
|
|
set -e # Exit on error
|
|
set -u # Exit on undefined variable
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
NC='\033[0m' # No Color
|
|
|
|
# Configuration
|
|
SSH_PORT="${SSH_PORT:-22}"
|
|
REMOTE_ROOT="${REMOTE_ROOT:-/httpsdocs}"
|
|
SOURCE_DIR="public"
|
|
|
|
#
|
|
# Print error message in red and exit
|
|
#
|
|
error() {
|
|
echo -e "${RED}ERROR: $1${NC}" >&2
|
|
exit 1
|
|
}
|
|
|
|
#
|
|
# Print warning message in yellow
|
|
#
|
|
warn() {
|
|
echo -e "${YELLOW}WARNING: $1${NC}" >&2
|
|
}
|
|
|
|
#
|
|
# Print success message in green
|
|
#
|
|
success() {
|
|
echo -e "${GREEN}$1${NC}"
|
|
}
|
|
|
|
#
|
|
# Print info message
|
|
#
|
|
info() {
|
|
echo "$1"
|
|
}
|
|
|
|
#
|
|
# Check all prerequisites before deployment
|
|
#
|
|
check_prerequisites() {
|
|
info "Checking prerequisites..."
|
|
|
|
# Check if public/ directory exists and is not empty
|
|
if [ ! -d "$SOURCE_DIR" ]; then
|
|
error "Directory '$SOURCE_DIR' does not exist. Please run 'hugo build' first."
|
|
fi
|
|
|
|
if [ ! "$(ls -A $SOURCE_DIR)" ]; then
|
|
error "Directory '$SOURCE_DIR' is empty. Please run 'hugo build' first."
|
|
fi
|
|
|
|
# Check if rsync is installed
|
|
if ! command -v rsync &> /dev/null; then
|
|
error "rsync is not installed. Please install rsync:
|
|
Ubuntu/Debian: sudo apt-get install rsync
|
|
macOS: rsync is pre-installed
|
|
Fedora: sudo dnf install rsync"
|
|
fi
|
|
|
|
# Check if SSH_USER is set
|
|
if [ -z "${SSH_USER:-}" ]; then
|
|
error "SSH_USER environment variable is not set.
|
|
Please set it before running this script:
|
|
export SSH_USER='your-username'"
|
|
fi
|
|
|
|
# Check if SSH_HOST is set
|
|
if [ -z "${SSH_HOST:-}" ]; then
|
|
error "SSH_HOST environment variable is not set.
|
|
Please set it before running this script:
|
|
export SSH_HOST='your-server.com'"
|
|
fi
|
|
|
|
success "All prerequisites met."
|
|
}
|
|
|
|
#
|
|
# Deploy site to server via rsync
|
|
#
|
|
deploy() {
|
|
info "Starting deployment to $SSH_HOST..."
|
|
info "Connecting as user: $SSH_USER"
|
|
info "Port: $SSH_PORT"
|
|
info "Syncing from: $SOURCE_DIR/"
|
|
info "Target directory: $REMOTE_ROOT/"
|
|
|
|
# Use rsync to mirror the content
|
|
# -a: archive mode (preserves permissions, timestamps, etc.)
|
|
# -v: verbose output
|
|
# -z: compress data during transfer
|
|
# --delete: delete files on remote that don't exist locally (mirror behavior)
|
|
# -e: specify SSH with custom port
|
|
rsync -avz --delete -e "ssh -p $SSH_PORT" "$SOURCE_DIR/" "$SSH_USER@$SSH_HOST:$REMOTE_ROOT/"
|
|
|
|
local exit_code=$?
|
|
|
|
if [ $exit_code -eq 0 ]; then
|
|
success "Deployment completed successfully!"
|
|
info "Files have been synced to $SSH_HOST:$REMOTE_ROOT"
|
|
return 0
|
|
else
|
|
error "Deployment failed with exit code $exit_code.
|
|
|
|
Troubleshooting:
|
|
- Verify SSH credentials and key-based authentication is set up
|
|
- Check network connectivity to $SSH_HOST
|
|
- Ensure the target directory '$REMOTE_ROOT' exists on the server
|
|
- Verify SSH_USER has write permissions to $REMOTE_ROOT
|
|
- Try connecting manually: ssh -p $SSH_PORT $SSH_USER@$SSH_HOST"
|
|
fi
|
|
}
|
|
|
|
#
|
|
# Main execution
|
|
#
|
|
main() {
|
|
info "=== Rsync Deployment Script ==="
|
|
info ""
|
|
|
|
check_prerequisites
|
|
info ""
|
|
|
|
deploy
|
|
}
|
|
|
|
# Run main function
|
|
main
|