Skip to content

Deployment Guide

This guide documents the actual current production path in the repo. For the step-by-step operator procedure, see Deploy Runbook.

Current Production Topology

                   ┌─────────────────────────────────┐
                   │ Cloudflare Pages                │
                   │ qgtmai.com                      │
                   │ project: qgtm-trading          │
                   └──────────────┬──────────────────┘
                                  │ HTTPS
                   ┌─────────────────────────────────┐
                   │ DigitalOcean Droplet            │
                   │ 142.93.1.195                    │
                   │ /opt/trading                    │
                   │ systemd + venv runtime          │
                   ├─────────────────────────────────┤
                   │ qgtm-api.service                │
                   │ qgtm-daemon.service             │
                   │ redis-server.service            │
                   └─────────────────────────────────┘

                   Docs deploy separately to Cloudflare Pages
                   project: qgtm-docs

What Deploys Where

Surface Current path Source of truth
Terminal web app Cloudflare Pages project qgtm-trading .github/workflows/deploy-web-self-hosted.yml
API DigitalOcean droplet via SSH deploy .github/workflows/deploy-api-self-hosted.yml
Daemon Restarted on the droplet during API deploy .github/workflows/deploy-api-self-hosted.yml + infra/systemd/qgtm-daemon.service
Redis OS package service on the droplet redis-server.service
Docs Cloudflare Pages project qgtm-docs .github/workflows/deploy-docs.yml
Release artifacts GitHub Releases with SBOM + signing .github/workflows/release.yml

CI / CD Behavior

CI

ci.yml handles linting, tests, and coverage on pushes to main. ci-fast.yml is the pull-request gate. Supply-chain/security scanning runs in security-scan.yml.

Production deploy

deploy-api-self-hosted.yml is the production API/daemon deploy workflow:

  1. fire after green CI on main or via guarded workflow_dispatch
  2. block normal deploys while the market is open
  3. SSH to the DigitalOcean droplet
  4. git fetch + git reset --hard origin/main inside /opt/trading
  5. refresh selected .env values from GitHub secrets when present
  6. reinstall the package into the droplet virtualenv
  7. restart qgtm-api
  8. verify /health
  9. cancel stale resting paper orders before daemon restart
  10. restart qgtm-daemon
  11. verify deep daemon telemetry; rollback to the previous commit on failure

Release engineering

release.yml is not the production deploy path. It builds artifacts, runs tests, generates SBOMs, signs outputs, and publishes a GitHub Release on tags.

Runtime Services

The droplet uses systemd units that run the checked-out Python package in /opt/trading/.venv:

  • infra/systemd/qgtm-api.service
  • infra/systemd/qgtm-daemon.service
  • redis-server.service from the OS package

Docker is still used for Grafana/Prometheus/node-exporter, not for the active API, daemon, or Redis runtime.

Verification Targets

After a production deploy, the minimum checks are:

  • https://qgtmai.com
  • https://api.qgtmai.com/health
  • https://api.qgtmai.com/api/v1/market-data/bars/GLD?limit=5
  • https://api.qgtmai.com/api/v1/forecast/gold

If the API health check fails during deploy, the workflow already performs a commit-level rollback on the droplet.

Legacy / Non-Canonical Surfaces

The repo still contains references to older or alternate infrastructure such as Fly.io, Neon, Upstash, Doppler, Terraform, and k8s manifests. Treat those as historical, experimental, or future-state assets unless they are explicitly reintroduced into the active deploy workflows.