feat: add NetBox Cloudron package (Infrastructure) [#648]

Official-image wrapper of netboxcommunity/netbox v4.6.10
(netbox-docker 5.0.2, Granian), digest-pinned. OIDC via
python-social-auth wired to the platform provider; RQ worker
backgrounded behind a web-port gate; addon waits cover the 30s
upstream DB timeout. Full-stack verified: migrations, Granian,
worker, login page + SSO button. 16/~57.

Detail + verification: https://projects.knownelement.com/issues/648#note-4976
This commit is contained in:
2026-09-06 06:26:54 -05:00
parent ee5344f5a5
commit cead1523ad
11 changed files with 392 additions and 14 deletions
@@ -0,0 +1,67 @@
# NetBox — Cloudron Package
[NetBox](https://github.com/netbox-community/netbox) v4.6.10 — open-source
IPAM/DCIM: IP addresses, prefixes, VLANs, sites, racks, devices, circuits,
virtualization, tenancy, REST + GraphQL APIs. Packaged as an
**official-image wrapper** around `netboxcommunity/netbox:v4.6.10`
(built from netbox-docker 5.0.2, served by Granian on :8080), digest-pinned.
## Authentication (auth gate: ✅ OIDC preferred)
NetBox 4.6 authenticates via **python-social-auth** with no legacy
`SOCIAL_AUTH_TYPE` involved:
- `REMOTE_AUTH_BACKEND = social_core.backends.open_id_connect.OpenIdConnectAuth`
- `SOCIAL_AUTH_OIDC_OIDC_ENDPOINT / KEY / SECRET` ← wired by `start.sh`
from the Cloudron platform OIDC provider (`CLOUDRON_OIDC_*`,
manifestVersion 2), scopes `openid profile email`.
Two consequences that matter on first boot:
1. **SSO-registered users are created without privileges.** An admin must
exist first — create it from the Cloudron **terminal**:
```sh
cd /opt/netbox/netbox
python3 manage.py createsuperuser
```
Then log in on `/login/` with the local form (it stays available
alongside the SSO button) and grant groups/permissions as needed.
2. The platform OIDC client must register the standard redirect:
`https://<app-domain>/complete/oidc/` (the Cloudron provider handles
this when the app is installed).
## Runtime layout
| Concern | How |
|---------|-----|
| Database | Cloudron `postgresql` addon (PG 16 ≥ NetBox 4.6's PG 14 floor; PG 15+ required from 4.7) |
| Cache + tasks | Cloudron `redis` addon — one instance, two logical DBs (tasks=0, caching=1, upstream convention) |
| Migrations | Run automatically by the upstream `docker-entrypoint.sh` (waits for PostgreSQL first) |
| RQ worker | Backgrounded by `start.sh`, started only after the web port answers (i.e. post-migration) — webhooks, scripts, reports, scheduled/housekeeping jobs |
| Persistence | `/app/data` (localstorage): `media/` (attachments), `reports/`, `scripts/` (custom code), `.secret_key` |
| SECRET_KEY | Generated once (64 hex chars), persisted; rotating it invalidates sessions |
| First boot | Allow up to ~10-15 min — `migrate` + `reindex --lazy` run before Granian binds :8080 (observed: ~24 min on a 3x-oversubscribed dev box, minutes on an idle host; subsequent boots are fast) |
## Operator knobs (`.env.example`)
| Variable | Default | Purpose |
|----------|---------|---------|
| `NETBOX_TIME_ZONE` | `UTC` | Django `TIME_ZONE` |
| `NETBOX_GRANIAN_WORKERS` | `4` | Web workers (lower on small installs) |
| `NETBOX_METRICS_ENABLED` | `false` | Prometheus endpoint at `/metrics` |
## Upgrades
The image is pinned by tag **and** digest in the `Dockerfile`. To upgrade,
bump both (verify the new amd64 digest with
`docker manifest inspect netboxcommunity/netbox:<tag>`) and rebuild —
migrations run automatically on first boot.
## Package pattern
Official-image wrapper + `start.sh` env mapping — see the repo
`JOURNAL.md` NetBox section for the full write-up (worker-gating trick,
build-time persistence symlinks, OIDC wiring).