Self-hosting
Tiers, stack and operational notes
Tiers
- Hobbyist: a single SQLite file, local artifact storage — a plant on a laptop.
- Scalable: PostgreSQL, S3-compatible artifacts (bundled RustFS or a remote S3), the full compose stack.
The compose stack
docker compose up -d starts PostgreSQL, Rauthy, OpenObserve, RustFS, Valkey and
the PNeX server. Persistence off by default for caches; storage backends are
configurable per tier.
The same Compose stack runs in development and in production — on a laptop, a Raspberry Pi or a cloud VM. Development builds the PNeX image; production pulls a tagged release image instead. Images build on Wolfi (Chainguard) for a minimal footprint.
Kubernetes: a Helm chart deploys the same stack on a cluster — see Installation → Kubernetes.
TLS everywhere
An nginx edge terminates all TLS on a single origin, https://<your-domain>, for
browsers, the native apps (desktop and Android) and devices alike:
- Local mode (default): a private certificate authority is generated once and
the server certificate is renewed automatically. The default name is
<hostname>.local, published on the LAN by mDNS — name your Raspberry Pipnexand the platform lives athttps://pnex.local. Import the CA once on each client. - Public VM without a domain:
--domain sslip --tls cloudnames the server after its public IP (pnex-203-0-113-7.sslip.io) and gets a Let's Encrypt certificate — see Names and TLS. - Cloud mode: certificates from Let's Encrypt, renewed automatically. Ports 80 and 443 must be reachable from the internet.
Devices pin the certificate authority in their firmware. nginx was chosen because it honours small TLS records, which the ESP8266 needs.
Object storage
Firmware artifacts and media are stored in the database by default. For larger
installations, set STORAGE_BACKEND=s3 and point PNeX at any S3-compatible store:
the RustFS instance bundled in the compose stack, or a remote S3 service.
| Variable | Purpose |
|---|---|
PNEX_S3_ENDPOINT | Endpoint URL of the S3 service |
PNEX_S3_BUCKET | Bucket name |
PNEX_S3_REGION | Region (optional for most self-hosted stores) |
PNEX_S3_ACCESS_KEY / PNEX_S3_SECRET_KEY | Credentials — inject them from a secrets manager |
PNEX_S3_PATH_STYLE | true for path-style addressing (typical for self-hosted stores) |
Pick the backend at install time: there is no migration between the database and S3 backends.
Operational notes
- The server is a single static binary: backups are the database plus artifacts.
- Reverse proxy in front of the web app and the API; WebSocket upgrades must pass.
- Versions: the API contract is versioned and the web app gates itself on boot against an incompatible server (compatibility gate).


Firmware builds need network access only to fetch PlatformIO platform packages on first build; everything else is embedded in the server.

