Files
michaelschiemer/.gitea/workflows/SECRETS_SETUP_GUIDE.md
Michael Schiemer 4eb7134853 feat(deploy): add Gitea CI/CD workflows and production Docker Compose config
- Add staging deployment workflow (deploy-staging.yml)
- Add production deployment workflow (deploy-production.yml)
- Add workflow documentation (README.md)
- Add secrets setup guide (SECRETS_SETUP_GUIDE.md)
- Add production Docker Compose configuration (docker-compose.prod.yml)

Workflows implement automated deployment with SSH-based remote execution,
health checks, rollback on failure, and smoke testing.
2025-11-24 18:37:27 +01:00

13 KiB

Gitea Secrets Configuration Guide

Purpose: Step-by-step guide to configure all required secrets for staging and production deployments.

Prerequisites:

  • Admin access to Gitea repository
  • SSH access to staging and production servers
  • OpenSSH installed locally

Quick Start Checklist

  • Generate SSH key pair
  • Distribute public key to target servers
  • Configure staging secrets in Gitea
  • Configure production secrets in Gitea
  • Test SSH connection manually
  • Verify secrets are accessible to workflows

Step 1: Generate SSH Keys

# Navigate to project root
cd /home/michael/dev/michaelschiemer

# Create SSH keys directory
mkdir -p .gitea/ssh-keys
cd .gitea/ssh-keys

# Generate staging key
ssh-keygen -t rsa -b 4096 -f gitea-staging-deploy \
  -C "gitea-staging-deployment" -N ""

# Generate production key
ssh-keygen -t rsa -b 4096 -f gitea-production-deploy \
  -C "gitea-production-deployment" -N ""

# Verify keys created
ls -la
# Expected output:
# gitea-staging-deploy       (private key)
# gitea-staging-deploy.pub   (public key)
# gitea-production-deploy    (private key)
# gitea-production-deploy.pub (public key)

⚠️ Security Note:

  • Private keys should NEVER be committed to git
  • Add .gitea/ssh-keys/ to .gitignore if not already present
  • Store private keys securely (e.g., password manager, Vault)

Step 2: Distribute Public Keys to Servers

Staging Server Setup

# Copy public key to staging server
ssh-copy-id -i .gitea/ssh-keys/gitea-staging-deploy.pub deploy@YOUR_STAGING_HOST

# Or manually (if ssh-copy-id not available):
cat .gitea/ssh-keys/gitea-staging-deploy.pub | \
  ssh deploy@YOUR_STAGING_HOST "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Set proper permissions on server
ssh deploy@YOUR_STAGING_HOST "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

# Test connection
ssh -i .gitea/ssh-keys/gitea-staging-deploy deploy@YOUR_STAGING_HOST "echo 'Staging SSH connection successful'"

Production Server Setup

# Copy public key to production server
ssh-copy-id -i .gitea/ssh-keys/gitea-production-deploy.pub deploy@YOUR_PRODUCTION_HOST

# Or manually:
cat .gitea/ssh-keys/gitea-production-deploy.pub | \
  ssh deploy@YOUR_PRODUCTION_HOST "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# Set proper permissions
ssh deploy@YOUR_PRODUCTION_HOST "chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

# Test connection
ssh -i .gitea/ssh-keys/gitea-production-deploy deploy@YOUR_PRODUCTION_HOST "echo 'Production SSH connection successful'"

Deployment User Requirements:

  • User must exist on target server (e.g., deploy, www-data, ubuntu)
  • User must have sudo privileges for Docker commands
  • User must have write access to deployment directories:
    • Staging: /opt/framework-staging/
    • Production: /opt/framework-production/

Step 3: Prepare Secret Values

Extract Private Key Content

cd /home/michael/dev/michaelschiemer/.gitea/ssh-keys

# Display staging private key (copy entire output)
echo "=== STAGING_SSH_KEY ==="
cat gitea-staging-deploy
echo ""

# Display production private key (copy entire output)
echo "=== PRODUCTION_SSH_KEY ==="
cat gitea-production-deploy
echo ""

Important: Copy the entire key content including:

-----BEGIN RSA PRIVATE KEY-----
[key content here]
-----END RSA PRIVATE KEY-----

Determine Server Details

Staging Server:

# Get staging hostname/IP (replace with your actual server)
STAGING_HOST="staging.michaelschiemer.de"  # or IP: 203.0.113.42

# Get SSH port (default: 22)
STAGING_SSH_PORT="22"

# Get deployment user
STAGING_USER="deploy"

Production Server:

# Get production hostname/IP
PRODUCTION_HOST="michaelschiemer.de"  # or IP: 198.51.100.10

# Get SSH port (default: 22)
PRODUCTION_SSH_PORT="22"

# Get deployment user
PRODUCTION_USER="deploy"

Step 4: Configure Secrets in Gitea

Access Gitea Secrets Configuration

  1. Navigate to Repository:

    • Open Gitea web interface
    • Go to your framework repository
  2. Access Secrets Settings:

    • Click Settings (⚙️ icon)
    • Click Secrets in left sidebar
    • Or direct URL: https://git.michaelschiemer.de/michael/framework/settings/secrets
  3. Add New Secret:

    • Click Add Secret button
    • Fill in Name and Value fields
    • Click Add Secret to save

Staging Secrets Configuration

Secret 1: STAGING_HOST

  • Name: STAGING_HOST
  • Value: staging.michaelschiemer.de (or your staging server hostname/IP)
  • Description: Staging server hostname or IP address

Secret 2: STAGING_USER

  • Name: STAGING_USER
  • Value: deploy (or your deployment user)
  • Description: SSH username for staging deployments

Secret 3: STAGING_SSH_KEY

  • Name: STAGING_SSH_KEY
  • Value: [Paste entire content of gitea-staging-deploy private key]
  • Description: Private SSH key for staging authentication
  • ⚠️ Important: Include -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- lines

Secret 4: STAGING_SSH_PORT

  • Name: STAGING_SSH_PORT
  • Value: 22 (or your custom SSH port)
  • Description: SSH port for staging server (optional, defaults to 22)

Production Secrets Configuration

Secret 5: PRODUCTION_HOST

  • Name: PRODUCTION_HOST
  • Value: michaelschiemer.de (or your production server hostname/IP)
  • Description: Production server hostname or IP address

Secret 6: PRODUCTION_USER

  • Name: PRODUCTION_USER
  • Value: deploy (or your deployment user)
  • Description: SSH username for production deployments

Secret 7: PRODUCTION_SSH_KEY

  • Name: PRODUCTION_SSH_KEY
  • Value: [Paste entire content of gitea-production-deploy private key]
  • Description: Private SSH key for production authentication
  • ⚠️ Important: Include -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY----- lines

Secret 8: PRODUCTION_SSH_PORT

  • Name: PRODUCTION_SSH_PORT
  • Value: 22 (or your custom SSH port)
  • Description: SSH port for production server (optional, defaults to 22)

Step 5: Verify Secrets Configuration

Via Gitea UI

  1. Navigate to SettingsSecrets

  2. Verify all 8 secrets are listed:

    • STAGING_HOST
    • STAGING_USER
    • STAGING_SSH_KEY
    • STAGING_SSH_PORT
    • PRODUCTION_HOST
    • PRODUCTION_USER
    • PRODUCTION_SSH_KEY
    • PRODUCTION_SSH_PORT
  3. Check that secrets show "Last Updated" timestamp

Note: Secret values are masked in the UI for security (you cannot view them after saving).


Manual SSH Connection Test

Test SSH connections using the same credentials that workflows will use:

cd /home/michael/dev/michaelschiemer/.gitea/ssh-keys

# Test staging connection
ssh -i gitea-staging-deploy deploy@YOUR_STAGING_HOST \
  "echo 'Staging SSH test successful'; docker --version"

# Test production connection
ssh -i gitea-production-deploy deploy@YOUR_PRODUCTION_HOST \
  "echo 'Production SSH test successful'; docker --version"

Expected Output:

Staging SSH test successful
Docker version 24.0.7, build afdd53b

If Connection Fails:

  • Verify hostname/IP is correct
  • Check SSH port (try specifying: ssh -p 2222 ...)
  • Verify public key is in ~/.ssh/authorized_keys on server
  • Check server firewall allows SSH connections
  • Verify user has Docker permissions: ssh user@host "docker ps"

Step 6: Test Workflow Access to Secrets

Trigger Test Workflow

Create a minimal test workflow to verify secrets are accessible:

File: .gitea/workflows/test-secrets.yml

name: Test Secrets Configuration

on:
  workflow_dispatch:

jobs:
  test-secrets:
    runs-on: ubuntu-latest
    steps:
      - name: Test staging secrets
        run: |
          echo "Testing staging secrets..."
          echo "STAGING_HOST: ${{ secrets.STAGING_HOST }}"
          echo "STAGING_USER: ${{ secrets.STAGING_USER }}"
          echo "STAGING_SSH_PORT: ${{ secrets.STAGING_SSH_PORT }}"
          echo "STAGING_SSH_KEY length: ${#STAGING_SSH_KEY}"
        env:
          STAGING_SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}

      - name: Test production secrets
        run: |
          echo "Testing production secrets..."
          echo "PRODUCTION_HOST: ${{ secrets.PRODUCTION_HOST }}"
          echo "PRODUCTION_USER: ${{ secrets.PRODUCTION_USER }}"
          echo "PRODUCTION_SSH_PORT: ${{ secrets.PRODUCTION_SSH_PORT }}"
          echo "PRODUCTION_SSH_KEY length: ${#PRODUCTION_SSH_KEY}"
        env:
          PRODUCTION_SSH_KEY: ${{ secrets.PRODUCTION_SSH_KEY }}

      - name: Test SSH connection to staging
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.STAGING_HOST }}
          username: ${{ secrets.STAGING_USER }}
          key: ${{ secrets.STAGING_SSH_KEY }}
          port: ${{ secrets.STAGING_SSH_PORT || 22 }}
          script: |
            echo "Staging SSH connection successful"
            docker --version
            docker-compose --version

      - name: Test SSH connection to production
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.PRODUCTION_HOST }}
          username: ${{ secrets.PRODUCTION_USER }}
          key: ${{ secrets.PRODUCTION_SSH_KEY }}
          port: ${{ secrets.PRODUCTION_SSH_PORT || 22 }}
          script: |
            echo "Production SSH connection successful"
            docker --version
            docker-compose --version

Run Test:

  1. Commit and push test workflow: git add .gitea/workflows/test-secrets.yml && git commit -m "Add secrets test workflow" && git push
  2. Go to Gitea Actions tab
  3. Select "Test Secrets Configuration" workflow
  4. Click "Run workflow"
  5. Monitor execution logs

Expected Result:

  • All secrets should be accessible
  • SSH connections should succeed
  • Docker/docker-compose versions should be displayed

Security Best Practices

SSH Key Management

Do:

  • Use 4096-bit RSA keys (or Ed25519)
  • Generate separate keys for staging and production
  • Rotate keys quarterly
  • Store private keys in secure password manager
  • Use dedicated deployment user (not root)
  • Restrict deployment user permissions

Don't:

  • Commit private keys to git
  • Share keys between environments
  • Use personal SSH keys for deployments
  • Store keys in plain text files
  • Reuse keys across projects

Secret Rotation Schedule

Quarterly (Every 3 Months):

  1. Generate new SSH key pairs
  2. Add new public keys to servers (keep old keys active)
  3. Update Gitea secrets with new private keys
  4. Test deployments with new keys
  5. Remove old public keys from servers
  6. Delete old private keys securely

Template for Rotation:

# Generate new keys with date suffix
ssh-keygen -t rsa -b 4096 -f gitea-staging-deploy-2025-04 \
  -C "gitea-staging-deployment-2025-04" -N ""

# Repeat process from Step 2 onwards

Access Control

Gitea Repository Permissions:

  • Limit "Secrets" access to repository admins only
  • Require 2FA for admin accounts
  • Audit secret access logs regularly

Server Access Control:

  • Deployment user should have minimal required permissions
  • Use sudo configuration for Docker commands only
  • Monitor SSH access logs
  • Implement IP whitelisting if possible

Troubleshooting

Issue: Secret Not Found in Workflow

Symptoms:

  • Workflow fails with "secret not found" error
  • Secret value is empty in workflow logs

Solutions:

  1. Verify secret name matches exactly (case-sensitive)
  2. Check secret is created at repository level (not organization or user level)
  3. Ensure workflow has access to repository secrets
  4. Try re-creating the secret

Issue: SSH Authentication Failed

Symptoms:

  • Workflow fails: "Permission denied (publickey)"
  • Cannot connect to server via SSH

Solutions:

  1. Verify entire private key content is in secret (including BEGIN/END lines)
  2. Check public key is in ~/.ssh/authorized_keys on server
  3. Verify SSH key format (PEM vs OpenSSH format)
  4. Check server SSH configuration allows public key authentication
  5. Test manual connection: ssh -i key-file user@host

Issue: Docker Permission Denied

Symptoms:

  • SSH connection succeeds but Docker commands fail
  • Error: "permission denied while trying to connect to Docker daemon"

Solutions:

# Add deployment user to docker group (on server)
ssh deploy@server
sudo usermod -aG docker deploy

# Log out and back in for group changes to take effect
exit
ssh deploy@server

# Verify Docker access
docker ps

Next Steps

After secrets are configured and tested:

  1. Secrets configured in Gitea
  2. Test staging deployment workflow
  3. Test production deployment workflow
  4. Update main deployment documentation
  5. Set up monitoring and alerting

Continue to: Testing Deployment Workflows section in main README.md


Last Updated: 2025-01-28 Guide Version: 1.0 Security Review Date: 2025-01-28