Files

5.8 KiB

ZarinPal Merchant Analytics — Deployment

This repository is the operational control plane for the hackathon project. It will own Docker Compose, Nginx, environment templates, deployment automation, backup/restore scripts, and cross-repository release orchestration. Product code belongs in the backend and frontend repositories.

The production stack is Docker Compose based and connects to the existing shared Caddy deployment. This repository does not publish host ports and does not run a second TLS proxy.

For direct Windows development without Docker Compose, see docs/LOCAL-DEVELOPMENT.md. This helper is deliberately separate from the production Compose contract.

Repository topology

zarinpal-analytics-deployment/  # this repository
├── backend/                    # ignored checkout of zarinpal-analytics-backend
├── frontend/                   # ignored checkout of zarinpal-analytics-frontend
├── docs/
└── (deployment assets created through the authorized task list)

The production hostname is zarinpal.amiirkhl.ir. Caddy routes /api/* and /healthz to the Go API and every other path to the static frontend. PostgreSQL, Redis, the worker, and all one-off commands remain on the private Compose data network; the worker additionally joins a dedicated bridge network for outbound AI-provider access without joining the shared Caddy proxy network.

Required server layout

/home/ubuntu/zarinpal-analytics-deployment/
├── .env
├── backend/
│   └── .env
└── frontend/
    └── .env

Clone the backend and frontend as ordinary ignored repositories, not submodules. Copy the three tracked examples to their ignored runtime names:

cp .env.example .env
cp backend/.env.production.example backend/.env
cp frontend/.env.production.example frontend/.env
chmod 600 .env backend/.env frontend/.env

Replace every change-me value. Generate URL-safe secrets with openssl rand -hex 32. The root file owns the PostgreSQL and Redis passwords plus the reviewed-calendar path and non-secret audit identities; Compose injects their connection settings into the Go containers. The frontend file contains public build-time switches only.

First production start

Before adding/reloading the Caddy route, place the independently reviewed calendar JSON at CALENDAR_FILE, make it read-only, and confirm that its sourceChecksum is not a review placeholder. Then validate and build the stack, import the immutable dataset, bootstrap the reviewed calendar, create the demo account, and only then start the public upstreams:

docker compose config --quiet
docker compose build backend frontend
docker compose up -d postgres redis
docker compose --profile tools run --rm migrate
docker compose --profile import run --rm importer
docker compose --profile tools run --rm calendar
docker compose --profile tools run --rm admin
docker compose up -d backend worker frontend
docker compose ps

After every service reports healthy, validate and reload Caddy from the separate Caddy deployment. This order prevents the first public activation from serving an empty or partially imported database.

Normal later deployments

Pull each repository manually, then run the guarded deploy script. It rejects dirty, non-main, or non-origin/main checkouts and never performs a fetch, reset, or checkout itself.

git pull --ff-only origin main
git -C backend pull --ff-only origin main
git -C frontend pull --ff-only origin main
bash scripts/deploy.sh

Normal deploys run migrations but never run the importer, calendar bootstrap, or admin command.

Re-running one-off tools

IMPORT_FILE in the root .env is the absolute host path of the immutable challenge_data.csv.gz; CALENDAR_FILE is the absolute path of the reviewed JSON catalog. If recovery requires an idempotent data/catalog bootstrap or the demo account must be reset, run the applicable command explicitly:

docker compose --profile import run --rm importer
docker compose --profile tools run --rm calendar
docker compose --profile tools run --rm admin

All three commands are explicit one-offs. Calendar bootstrap resumes the same reviewed version safely and rejects placeholder checksums, conflicting metadata, retired versions, or replacement of a different active catalog. Future catalog rotation must use the separately reviewed import, approve, and activate workflow.

Operations

docker compose ps
docker compose logs --tail=200 backend worker frontend postgres redis
docker compose restart backend worker frontend
docker compose down

Do not use docker compose down -v in production; -v deletes the PostgreSQL and Redis volumes. Caddy is managed from its own repository and must already provide the external caddy_proxy network.

Documentation workflow

  • CAPABILITY-MAP.md is the approved Phase 0 decomposition.
  • Each capability receives a spec before implementation.
  • Surprising or hard-to-reverse decisions receive an ADR in docs/decisions/.
  • Raw datasets and database state are never committed.
  • Every material change is a small Conventional Commit.

Platform operations documents

  • docs/PLATFORM-OPERATIONS-SPEC.md defines the production topology and is amended by ADR 0006 for the shared Caddy ingress.
  • docs/QLOCKIFY-ADAPTATION-CONTRACT.md maps Qlockify's tracked deployment files and environment layout to the planned ZarinPal artifacts without requiring real server values during planning.
  • docs/runbooks/FIRST-SERVER-BOOTSTRAP.md defines the safe first-host sequence without implementing a bootstrap script.
  • docs/runbooks/BACKUP-RESTORE.md defines logical PostgreSQL backup, encryption/retention, guarded restore, and rehearsal.
  • tasks/plan.md and tasks/todo.md hold the approved implementation plan and dependency-ordered Phase 4 tasks.