Skip to main content

Deployment

GhostPour runs as a Docker container behind Nginx Proxy Manager on a GCP VM.

Infrastructure

ComponentDetails
Containerghostpour on proxy-tier Docker network
RoutingNginx Proxy Manager routes your domain → ghostpour:8000
CI/CDPush to main → GitHub Actions → GHCR → SSH deploy
DataSQLite DB persisted in Docker volume at /app/data/
Config.env.prod + docker-compose.prod.yml

Docker Setup

The website runs as a static Docusaurus build served by nginx:

FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80

Manual Deploy

ssh into GCP VM
cd ~/ghostpour-website
docker compose pull && docker compose up -d --force-recreate

CI/CD Pipeline

GitHub Actions deploys on push to main:

  1. SCP files to GCP VM
  2. SSH in and run docker compose up -d --build
  3. Prune old images

Admin Dashboard

The GhostPour API includes a web-based admin dashboard at /admin with these tabs:

  • Overview: Today's stats, user counts by tier, allocation alerts (users >80%), trial funnel, daily trends
  • Models: Usage by provider/model (requests, tokens, cost, latency)
  • Users: All users with tier badges, inline set-tier dropdown, drill-down detail
  • Tiers: Tier config cards with simulate button, per-feature state toggles
  • Latency: Response time percentiles (p50/p75/p90/p95/p99)
  • Providers: API key management, credit balance checks
  • Errors: Error summary by status/provider, recent error log

Admin Simulation

The admin dashboard can simulate any tier for a user without changing their real subscription — useful for testing the full upgrade flow end-to-end:

POST /webhooks/admin/simulate-tier
{ "user_id": "...", "tier": "ultra", "exhausted": true }

Clear simulation with "tier": null to revert to the user's real tier.