QuickPredict

Deploying QuickPredict

The app is a single long-running process (Telegram long-polling + the 20s settlement keeper) with a local SQLite file that holds users’ encrypted wallet keys. That dictates everything below:

CI/CD is GitHub Actions:

Workflow Trigger What it does
ci.yml every PR typecheck + prove the Docker image builds
deploy.yml push to main typecheck → push image to GHCR → deploy to Fly (if FLY_API_TOKEN is set, else skips cleanly)

One-time setup:

fly launch --no-deploy --copy-config --name <your-app-name>   # uses ./fly.toml
fly volumes create data --size 1 --region fra                  # SQLite volume
fly secrets set BOT_TOKEN=...                                  # + any other secrets
fly deploy --remote-only                                       # first deploy, from your machine

Wire up CI/CD (after the first deploy works):

fly tokens create deploy

Save the output as the FLY_API_TOKEN repo secret on GitHub (Settings → Secrets and variables → Actions). From then on every push to main deploys automatically.

Notes:

Any small VPS (Hetzner CX22-class). Once Docker is installed:

git clone <repo> && cd QuickPredict
cp .env.example .env        # fill: BOT_TOKEN, LITESTREAM_* (bucket + creds)
docker compose up -d --build

Or run the image CI already published instead of building on the box:

IMAGE=ghcr.io/<owner>/quickpredict:latest docker compose up -d

Backups are Litestream, running as a sidecar (litestream.yml): it streams every SQLite change to an S3-compatible bucket (S3 / Backblaze B2 / Cloudflare R2). Set in .env:

Run the restore drill before trusting it with real funds:

docker compose run --rm litestream \
  restore -config /etc/litestream.yml -o /data/restored.db /data/quick-predict.db

A backup you’ve never restored is a hope, not a backup.

Auto-update on push (optional): add Watchtower or a tiny cron docker compose pull && docker compose up -d — CI already pushes ghcr.io/<owner>/quickpredict:latest on every merge to main.


Production checklist