Exporters: - postgres_exporter: DB connections, transactions, cache hit ratio, query stats - node_exporter: host CPU, memory, disk, network - cAdvisor: per-container CPU and memory usage PostgreSQL: - Enable pg_stat_statements for query-level performance tracking - Track index scans vs sequential scans, cache hit ratio Dashboard (service-health.json): - DB: connections, size, transactions/s, slow queries, cache hit ratio, index usage - Host: disk gauge, CPU, memory, network I/O, disk I/O - BRouter: request latency p50/p95/p99, container CPU + memory - All containers: CPU and memory comparison Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
87 lines
3.2 KiB
YAML
87 lines
3.2 KiB
YAML
name: CD Infra
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- "infrastructure/**"
|
|
workflow_dispatch:
|
|
inputs:
|
|
restart_all:
|
|
description: "Restart all containers (not just infra)"
|
|
type: boolean
|
|
default: false
|
|
|
|
concurrency:
|
|
group: deploy-infra
|
|
cancel-in-progress: true
|
|
|
|
jobs:
|
|
deploy:
|
|
name: Deploy Infrastructure
|
|
runs-on: ubuntu-latest
|
|
environment: infra
|
|
steps:
|
|
- uses: actions/checkout@v6
|
|
|
|
- name: Decrypt secrets
|
|
run: |
|
|
curl -sLO https://github.com/getsops/sops/releases/download/v3.9.4/sops-v3.9.4.linux.amd64
|
|
chmod +x sops-v3.9.4.linux.amd64
|
|
# Merge app + infra secrets into one .env for docker-compose
|
|
SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.app.env > infrastructure/.env
|
|
SOPS_AGE_KEY="${{ secrets.AGE_SECRET_KEY }}" ./sops-v3.9.4.linux.amd64 -d infrastructure/secrets.infra.env >> infrastructure/.env
|
|
echo "DOMAIN=trails.cool" >> infrastructure/.env
|
|
|
|
- name: Copy configs to server
|
|
uses: appleboy/scp-action@v1
|
|
with:
|
|
host: ${{ secrets.DEPLOY_HOST }}
|
|
username: root
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
source: "infrastructure/docker-compose.yml,infrastructure/Caddyfile,infrastructure/prometheus/prometheus.yml,infrastructure/loki/loki-config.yml,infrastructure/grafana/provisioning,infrastructure/grafana/dashboards"
|
|
target: /opt/trails-cool
|
|
strip_components: 1
|
|
|
|
- name: Copy secrets to server
|
|
uses: appleboy/scp-action@v1
|
|
with:
|
|
host: ${{ secrets.DEPLOY_HOST }}
|
|
username: root
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
source: "infrastructure/.env"
|
|
target: /opt/trails-cool
|
|
strip_components: 1
|
|
|
|
- name: Deploy via SSH
|
|
uses: appleboy/ssh-action@v1
|
|
with:
|
|
host: ${{ secrets.DEPLOY_HOST }}
|
|
username: root
|
|
key: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
script: |
|
|
cd /opt/trails-cool
|
|
|
|
# .env was placed by the SCP step (decrypted app + infra secrets)
|
|
|
|
# Login to ghcr.io (for pulling monitoring images)
|
|
GHCR_TOKEN=$(grep DEPLOY_GHCR_TOKEN .env | cut -d= -f2-)
|
|
echo "$GHCR_TOKEN" | docker login ghcr.io -u stigi --password-stdin 2>/dev/null || true
|
|
|
|
# Check if full restart requested via:
|
|
# - workflow_dispatch input: restart_all=true
|
|
# - commit message containing [restart-all]
|
|
RESTART_ALL="${{ github.event.inputs.restart_all }}"
|
|
if [ "$RESTART_ALL" != "true" ] && echo "${{ github.event.head_commit.message }}" | grep -q '\[restart-all\]'; then
|
|
RESTART_ALL="true"
|
|
fi
|
|
|
|
if [ "$RESTART_ALL" = "true" ]; then
|
|
docker compose --env-file .env up -d --remove-orphans
|
|
else
|
|
# Restart infra services (except Caddy — just reload its config)
|
|
docker compose --env-file .env up -d postgres prometheus loki grafana postgres-exporter node-exporter cadvisor
|
|
docker compose exec caddy caddy reload --config /etc/caddy/Caddyfile
|
|
fi
|
|
|
|
docker compose ps
|