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>
220 lines
5.7 KiB
Markdown
220 lines
5.7 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```bash
|
|
hugo build
|
|
```
|
|
|
|
This generates the static files in the `public/` directory.
|
|
|
|
### 2. Set Environment Variables
|
|
|
|
Set the SSH connection details as environment variables:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
./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:
|
|
|
|
```bash
|
|
# 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):
|
|
|
|
```bash
|
|
# .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:
|
|
|
|
```bash
|
|
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:
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
# 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:
|
|
|
|
```yaml
|
|
- 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
|