Files
nick-doc/01 - Architecture/Infrastructure.md
2026-05-23 20:35:34 +03:30

8.4 KiB

title, tags, created
title tags created
Infrastructure
architecture
infrastructure
docker
devops
2026-05-23

Infrastructure

How the system is packaged, deployed and run in production. Read alongside Docker Setup (operations runbook) and CI-CD Pipeline.


1. Runtime topology

flowchart LR
    DNS[DNS amn.gg] --> CF[CloudFlare / Edge SSL]
    CF --> Nginx
    subgraph Host[Single Docker host]
        Nginx[nginx:alpine<br/>nickapp-nginx<br/>:8083]
        FE[nickapp-frontend:latest<br/>Next.js standalone<br/>:8083]
        BE[nickapp-backend:latest<br/>Express + Socket.IO<br/>:5001]
        Mongo[(mongo:8.0<br/>mongodb_data volume)]
        Redis[(redis:8-alpine<br/>redis_data volume)]
        Up[/uploads volume/]
    end
    Nginx --> FE
    Nginx --> BE
    BE --> Mongo
    BE --> Redis
    BE --- Up
    FE --- Up
    Watchtower>Watchtower<br/>auto-update] -.-> BE
    Watchtower -.-> FE

[!info] Single-host today. Horizontal scaling requires Redis pub/sub adapter for Socket.IO and externalizing the uploads/ volume (S3 / R2).


2. Docker images

Image Source Dockerfile Stages Final size target User
nickapp-backend:latest backend/Dockerfile.prod builder + runner ~200 MB marketplace (uid 1001)
nickapp-backend:dev backend/Dockerfile.dev single ~400 MB marketplace (uid 1001)
nickapp-frontend:latest frontend/Dockerfile builder + runner ~250 MB nextjs (uid 1001)
nickapp-frontend:dev frontend/Dockerfile.dev single ~600 MB root

All built on node:22-alpine. Backend images include Python+make+g++ in the builder stage for native deps (bcrypt). Frontend runner only ships the .next/standalone output + public/.


3. Compose stacks

3.1 docker-compose.dev.yml (backend repo)

Used by developers running npm run docker:dev. Three services:

Service Image Ports Volumes Depends on
nickdev-backend built from Dockerfile.dev 5001:5001 ./src:/app/src, ./uploads:/app/uploads mongodb, redis
nickdev-mongodb mongo:8.0 27017:27017 mongodb_data:/data/db
nickdev-redis redis:8-alpine (internal) redis_data:/data

Network: nickapp-network (bridge). Env: .env.local.

Frontend dev runs OUTSIDE compose — developer launches yarn dev on host so React Fast Refresh works.

3.2 docker-compose.production.yml (backend repo)

Used in production. Five services:

Service Image Ports Healthcheck Watchtower
nickapp-nginx nginx:alpine 8083:80 implicit
nickapp-backend nickapp-backend:latest (pulled) 5001 internal node healthcheck.js 30s
nickapp-frontend nickapp-frontend:latest (pulled) 8083 internal curl http://localhost:8083 30s
nickapp-mongodb mongo:8.0 internal mongosh ping 30s
nickapp-redis redis:8-alpine (with --requirepass) internal redis-cli ping 30s

Volumes: mongodb_data, redis_data, ./uploads, ./nginx/nginx.conf, ./nginx/logs. Env: single root .env.

Warning

REDIS_PASSWORD MUST be set in the production .env before starting — otherwise the Redis container fails its healthcheck and dependents won't start.


4. Nginx configuration

The Nginx proxy at ./nginx/nginx.conf (mounted read-only) is responsible for:

  • Terminating internal HTTP (SSL handled by an external edge — CloudFlare / nginx-proxy / Caddy)
  • Routing /api/* and /socket.io/* to nickapp-backend:5001
  • Routing everything else to nickapp-frontend:8083
  • Serving /uploads/* directly from the shared volume (bypasses the Node process)
  • Standard gzip / compression / client_max_body_size (≥10 MB to match backend body limit)

Tip

Put the Nginx access log path on a tmpfs or rotate it aggressively — the container exposes ./nginx/logs so the host can manage retention.


5. Watchtower (auto-update)

Both nickapp-backend and nickapp-frontend carry the watchtower.enable=true label. Watchtower polls the container registry on its configured interval and re-pulls when the latest tag moves.

Release cycle:

  1. Developer pushes commits to a feature branch → merged into development.
  2. Manual Gitea workflow docker-build-simple.yml builds & pushes nickapp-backend:latest (and a versioned tag) to git.manko.yoga/manawenuz/escrow-backend.
  3. Within the next poll interval (default 5 min) Watchtower restarts the affected service.

Warning

Because Watchtower restarts only on tag change, sequential pushes are safe — but a broken build pushed to latest will roll out automatically. Keep dev and production tags separated, or pin production to a versioned tag.


6. Persistent storage

Volume What it stores Backup priority
mongodb_data All business data (users, requests, payments, chats, disputes...) Critical — daily dump
redis_data Cache, session, rate counters Low — losing it logs everyone out but no data loss
./uploads (host bind) Avatars, product images, dispute evidence, documents High — daily rsync
./nginx/logs Access / error logs Medium

See Backup & Recovery for the runbook.


7. CI / CD

Located at backend/.gitea/workflows/:

Workflow Trigger Output
docker-build-simple.yml manual Build → push backend image to registry (latest + version)
docker-build-dev.yml manual Dev image variant
docker-build-no-cache.yml manual Clean build (no GH-Actions cache)

Frontend at frontend/.gitea/workflows/:

Workflow Trigger Output
deploy.yml push to main/master, manual Runs scripts/deploy.sh (deploy via SSH)
devDeploy.yml manual Deploy to dev env

Single secret required: GITEATOKEN (Gitea PAT with write:package).

Full breakdown → CI-CD Pipeline.


8. Secrets

Never committed. Required in production .env:

  • JWT_SECRET, REFRESH_TOKEN_SECRET
  • MONGODB_URI, REDIS_PASSWORD
  • SHKEEPER_API_KEY, SHKEEPER_WEBHOOK_SECRET
  • SMTP_USER, SMTP_PASS
  • OPENAI_API_KEY
  • GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
  • NEXT_PUBLIC_ALCHEMY_API_KEY_* (frontend public envs — embedded at build)

Recommend storing host-side in an .env outside the repo, mounted via Compose. For multi-host: Vault / AWS SSM / GCP Secret Manager.


9. Observability

Signal Where
App logs container stdoutdocker logs nickapp-backend
Access logs ./nginx/logs
Frontend errors Sentry (@sentry/nextjs)
Backend errors Sentry (optional — add @sentry/node)
Healthchecks GET /health (backend) · GET / (frontend) · mongosh ping · redis-cli ping

See Monitoring for the full table of metrics & recommended alerts.


10. Networking

Direction Port Protocol Notes
Internet → Nginx 8083 HTTP SSL terminated upstream
Browser → Backend 5001 HTTP + WS via Nginx /api, /socket.io
Backend → MongoDB 27017 TCP Docker network
Backend → Redis 6379 TCP Docker network
Backend → SHKeeper 443 HTTPS External
Backend → SMTP 587 TLS External
Backend → OpenAI 443 HTTPS External
Browser → Blockchain RPC 443 HTTPS Alchemy URLs
Browser → WalletConnect 443 HTTPS Relay server

11. Hardening checklist

  • Non-root user inside every container (marketplace / nextjs) ✓ in Dockerfiles
  • Read-only Nginx config mount ✓
  • Redis requires password ✓
  • MongoDB has root credentials + bind to internal network only ✓
  • Rate limit enabled before public traffic ⚠ currently disabled
  • Refresh tokens rotated on use ⚠ partial
  • All public env values reviewed (no IS_DEVELOPMENT=true in prod build) ⚠
  • Watchtower scoped to specific repos
  • Sentry source-map upload at build time ✓ (frontend)

See Security Architecture for the deeper review.