This guide shows how to deploy this project using GitHub Actions, SSH, and Docker Compose.
We separate authentication into two layers:
- GitHub Actions β Server π (SSH key or password)
- Server β GitHub π₯οΈ (Deploy key)
GitHub Actions
|
| (SSH_PRIVATE_KEY)
v
Remote Server
|
| (Server Deploy Key)
v
GitHub Repository
Before running the workflow, you need to set the following secrets in your repository:
| Secret Name | Description | Example / Notes |
|---|---|---|
SSH_PRIVATE_KEY |
Private SSH key used by GitHub Actions to connect to the server | The private key corresponding to the server's authorized key |
SERVER_USER |
Username on the deployment server | ubuntu, deploy, etc. |
SERVER_HOST |
Hostname or IP of the deployment server | 123.45.67.89 or server.example.com |
SERVER_PASSWORD |
(Optional) Server password if you are using password-based SSH | Only needed if using SSH password fallback |
How to add secrets:
GitHub β Repository β Settings β Secrets and Variables β Actions β New repository secret
These secrets are never exposed in logs and are injected securely into the workflow as environment variables.
On the deployment server, create a dedicated SSH key:
ssh-keygen -t ed25519 -C "deploy-key"- Press Enter for the default path
- Leave passphrase empty
View the public key:
cat ~/.ssh/id_ed25519.pubAdd this public key to your repository as a Deploy Key:
Repository β Settings β Deploy keys β Add deploy key
Test access from the server:
ssh -T git@github.com
git pullIf you cannot use keys, you can connect with a password.
β οΈ Warning: storing passwords is insecure; use SSH keys whenever possible.
Install sshpass on the server:
sudo apt install -y sshpassExample usage in GitHub Actions:
sshpass -p "${{ secrets.SERVER_PASSWORD }}" ssh ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} "
cd /PATH/TO/PROJECT &&
git pull origin main &&
sudo docker compose up -d --build &&
sudo docker compose logs --tail=50
"On the server, generate a key specifically for GitHub access:
ssh-keygen -t ed25519 -C "server-deploy-key"Add the public key to the repositoryβs Deploy Keys section.
Verify:
ssh -T git@github.com
git pullname: Deploy
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Deploy via SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
ssh-keyscan -H ${{ secrets.SERVER_HOST }} >> ~/.ssh/known_hosts
ssh ${{ secrets.SERVER_USER }}@${{ secrets.SERVER_HOST }} "
cd /PATH/TO/PROJECT &&
git pull origin main &&
sudo docker compose up -d --build &&
sleep 5 &&
sudo docker compose logs --tail=50
"For password SSH, replace the
sshcommand withsshpass -p "${{ secrets.SERVER_PASSWORD }}" ssh ...
Allow the deployment user to run Docker without a password:
sudo visudoAdd:
SERVER_USER ALL=(ALL) NOPASSWD: /usr/bin/docker, /usr/bin/docker compose
After deployment:
docker compose ps
docker compose logs -f- Always prefer SSH keys over passwords
- Use a dedicated deploy key per server
- Rotate keys periodically
- Avoid storing passwords in plaintext
- Limit write access unless necessary
| Direction | Authentication |
|---|---|
| GitHub Actions β Server | π SSH key (passwordless) or π password fallback |
| Server β GitHub | π₯οΈ Repository Deploy Key |
| Server β Docker | π³ Passwordless sudo |
This setup provides a secure, repeatable, and easy-to-use deployment workflow.