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/
This commit is contained in:
2026-04-29 06:30:22 +00:00
parent 44c3a6c910
commit c766571b7d
11 changed files with 196 additions and 0 deletions

7
.gitignore vendored
View File

@@ -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/

40
docs/POSTGRESQL_TUNING.md Normal file
View File

@@ -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.<timestamp>`
## pg_hba Adjustment for Monitoring
Added Docker network access for postgres-exporter:
```
host nexus_autoparts postgres 172.17.0.0/16 trust
```

35
docs/SYSTEMD_SERVICES.md Normal file
View File

@@ -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
```

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

23
systemd/nexus-pos.service Normal file
View File

@@ -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

View File

@@ -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

17
systemd/nexus.service Normal file
View File

@@ -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