8.7 KiB
Qlockify deployment adaptation contract
- Status: Approved planning baseline
- Source:
D:/Programing/Scripts/Qlockify/qlockify-deployment(read-only) - Target:
/home/ubuntu/zarinpal-analytics-deployment - Implementation authorization: Not granted
- Last updated: 2026-08-20
Purpose
Use Qlockify's proven single-server deployment shape and environment-file layout for ZarinPal Analytics without requiring production IPs, credentials, or operator names during planning. Real values are supplied on the server when deployment occurs; they are not planning blockers and never enter public Git.
Repository layout
/home/ubuntu/zarinpal-analytics-deployment/
├── .env ignored deployment/TLS/backup values
├── backend/ ignored backend Git checkout
│ └── .env ignored backend/runtime values
├── frontend/ ignored frontend Git checkout
│ └── .env ignored public build values only
├── data/incoming/ ignored one-time CSV input
├── data/reports/ ignored import reports
├── releases/ ignored non-secret release records
└── backups/ ignored encrypted local backups
This deliberately simplifies Qlockify's extra application subdirectory layer. Each service checkout is directly under the deployment root and keeps an independent .git directory.
File adaptation matrix
| Qlockify source | Planned ZarinPal artifact | Adaptation |
|---|---|---|
.env.sample |
.env.example |
Keep TLS and ParsPack variable names; use the ZarinPal domain/prefix; remove alternate-domain and duplicate database values. |
backend/.env.sample |
backend-owned .env.example, consumed as backend/.env |
Replace Django, JWT, Celery, OAuth, SMS, and demo-cleanup variables with the Go API/worker/import contracts. |
frontend/.env.sample |
frontend-owned .env.example, consumed as frontend/.env |
Keep only public same-origin build configuration; never place a secret here. |
docker-compose.yml |
compose.yaml |
Keep single-host orchestration and nested build contexts; replace Django/Celery/media services with API, worker, migrate, importer, and admin boundaries. |
backend/Dockerfile |
deployment backend image definition | Build the backend checkout once and select API/worker/migrate/import/admin commands from the same recorded backend revision. |
frontend/Dockerfile |
deployment frontend image definition | Build the ordinary frontend checkout, including its tracked font and license. |
nginx/* |
nginx/* |
Keep HTTP-01, automatic renewal, temporary bootstrap certificate, and reload flow; use only zarinpal.amiirkhl.ir and ZarinPal routes. |
scripts/deploy.sh |
scripts/deploy.sh plus release-record helper |
Keep manual Compose build/start structure; Git pulls happen interactively before the script; remove fetch/reset and partial-repository release selection. |
scripts/backup.sh |
scripts/backup.sh |
Keep plain-SQL pg_dump and temporary archive structure; include PostgreSQL plus non-secret manifest/checksums only. |
scripts/backup-upload-s3.sh |
same filename | Keep root .env loading, OpenSSL/rclone flow, ParsPack support, and 3/7 retention; retain encrypted local artifacts. |
scripts/restore.sh |
same filename | Keep plain-SQL restore basis; remove env/media restore and add empty-target plus production guards. |
scripts/restore-from-s3.sh |
same filename | Keep rclone/decrypt handoff; require an explicit object id for production and validate it before restore. |
.gitea/workflows/* |
none | Do not port. ZarinPal deployment is manual and has no CI/CD pipeline or runner. |
Environment layout
Future tracked examples contain placeholders or safe public defaults only. Production files are Git-ignored, owned by ubuntu, mode 0600, excluded from backup, and loaded without printing resolved values.
Deployment root .env
The future .env.example uses this deployment-owned contract:
COMPOSE_PROJECT_NAME=zarinpal_analytics
SSL_CERT_MODE=letsencrypt
LETSENCRYPT_EMAIL=
PRIMARY_DOMAIN=zarinpal.amiirkhl.ir
CERTBOT_STAGING=0
S3_BACKUP_BUCKET=
S3_BACKUP_PREFIX=backup/zarinpal-analytics
S3_BACKUP_ENDPOINT_URL=
S3_BACKUP_ACCESS_KEY_ID=
S3_BACKUP_SECRET_ACCESS_KEY=
BACKUP_ENCRYPTION_PASSPHRASE=
BACKUP_LOCAL_KEEP_LATEST=3
BACKUP_REMOTE_KEEP_LATEST=7
There is no ALT_DOMAINS, runner, registry, deploy-host, SSH-key, or CI variable. The endpoint, bucket, email, access keys, and passphrase may remain blank in the tracked example; the future validation command requires them only for the operation that consumes them.
Backend backend/.env
The backend repository owns the complete Go application example. Deployment requires these semantic groups and consumes their eventual exact backend-owned names without maintaining a second competing template:
- production mode and structured-log level
- API listen address and public origin
https://zarinpal.amiirkhl.ir POSTGRES_HOST=postgres, port5432, database/user/passwordREDIS_HOST=redis, port6379, password, and database selection required by the backend/Asynq contract- session/cookie secrets and secure same-origin cookie settings
- analytics TTL, rate limits, worker concurrency
16, per-merchant concurrency4, 60-second attempt timeout, and retry policy - import source/report paths, schema version, readiness timeout, and bounded batch/resource settings
The same protected file supplies PostgreSQL, Redis, API, worker, migrate, importer, and admin services only with the variables each service needs. Qlockify-only Django, JWT, Celery, Google OAuth, SMS, demo-environment, media, and scheduled-cleanup variables are not carried over.
Frontend frontend/.env
The frontend repository owns its exact public variable name. Its production value is the same-origin API prefix, initially /api/v1. No database, Redis, session, backup, AvalAI, or other secret is allowed in this file or the browser bundle.
Manual deployment flow
- The operator manually runs
git pull --ff-only origin mainin deployment, backend, and frontend checkouts and enters source-forge credentials interactively. - The future deploy command acquires the operation lock and verifies exact paths, remotes,
main, equality withorigin/main, and clean trees. It performs no Git fetch, pull, checkout, or reset. - It records all three commit hashes and validates the root/backend/frontend environment contracts without printing values.
- It validates Compose, builds from the three recorded revisions, starts data services, runs the one-off migration, and replaces application services only after the required gates pass.
- It validates private readiness plus public TLS/routing/font/SSE behavior, observes for 15 minutes, then marks the release active.
- Rollback selects the prior release's three hashes, rebuilds, and re-runs the same checks. It never automatically reverses a migration.
The ordinary deployment path never invokes CSV import or credential generation. The first server uses the separately planned first-start.sh path after migration and before the first public activation.
Always / Ask / Never
Always
- Adapt from the named tracked Qlockify source file and record intentional differences.
- Keep all three real
.envfiles ignored, mode0600, and out of backups/logs. - Validate only the variables needed by the requested operation.
- Preserve exact-path guards before any mutation, cleanup, restore, or retention action.
Ask first
- Rename a deployment-owned variable after implementation begins.
- Add a public origin/domain, external provider, persistent data class, or secret consumer.
- Change the manual three-repository release rule or Qlockify-derived backup encryption/retention contract.
Never
- Port Qlockify's Gitea workflows, runner/deploy-key variables, or automated deployment.
- Port Qlockify's destructive
git reset --hardsynchronization. - Copy Qlockify credentials, domains, database names, service names, or secret values.
- Back up or restore
.envfiles, Redis, TLS keys, raw CSV, credentials, logs, or frontend assets. - Create a second font path or private asset-injection workflow.
Planning acceptance
- Every future deployment artifact maps to a named Qlockify source or a documented ZarinPal-only requirement.
- Root/backend/frontend environment ownership is unambiguous and has no duplicate secret source.
- Tracked examples can be committed with blank secret placeholders and useful safe defaults.
- Planning and local validation do not require a server IP, real DNS access, real ParsPack values, or named operators.
- Real values are required only at the first-server or operation-specific execution gate.