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:
+94
-1
@@ -4,7 +4,7 @@
|
||||
**Project**: TSYSDevStack-SupportStack-Cloudron
|
||||
**Goal**: Package ~57 applications for Cloudron PaaS platform
|
||||
**Start Date**: 2025-01-24
|
||||
**Current Status**: 15/~57 packages completed (~26%)
|
||||
**Current Status**: 16/~57 packages completed (~28%)
|
||||
|
||||
## Completed Packages
|
||||
|
||||
@@ -1211,6 +1211,99 @@ IdP if the directory path disappoints.
|
||||
|
||||
---
|
||||
|
||||
### 16. NetBox (Infrastructure) ✅
|
||||
**Date**: 2026-09-06
|
||||
**Application**: NetBox — open-source IPAM/DCIM (IP addresses, prefixes,
|
||||
VLANs, sites, racks, devices, circuits, virtualization, REST + GraphQL
|
||||
APIs). Upstream: https://github.com/netbox-community/netbox
|
||||
(Apache-2.0), v4.6.10. First package in the workspace verified with a
|
||||
**full-stack local test** (ephemeral PG16 + Redis 7 → migrations →
|
||||
Granian bind → RQ worker → login page 200 + OIDC button).
|
||||
|
||||
**Ticket**: [#648](https://projects.knownelement.com/issues/648)
|
||||
|
||||
**Pattern**: official-image wrapper. NetBox itself has no Docker
|
||||
tooling — images come from the separate netbox-docker repo; v4.6.10 is
|
||||
built from netbox-docker **5.0.2** (beware stale docs claiming 3.x:
|
||||
3.4.2 was the last nginx-unit release; 4.0+ serves via **Granian** on
|
||||
:8080). The image's configuration is env-driven
|
||||
(`DB_*`, `REDIS[_CACHE]_*`, `SECRET_KEY`, `ALLOWED_HOSTS`,
|
||||
`CSRF_TRUSTED_ORIGINS`, `REMOTE_AUTH_BACKEND`, `SOCIAL_AUTH_OIDC_*`),
|
||||
so no config-file generation is needed — start.sh only maps Cloudron
|
||||
env onto it.
|
||||
|
||||
**Auth gate verdict**: ✅ OIDC preferred. NetBox 4.6 uses
|
||||
python-social-auth directly; there is NO `SOCIAL_AUTH_TYPE` (legacy
|
||||
netbox-docker 1.x/2.x mechanism). Minimum viable OIDC:
|
||||
`REMOTE_AUTH_BACKEND='social_core.backends.open_id_connect.OpenIdConnectAuth'`
|
||||
+ `SOCIAL_AUTH_OIDC_{OIDC_ENDPOINT,KEY,SECRET}` — wired from
|
||||
`CLOUDRON_OIDC_*`, with the issuer normalized to a trailing slash
|
||||
(social-core discovery requirement). Local Django login stays available
|
||||
for admin bootstrap (`manage.py createsuperuser` via the Cloudron
|
||||
terminal); SSO users register WITHOUT privileges.
|
||||
|
||||
**Key decisions**:
|
||||
|
||||
- **One-container problem**: upstream compose runs the RQ worker as a
|
||||
separate service; Cloudron is one container per app. start.sh
|
||||
backgrounds `manage.py rqworker` behind a gate that waits for
|
||||
127.0.0.1:8080 to answer — Granian binding is the signal that
|
||||
docker-entrypoint.sh finished migrating, so the worker never races
|
||||
the schema. When Granian exits, the container dies and takes the
|
||||
worker with it.
|
||||
- **Addon waits BEFORE the entrypoint**: netbox-docker's own DB wait is
|
||||
only `DB_WAIT_TIMEOUT=30s` — too tight against a cold Cloudron
|
||||
postgres addon. start.sh does the repo-standard bash `/dev/tcp` wait
|
||||
for PostgreSQL AND Redis first (same pattern as ChirpStack/eLabFTW).
|
||||
- **Persistence via build-time symlinks**: the container runs as
|
||||
unprivileged `netbox` (uid 999, gid 0), so `/opt/netbox/netbox/
|
||||
{media,reports,scripts}` are replaced by symlinks into `/app/data`
|
||||
at BUILD time (root), not in start.sh.
|
||||
- **One Redis instance, two logical DBs**: tasks=0, caching=1
|
||||
(upstream convention; Cloudron's single redis addon suffices).
|
||||
- **SKIP_SUPERUSER=true**: no baked-in admin password; README covers
|
||||
`createsuperuser` via the terminal (mirrors the ChirpStack bootstrap
|
||||
story). `SECRET_KEY` generated as 64 hex chars (NetBox enforces
|
||||
>= 50), persisted under /app/data.
|
||||
- **PG floor**: 4.6 requires PostgreSQL 14+ (15+ from 4.7) — the
|
||||
Cloudron postgresql addon satisfies it.
|
||||
|
||||
**Verification** (the deepest in the workspace so far):
|
||||
|
||||
- `docker build --cgroup-parent ukrrs-batch.slice` green (image
|
||||
pulled by digest, ~1GB).
|
||||
- No-addons smoke: secret generated, entrypoint reached its DB wait —
|
||||
i.e. Django configuration parsed cleanly.
|
||||
- Full-stack test on a scratch docker network: ephemeral postgres:16
|
||||
+ redis:7 (requirepass), mapped through the same `CLOUDRON_*` env
|
||||
the platform injects. Results: all ~230 migrations applied; config
|
||||
banner confirmed every `/etc/netbox/config/*.py` loaded; Granian
|
||||
`[INFO] Listening at: http://:::8080`; worker gate fired ("web port
|
||||
is up" → RQ `Listening on high, default, low`); `GET /login/` = 200
|
||||
with the SSO button linking `/oauth/login/oidc/` — the OIDC backend
|
||||
is registered. (A `Host: 127.0.0.1` curl returns 400 — ALLOWED_HOSTS
|
||||
working as designed; the Cloudron proxy sends the real domain.)
|
||||
- First boot took ~24 min under a load-19 contended dev box (migrate
|
||||
~15 min + reindex); minutes on an idle host — noted in the README.
|
||||
|
||||
**Files Created**:
|
||||
|
||||
- Dockerfile (official-image wrapper, tag+amd64-manifest-digest
|
||||
pinned, build-time persistence symlinks, tini ENTRYPOINT preserved)
|
||||
- CloudronManifest.json (manifestVersion 2, port 8080, healthCheckPath
|
||||
/login/, localstorage + postgresql + redis, memoryLimit 2048)
|
||||
- start.sh (secret persistence, env mapping, OIDC wiring, addon waits,
|
||||
gated RQ worker, entrypoint handoff) — committed executable
|
||||
- README.md (auth story, admin bootstrap, runtime layout, knobs)
|
||||
- CHANGELOG.md
|
||||
- .env.example (TIME_ZONE / GRANIAN_WORKERS / METRICS_ENABLED)
|
||||
- .dockerignore (excludes the cloned repo/ from the build context)
|
||||
- logo.png (from upstream netbox/project-static/img/netbox_touch-icon-180.png)
|
||||
|
||||
**Commit**: `feat: add NetBox Cloudron package (Infrastructure) [#648]`
|
||||
|
||||
---
|
||||
|
||||
## Packaging Pattern: Download Pre-Compiled Binaries
|
||||
|
||||
### When to Use
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
repo
|
||||
@@ -0,0 +1,11 @@
|
||||
# NetBox operator knobs (all optional; defaults shown)
|
||||
# Copy values into the Cloudron app's custom env config as needed.
|
||||
|
||||
# Django TIME_ZONE (IANA name)
|
||||
NETBOX_TIME_ZONE=UTC
|
||||
|
||||
# Granian web workers (default 4; lower on small installs)
|
||||
NETBOX_GRANIAN_WORKERS=4
|
||||
|
||||
# Expose Prometheus metrics at /metrics
|
||||
NETBOX_METRICS_ENABLED=false
|
||||
@@ -0,0 +1,13 @@
|
||||
# Changelog — NetBox Cloudron Package
|
||||
|
||||
## 1.0.0 — 2026-09-06
|
||||
|
||||
- Initial package: NetBox 4.6.10 (netboxcommunity/netbox v4.6.10, from
|
||||
netbox-docker 5.0.2), digest-pinned amd64 manifest
|
||||
`sha256:5ee780bd…`
|
||||
- Official-image wrapper; Granian web on :8080, RQ worker backgrounded by
|
||||
start.sh after migrations complete
|
||||
- postgresql + redis + localstorage addons; tasks DB 0 / caching DB 1
|
||||
- Platform OIDC wired via `REMOTE_AUTH_BACKEND` (OpenIdConnectAuth) +
|
||||
`SOCIAL_AUTH_OIDC_*`; local Django login retained for admin bootstrap
|
||||
- Persistence: media / reports / scripts / .secret_key under /app/data
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"manifestVersion": 2,
|
||||
"type": "app",
|
||||
"id": "io.cloudron.netbox",
|
||||
"title": "NetBox",
|
||||
"description": "Open-source IPAM and DCIM web application: IP address and prefix management, VLANs, circuits, racks, devices, virtualization, tenancy, plus REST and GraphQL APIs. PostgreSQL stores all state; Redis backs caching and background jobs (webhooks, scripts, reports, scheduled tasks). SSO via the Cloudron OIDC provider; local Django login remains available for admin bootstrap.",
|
||||
"author": "NetBox Community / NetBox-Docker contributors",
|
||||
"website": "https://netbox.readthedocs.io/",
|
||||
"contactEmail": "cloudron@tsys.dev",
|
||||
"tagline": "IP address management (IPAM) and data center infrastructure management (DCIM)",
|
||||
"version": "4.6.10",
|
||||
"healthCheckPath": "/login/",
|
||||
"httpPort": 8080,
|
||||
"memoryLimit": 2048,
|
||||
"addons": {
|
||||
"localstorage": {},
|
||||
"postgresql": {},
|
||||
"redis": {}
|
||||
},
|
||||
"mediaLinks": [],
|
||||
"changelog": "Initial Cloudron package for NetBox 4.6.10 (official-image wrapper of netboxcommunity/netbox v4.6.10, built from netbox-docker 5.0.2, digest pinned). start.sh maps the Cloudron postgresql/redis addons and the platform OIDC provider onto the image's env-driven configuration, persists the Django SECRET_KEY under /app/data, rebinds media/reports/scripts into localstorage, and backgrounds the RQ worker (gated on the web port so migrations finish first). First admin is created via the Cloudron terminal (manage.py createsuperuser); SSO users register without privileges.",
|
||||
"icon": "file://logo.png"
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
# NetBox Cloudron Package
|
||||
#
|
||||
# NetBox is an open-source IPAM / DCIM web application (Django): circuits,
|
||||
# devices, racks, IP address management, prefixes, VLANs, virtualization,
|
||||
# with a REST + GraphQL API. PostgreSQL for storage, Redis for caching and
|
||||
# background tasks (RQ webhooks/scripts/jobs).
|
||||
#
|
||||
# Upstream: https://github.com/netbox-community/netbox (Apache-2.0), v4.6.10
|
||||
# - Built/published by the separate netbox-docker repo; v4.6.10 images
|
||||
# come from netbox-docker 5.0.2 (tag alias v4.6.10-5.0.2, pushed
|
||||
# 2026-09-02). 5.x serves HTTP via Granian on port 8080 (nginx-unit is
|
||||
# gone since 4.0), runs as user netbox (uid 999, gid 0), and the
|
||||
# default container is WEB-ONLY: upstream compose runs the RQ worker
|
||||
# as a separate service. Cloudron is one-container-per-app, so
|
||||
# start.sh backgrounds `manage.py rqworker` (gated on the web port so
|
||||
# it only starts once the entrypoint's migrations have finished).
|
||||
# - The image configuration is env-driven (netbox-docker
|
||||
# configuration/configuration.py): DB_*, REDIS[_CACHE]_*, SECRET_KEY,
|
||||
# ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, REMOTE_AUTH_BACKEND +
|
||||
# SOCIAL_AUTH_OIDC_* all map straight onto Cloudron addon/platform env.
|
||||
# - docker-entrypoint.sh waits for the DB, migrates, and creates the
|
||||
# superuser unless SKIP_SUPERUSER=true (our default; the README covers
|
||||
# creating the admin via the Cloudron terminal).
|
||||
#
|
||||
# Authentication: NATIVE OIDC (preferred). NetBox 4.6 uses python-social-
|
||||
# auth directly: REMOTE_AUTH_BACKEND=OpenIdConnectAuth + the
|
||||
# SOCIAL_AUTH_OIDC_{OIDC_ENDPOINT,KEY,SECRET} trio, wired in start.sh from
|
||||
# the Cloudron platform provider (CLOUDRON_OIDC_*). The local Django login
|
||||
# form remains available alongside SSO for admin bootstrap; SSO-registered
|
||||
# users arrive with no privileges (README).
|
||||
#
|
||||
# Pattern: official-image wrapper. Image pinned by tag AND digest (amd64
|
||||
# manifest digest of the v4.6.10 tag, from docker manifest inspect — the
|
||||
# Hub API's index digest is NOT usable as tag@digest, see JOURNAL #668).
|
||||
FROM netboxcommunity/netbox:v4.6.10@sha256:5ee780bdc63b5a5f7ad5073e05e265f74d1a1c52ca0057facc9e4279fcfdb8cc
|
||||
|
||||
# Persistence rebinds must happen at BUILD time: the container runs as the
|
||||
# unprivileged netbox user (999) and could not replace these directories
|
||||
# later. Symlink targets are created by start.sh under /app/data.
|
||||
USER root
|
||||
RUN rm -rf /opt/netbox/netbox/media /opt/netbox/netbox/reports /opt/netbox/netbox/scripts \
|
||||
&& ln -s /app/data/media /opt/netbox/netbox/media \
|
||||
&& ln -s /app/data/reports /opt/netbox/netbox/reports \
|
||||
&& ln -s /app/data/scripts /opt/netbox/netbox/scripts
|
||||
|
||||
# start.sh (runs as the netbox user): persists the SECRET_KEY, maps the
|
||||
# Cloudron addon/platform env onto the image's env-driven configuration,
|
||||
# backgrounds the RQ worker, then execs the upstream entrypoint chain
|
||||
# (docker-entrypoint.sh launch-netbox.sh) under tini.
|
||||
# Made executable on the host, not at build time (Cloudron builds hit
|
||||
# permission errors on RUN chmod).
|
||||
COPY start.sh /app/start.sh
|
||||
|
||||
# Granian binds :: (dual-stack) on 8080; Cloudron proxies TLS here.
|
||||
EXPOSE 8080
|
||||
|
||||
USER 999:0
|
||||
|
||||
# Keep upstream's tini as PID 1; start.sh execs the upstream CMD chain.
|
||||
ENTRYPOINT ["/usr/bin/tini", "--", "/bin/bash", "/app/start.sh"]
|
||||
@@ -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).
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.7 KiB |
+106
@@ -0,0 +1,106 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# NetBox runtime setup for Cloudron:
|
||||
# 1. create the persistent data dirs (media / reports / scripts — the
|
||||
# image paths are build-time symlinks into /app/data)
|
||||
# 2. persist the Django SECRET_KEY (>= 50 chars; rotating it invalidates
|
||||
# sessions and encrypted values)
|
||||
# 3. map the Cloudron addon + platform env onto the image's env-driven
|
||||
# configuration (netbox-docker configuration/configuration.py):
|
||||
# DB_* from postgresql, REDIS[_CACHE]_* from redis, OIDC from the
|
||||
# platform OIDC provider
|
||||
# 4. background the RQ worker (gated on the web port so it only starts
|
||||
# after the entrypoint's migrations), then exec the upstream
|
||||
# entrypoint chain, which waits for the DB, migrates, and hands over
|
||||
# to Granian on :8080
|
||||
#
|
||||
# Authentication: SSO via the Cloudron platform OIDC provider
|
||||
# (REMOTE_AUTH_BACKEND = OpenIdConnectAuth + SOCIAL_AUTH_OIDC_*). The
|
||||
# local Django login stays available on /login/ for admin bootstrap;
|
||||
# SSO-registered users are created WITHOUT privileges (see README).
|
||||
|
||||
DATA_DIR="/app/data"
|
||||
SECRET_FILE="${DATA_DIR}/.secret_key"
|
||||
|
||||
# --- 1. persistent data directories -------------------------------------------
|
||||
mkdir -p "${DATA_DIR}/media" "${DATA_DIR}/reports" "${DATA_DIR}/scripts"
|
||||
|
||||
# --- 2. persistent SECRET_KEY --------------------------------------------------
|
||||
# hex on purpose: 64 chars, comfortably over NetBox's 50-char minimum
|
||||
if [[ ! -s "${SECRET_FILE}" ]]; then
|
||||
( umask 077; head -c 32 /dev/urandom | od -An -tx1 | tr -d ' \n' > "${SECRET_FILE}" )
|
||||
echo "Generated new NetBox secret key"
|
||||
fi
|
||||
export SECRET_KEY="$(cat "${SECRET_FILE}")"
|
||||
|
||||
# --- 3. Cloudron -> netbox-docker environment -----------------------------------
|
||||
export DB_HOST="${CLOUDRON_POSTGRESQL_HOST:-127.0.0.1}"
|
||||
export DB_PORT="${CLOUDRON_POSTGRESQL_PORT:-5432}"
|
||||
export DB_NAME="${CLOUDRON_POSTGRESQL_DATABASE:-netbox}"
|
||||
export DB_USER="${CLOUDRON_POSTGRESQL_USERNAME:-netbox}"
|
||||
export DB_PASSWORD="${CLOUDRON_POSTGRESQL_PASSWORD:-}"
|
||||
|
||||
# one Cloudron redis instance, two logical databases (upstream convention:
|
||||
# tasks on 0, caching on 1)
|
||||
export REDIS_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}"
|
||||
export REDIS_PORT="${CLOUDRON_REDIS_PORT:-6379}"
|
||||
export REDIS_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}"
|
||||
export REDIS_DATABASE=0
|
||||
export REDIS_CACHE_HOST="${CLOUDRON_REDIS_HOST:-127.0.0.1}"
|
||||
export REDIS_CACHE_PORT="${CLOUDRON_REDIS_PORT:-6379}"
|
||||
export REDIS_CACHE_PASSWORD="${CLOUDRON_REDIS_PASSWORD:-}"
|
||||
export REDIS_CACHE_DATABASE=1
|
||||
|
||||
# hosts / CSRF: Cloudron terminates TLS at the platform proxy
|
||||
export ALLOWED_HOSTS="${CLOUDRON_APP_DOMAIN:-localhost} localhost"
|
||||
export CSRF_TRUSTED_ORIGINS="${CLOUDRON_APP_ORIGIN:-http://localhost}"
|
||||
|
||||
# first admin is created by the operator via the Cloudron terminal
|
||||
# (README): the entrypoint's own superuser seeding is skipped
|
||||
export SKIP_SUPERUSER=true
|
||||
|
||||
# operator knobs (see .env.example)
|
||||
export TIME_ZONE="${NETBOX_TIME_ZONE:-UTC}"
|
||||
export GRANIAN_WORKERS="${NETBOX_GRANIAN_WORKERS:-4}"
|
||||
export METRICS_ENABLED="${NETBOX_METRICS_ENABLED:-false}"
|
||||
|
||||
# --- 3b. platform OIDC provider -> python-social-auth ---------------------------
|
||||
# social-core needs the issuer base URL WITH a trailing slash for
|
||||
# .well-known/openid-configuration discovery
|
||||
OIDC_ISSUER="${CLOUDRON_OIDC_ISSUER:-}"
|
||||
OIDC_ISSUER="${OIDC_ISSUER%/}/"
|
||||
export REMOTE_AUTH_BACKEND='social_core.backends.open_id_connect.OpenIdConnectAuth'
|
||||
export SOCIAL_AUTH_OIDC_OIDC_ENDPOINT="${OIDC_ISSUER}"
|
||||
export SOCIAL_AUTH_OIDC_KEY="${CLOUDRON_OIDC_CLIENT_ID:-}"
|
||||
export SOCIAL_AUTH_OIDC_SECRET="${CLOUDRON_OIDC_CLIENT_SECRET:-}"
|
||||
export SOCIAL_AUTH_OIDC_SCOPE='openid profile email'
|
||||
export LOGOUT_REDIRECT_URL="${CLOUDRON_APP_ORIGIN:-/}"
|
||||
|
||||
# --- 4. RQ worker + upstream entrypoint -----------------------------------------
|
||||
# wait for the addons FIRST: netbox-docker's entrypoint gives up on the DB
|
||||
# after only DB_WAIT_TIMEOUT=30s, which can lose the race with a cold
|
||||
# Cloudron postgres addon
|
||||
wait_tcp() {
|
||||
local host="$1" port="$2" name="$3"
|
||||
echo "Waiting for ${name} at ${host}:${port} ..."
|
||||
until (exec 3<>"/dev/tcp/${host}/${port}") 2>/dev/null; do
|
||||
echo "${name} is unavailable - sleeping"
|
||||
sleep 2
|
||||
done
|
||||
echo "${name} is up"
|
||||
}
|
||||
|
||||
wait_tcp "${DB_HOST}" "${DB_PORT}" "PostgreSQL"
|
||||
wait_tcp "${REDIS_HOST}" "${REDIS_PORT}" "Redis"
|
||||
|
||||
# The worker must not run before the schema exists; Granian answering on
|
||||
# 8080 is the signal that docker-entrypoint.sh finished migrating.
|
||||
(
|
||||
until (exec 3<>/dev/tcp/127.0.0.1/8080) 2>/dev/null; do sleep 2; done
|
||||
echo "web port is up - starting RQ worker"
|
||||
exec python3 /opt/netbox/netbox/manage.py rqworker
|
||||
) &
|
||||
|
||||
echo "Starting NetBox (migrations run automatically, then Granian binds :8080) ..."
|
||||
exec /opt/netbox/docker-entrypoint.sh /opt/netbox/launch-netbox.sh
|
||||
@@ -9,9 +9,9 @@ The Cloudron component focuses on packaging upstream free/libre/open application
|
||||
### 📊 Current Progress
|
||||
|
||||
- **Total Applications**: ~57 (see [GitUrlList.txt](GitUrlList.txt))
|
||||
- **Completed Packages**: 15/~57 (~26%)
|
||||
- **Completed Packages**: 16/~57 (~28%)
|
||||
- **Packaging Templates**: Created ✅
|
||||
- **Packages Committed & Pushed**: 15 ✅
|
||||
- **Packages Committed & Pushed**: 16 ✅
|
||||
- **Build Tickets**: 46 filed (#633-#678, umbrella
|
||||
[#632](https://projects.knownelement.com/issues/632), Redmine project 55);
|
||||
grist-core excluded (packaged upstream)
|
||||
@@ -37,6 +37,7 @@ The Cloudron component focuses on packaging upstream free/libre/open application
|
||||
| 13 | FX | DevOps-Tools | 3.55GB | 8000 | localstorage (auth proxy) | ✅ Committed |
|
||||
| 14 | ChirpStack | Infrastructure | 83.4MB | 8080 | localstorage, postgresql, redis | ✅ Committed |
|
||||
| 15 | eLabFTW | Business-Apps | ~209MB (compressed) | 443 | localstorage, mysql, ldap | ✅ Committed |
|
||||
| 16 | NetBox | Infrastructure | ~1GB | 8080 | localstorage, postgresql, redis | ✅ Committed |
|
||||
|
||||
### 📦 Packages in Development
|
||||
|
||||
|
||||
@@ -3,23 +3,24 @@
|
||||
> **Human read-only. Agents maintain this file automatically after each work
|
||||
> session.** Do not edit by hand — the next agent run will overwrite it.
|
||||
>
|
||||
> **Last updated:** 2026-09-02 by ZCode (GLM-5.3) — eLabFTW commit landed
|
||||
> (#669, Business-Apps, 15th package; packaged 2026-09-01 by Crush
|
||||
> GLM-5.2, gardening finished + committed 2026-09-02 after the prior
|
||||
> session ended before committing). Auth gate verdict: no OIDC upstream
|
||||
> (local/SAML/LDAP only) → native LDAP wired to the platform directory
|
||||
> with an auth-risk flag; official-image wrapper of elabimg 5.6.12.
|
||||
> **Last updated:** 2026-09-06 by ZCode (GLM-5.3) — NetBox packaged
|
||||
> (#648, Infrastructure, 16th package); auth gate verdict: native OIDC via
|
||||
> python-social-auth (OpenIdConnectAuth + SOCIAL_AUTH_OIDC_*) wired to the
|
||||
> platform provider; official-image wrapper of netboxcommunity/netbox
|
||||
> v4.6.10 (netbox-docker 5.0.2), full-stack verified (migrations, Granian,
|
||||
> gated RQ worker, OIDC login button). Session also finished #685's apply
|
||||
> pass (memlimits script repairs + photos floor-limit).
|
||||
|
||||
## Current State: STABLE (packaging phase, ongoing)
|
||||
|
||||
Cloudron packaging pipeline is operational. 15 of ~57 upstream applications are
|
||||
Cloudron packaging pipeline is operational. 16 of ~57 upstream applications are
|
||||
packaged, committed, and pushed. Packaging templates exist for the core
|
||||
patterns. The gardening protocol (this file + AGENTS.md) keeps docs in sync.
|
||||
All remaining apps now carry build tickets (#633-#678) under umbrella
|
||||
[#632](https://projects.knownelement.com/issues/632) in Redmine project 55 —
|
||||
ready for the sequential grind-driver pattern.
|
||||
|
||||
## Completed Packages (15)
|
||||
## Completed Packages (16)
|
||||
|
||||
| # | Application | Category | Pattern | Port(s) | Addons |
|
||||
|---|-------------|----------|---------|---------|--------|
|
||||
@@ -38,12 +39,13 @@ ready for the sequential grind-driver pattern.
|
||||
| 13 | FX | DevOps-Tools | Pre-compiled binaries + auth proxy | 8000 | localstorage |
|
||||
| 14 | ChirpStack | Infrastructure | Official-image wrapper | 8080 | localstorage, postgresql, redis |
|
||||
| 15 | eLabFTW | Business-Apps | Official-image wrapper | 443 | localstorage, mysql, ldap |
|
||||
| 16 | NetBox | Infrastructure | Official-image wrapper + start.sh | 8080 | localstorage, postgresql, redis |
|
||||
|
||||
Each package lives in `Package-Workspace/<Category>/<app>/` and contains a
|
||||
`Dockerfile`, `CloudronManifest.json`, `README.md`, `CHANGELOG.md`, `logo.png`,
|
||||
and (where relevant) `start.sh` + `.env.example`.
|
||||
|
||||
## Build Ticket Map (46 filed 2026-09-01; 40 open — 6 landed: #639, #640, #650, #651, #668, #669)
|
||||
## Build Ticket Map (46 filed 2026-09-01; 39 open — 7 landed: #639, #640, #648, #650, #651, #668, #669)
|
||||
|
||||
All under umbrella [#632](https://projects.knownelement.com/issues/632)
|
||||
(Redmine project 55, tracker Feature). Excluded: **grist-core** (a Cloudron
|
||||
@@ -126,7 +128,7 @@ Full write-ups of each pattern + challenges are in [`JOURNAL.md`](JOURNAL.md).
|
||||
| DevOps-Tools | 1 | 1/1 (100%) ✅ | fx done |
|
||||
| Financial-Payments | 1 | 0/1 | |
|
||||
| Financial-Trading | 1 | 0/1 | |
|
||||
| Infrastructure | 6 | 4/6 | easy-gate, rathole, database-gateway, chirpstack done |
|
||||
| Infrastructure | 6 | 5/6 | easy-gate, rathole, database-gateway, chirpstack, netbox done |
|
||||
| Legal | 1 | 0/1 | |
|
||||
| Project-Management | 1 | 0/1 | |
|
||||
| Scientific-Computing | 2 | 0/2 | |
|
||||
@@ -140,7 +142,7 @@ Auth capability is a hard gate before packaging (see
|
||||
LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only
|
||||
(unacceptable / blocked-on-auth).
|
||||
|
||||
### Completed packages (15)
|
||||
### Completed packages (16)
|
||||
|
||||
| App | OIDC | LDAP | Verdict | Note |
|
||||
|-----|------|------|---------|------|
|
||||
@@ -159,6 +161,7 @@ LDAP acceptable (risk flag), 🔄 = auth-proxy (no users), ❌ = local-only
|
||||
| FX | n/a | n/a | 🔄 proxy | **Packaged**; CLI-only FaaS tool with no user concept — pinned binary + workspace driven from the Cloudron terminal; landing page gated by `httpAuth.type=proxy` |
|
||||
| ChirpStack | yes | no | ✅ preferred | **Packaged**; native `[user_authentication.openid_connect]` wired to `CLOUDRON_OIDC_*`; OIDC-registered users are non-admin — one-time `CHIRPSTACK_AUTH_MODE=internal` bootstrap links the seeded `admin` to your SSO email (README) |
|
||||
| eLabFTW | no | yes | ⚠️ risk (LDAP) | **Packaged**; no OIDC upstream (auth = local/SAML/LDAP per `src/Enums/AuthMethod.php`); `ldap` addon enabled, README maps `CLOUDRON_LDAP_*` → sysconfig LDAP panel — must be validated on the live Cloudron before production; SAML possible via external IdP |
|
||||
| NetBox | yes | plugin | ✅ preferred | **Packaged**; python-social-auth OIDC (`REMOTE_AUTH_BACKEND=OpenIdConnectAuth` + `SOCIAL_AUTH_OIDC_*`) wired from `CLOUDRON_OIDC_*`; local Django login retained for admin bootstrap; SSO users register without privileges (README) |
|
||||
|
||||
### Candidates researched
|
||||
|
||||
|
||||
Reference in New Issue
Block a user