Architecture
Static description of the AX-NEWS technical stack — no live metrics.
Request Flow
Browser / Client
→ Cloudflare (CDN + DDoS)
→ HAProxy (TLS termination, ax-lab05:443)
→ Nginx (vhost, static assets, rate limiting)
→ FastAPI / uvicorn (port 8000, 2 workers)
→ PostgreSQL 16 (local socket)
Static assets (CSS, JS, images) are served directly by Nginx from /opt/ax-news/frontend/ without hitting FastAPI. HTML pages go through FastAPI for per-request CSP nonce injection via Jinja2 templates.
Stack
| Layer | Technology | Role |
|---|---|---|
| Edge / CDN | Cloudflare | DDoS protection, global CDN, Proxy DNS |
| Load balancer | HAProxy | TLS termination, HTTP→HTTPS redirect |
| Web server | Nginx | Static files, reverse proxy, rate limiting (login: 5/min, API: 120/min) |
| Application | FastAPI + uvicorn | REST API, Jinja2 HTML rendering, background tasks |
| Database | PostgreSQL 16 | Articles, users, sessions, NLP metadata |
| RSS ingestion | FreshRSS (PHP 8.3) | 200+ RSS feeds aggregated at /news |
| Translation | Argos Translate | CJK/Korean titles translated to English — runs as a standalone systemd service to avoid OOM in uvicorn |
| Enrichment | Keyword analysis (Python) | Entity extraction, sentiment classification, country tagging — runs at sync time |
| Hosting | ax-lab05 VM (~3.8 GB RAM) | Single Linux VM, all services via systemd |
Data Flow — Article Lifecycle
- Ingestion: FreshRSS syncs feeds every 15 min → FastAPI upserts into
articlestable - Enrichment: Keyword analysis runs at sync time — extracts entities, sentiment, country code
- Translation: CJK/Korean titles translated by Argos standalone worker (every 10 min)
- Deduplication: Dedup worker runs every 6 hours to remove near-identical articles
- Image prefetch: OG image fetched nightly for articles missing thumbnails
- Purge: an optional weekly job (Monday 3 AM) deletes articles older than 30 days
Security Notes
This page is intentionally static and descriptive. It does not expose live system metrics (CPU, RAM, disk, hostname). A previous
/api/metrics endpoint was removed because it disclosed server internals without authentication.
- CSP with per-request nonce injected by FastAPI — no
unsafe-evalin practice - No cookies except session (httpOnly, SameSite=Lax)
- No localStorage / sessionStorage (privacy policy — zero client-side persistence)
- Public feed is unauthenticated read-only — write operations and admin actions require session
- Rate limiting at Nginx level for login and API endpoints
Source Code
The full source is available on GitHub: github.com/plkarin/ax-news (MIT license).