Files
gurixandClaude fcb82acc6f refactor: switch from FTPS/lftp to rsync for deployment
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>
2025-10-28 16:02:35 +01:00

5.7 KiB

Deployment Guide

This guide explains how to deploy the Hugo-built static site to the production server via rsync over SSH, properly mirroring the content.

Prerequisites

Before deploying, ensure you have:

  1. Built the site: Run hugo build to generate the public/ directory
  2. SSH access configured: You need SSH access to your server with key-based authentication
  3. Rsync available: The deployment script requires the rsync command-line tool

Installing Rsync

Rsync is typically pre-installed on most systems, but if needed:

# Ubuntu/Debian
sudo apt-get install rsync

# macOS (usually pre-installed)
# No action needed, or: brew install rsync

# Fedora
sudo dnf install rsync

Deployment Process

1. Build the Site

First, build the Hugo site:

hugo build

This generates the static files in the public/ directory.

2. Set Environment Variables

Set the SSH connection details as environment variables:

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

Important: Ensure SSH key-based authentication is set up for password-less access.

3. Run the Deployment Script

Execute the deployment script:

./scripts/deploy.sh

The script will:

  • Check that all prerequisites are met
  • Connect to your server via rsync over SSH
  • Sync all files from public/ to the specified remote directory
  • Delete remote files that don't exist locally (true mirror behavior)
  • Display progress and completion status

Complete Example

Here's the full workflow:

# Build the site
hugo build

# Set connection details (only needed once per session)
export SSH_USER='your-username'
export SSH_HOST='your-server.com'
export SSH_PORT='22'  # Optional
export REMOTE_ROOT='/httpsdocs'  # Optional

# Deploy
./scripts/deploy.sh

Server Configuration

The deployment script uses the following configuration:

  • Protocol: rsync over SSH
  • Default Port: 22 (configurable via SSH_PORT)
  • Default Target Directory: /httpsdocs (configurable via REMOTE_ROOT)
  • Source Directory: public/
  • Sync Behavior: Mirror mode with --delete flag (removes remote files not present locally)

Security Notes

SSH Key-Based Authentication

The deployment script uses SSH/SCP, which supports key-based authentication:

  • Set up SSH keys: Generate an SSH key pair and add your public key to the server's ~/.ssh/authorized_keys
  • Test SSH access: Verify you can connect without a password: ssh -p 22 user@server
  • No password required: SCP will use your SSH keys automatically
  • Never commit private keys to version control

Optional: Using .env Files

For convenience, you can create a .env file (which is ignored by git):

# .env
export SSH_USER='your-username'
export SSH_HOST='your-server.com'
export SSH_PORT='22'
export REMOTE_ROOT='/httpsdocs'

Then source it before deployment:

source .env
./scripts/deploy.sh

Troubleshooting

Error: "Directory 'public' does not exist"

Cause: The Hugo site hasn't been built yet.

Solution: Run hugo build before deploying.

Error: "rsync is not installed"

Cause: The rsync tool is not available on your system.

Solution: Install rsync using the instructions above.

Error: "SSH_USER environment variable is not set"

Cause: Required environment variables haven't been set.

Solution: Set the required variables:

export SSH_USER='your-username'
export SSH_HOST='your-server.com'

SSH Connection Failures

Cause: SSH authentication issues or network problems.

Solutions:

  • Verify you can connect manually: ssh -p 22 user@server
  • Check that your SSH key is added to the server's ~/.ssh/authorized_keys
  • Ensure your internet connection is working
  • Verify the server is accessible
  • Check firewall settings aren't blocking SSH (default port 22)

Permission Denied on Remote Directory

Cause: User doesn't have write permissions to the target directory.

Solution:

  • Verify the REMOTE_ROOT directory exists on the server
  • Ensure your SSH user has write permissions to that directory
  • Contact your server administrator if needed

Advanced Usage

Testing SSH Connection

To test your SSH connection before deploying:

# Test basic SSH connection
ssh -p "${SSH_PORT:-22}" "$SSH_USER@$SSH_HOST"

# Test that you can write to the target directory
ssh -p "${SSH_PORT:-22}" "$SSH_USER@$SSH_HOST" "touch ${REMOTE_ROOT:-/httpsdocs}/test.txt && rm ${REMOTE_ROOT:-/httpsdocs}/test.txt"

Deployment from CI/CD

For automated deployments from CI/CD pipelines:

  1. Set up SSH key-based authentication for your CI/CD runner
  2. Store SSH_USER and SSH_HOST as environment variables or secrets
  3. Ensure the CI/CD environment has rsync installed
  4. Run the deployment script after successful builds

Example GitHub Actions workflow snippet:

- name: Setup SSH key
  run: |
    mkdir -p ~/.ssh
    echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
    chmod 600 ~/.ssh/id_rsa
    ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts

- name: Deploy to server
  env:
    SSH_USER: ${{ secrets.SSH_USER }}
    SSH_HOST: ${{ secrets.SSH_HOST }}
    SSH_PORT: ${{ secrets.SSH_PORT }}
    REMOTE_ROOT: ${{ secrets.REMOTE_ROOT }}
  run: ./scripts/deploy.sh

Support

If you encounter issues not covered in this guide:

  1. Test SSH connectivity manually: ssh user@server
  2. Check server logs for authentication or permission issues
  3. Verify the target directory exists and has correct permissions
  4. Contact your hosting provider for server-side issues