Skip to content

Infrastructure & Deployment

The portfolio's deployment baseline is Docker Compose on a self-hosted IONOS VPS, fronted by nginx. ~75% of apps follow this pattern. The exceptions are a small set of static-export marketing sites and Tauri / Electron desktop apps that ship as binaries.

The baseline stack

For the typical app, docker-compose.yml defines:

nginx           (reverse proxy, port 80/443 → app)
app             (node:20-slim or php:8.2-fpm)
db              (postgres:15-alpine + pgvector or mysql:8.0)
redis           (redis:7-alpine, optional)
worker          (BullMQ / Celery / arq, optional)
minio           (object storage, on AI document apps)

External port range is 80888151 (per the user's local notes — careful not to collide). Internal services bind to 3000, 3001, 5432, 6379 inside the bridge network.


Docker

What it is. Containerization — package an app + its OS deps into an image, run it isolated.

Patterns universal across the portfolio: - Multi-stage builds. FROM node:20-slim AS builderFROM node:20-alpine AS runner. Cuts production image size 5–10×. - .dockerignore to exclude node_modules, .git, .env, build artifacts. - Health checks in docker-compose.yml: curl/wget /healthz for app services, SQL readiness probes for DBs. - Restart policy: unless-stopped (auto-restart on crash, stay down if explicitly stopped). - Volumes for DB data and MinIO. node_modules is typically NOT volume-mounted in prod (rebuilt on every image). - Custom bridge network per app — services find each other by service name, not IP.

Base images seen: - Node: node:20-slim, node:20-alpine. - Python: python:3.11-slim (Automotive, GoGreen-DOC-AI, GoGreen-SmartForms). - PHP: php:8.2-fpm (Maximus, AI-Wordpress, Voting). - Reverse proxy: nginx:alpine. - Databases: postgres:15-alpine, pgvector/pgvector:pg15 or pg16/pg17, mysql:8.0, mariadb:10.4. - Cache / queue: redis:7-alpine. - Storage: minio/minio.


nginx

What it is. Reverse proxy, web server, SSL terminator. Routes incoming requests by host or path to the right backend container.

Used in: ~25 apps as the docker-compose front door.

Common patterns: - Path-based routing for sub-path deploys (e.g. pawsc-explorer ships at /pawsc/ on a shared host). - WebSocket upgrade headers for Socket.IO / ws apps. - Static-asset caching with expires headers. - Let's Encrypt / Certbot for TLS — cron-renewed.

The user's nginx note (per global CLAUDE.md): Never use sed on nginx via SSH. Use scp'd Python scripts to edit nginx configs — the escaping issues are well-documented in their feedback_nginx_escaping.md memory.


Caddy / Traefik / Apache (not used)

Caddy and Traefik are popular nginx alternatives. Traefik shines with auto-discovery in Docker (labels-based config). The portfolio chose nginx for familiarity. Apache is only present inside WordPress containers.


IONOS VPS

The single production host: 74.208.129.33. SSH key auth as root. Locations of note (per user's global rules):

  • Nginx config: /etc/nginx/sites-available/gogreen-verify
  • WordPress: /var/www/html/Wordpress/
  • PHP 8.3-fpm, MariaDB, WP-CLI installed.

Process supervision is Docker, not systemd or PM2. restart: unless-stopped handles crash-recovery; reboots come back to a clean state because every service has a docker-compose up -d invocation.

TLS: Let's Encrypt via Certbot. Auto-renewed via cron.


Hosting alternatives present in the portfolio

Platform Used for
IONOS VPS ~35 apps (production)
Tauri binary AscendOne, ChoreAndMoreTracker, GoGreenMarketing, Jarvis_Rust_Tauri
Electron binary Ecom-Sales, FamilyChat, GogreenSellerAI, PolyMarketAI, Jarvis_Electron
Vercel / Netlify A handful of static-export sites may be there; not explicitly in docker-compose configs

No Kubernetes, no AWS ECS / Fargate, no Cloud Run. The portfolio explicitly stays at the Docker-Compose-on-VPS level — the team has decided not to introduce orchestration complexity until justified.


Build & dev tools

Tool Used
npm 17+ apps
pnpm FamilyChat, GoGreen-AI-Concierge (monorepos)
yarn 0 apps
bun OpenSentinel (runtime, not just package mgr)
Composer (PHP) Maximus, AI-Wordpress, Voting
pip / poetry / uv Automotive, DOC-AI, SmartForms (Python apps)
cargo ChoreAndMoreTracker (Rust), Jarvis_Rust_Tauri

No Turborepo, Nx, or Lerna. Two pnpm-workspaces monorepos. Most apps are single-repo single-package.

Make / Just / Taskfile. Not used. npm scripts (npm run start, npm run build, npm run deploy) handle task running.


Cloudflare / CDN

Status: referenced in user's notes ("possibly Cloudflare proxying") but no app config explicitly shows Cloudflare. CDN is generally handled at the domain-DNS layer rather than in app code.


Domain & DNS

Most likely: IONOS DNS (since the VPS is IONOS). No Cloudflare DNS, Route53, or third-party DNS configs surfaced in the audit.

The user's portfolio reference memory tracks a per-app domain-to-app mapping (see reference_portfolio.md and feedback_domain_mappings.md in their persistent memory).


Secrets management

Approach: .env files at the project root, gitignored. .env.example checked in as the schema. The master file API_Keys_and_Secrets_Master.md at the portfolio root is the source of truth for which keys belong to which app.

Not used: AWS Secrets Manager, HashiCorp Vault, Doppler, Infisical, 1Password Secrets Automation. Per the user's tooling preferences, .env + the master Markdown file is intentional.


Comparison alternatives (not used)

Pattern Notes
Kubernetes Heavy ops cost. The portfolio doesn't have multi-region or multi-cluster needs.
Serverless (Vercel Functions / Lambda / Cloud Run) Doesn't fit the always-on Postgres + Redis + queue worker model.
Render / Railway / Fly.io "PaaS-on-Docker." Self-hosted IONOS is cheaper at portfolio scale.
Docker Swarm Light-weight orchestration. Compose is enough.
Nomad Same.
Terraform / Ansible / Pulumi IaC. Manual deploy is the current model — feasible because there's only one production host.

Decision guide

New web app, going to production?       Dockerfile + docker-compose.yml + nginx + IONOS.
Need a TLS cert?                        Certbot, cron-renewed.
Need a CDN?                              Cloudflare in front of nginx.
Need scheduled jobs?                     BullMQ repeatable jobs (Node) or arq/Celery (Python). No cron container.
Static marketing site, no auth?         Next.js static export → nginx serves the /out dir.
Desktop app distribution?                Tauri (small) or Electron (familiar).
"Should we move to Kubernetes?"          Not until you're running multiple production hosts. Compose is fine.

What lives where (mental map)

74.208.129.33 (IONOS VPS)
├── nginx (host-level)
│   ├── /etc/nginx/sites-available/* (per-app vhost)
│   └── Let's Encrypt cron
├── /var/www/html/Wordpress/ (legacy WordPress)
└── /opt/apps/{appname}/  (per-app docker-compose stacks)
    ├── docker-compose.yml
    ├── .env
    └── data volumes (postgres, redis, minio)