2025-10-28 10:53:45 +01:00
|
|
|
# Deployment Guide
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
This guide explains how to deploy the Hugo-built static site to the production server via rsync over SSH, properly mirroring the content.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
## Prerequisites
|
|
|
|
|
|
|
|
|
|
Before deploying, ensure you have:
|
|
|
|
|
|
|
|
|
|
1. **Built the site**: Run `hugo build` to generate the `public/` directory
|
2025-10-28 16:02:35 +01:00
|
|
|
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
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### Installing Rsync
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
Rsync is typically pre-installed on most systems, but if needed:
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Ubuntu/Debian
|
2025-10-28 16:02:35 +01:00
|
|
|
sudo apt-get install rsync
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
# macOS (usually pre-installed)
|
|
|
|
|
# No action needed, or: brew install rsync
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
# Fedora
|
2025-10-28 16:02:35 +01:00
|
|
|
sudo dnf install rsync
|
2025-10-28 10:53:45 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Deployment Process
|
|
|
|
|
|
|
|
|
|
### 1. Build the Site
|
|
|
|
|
|
|
|
|
|
First, build the Hugo site:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
hugo build
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
This generates the static files in the `public/` directory.
|
|
|
|
|
|
2025-10-28 11:11:53 +01:00
|
|
|
### 2. Set Environment Variables
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
Set the SSH connection details as environment variables:
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
```bash
|
2025-10-28 16:02:35 +01:00
|
|
|
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
|
2025-10-28 10:53:45 +01:00
|
|
|
```
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Important**: Ensure SSH key-based authentication is set up for password-less access.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
### 3. Run the Deployment Script
|
|
|
|
|
|
|
|
|
|
Execute the deployment script:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
./scripts/deploy.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
The script will:
|
|
|
|
|
- Check that all prerequisites are met
|
2025-10-28 16:02:35 +01:00
|
|
|
- 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)
|
2025-10-28 10:53:45 +01:00
|
|
|
- Display progress and completion status
|
|
|
|
|
|
|
|
|
|
### Complete Example
|
|
|
|
|
|
|
|
|
|
Here's the full workflow:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# Build the site
|
|
|
|
|
hugo build
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
# 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
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
# Deploy
|
|
|
|
|
./scripts/deploy.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Server Configuration
|
|
|
|
|
|
|
|
|
|
The deployment script uses the following configuration:
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
- **Protocol**: rsync over SSH
|
|
|
|
|
- **Default Port**: 22 (configurable via SSH_PORT)
|
|
|
|
|
- **Default Target Directory**: /httpsdocs (configurable via REMOTE_ROOT)
|
2025-10-28 10:53:45 +01:00
|
|
|
- **Source Directory**: public/
|
2025-10-28 16:02:35 +01:00
|
|
|
- **Sync Behavior**: Mirror mode with `--delete` flag (removes remote files not present locally)
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
## Security Notes
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### SSH Key-Based Authentication
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
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
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
### Optional: Using .env Files
|
|
|
|
|
|
|
|
|
|
For convenience, you can create a `.env` file (which is ignored by git):
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# .env
|
2025-10-28 16:02:35 +01:00
|
|
|
export SSH_USER='your-username'
|
|
|
|
|
export SSH_HOST='your-server.com'
|
|
|
|
|
export SSH_PORT='22'
|
|
|
|
|
export REMOTE_ROOT='/httpsdocs'
|
2025-10-28 10:53:45 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### Error: "rsync is not installed"
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Cause**: The `rsync` tool is not available on your system.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Solution**: Install rsync using the instructions above.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### Error: "SSH_USER environment variable is not set"
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Cause**: Required environment variables haven't been set.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Solution**: Set the required variables:
|
|
|
|
|
```bash
|
|
|
|
|
export SSH_USER='your-username'
|
|
|
|
|
export SSH_HOST='your-server.com'
|
|
|
|
|
```
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### SSH Connection Failures
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Cause**: SSH authentication issues or network problems.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
**Solutions**:
|
2025-10-28 16:02:35 +01:00
|
|
|
- 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)
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### Permission Denied on Remote Directory
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**Cause**: User doesn't have write permissions to the target directory.
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
**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
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
## Advanced Usage
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
### Testing SSH Connection
|
2025-10-28 10:53:45 +01:00
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
To test your SSH connection before deploying:
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
```bash
|
2025-10-28 16:02:35 +01:00
|
|
|
# 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"
|
2025-10-28 10:53:45 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Deployment from CI/CD
|
|
|
|
|
|
|
|
|
|
For automated deployments from CI/CD pipelines:
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
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
|
2025-10-28 10:53:45 +01:00
|
|
|
|
|
|
|
|
Example GitHub Actions workflow snippet:
|
|
|
|
|
|
|
|
|
|
```yaml
|
2025-10-28 16:02:35 +01:00
|
|
|
- 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
|
|
|
|
|
|
2025-10-28 10:53:45 +01:00
|
|
|
- name: Deploy to server
|
|
|
|
|
env:
|
2025-10-28 16:02:35 +01:00
|
|
|
SSH_USER: ${{ secrets.SSH_USER }}
|
|
|
|
|
SSH_HOST: ${{ secrets.SSH_HOST }}
|
|
|
|
|
SSH_PORT: ${{ secrets.SSH_PORT }}
|
|
|
|
|
REMOTE_ROOT: ${{ secrets.REMOTE_ROOT }}
|
2025-10-28 10:53:45 +01:00
|
|
|
run: ./scripts/deploy.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Support
|
|
|
|
|
|
|
|
|
|
If you encounter issues not covered in this guide:
|
|
|
|
|
|
2025-10-28 16:02:35 +01:00
|
|
|
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
|
2025-10-28 10:53:45 +01:00
|
|
|
4. Contact your hosting provider for server-side issues
|