NetBox is the open-source source of truth for network infrastructure — IP address management (IPAM), data centre infrastructure management (DCIM), circuits, VPNs, wireless and virtualisation, with a full REST and GraphQL API.
This repository is a thin build layer over the official netbox-docker image. It holds only what Railway needs; NetBox itself is unmodified.
Both Railway services build from this one Dockerfile and differ only in their start command, so their NetBox versions can never drift apart.
| Service | Start command | Public |
|---|---|---|
netbox |
image default (docker-entrypoint.sh → bin/web.sh) |
yes |
netbox-worker |
/usr/bin/tini -- /opt/netbox/railway/worker.sh |
no |
They depend on a Postgres database, two Redis instances (one for the task queue, one for the cache, as upstream's production compose file splits them) and an S3-compatible bucket.
config/zz_railway.py — points Django's default and scripts storages at
object storage. Upstream's compose file mounts one media volume and one scripts
volume into both the web and worker containers; Railway volumes are strictly
one per service and cannot be shared, so the two roles would silently diverge.
NetBox loads script modules through storages['scripts'] rather than the
filesystem, so S3-backed custom scripts execute normally. The file also marks the
session and CSRF cookies secure — NetBox defaults both to False and exposes no
environment variable for them — and derives CSRF_TRUSTED_ORIGINS from
RAILWAY_PUBLIC_DOMAIN at boot. ALLOWED_HOSTS is left at netbox-docker's *
on purpose: Railway's edge routes strictly by Host and rejects an unrecognised
one itself, so pinning the generated domain would only break custom domains.
docker/granian.py — replaces netbox-docker's proxy-header helper. Granian's
own helper trusts RFC1918 and fc00::/7, but Railway's edge reaches the
container from 100.64.0.0/10 (CGNAT), so every X-Forwarded-* header was
discarded and Django treated HTTPS requests as plain HTTP. It also walks
X-Forwarded-For right-to-left, which on Railway lands on the edge's own
rotating public address rather than the client. This version trusts the CGNAT
peer and takes the leftmost entry.
bin/worker.sh — waits for the web service to apply database migrations
instead of applying them itself. Railway starts every service at once with no
dependency ordering, and two containers running manage.py migrate against one
database concurrently is not safe.
bin/web.sh — upstream's granian launcher with the listen address and port
read from the environment, so Railway's PORT drives the health check.
Everything else is configured with netbox-docker's environment variables. The variables this layer adds:
| Variable | Purpose |
|---|---|
S3_BUCKET |
Bucket name. Object storage is disabled when this is empty. |
S3_ENDPOINT |
S3 endpoint URL, including the scheme. |
S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY |
Bucket credentials. |
S3_REGION |
Signing region (default auto). |
S3_URL_EXPIRY |
Lifetime in seconds of presigned media URLs (default 3600). |
GRANIAN_HOST |
Listen address (default ::). |
GRANIAN_WORKERS |
Worker processes (default 4). |
GRANIAN_LOG_LEVEL |
Granian log level (default info). |
MIGRATION_WAIT_SECONDS |
How long the worker waits for migrations (default 900). |
NetBox is licensed under the Apache License 2.0 by NetBox Labs and the NetBox community. This packaging layer carries the same licence.