Architecture
ZaneOps is a self-hosted PaaS platform designed to manage, deploy, and monitor services with docker swarm. Each service and app deployed on ZaneOps correspond one-to-one to a swarm service.
Components
Section titled “Components”🔌 Proxy (caddy)
Acts as the single entrypoint for all HTTP traffic. Routes API and service requests appropriately and serves static assets.
🧠 App (Backend + Frontend)
- Backend: Django + Django REST Framework
- Frontend: Single Page App (SPA) made with React Router
- Provides the user interface and the core API logic.
⚙️ Workers
- Run scheduled/background jobs.
- Use the same Docker image as the main app.
🧾 Log Collector (fluentd)
- Aggregates all logs from running services.
- Collects logs from proxy for HTTP logs.
🔍 Log Searcher (grafana/loki)
- Stores and indexes logs for querying.
⚡️ Cache (valkey)
- Used for caching and session storage.
🗃️ Database (PostgreSQL)
- Stores all persistent application data.
📬 Task Queue (temporal)
- Orchestrates background tasks and worker coordination.
Core Scenarios
Section titled “Core Scenarios”1. Deploy a New Service
Section titled “1. Deploy a New Service”Step-by-Step
Section titled “Step-by-Step”-
User Action:
PUT /deploys/XYZis sent to the proxy. -
Routing:
The proxy forwards it to the app backend. -
App Logic:
App creates a new deployment record in the database with statusPENDING. -
Task Queue:
App sends adeploy_service(XYZ)message to the task queue (Temporal). -
Worker Execution:
A worker picks up the task and runs the deployment logic (Docker service creation). -
Completion:
Worker notifies the task queue that the task is done. -
State Update:
Worker updates the Deployment state in the DB toHEALTHYorFAILED. -
Proxy Mapping:
The proxy mapsxyz.comto the new service, e.g.,service_XYZ:3000.
2. Deploy the same service again
Section titled “2. Deploy the same service again”Step-by-Step
Section titled “Step-by-Step”-
User Action:
PUT /deploys/XYZsent again. -
App Processing:
The app creates a new deployment version and sends a deploy task. -
Worker Logic:
- Stops (removes) the previous Docker service (v1).
- Starts a new one with the updated spec (v2).
-
State Update:
DB updated accordingly (HEALTHYorFAILED). -
Proxy Keeps Same Mapping:
xyz.comstill points toservice_XYZ, which now resolves to the new container.
3. Access a Running Service
Section titled “3. Access a Running Service”Step-by-Step
Section titled “Step-by-Step”-
User Request:
Browser makesGET xyz.com. -
Proxy Resolution:
Proxy resolves the domain to the correct internal service (Docker alias or internal hostname). -
Routing:
The request is forwarded to the running container. -
Response:
Container sends back the HTTP response via the proxy.
4. Logs Collection
Section titled “4. Logs Collection”Step-by-Step
Section titled “Step-by-Step”-
Logs Emitted:
Each service sends logs to Fluentd overstdout. -
Collector Buffering:
Fluentd waits ~5 seconds and tags/filters logs. -
Forward to App:
Logs are forwarded to the API/logs/ingest. -
App Preprocessing:
Enriches logs (adds metadata like service/deployment IDs). -
Send to Loki:
App sends structured logs to Loki.
5. Logs Search
Section titled “5. Logs Search”Step-by-Step
Section titled “Step-by-Step”-
User Request:
GET /search/logshits the proxy. -
Routing:
Proxy forwards to the app backend. -
Query Execution:
App translates filters and queries Loki. -
Return:
Logs are returned to the frontend (paginated, filtered, etc.).