Architecture
Diagram
Domain Architecture
| Subdomain | Service | Hosting |
|---|---|---|
manga-db.org |
Frontend (Nuxt SSR) | Cloudflare Pages |
api.manga-db.org |
Backend API | Docker → Nginx → api:4545 |
io.manga-db.org |
File service | Docker → Nginx → io:4546 |
cdn.manga-db.org |
Image CDN | Docker → Nginx → cdn:5555 |
status.manga-db.org |
Status page | External monitoring |
| phpMyAdmin | DB admin UI | SSH tunnel → localhost:8080 (not public) |
Technology Stack Overview
Maintenance Worker
A Cloudflare Worker sits between the user and the frontend to handle maintenance mode.
Role:
- Intercepts user requests to the frontend
- Can serve a maintenance page or forward requests to the frontend
- Allows toggling maintenance mode without redeploying the frontend
Frontend
The frontend is built using Nuxt and runs on Cloudflare Pages with SSR via Cloudflare Workers.
- Framework: Nuxt
4.1.1 - Server Engine: Nitro
2.12.5withcloudflare-pagespreset - Rendering: Server-side rendering (SSR) for SEO and Open Graph tags
- Role:
- Renders the user-facing application with SSR
- Communicates with backend services over HTTPS
- Requests media and assets from the CDN service
Deployment Zones
| Zone | Git Branch | Purpose |
|---|---|---|
| prod-zone | main |
Production deployment |
| dev-zone | development |
Development/staging deployment |
Backend Services (Docker)
All backend services run as Docker containers on a virtual server, orchestrated by Docker Compose with an Nginx reverse proxy for SSL termination.
- Runtime: Node.js
16(LTS) - Container orchestration: Docker Compose
- Reverse proxy: Nginx (Alpine) with Cloudflare origin certificates
- Services:
| Container | Entry Point | Port | Purpose |
|---|---|---|---|
api |
node server.js |
4545 | REST API |
io |
node server.js --is-file-service |
4546 | File upload/serving |
cdn |
node image-cdn.js |
5555 | Image delivery + caching |
mariadb |
— | 3306 | Database |
phpmyadmin |
— | 80 | Database admin UI |
nginx |
— | 80, 443 | Reverse proxy + SSL |
The api, io, and cdn containers use the same Docker image (mangalib-backend) with different commands.
Rate Limiting
The API applies rate limiting via express-rate-limit to protect against abuse:
| Limiter | Scope | Limit |
|---|---|---|
| General | All routes | 200 requests / minute per IP |
| Login | POST /auth/login |
10 attempts / 15 min per IP |
| Register | POST /auth/register |
10 attempts / 1 hour per IP |
Limits are configurable via environment variables (RATE_LIMIT_GENERAL). The server is configured with trust proxy: 1 so client IPs are correctly read from the X-Forwarded-For header set by Cloudflare.
phpMyAdmin
phpMyAdmin is not publicly exposed. It is bound to 127.0.0.1:8080 inside the Docker network and accessible only via SSH tunnel:
ssh -L 8080:localhost:8080 user@server
# Then open http://localhost:8080 in your browser
Status Page
The system includes a status page (status.manga-db.org) for monitoring.
Role:
- Monitors the health and uptime of all services
- Provides visibility into the frontend, backend, IO, and CDN services
Database
The system uses MariaDB as its relational database.
- Database Engine: MariaDB
10.4 - Storage: Docker named volume (
db_data), persists across container restarts - Usage:
- Stores application data and metadata
- Accessed by the API, IO, and CDN containers
Technology Relationships
- The Maintenance Worker intercepts user requests and forwards them to the frontend when the site is operational
- The Nuxt frontend runs SSR on Cloudflare Workers and communicates with backend Docker services over HTTPS
- Media and file requests are served directly by the Docker CDN container (
cdn.manga-db.org), which caches images in-memory - Docker containers share a compose network and access MariaDB via the internal
mariadbhostname - Nginx handles SSL termination using Cloudflare origin certificates and routes external traffic to the correct container
- The media directory is bind-mounted from the host filesystem and shared between the
api,io, andcdncontainers