Skip to content
deploy docker github-actions ci-cd

Production deploy: Actions, Docker, and go-live

GitHub Actions SSH deploy, Docker rebuild on the VPS, and TLS routing to the live Astro SSR site.

S

Stack Team

2 min read

This guide covers steps 4–6 of the homepage deploy pipeline: CI/CD, containers, and the live site.

GitHub Actions deploy

On push to main (production) or develop (test), the workflow:

  1. SSHs into the VPS using repository secrets
  2. git fetch + reset --hard to the branch tip
  3. Verifies .env exists
  4. Substitutes AUTH_GATEWAY_URL into public/admin/config.yml
  5. Tags Docker images (latestprevious) for rollback
  6. Runs docker compose build app auth-gateway
  7. Runs docker compose up -d --force-recreate

Required GitHub secrets (per environment):

SecretPurpose
SSH_HOSTVPS hostname or IP
SSH_USERDeploy user
SSH_PRIVATE_KEYKey for Actions → VPS
DEPLOY_PATH_PRODProduction clone path
DEPLOY_PATH_TESTStaging clone path

BuildKit cache mounts speed up repeated pnpm and Astro builds.

Docker rebuild on VPS

Two containers share the external web-public Docker network:

ServiceRole
appAstro SSR on port 4325 — pages, API routes, integrations
auth-gatewayGitHub OAuth for Decap on port 3000

Multi-stage Dockerfiles keep runtime images small. Container names and image tags come from .env so production and test can run on the same VPS without collisions.

Rollback after a bad deploy:

docker tag astro-stack:previous astro-stack:latest
docker compose up -d --force-recreate app

Live site updated

Nginx Proxy Manager terminates TLS and routes traffic:

RouteTarget
stack.example.comastro-stack-app:4325
/api/authastro-stack-auth:3000

After compose up, the new Astro build serves SSR pages, API routes (/api/leads, /api/demo/*), and static assets. No separate CDN required — the VPS + NPM stack is the delivery path.

Common issues:

  • OAuth redirect mismatch — callback must match AUTH_GATEWAY_URL/api/auth/callback
  • Container unreachable — verify both services joined web-public
  • Missing .env — deploy fails intentionally; copy from .env.example

Previous: Content pipeline · Back to pipeline

Back to docs
Share:

Related solutions