Difference between revisions of "Github Action using ssh"
From Logic Wiki
| Line 47: | Line 47: | ||
KEYCLOAK_ADMIN_PASSWORD: ${{ steps.ssm.outputs.KEYCLOAK_ADMIN_PASSWORD }} | KEYCLOAK_ADMIN_PASSWORD: ${{ steps.ssm.outputs.KEYCLOAK_ADMIN_PASSWORD }} | ||
steps: | steps: | ||
| + | - name: Exit early if file not changed | ||
| + | run: | | ||
| + | FILE="docker-compose-data.yml" | ||
| + | |||
| + | # Compare against previous commit for push | ||
| + | if git diff --name-only HEAD~1 HEAD | grep -qv "^$FILE$"; then | ||
| + | # Check if our file is among the changes | ||
| + | if ! git diff --name-only HEAD~1 HEAD | grep -q "^$FILE$"; then | ||
| + | echo "$FILE not changed — exiting workflow successfully." | ||
| + | exit 0 | ||
| + | fi | ||
| + | fi | ||
- name: Configure AWS credentials | - name: Configure AWS credentials | ||
uses: aws-actions/configure-aws-credentials@v4 | uses: aws-actions/configure-aws-credentials@v4 | ||
| Line 144: | Line 156: | ||
=== Notes about the Yaml file === | === Notes about the Yaml file === | ||
Build job must output the variables to use them in deploy job. If steps are in the same job there is no need to do that. | Build job must output the variables to use them in deploy job. If steps are in the same job there is no need to do that. | ||
| + | |||
| + | In the first step it checks if docker-compose-data.yml is changed. If not it exits with success | ||
To hide echo in the logs I used | To hide echo in the logs I used | ||
Revision as of 13:29, 5 December 2025
Introducing github to server
First create a ssh key in the local machine (I named it as "github-deploy" when it asked)
ssh-keygen -t ed25519 -C "github-deploy"
-t ed25519 : encryption algorithm
-C "github-deploy" : puts a comment in public key file
Copy it to server
ssh-copy-id -i ~/.ssh/github-deploy.pub bookit
Create a secret in Github repo and store private key in it.
OR
Create the key on the server and copy private key to github secrets
Server Side
- Add public key to authorized_keys
- install docker
- install docker-compose
- create folder for deployment
Action
name: Deploy:Live:IONOS
on:
push:
branches:
- main
env:
ENVIRONMENT: prod
jobs:
build:
runs-on: ubuntu-latest
outputs:
RABBITMQ_DEFAULT_USER: ${{ steps.ssm.outputs.RABBITMQ_DEFAULT_USER }}
RABBITMQ_DEFAULT_PASS: ${{ steps.ssm.outputs.RABBITMQ_DEFAULT_PASS }}
MONGO_INITDB_ROOT_USERNAME: ${{ steps.ssm.outputs.MONGO_INITDB_ROOT_USERNAME }}
MONGO_INITDB_ROOT_PASSWORD: ${{ steps.ssm.outputs.MONGO_INITDB_ROOT_PASSWORD }}
POSTGRES_USER: ${{ steps.ssm.outputs.POSTGRES_USER }}
POSTGRES_PASSWORD: ${{ steps.ssm.outputs.POSTGRES_PASSWORD }}
KEYCLOAK_ADMIN: ${{ steps.ssm.outputs.KEYCLOAK_ADMIN }}
KEYCLOAK_ADMIN_PASSWORD: ${{ steps.ssm.outputs.KEYCLOAK_ADMIN_PASSWORD }}
steps:
- name: Exit early if file not changed
run: |
FILE="docker-compose-data.yml"
# Compare against previous commit for push
if git diff --name-only HEAD~1 HEAD | grep -qv "^$FILE$"; then
# Check if our file is among the changes
if ! git diff --name-only HEAD~1 HEAD | grep -q "^$FILE$"; then
echo "$FILE not changed — exiting workflow successfully."
exit 0
fi
fi
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Load multiple AWS parameters
id: ssm
run: |
PARAMS=$(aws ssm get-parameters \
--names "/${{env.ENVIRONMENT}}/bookitfor.me.uk/rabbitMQ/username" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/rabbitMQ/password" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/mongodb/username" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/mongodb/password" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/postgresql/username" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/postgresql/password" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/keycloak/username" \
"/${{env.ENVIRONMENT}}/bookitfor.me.uk/keycloak/password" \
--output json )
RABBITMQ_DEFAULT_USER=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/rabbitMQ/username") | .Value')
RABBITMQ_DEFAULT_PASS=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/rabbitMQ/password") | .Value')
MONGO_INITDB_ROOT_USERNAME=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/mongodb/username") | .Value')
MONGO_INITDB_ROOT_PASSWORD=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/mongodb/password") | .Value')
POSTGRES_USER=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/postgresql/username") | .Value')
POSTGRES_PASSWORD=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/postgresql/password") | .Value')
KEYCLOAK_ADMIN=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/keycloak/username") | .Value')
KEYCLOAK_ADMIN_PASSWORD=$(echo "$PARAMS" | jq -r '.Parameters[] | select(.Name=="/${{env.ENVIRONMENT}}/bookitfor.me.uk/keycloak/password") | .Value')
echo "::group::Hidden section"
echo "RABBITMQ_DEFAULT_USER=$RABBITMQ_DEFAULT_USER" >> $GITHUB_OUTPUT
echo "RABBITMQ_DEFAULT_PASS=$RABBITMQ_DEFAULT_PASS" >> $GITHUB_OUTPUT
echo "MONGO_INITDB_ROOT_USERNAME=$MONGO_INITDB_ROOT_USERNAME" >> $GITHUB_OUTPUT
echo "MONGO_INITDB_ROOT_PASSWORD=$MONGO_INITDB_ROOT_PASSWORD" >> $GITHUB_OUTPUT
echo "POSTGRES_USER=$POSTGRES_USER" >> $GITHUB_OUTPUT
echo "POSTGRES_PASSWORD=$POSTGRES_PASSWORD" >> $GITHUB_OUTPUT
echo "KEYCLOAK_ADMIN=$KEYCLOAK_ADMIN" >> $GITHUB_OUTPUT
echo "KEYCLOAK_ADMIN_PASSWORD=$KEYCLOAK_ADMIN_PASSWORD" >> $GITHUB_OUTPUT
echo "::endgroup::"
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up SSH
run: |
mkdir -p ~/.ssh
echo "${{ secrets.IONOS_SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
- name: Test SSH connection
run: |
ssh -o StrictHostKeyChecking=accept-new \
${{ secrets.IONOS_REMOTE_USER }}@${{ secrets.IONOS_REMOTE_HOST }} "echo Connected successfully"
- name: Copy files to remote server
run: |
scp -i ~/.ssh/id_rsa -r ./docker-compose-data.yml \
${{ secrets.IONOS_REMOTE_USER }}@${{ secrets.IONOS_REMOTE_HOST }}:/home/logicmade/bookitfor.me.uk/
scp -i ~/.ssh/id_rsa -r ./sql \
${{ secrets.IONOS_REMOTE_USER }}@${{ secrets.IONOS_REMOTE_HOST }}:/home/logicmade/bookitfor.me.uk/sql
- name: Persist env variables on remote host
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.IONOS_REMOTE_HOST }}
username: ${{ secrets.IONOS_REMOTE_USER }}
key: ${{ secrets.IONOS_SSH_PRIVATE_KEY }}
script: |
echo "::group::Hidden section"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export RABBITMQ_DEFAULT_USER='${{ needs.build.outputs.RABBITMQ_DEFAULT_USER }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export RABBITMQ_DEFAULT_PASS='${{ needs.build.outputs.RABBITMQ_DEFAULT_PASS }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export MONGO_INITDB_ROOT_USERNAME='${{ needs.build.outputs.MONGO_INITDB_ROOT_USERNAME }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export MONGO_INITDB_ROOT_PASSWORD='${{ needs.build.outputs.MONGO_INITDB_ROOT_PASSWORD }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export POSTGRES_USER='${{ needs.build.outputs.POSTGRES_USER }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export POSTGRES_PASSWORD='${{ needs.build.outputs.POSTGRES_PASSWORD }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export KEYCLOAK_ADMIN='${{ needs.build.outputs.KEYCLOAK_ADMIN }}'\" >> /etc/environment"
echo ${{ secrets.IONOS_SUDO_PASS }} | sudo -S bash -c "echo \"export KEYCLOAK_ADMIN_PASSWORD='${{ needs.build.outputs.KEYCLOAK_ADMIN_PASSWORD }}'\" >> /etc/environment"
echo "::endgroup::"
echo "Environment updated."
- name: Restart Docker containers on remote server
uses: appleboy/ssh-action@v1.2.0
with:
host: ${{ secrets.IONOS_REMOTE_HOST }}
username: ${{ secrets.IONOS_REMOTE_USER }}
key: ${{ secrets.IONOS_SSH_PRIVATE_KEY }}
script: |
cd /home/logicmade/bookitfor.me.uk/
docker compose -f docker-compose-data.yml down
docker compose -f docker-compose-data.yml up -d --build
Notes about the Yaml file
Build job must output the variables to use them in deploy job. If steps are in the same job there is no need to do that.
In the first step it checks if docker-compose-data.yml is changed. If not it exits with success
To hide echo in the logs I used
echo "::group::Hidden section"
......
echo "::endgroup::"
to use sudo with password I used this syntax
echo $Template:Secrets.IONOS SUDO PASS | sudo -S bash -c "echo \"export RABBITMQ_DEFAULT_USER='$Template:Needs.build.outputs.RABBITMQ DEFAULT USER'\" >> /etc/environment"