mirror of
https://github.com/ipnet-mesh/meshcore-hub.git
synced 2026-10-31 04:02:03 +01:00
116 lines
5.7 KiB
Markdown
116 lines
5.7 KiB
Markdown
# Deployment
|
||
|
||
This document covers production deployments of MeshCore Hub: reverse-proxy setup, multi-instance routing, API scaling, and the optional Redis response cache. For the full environment-variable reference, see [configuration.md](configuration.md).
|
||
|
||
## Production Setup
|
||
|
||
For production deployments, use `docker-compose.prod.yml` which connects services to an external proxy network. No ports are exposed directly — all traffic goes through your reverse proxy.
|
||
|
||
**Prerequisites:**
|
||
|
||
1. A reverse proxy (Nginx Proxy Manager, Caddy, Traefik, etc.)
|
||
2. Docker network for proxy communication
|
||
|
||
**Steps:**
|
||
|
||
```bash
|
||
# Create proxy network (once)
|
||
docker network create proxy-net
|
||
|
||
# Download compose files and config
|
||
mkdir meshcore-hub && cd meshcore-hub
|
||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/docker-compose.yml
|
||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/docker-compose.prod.yml
|
||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/.env.example
|
||
cp .env.example .env
|
||
# Edit .env: set COMPOSE_PROJECT_NAME, MQTT credentials, API keys, etc.
|
||
|
||
# Start core services
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml --profile core up -d
|
||
|
||
# Or include local MQTT broker
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml --profile mqtt --profile core up -d
|
||
|
||
# Or include packet capture on the same host
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml --profile mqtt --profile core --profile observer up -d
|
||
```
|
||
|
||
Configure your reverse proxy to forward to the containers:
|
||
|
||
| Service | Container | Port | Path |
|
||
| -------------- | ----------------------------- | ---- | -------------------------------- |
|
||
| Web Dashboard | `{COMPOSE_PROJECT_NAME}-web` | 8080 | `/` |
|
||
| API | `{COMPOSE_PROJECT_NAME}-api` | 8000 | `/api`, `/metrics`, `/health` |
|
||
| MQTT WebSocket | `{COMPOSE_PROJECT_NAME}-mqtt` | 1883 | `/` (only if using local broker) |
|
||
|
||
> **Important:** Do not host under a subpath (e.g., `/meshcore`). Proxy at `/`.
|
||
|
||
### Reverse Proxy
|
||
|
||
MeshCore Hub is designed to run behind a reverse proxy in production. A Traefik override file is provided with pre-configured labels:
|
||
|
||
```bash
|
||
# Download the Traefik override
|
||
wget https://raw.githubusercontent.com/ipnet-mesh/meshcore-hub/refs/heads/main/docker-compose.traefik.yml
|
||
|
||
# Set your domain in .env
|
||
echo "TRAEFIK_DOMAIN=meshcore.example.com" >> .env
|
||
|
||
# Start with Traefik labels
|
||
docker compose -f docker-compose.yml -f docker-compose.prod.yml -f docker-compose.traefik.yml --profile core up -d
|
||
```
|
||
|
||
This routes the web dashboard and API to `TRAEFIK_DOMAIN` with automatic TLS.
|
||
|
||
### Multi-Instance Deployments
|
||
|
||
To run multiple Hub instances (e.g., production + staging) on the same Docker host, set `TRAEFIK_PRIORITY` to control which router wins when domains overlap. Higher values are matched first:
|
||
|
||
```bash
|
||
# Production (.env)
|
||
COMPOSE_PROJECT_NAME=hub
|
||
TRAEFIK_DOMAIN=example.com
|
||
TRAEFIK_PRIORITY=10
|
||
|
||
# Staging (.env) — separate directory with its own config
|
||
COMPOSE_PROJECT_NAME=hub-beta
|
||
TRAEFIK_DOMAIN=beta.example.com
|
||
TRAEFIK_PRIORITY=20
|
||
```
|
||
|
||
This ensures `beta.example.com` (priority 20) is matched before the production wildcard `*.example.com` (priority 10). For other services on the same network (e.g., an MQTT broker at `mqtt.example.com`), use an even higher priority (e.g., 30).
|
||
|
||
> **Shared Postgres cluster:** the setup above runs each instance in its own directory with its own volumes (bundled Postgres container per instance). To instead run several instances (e.g. `prod` + `stg`) against **one** PostgreSQL cluster — isolated via a per-instance schema (`search_path`) — see [database.md](database.md#schema-per-instance-search_path).
|
||
|
||
## Scaling the API
|
||
|
||
The API is read-mostly and holds no per-process state — the response cache lives in Redis and authentication is stateless — so it scales across multiple worker processes. Set `API_WORKERS` to run more than one worker in a single container:
|
||
|
||
```bash
|
||
# .env
|
||
API_WORKERS=4
|
||
```
|
||
|
||
Each worker is an independent process sharing one listening socket, so the kernel balances connections across them and CPU-bound work (JSON serialisation, validation) spreads over multiple cores. Workers read their configuration from **environment variables** (CLI flags are not propagated to forked workers), which is how Docker Compose already supplies config. Enabling Redis (`REDIS_ENABLED=true`) is recommended so all workers share one cache.
|
||
|
||
Pick a worker count around the number of CPU cores available to the container; start with `2`–`4` and measure under realistic load. Workers all talk to the same PostgreSQL database (the bundled container or an external instance — see [database.md](database.md)), so scaling extends across hosts unchanged.
|
||
|
||
> Prefer `API_WORKERS` over running multiple `api` containers (`--scale api=N`): the `api` service uses a fixed `container_name`, and one process-managed container per stack keeps logs, health checks, and monitoring simple.
|
||
|
||
## Redis Caching
|
||
|
||
Optional Redis-backed caching for API responses. When disabled or unavailable, the API queries the database directly.
|
||
|
||
**Docker:** Redis is included in the `cache` profile. Disabled by default — set `REDIS_ENABLED=true` to enable.
|
||
|
||
```bash
|
||
docker compose --profile cache up # Start with bundled Redis
|
||
docker compose --profile core up # Start without Redis
|
||
```
|
||
|
||
**Bare-metal:** Install Redis separately, then set `REDIS_ENABLED=true` and `REDIS_HOST=localhost`.
|
||
|
||
**Multi-instance:** Use different `REDIS_KEY_PREFIX` values per instance to share one Redis without key collisions.
|
||
|
||
For the full list of `REDIS_*` environment variables, see [configuration.md → Caching](configuration.md#caching).
|