From c766571b7d6f1e88d69a185c3e9db7ac0059e5f5 Mon Sep 17 00:00:00 2001 From: consultoria-as Date: Wed, 29 Apr 2026 06:30:22 +0000 Subject: [PATCH] docs(infra): add PostgreSQL tuning and systemd service documentation - POSTGRESQL_TUNING.md: documents applied config (8GB shared_buffers, 64MB work_mem, 8GB max_wal_size, SSD params) - SYSTEMD_SERVICES.md: lists all production systemd services - systemd/: versioned copies of all .service and .timer files - .gitignore: ignore package-lock.json and backups/ --- .gitignore | 7 ++++++ docs/POSTGRESQL_TUNING.md | 40 ++++++++++++++++++++++++++++++++ docs/SYSTEMD_SERVICES.md | 35 ++++++++++++++++++++++++++++ systemd/nexus-cache-warm.service | 11 +++++++++ systemd/nexus-cache-warm.timer | 9 +++++++ systemd/nexus-celery.service | 19 +++++++++++++++ systemd/nexus-mv-refresh.service | 10 ++++++++ systemd/nexus-mv-refresh.timer | 9 +++++++ systemd/nexus-pos.service | 23 ++++++++++++++++++ systemd/nexus-quart.service | 16 +++++++++++++ systemd/nexus.service | 17 ++++++++++++++ 11 files changed, 196 insertions(+) create mode 100644 docs/POSTGRESQL_TUNING.md create mode 100644 docs/SYSTEMD_SERVICES.md create mode 100644 systemd/nexus-cache-warm.service create mode 100644 systemd/nexus-cache-warm.timer create mode 100644 systemd/nexus-celery.service create mode 100644 systemd/nexus-mv-refresh.service create mode 100644 systemd/nexus-mv-refresh.timer create mode 100644 systemd/nexus-pos.service create mode 100644 systemd/nexus-quart.service create mode 100644 systemd/nexus.service diff --git a/.gitignore b/.gitignore index dbb0a33..45a4bee 100644 --- a/.gitignore +++ b/.gitignore @@ -80,3 +80,10 @@ node_modules/ # Diagram images (served from static, too large for git) dashboard/static/diagrams/ + +# Playwright / Node +package-lock.json + +# Backups +backups/ + diff --git a/docs/POSTGRESQL_TUNING.md b/docs/POSTGRESQL_TUNING.md new file mode 100644 index 0000000..ccd14f2 --- /dev/null +++ b/docs/POSTGRESQL_TUNING.md @@ -0,0 +1,40 @@ +# PostgreSQL Tuning — Nexus Autoparts + +**Server:** 48 GB RAM, 8 cores, SSD (QEMU) +**Applied:** 2026-04-26 +**Requires restart:** Yes (done) + +## Configuration Changes + +File: `/etc/postgresql/17/main/postgresql.conf` + +| Parameter | Before | After | Rationale | +|-----------|--------|-------|-----------| +| `shared_buffers` | 128 MB | **8 GB** | ~25% of RAM for PostgreSQL buffer cache | +| `work_mem` | 4 MB | **64 MB** | Larger sorts/joins without disk spilling | +| `maintenance_work_mem` | 64 MB | **1 GB** | Faster VACUUM, CREATE INDEX, ALTER | +| `effective_cache_size` | 4 GB | **36 GB** | Planner knows OS cache is large | +| `max_wal_size` | 1 GB | **8 GB** | Fewer checkpoints under heavy write load | +| `checkpoint_completion_target` | 0.5 | **0.9** | Spread checkpoint I/O over more time | +| `wal_buffers` | - | **16 MB** | WAL buffer sizing | +| `random_page_cost` | 4.0 | **1.1** | SSD-appropriate random read cost | +| `effective_io_concurrency` | 1 | **200** | SSD can handle many concurrent requests | +| `max_connections` | 100 | **200** | Headroom for Celery, Quart, Dashboard, PgBouncer | + +## Verification + +```bash +sudo -u postgres psql -d nexus_autoparts -c "SHOW shared_buffers;" +``` + +## Backup + +A backup of the previous config is stored at: +`/etc/postgresql/17/main/postgresql.conf.backup.` + +## pg_hba Adjustment for Monitoring + +Added Docker network access for postgres-exporter: +``` +host nexus_autoparts postgres 172.17.0.0/16 trust +``` diff --git a/docs/SYSTEMD_SERVICES.md b/docs/SYSTEMD_SERVICES.md new file mode 100644 index 0000000..a620252 --- /dev/null +++ b/docs/SYSTEMD_SERVICES.md @@ -0,0 +1,35 @@ +# Systemd Services — Nexus Autoparts + +All production services are managed via systemd. Files are versioned in `systemd/`. + +## Services + +| Service | Description | Status | +|---------|-------------|--------| +| `nexus-pos.service` | Gunicorn POS (Flask), port 5001 | Active | +| `nexus.service` | Dashboard (Flask), port 5000 | Active | +| `nexus-quart.service` | Hypercorn async catalog, port 5002 | Active | +| `nexus-celery.service` | Celery worker (4 prefork) | Active | +| `nexus-mv-refresh.timer` | Daily MV refresh at 03:00 UTC | Active | +| `nexus-cache-warm.timer` | Daily Redis cache warming at 04:00 UTC | Active | + +## Commands + +```bash +# Reload all +systemctl daemon-reload + +# Restart POS +systemctl restart nexus-pos.service + +# View logs +journalctl -u nexus-pos.service -f +``` + +## Installation + +```bash +sudo cp systemd/*.service systemd/*.timer /etc/systemd/system/ +systemctl daemon-reload +systemctl enable --now nexus-pos.service nexus-cache-warm.timer +``` diff --git a/systemd/nexus-cache-warm.service b/systemd/nexus-cache-warm.service new file mode 100644 index 0000000..b7fc9e8 --- /dev/null +++ b/systemd/nexus-cache-warm.service @@ -0,0 +1,11 @@ +[Unit] +Description=Warm Redis cache for Nexus vehicle info +After=postgresql.service redis-server.service + +[Service] +Type=oneshot +User=postgres +WorkingDirectory=/home/Autopartes +ExecStart=/usr/bin/python3 /home/Autopartes/scripts/warm_vehicle_cache.py --batch-size 10000 --ttl 7200 +StandardOutput=append:/var/log/nexus-pos/cache_warm.log +StandardError=append:/var/log/nexus-pos/cache_warm.log diff --git a/systemd/nexus-cache-warm.timer b/systemd/nexus-cache-warm.timer new file mode 100644 index 0000000..24e7837 --- /dev/null +++ b/systemd/nexus-cache-warm.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Daily Redis cache warming at 04:00 UTC (1h after MV refresh) + +[Timer] +OnCalendar=*-*-* 04:00:00 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/systemd/nexus-celery.service b/systemd/nexus-celery.service new file mode 100644 index 0000000..7ac4faf --- /dev/null +++ b/systemd/nexus-celery.service @@ -0,0 +1,19 @@ +[Unit] +Description=Nexus POS Celery Worker +After=network.target postgresql.service redis.service + +[Service] +Type=simple +User=postgres +WorkingDirectory=/home/Autopartes/pos +Environment=MASTER_DB_URL=postgresql://postgres@/nexus_autoparts +Environment=REDIS_URL=redis://localhost:6379/0 +Environment=PYTHONPATH=/home/Autopartes/pos +ExecStart=/usr/bin/python3 -m celery -A celery_app worker --loglevel=info --concurrency=4 -n nexus-worker@%h +Restart=on-failure +RestartSec=10 +StandardOutput=append:/var/log/nexus-pos/celery.log +StandardError=append:/var/log/nexus-pos/celery.log + +[Install] +WantedBy=multi-user.target diff --git a/systemd/nexus-mv-refresh.service b/systemd/nexus-mv-refresh.service new file mode 100644 index 0000000..a1052c6 --- /dev/null +++ b/systemd/nexus-mv-refresh.service @@ -0,0 +1,10 @@ +[Unit] +Description=Refresh Nexus part_vehicle_preview materialized view +After=postgresql.service + +[Service] +Type=oneshot +User=postgres +ExecStart=/usr/bin/python3 /home/Autopartes/scripts/refresh_part_vehicle_preview.py +StandardOutput=append:/var/log/nexus-pos/mv_refresh.log +StandardError=append:/var/log/nexus-pos/mv_refresh.log diff --git a/systemd/nexus-mv-refresh.timer b/systemd/nexus-mv-refresh.timer new file mode 100644 index 0000000..2d0d854 --- /dev/null +++ b/systemd/nexus-mv-refresh.timer @@ -0,0 +1,9 @@ +[Unit] +Description=Daily refresh of part_vehicle_preview materialized view at 03:00 + +[Timer] +OnCalendar=*-*-* 03:00:00 +Persistent=true + +[Install] +WantedBy=timers.target diff --git a/systemd/nexus-pos.service b/systemd/nexus-pos.service new file mode 100644 index 0000000..96c984c --- /dev/null +++ b/systemd/nexus-pos.service @@ -0,0 +1,23 @@ +[Unit] +Description=Nexus POS (Gunicorn) +After=network.target postgresql.service redis-server.service + +[Service] +Type=simple +User=root +WorkingDirectory=/home/Autopartes/pos +ExecStart=/usr/local/bin/gunicorn -c gunicorn.conf.py "app:create_app()" +Restart=always +RestartSec=5 +Environment=PYTHONUNBUFFERED=1 +Environment=PYTHONPATH=/home/Autopartes/pos +Environment=MASTER_DB_URL=postgresql://postgres@/nexus_autoparts +Environment=TENANT_DB_URL_TEMPLATE=postgresql://postgres@/nexus_autoparts +Environment=POS_JWT_SECRET=nexus-pos-jwt-secret-12345678901234567890123456789012 +Environment=REDIS_URL=redis://localhost:6379/0 +Environment=REDIS_ENABLED=true +Environment=MEILI_URL=http://localhost:7700 +Environment=MEILI_ENABLED=true + +[Install] +WantedBy=multi-user.target diff --git a/systemd/nexus-quart.service b/systemd/nexus-quart.service new file mode 100644 index 0000000..75b0695 --- /dev/null +++ b/systemd/nexus-quart.service @@ -0,0 +1,16 @@ +[Unit] +Description=Nexus Quart Async Catalog (hypercorn) +After=network.target postgresql.service + +[Service] +Type=simple +User=root +WorkingDirectory=/home/Autopartes/pos +ExecStart=/usr/local/bin/hypercorn async_catalog:app --bind 0.0.0.0:5002 +Restart=always +RestartSec=5 +Environment=PYTHONUNBUFFERED=1 +Environment=MASTER_DB_URL=postgresql://postgres@localhost/nexus_autoparts + +[Install] +WantedBy=multi-user.target diff --git a/systemd/nexus.service b/systemd/nexus.service new file mode 100644 index 0000000..c712be1 --- /dev/null +++ b/systemd/nexus.service @@ -0,0 +1,17 @@ +[Unit] +Description=Nexus Autoparts Dashboard +After=network.target postgresql.service + +[Service] +Type=simple +User=root +WorkingDirectory=/home/Autopartes/dashboard +ExecStart=/usr/bin/python3 server.py +Restart=always +RestartSec=5 +Environment=PYTHONUNBUFFERED=1 +Environment=DATABASE_URL=postgresql://postgres@localhost/nexus_autoparts +Environment=JWT_SECRET=nexus-dashboard-jwt-secret-12345678901234567890123456789012 + +[Install] +WantedBy=multi-user.target