name: Deploy Environment Monitoring to Production Environment on: push: branches: - prod-env concurrency: group: prod-monitoring-deploy cancel-in-progress: false jobs: deploy: runs-on: prod-runner steps: - name: Checkout Branch uses: actions/checkout@v4 - name: Connect Runner to Overlay Network run: | docker network connect iklimco-net $(hostname) || true - name: Install Required Tools run: | sudo sed -i 's|http://archive.ubuntu.com/ubuntu|http://mirror.hetzner.com/ubuntu/packages|g' /etc/apt/sources.list.d/ubuntu.sources || true sudo sed -i 's|http://archive.ubuntu.com/ubuntu|http://mirror.hetzner.com/ubuntu/packages|g' /etc/apt/sources.list || true sudo sed -i 's|http://security.ubuntu.com/ubuntu|http://mirror.hetzner.com/ubuntu/packages|g' /etc/apt/sources.list.d/ubuntu.sources || true sudo sed -i 's|http://security.ubuntu.com/ubuntu|http://mirror.hetzner.com/ubuntu/packages|g' /etc/apt/sources.list || true sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list sudo rm -f /etc/apt/sources.list.d/git-core-ubuntu-ppa*.list sudo rm -f /etc/apt/sources.list.d/github_git-lfs.list sudo apt-get update sudo apt-get install -y gettext jq - name: Set up SSH Key and Add to known_hosts run: | mkdir -p ~/.ssh echo "${{ secrets.STORAGEBOX_SSH_PRIV }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -p 23 ${{ vars.STORAGEBOX_USER }}.your-storagebox.de >> ~/.ssh/known_hosts - name: Download Deploy Inputs run: | rm -f .env .env.secrets.swag scp -P 23 ${{ vars.STORAGEBOX_USER }}@${{ vars.STORAGEBOX_USER }}.your-storagebox.de:prod/secrets/iklim.co/.env ./.env scp -P 23 ${{ vars.STORAGEBOX_USER }}@${{ vars.STORAGEBOX_USER }}.your-storagebox.de:prod/secrets/iklim.co/.env.secrets.swag ./.env.secrets.swag test -s .env test -s .env.secrets.swag - name: Create Dozzle Auth Secret env: DOZZLE_USERS_YML_B64: ${{ secrets.DOZZLE_USERS_YML_B64 }} DOZZLE_USERS_YML: ${{ secrets.DOZZLE_USERS_YML }} run: | set -euo pipefail if [ -n "${DOZZLE_USERS_YML_B64:-}" ]; then printf '%s' "$DOZZLE_USERS_YML_B64" | base64 -d > /tmp/dozzle-users.yml elif [ -n "${DOZZLE_USERS_YML:-}" ]; then printf '%s\n' "$DOZZLE_USERS_YML" > /tmp/dozzle-users.yml else echo "DOZZLE_USERS_YML_B64 or DOZZLE_USERS_YML secret is required" exit 1 fi grep -q '^users:' /tmp/dozzle-users.yml docker service rm iklimco_dozzle || true for i in $(seq 1 24); do if ! docker service inspect iklimco_dozzle >/dev/null 2>&1; then break fi echo "Waiting for old iklimco_dozzle service to be removed..." sleep 5 done docker secret rm dozzle_users || true docker secret create dozzle_users /tmp/dozzle-users.yml >/dev/null shred -u /tmp/dozzle-users.yml || rm -f /tmp/dozzle-users.yml - name: Deploy Dozzle Stack run: | set -a; . ./.env; set +a export IMAGE_DOZZLE="${IMAGE_DOZZLE:-amir20/dozzle:v10.6.6}" export DOZZLE_USERS_SECRET_NAME=dozzle_users docker stack deploy \ --resolve-image changed \ -c docker-stack-service.yml \ iklimco - name: Wait for Dozzle run: | for i in $(seq 1 36); do REPLICAS=$(docker service ls --filter name=iklimco_dozzle --format "{{.Replicas}}" | head -1) if echo "$REPLICAS" | awk -F'[/ ]' '$1>0 && $1==$2{found=1} END{exit !found}'; then echo "Dozzle is ready: $REPLICAS" exit 0 fi echo "Dozzle not ready yet (${REPLICAS:-missing}), waiting 5s..." sleep 5 done docker service ps iklimco_dozzle || true exit 1 - name: Configure SWAG Reverse Proxy run: | set -a; . ./.env; . ./.env.secrets.swag; set +a export DOZZLE_SUBDOMAIN="${DOZZLE_SUBDOMAIN:-dozzle.iklim.co}" envsubst '${DOZZLE_SUBDOMAIN}' < swag/dozzle.conf.tpl | docker run --rm -i \ -v "${SWAG_SITE_CONFS_DIR}:/output" \ alpine sh -c "cat > /output/dozzle.conf" SWAG_CTR=$(docker ps -q -f name=iklimco_swag 2>/dev/null | head -1) if [ -n "$SWAG_CTR" ]; then docker exec "$SWAG_CTR" nginx -t && docker exec "$SWAG_CTR" nginx -s reload fi - name: Configure APISIX Reverse Proxy run: | set -a; . ./.env; set +a export SPRING_PROFILES_ACTIVE=prod export DOZZLE_SUBDOMAIN="${DOZZLE_SUBDOMAIN:-dozzle.iklim.co}" /bin/bash init/apisix-dozzle.sh - name: Update DNS Record run: | set -a; . ./.env; . ./.env.secrets.swag; set +a FLOATING_IP="${{ vars.PROD_FLOATING_IP }}" DOMAIN="iklim.co" RECORD="${DOZZLE_DNS_RECORD:-dozzle}" CURRENT=$(curl -s \ -H "Authorization: sso-key ${GODADDY_KEY}:${GODADDY_SECRET}" \ "https://api.godaddy.com/v1/domains/${DOMAIN}/records/A/${RECORD}" \ 2>/dev/null | jq -r '.[0].data // empty' 2>/dev/null || true) if [ "$CURRENT" = "$FLOATING_IP" ]; then echo "${RECORD}.${DOMAIN} -> ${FLOATING_IP} exists, skipping" else curl -sf -X PUT \ -H "Authorization: sso-key ${GODADDY_KEY}:${GODADDY_SECRET}" \ -H "Content-Type: application/json" \ "https://api.godaddy.com/v1/domains/${DOMAIN}/records/A/${RECORD}" \ -d "[{\"data\":\"${FLOATING_IP}\",\"ttl\":600}]" echo "${RECORD}.${DOMAIN} -> ${FLOATING_IP} added/updated" fi - name: Verify Deployment run: | docker service ps iklimco_dozzle \ --filter "desired-state=running" \ --format "table {{.Name}}\t{{.Node}}\t{{.CurrentState}}\t{{.Image}}" | head -20