# 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`](docs/LOCAL-DEVELOPMENT.md). This helper is deliberately separate from the production Compose contract. ## Repository topology ```text 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. ## Required server layout ```text /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: ```bash 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; 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, validate and build the stack, import the immutable dataset, create the demo account, and only then start the public upstreams: ```bash 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 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. ```bash 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 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`. If recovery requires the idempotent importer or the demo account must be reset, run them explicitly: ```bash docker compose --profile import run --rm importer docker compose --profile tools run --rm admin ``` Both commands are explicit one-offs. Re-running the importer relies on the backend's checksum-based idempotency guard. ## Operations ```bash 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.