--- tags: - GIT - CI/CD - CI-CD --- 🚀 Part 2: Automatically Deploy to a Live Server The safest, cleanest way to deploy to a remote homelab server from a runner is using **SSH and Docker Contexts**. This allows your Gitea Actions runner to securely command your live server's Docker daemon across your local network without needing Git installed on the destination server. 1. Generate a Deployment SSH Key [[1](https://ecostack.dev/posts/automated-docker-compose-deployment-github-actions/)] On your local machine or server, generate a dedicated SSH key pair for Gitea Actions. **Do not use a passphrase.** ssh-keygen -t ed25519 -f ~/.ssh/gitea_deploy_key -N "" - Append the contents of `gitea_deploy_key.pub` to the `~/.ssh/authorized_keys` file on your **live deployment server**. - Copy the contents of the private key `gitea_deploy_key`. Save it in your Gitea Repository Secrets as **`DEPLOY_SSH_KEY`**. - Save your live server's local IP address or local hostname in Gitea Secrets as **`DEPLOY_HOST`**. - Save your live server's SSH username in Gitea Secrets as **`DEPLOY_USER`**. 2. Create the Complete Production Workflow Create or update your `.gitea/workflows/deploy.yaml` file. This workflow will validate your code first, and then deploy it only if the branch is `main`. name: Validate and Deploy Homelab on: push: branches: [ "main" ] jobs: test-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout Repository Code uses: actions/checkout@v4 - name: Verify Compose File Validity env: DB_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }} DB_PASSWORD: ${{ secrets.MYSQL_PASSWORD }} run: docker compose config # --- DEPLOYMENT PHASE --- - name: Set up SSH Private Key run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 # Scan the host key to prevent SSH hanging on a manual confirmation prompt ssh-keyscan -H ${{ secrets.DEPLOY_HOST }} >> ~/.ssh/known_hosts - name: Create Remote Docker Context run: | # Define a remote endpoint pointing to your live server over SSH docker context create homelab-target \ --docker "host=ssh://${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }}" - name: Deploy Containers to Live Server env: # Pass your production secrets to the live deployment step DB_ROOT_PASSWORD: ${{ secrets.MYSQL_ROOT_PASSWORD }} DB_PASSWORD: ${{ secrets.MYSQL_PASSWORD }} run: | echo "Switching Docker context to live server..." docker context use homelab-target echo "Pulling latest images and starting services remotely..." # The --project-directory . flag ensures it reads the docker-compose file fetched by Git docker compose --project-directory . up -d --remove-orphans 💡 Why This Setup Wins for Homelabs - **Zero Overhead:** You do not need to install complex deployment tools or agents on your production server. It only requires standard SSH and Docker. - **Security:** If you ever need to revoke the runner's deployment access, you simply delete the single public key from your live server's `authorized_keys` file. - **Atomic Changes:** The `--remove-orphans` flag cleans up old containers that you removed from your Compose file since the last Git commit, keeping your server immaculate.