Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,16 +151,16 @@ jobs:

printf '%s' "${{ secrets.SERVER_ENV_PRODUCTION }}" > server/.env.production

cat > .env.stack <<EOF
REGISTRY=docker.io
IMAGE_NAMESPACE=${{ steps.vars.outputs.namespace }}
IMAGE_TAG=${{ github.sha }}
POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}
EOF
export REGISTRY=docker.io
export IMAGE_NAMESPACE=${{ steps.vars.outputs.namespace }}
export IMAGE_TAG=${{ github.sha }}
export POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}
export ACCESS_TOKEN_SECRET=${{ secrets.ACCESS_TOKEN_SECRET }}
export JWT_ACCESS_SECRET=${{ secrets.ACCESS_TOKEN_SECRET }}

echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login docker.io -u "${{ secrets.DOCKERHUB_USERNAME }}" --password-stdin

docker compose --env-file .env.stack -f docker-compose.prod.yaml pull
docker compose --env-file .env.stack -f docker-compose.prod.yaml up -d
docker compose --env-file .env.stack -f docker-compose.prod.yaml run --rm ph-server sh -lc "pnpm prisma migrate deploy --schema=prisma/schema"
docker compose -f docker-compose.prod.yaml pull
docker compose -f docker-compose.prod.yaml up -d
docker compose -f docker-compose.prod.yaml run --rm ph-server sh -lc "pnpm prisma migrate deploy --schema=prisma/schema"
docker image prune -f
2 changes: 1 addition & 1 deletion docker-compose.prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ services:
restart: unless-stopped
environment:
JWT_ACCESS_SECRET: ${JWT_ACCESS_SECRET}
ACCESS_TOKEN_SECRET: ${JWT_ACCESS_SECRET}
ACCESS_TOKEN_SECRET: ${ACCESS_TOKEN_SECRET}
depends_on:
- ph-server
networks:
Expand Down
5 changes: 5 additions & 0 deletions scripts/set-github-secrets.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ Set-Secret -Name "VPS_HOST" -Value $inputSecrets["VPS_HOST"]
Set-Secret -Name "VPS_USER" -Value $inputSecrets["VPS_USER"]
Set-Secret -Name "VPS_APP_DIR" -Value $inputSecrets["VPS_APP_DIR"]
Set-Secret -Name "CLIENT_PUBLIC_API_BASE_URL" -Value $inputSecrets["CLIENT_PUBLIC_API_BASE_URL"]
if ([string]::IsNullOrWhiteSpace($inputSecrets["ACCESS_TOKEN_SECRET"])) {
Set-Secret -Name "ACCESS_TOKEN_SECRET" -Value $serverEnv["ACCESS_TOKEN_SECRET"]
} else {
Set-Secret -Name "ACCESS_TOKEN_SECRET" -Value $inputSecrets["ACCESS_TOKEN_SECRET"]
}
Set-Secret -Name "POSTGRES_PASSWORD" -Value $postgresPassword
Set-Secret -Name "SERVER_ENV_PRODUCTION" -Value $serverEnvText

Expand Down
89 changes: 89 additions & 0 deletions skills/backend-vps-cicd-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# Backend Skill: VPS + CI/CD + Docker

Use this skill when deploying a Node.js/TypeScript backend to a VPS with Docker Compose and CI/CD.

## 1) Outcome

- Backend image builds and pushes from CI.
- VPS pulls backend image and starts service.
- Database connectivity and migrations succeed.
- Nginx proxies API requests to backend on localhost.

## 2) Required Inputs

- Production `.env` values for backend.
- Docker Hub access.
- VPS SSH access.
- Postgres password and connection URL.

## 3) Backend Runtime Rules

- Use deterministic start command.
- Include required files in image (`src` or `dist`, `prisma`, config).
- Ensure env secrets are available at runtime.

## 4) CI/CD Skill Flow

1. Trigger on push to `main`.
2. Install dependencies, lint, build.
3. Build and push backend image tag `${GITHUB_SHA}`.
4. SSH deploy to VPS.
5. Pull and recreate `ph-server`.
6. Run DB migrations if needed.

## 5) GitHub Secrets Checklist

- `DOCKERHUB_USERNAME`
- `DOCKERHUB_TOKEN`
- `POSTGRES_PASSWORD`
- `VPS_HOST`
- `VPS_USER`
- `VPS_SSH_KEY`

## 6) VPS Deployment Commands

```bash
docker compose --env-file .env.stack -f docker-compose.prod.yaml pull ph-server
docker compose --env-file .env.stack -f docker-compose.prod.yaml up -d --force-recreate ph-server
docker compose --env-file .env.stack -f docker-compose.prod.yaml run --rm ph-server sh -lc "pnpm prisma migrate deploy --schema=prisma/schema"
docker logs ph-server --tail 120
```

## 7) Nginx API Check

```bash
curl -I http://127.0.0.1:5000/api/v1/
curl -I http://YOUR_PUBLIC_IP/api/v1/
nginx -t
systemctl reload nginx
```

## 8) Common Backend Failures

- Symptom: `502 Bad Gateway`.
- Fix: check `ph-server` logs and container status, then verify backend listens on `127.0.0.1:5000`.

- Symptom: `MODULE_NOT_FOUND` or ESM import error.
- Fix: validate start command, image contents, and Node module resolution strategy.

- Symptom: Prisma migration/schema issues.
- Fix: ensure `prisma` folder exists in image and run migration command manually.

- Symptom: auth token validation mismatch.
- Fix: ensure signing and verification secrets match between backend and middleware runtime.

## 9) Validation Checklist

- `ph-server` container is `Up`.
- `/api/v1/` returns valid HTTP response.
- auth endpoints return expected status.
- migrations are applied successfully.

## 10) Fast Rollback

- Set `.env.stack` `IMAGE_TAG` to last working tag.
- Recreate backend service.

```bash
docker compose --env-file .env.stack -f docker-compose.prod.yaml up -d --force-recreate ph-server
```
94 changes: 94 additions & 0 deletions skills/frontend-vps-cicd-docker.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Frontend Skill: VPS + CI/CD + Docker

Use this skill when deploying a Next.js frontend to a VPS using Docker and GitHub Actions.

## 1) Outcome

- Frontend image builds in CI.
- Image pushes to Docker Hub.
- VPS pulls the new image and runs it with Docker Compose.
- Nginx proxies public traffic to frontend container on localhost.

## 2) Required Inputs

- Docker Hub username and token.
- VPS SSH access.
- Public IP or domain.
- Image tag strategy (recommended: commit SHA).

## 3) Frontend Docker Rules

- Build with production API base URL injected at build time.
- Expose app on port 3000 in container.
- Run with `next start -H 0.0.0.0 -p 3000`.

Example build args:

```bash
--build-arg NEXT_PUBLIC_API_BASE_URL=http://YOUR_PUBLIC_IP/api/v1
```

## 4) CI/CD Skill Flow

1. Trigger on push to `main`.
2. Run quality gates: install, lint, build.
3. Build frontend image with tag `${GITHUB_SHA}`.
4. Push image to Docker Hub.
5. SSH to VPS and pull new image.
6. Recreate frontend service.

## 5) GitHub Secrets Checklist

- `DOCKERHUB_USERNAME`
- `DOCKERHUB_TOKEN`
- `CLIENT_PUBLIC_API_BASE_URL`
- `VPS_HOST`
- `VPS_USER`
- `VPS_SSH_KEY`

## 6) VPS Deployment Commands

From project root on VPS:

```bash
docker compose --env-file .env.stack -f docker-compose.prod.yaml pull ph-client
docker compose --env-file .env.stack -f docker-compose.prod.yaml up -d --force-recreate ph-client
docker compose --env-file .env.stack -f docker-compose.prod.yaml ps
docker logs ph-client --tail 100
```

## 7) Nginx Frontend Check

```bash
curl -I http://127.0.0.1:3000
curl -I http://YOUR_PUBLIC_IP
nginx -t
systemctl status nginx --no-pager
```

## 8) Common Frontend Failures

- Symptom: old UI after deploy.
- Fix: hard refresh browser, clear cache, recreate container.

- Symptom: server action mismatch.
- Fix: deploy frontend and backend from same commit, then force recreate both services.

- Symptom: login stuck on auth page.
- Fix: verify cookies are set and middleware runtime env is present in `ph-client`.

## 9) Validation Checklist

- Homepage loads at public URL.
- Login form submits.
- Protected routes open after login.
- `docker compose ps` shows `ph-client` as `Up`.

## 10) Fast Rollback

- Set `IMAGE_TAG` in `.env.stack` to previous working tag.
- Recreate frontend service.

```bash
docker compose --env-file .env.stack -f docker-compose.prod.yaml up -d --force-recreate ph-client
```
Loading