I want every push to main to deploy my app to my server. I do not want to store my personal private key in the repo. What is a safe workflow?
#github-actions#deployment#ssh
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
I want every push to main to deploy my app to my server. I do not want to store my personal private key in the repo. What is a safe workflow?
#github-actions#deployment#ssh
Create a dedicated deploy key pair, store the private half in GitHub Secrets, and give the matching user minimal rights on the server.
1. Generate a key just for CI
ssh-keygen -t ed25519 -f deploy_key -N "" -C "github-actions"
Append deploy_key.pub to ~/.ssh/authorized_keys of a deploy user on the server. Optionally restrict it in authorized_keys with command="/home/deploy/deploy.sh",no-port-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAA....
2. Add repository secrets: SSH_PRIVATE_KEY (file contents), SSH_HOST, SSH_USER, and SSH_KNOWN_HOSTS (output of ssh-keyscan -t ed25519 your.host). Pinning known hosts prevents man in the middle attacks; avoid StrictHostKeyChecking no.
3. Workflow .github/workflows/deploy.yml:
name: Deploy
on:
push:
branches: [main]
concurrency: deploy-production
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up SSH
run: |
install -m 700 -d ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
echo "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts
- name: Deploy
run: ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} 'bash /home/deploy/deploy.sh'
Keep the heavy lifting in a script on the server (pull, install, build, migrate, reload), so the workflow stays small. Build and test in a prior job and only deploy when it passes (needs:).
Tips
concurrency stops two deployments overlapping.