Early beta (0.1.0), not yet for critical processes. See the roadmap
PNeX logo

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 Pi pnex and the platform lives at https://pnex.local. Import the CA once on each client.
  • Public VM without a domain: --domain sslip --tls cloud names 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.

VariablePurpose
PNEX_S3_ENDPOINTEndpoint URL of the S3 service
PNEX_S3_BUCKETBucket name
PNEX_S3_REGIONRegion (optional for most self-hosted stores)
PNEX_S3_ACCESS_KEY / PNEX_S3_SECRET_KEYCredentials — inject them from a secrets manager
PNEX_S3_PATH_STYLEtrue 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).

Platform status page

Data retention page

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

On this page