Self-Hosting NetBox with Docker Compose
What Is NetBox?
NetBox is the industry-standard open-source platform for modeling and documenting computer networks. Built by DigitalOcean and now maintained by the NetBox community, it tracks IP addresses, racks, devices, circuits, connections, and virtually every other piece of network infrastructure you manage. Think of it as a single source of truth for your entire network — from physical rack layouts to IP assignments to cable connections.
For self-hosters running anything beyond a couple of Docker containers, NetBox eliminates the “which IP did I assign to what?” spreadsheet problem. It has a full REST API, GraphQL endpoint, and webhook support, making it the backbone for network automation workflows.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 2 GB of free RAM (NetBox + PostgreSQL + Redis)
- 1 GB of free disk space
- A domain name (optional, for HTTPS access)
Docker Compose Configuration
Create a directory for NetBox:
mkdir -p /opt/netbox && cd /opt/netbox
Create a docker-compose.yml:
services:
netbox:
image: netboxcommunity/netbox:v4.5.4
container_name: netbox
ports:
- "8000:8080"
environment:
DB_HOST: postgres
DB_NAME: netbox
DB_USER: netbox
DB_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
REDIS_PASSWORD: ${REDIS_PASSWORD}
REDIS_CACHE_HOST: redis-cache
REDIS_CACHE_PASSWORD: ${REDIS_CACHE_PASSWORD}
SECRET_KEY: ${SECRET_KEY}
SUPERUSER_NAME: admin
SUPERUSER_EMAIL: [email protected]
SUPERUSER_PASSWORD: ${SUPERUSER_PASSWORD}
SKIP_SUPERUSER: "false"
GRAPHQL_ENABLED: "true"
WEBHOOKS_ENABLED: "true"
CORS_ORIGIN_ALLOW_ALL: "true"
volumes:
- netbox-media:/opt/netbox/netbox/media
- netbox-reports:/opt/netbox/netbox/reports
- netbox-scripts:/opt/netbox/netbox/scripts
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
redis-cache:
condition: service_healthy
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/login/"]
interval: 15s
timeout: 3s
start_period: 90s
retries: 5
restart: unless-stopped
netbox-worker:
image: netboxcommunity/netbox:v4.5.4
container_name: netbox-worker
command: /opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py rqworker
environment:
DB_HOST: postgres
DB_NAME: netbox
DB_USER: netbox
DB_PASSWORD: ${DB_PASSWORD}
REDIS_HOST: redis
REDIS_PASSWORD: ${REDIS_PASSWORD}
REDIS_CACHE_HOST: redis-cache
REDIS_CACHE_PASSWORD: ${REDIS_CACHE_PASSWORD}
SECRET_KEY: ${SECRET_KEY}
volumes:
- netbox-media:/opt/netbox/netbox/media
- netbox-reports:/opt/netbox/netbox/reports
- netbox-scripts:/opt/netbox/netbox/scripts
depends_on:
netbox:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "ps -aux | grep -v grep | grep -q rqworker || exit 1"]
interval: 15s
timeout: 3s
start_period: 20s
restart: unless-stopped
postgres:
image: postgres:17-alpine
container_name: netbox-postgres
environment:
POSTGRES_USER: netbox
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: netbox
volumes:
- netbox-postgres:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -q -t 2 -d netbox -U netbox"]
interval: 10s
timeout: 5s
start_period: 20s
retries: 5
restart: unless-stopped
redis:
image: valkey/valkey:9.0-alpine
container_name: netbox-redis
command: valkey-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- netbox-redis:/data
healthcheck:
test: ["CMD-SHELL", "valkey-cli --pass ${REDIS_PASSWORD} ping | grep -q PONG"]
interval: 10s
timeout: 3s
start_period: 5s
retries: 5
restart: unless-stopped
redis-cache:
image: valkey/valkey:9.0-alpine
container_name: netbox-redis-cache
command: valkey-server --requirepass ${REDIS_CACHE_PASSWORD}
volumes:
- netbox-redis-cache:/data
healthcheck:
test: ["CMD-SHELL", "valkey-cli --pass ${REDIS_CACHE_PASSWORD} ping | grep -q PONG"]
interval: 10s
timeout: 3s
start_period: 5s
retries: 5
restart: unless-stopped
volumes:
netbox-media:
netbox-reports:
netbox-scripts:
netbox-postgres:
netbox-redis:
netbox-redis-cache:
Create the .env file:
cat > /opt/netbox/.env << 'EOF'
# CHANGE ALL OF THESE VALUES
DB_PASSWORD=change-this-strong-db-password
REDIS_PASSWORD=change-this-redis-password
REDIS_CACHE_PASSWORD=change-this-cache-password
SECRET_KEY=change-this-to-a-random-50-char-string-use-openssl-rand
SUPERUSER_PASSWORD=change-this-admin-password
EOF
Generate a proper secret key:
# Replace the SECRET_KEY line in .env with a generated value
SECRET_KEY=$(openssl rand -hex 25)
sed -i "s/^SECRET_KEY=.*/SECRET_KEY=$SECRET_KEY/" /opt/netbox/.env
Start the stack:
docker compose up -d
The first start takes 60-90 seconds for database migrations. Check readiness:
docker compose logs -f netbox
# Wait for: "Listening at: http://0.0.0.0:8080"
Initial Setup
1. Log In
Open http://your-server-ip:8000 and log in with the credentials you set in .env:
- Username:
admin - Password: the value of
SUPERUSER_PASSWORD
2. Configure Sites
Navigate to Organization > Sites and create your first site (e.g., “Home Lab”, “Office Rack”). Sites are the top-level organizational unit.
3. Add IP Prefixes
Go to IPAM > Prefixes and add your network ranges:
192.168.1.0/24— Home LAN10.0.0.0/8— Docker internal172.16.0.0/12— VPN range
4. Document Devices
Under Devices > Device Types, create templates for your hardware. Then add actual devices under Devices > Devices, assigning them to sites, racks, and IP addresses.
Configuration
Key Features
| Feature | Description |
|---|---|
| IPAM | IP address management with prefix hierarchies and VLAN tracking |
| DCIM | Data center infrastructure modeling — racks, devices, cables |
| Circuits | WAN circuit and provider tracking |
| Virtualization | VM and cluster documentation |
| Contacts | Organizational contacts linked to infrastructure |
| Tenancy | Multi-tenant resource assignment |
| Custom Fields | Extend any model with custom attributes |
| Webhooks | HTTP callbacks on data changes |
| REST API | Full CRUD API for automation |
| GraphQL | Flexible querying for complex relationships |
API Access
NetBox’s REST API is comprehensive. Generate an API token under Admin > API Tokens:
# List all devices
curl -H "Authorization: Token your-api-token" \
http://localhost:8000/api/dcim/devices/
# Create an IP address
curl -X POST -H "Authorization: Token your-api-token" \
-H "Content-Type: application/json" \
http://localhost:8000/api/ipam/ip-addresses/ \
-d '{"address":"192.168.1.50/24","status":"active","description":"Proxmox host"}'
Custom Fields
Extend any NetBox model with custom fields — useful for tracking self-hosting-specific data:
- Navigate to Customization > Custom Fields
- Add fields like
docker_host,backup_schedule,last_patched - Fields appear on the relevant object forms and API responses
Advanced Configuration
LDAP/SSO Authentication
Mount a custom configuration file for LDAP integration:
volumes:
- ./configuration/ldap_config.py:/etc/netbox/config/ldap_config.py:ro
Plugins
NetBox supports community plugins (BGP, DNS, access lists, etc.). Install by extending the Docker image:
FROM netboxcommunity/netbox:v4.5.4
RUN /opt/netbox/venv/bin/pip install netbox-bgp netbox-dns
Update your compose file to use the custom image.
Reverse Proxy
For HTTPS access, route through Nginx Proxy Manager or Caddy:
Caddy:
netbox.yourdomain.com {
reverse_proxy localhost:8000
}
See Reverse Proxy Setup for detailed instructions.
Backup
Critical Data
| Data | Location | Method |
|---|---|---|
| All configuration, devices, IPs | PostgreSQL database | pg_dump |
| Uploaded images, attachments | netbox-media volume | File copy |
| Custom reports | netbox-reports volume | File copy |
| Custom scripts | netbox-scripts volume | File copy |
Backup Script
#!/bin/bash
BACKUP_DIR="/opt/backups/netbox/$(date +%F)"
mkdir -p "$BACKUP_DIR"
# Database dump
docker exec netbox-postgres pg_dump -U netbox netbox > "$BACKUP_DIR/netbox.sql"
# Config and volumes
cp /opt/netbox/.env "$BACKUP_DIR/"
docker run --rm -v netbox-media:/data -v "$BACKUP_DIR":/backup alpine \
tar czf /backup/media.tar.gz -C /data .
See Backup Strategy for comprehensive approaches.
Troubleshooting
NetBox Stuck on “Applying database migrations”
Symptom: Container health check fails, logs show migration running for 5+ minutes
Fix: First-time migrations on a fresh database can take several minutes. Wait up to 5 minutes. If it persists, check PostgreSQL health:
docker compose logs postgres
Worker Not Processing Jobs
Symptom: Webhooks, reports, or scripts don’t execute
Fix: Check the worker container is running and healthy:
docker compose ps netbox-worker
docker compose logs netbox-worker
“CSRF Verification Failed” on Login
Symptom: Login form returns CSRF error
Fix: If behind a reverse proxy, ensure the proxy forwards the Host header and set CORS_ORIGIN_ALLOW_ALL=true or configure ALLOWED_HOSTS in a custom configuration file.
Redis Connection Refused
Symptom: NetBox can’t connect to Redis, logs show ConnectionRefusedError
Fix: Ensure both Redis containers (broker and cache) are healthy. Verify the passwords in .env match between NetBox and Redis services.
Slow Page Loads
Symptom: Pages take 3+ seconds to render
Fix: Increase worker count. Add to NetBox environment:
GRANIAN_WORKERS: "4" # Match to CPU cores
Resource Requirements
| Resource | Value |
|---|---|
| RAM | ~800 MB total (NetBox ~300 MB + PostgreSQL ~200 MB + 2× Redis ~50 MB each + Worker ~200 MB) |
| CPU | Moderate — Django ORM is CPU-bound on complex queries |
| Disk | ~1 GB for containers + database grows with infrastructure size |
| Network | Minimal; web traffic only |
Verdict
NetBox is the definitive tool for network documentation and IP address management. If you run more than a handful of devices and services, the structured approach to tracking IPs, VLANs, racks, and connections pays for itself in reduced “wait, what’s on 192.168.1.47?” moments. The REST API makes it the foundation for network automation.
For simple IP tracking without the full DCIM/infrastructure modeling, phpIPAM is lighter. NetBox is the right choice when you want comprehensive infrastructure documentation, not just IP management.
FAQ
Is NetBox an alternative to a DNS server?
No. NetBox documents your network — it doesn’t serve DNS queries. Use it alongside Unbound, CoreDNS, or Pi-hole for DNS resolution. NetBox tracks what IP goes where; DNS servers resolve names to those IPs.
Can NetBox manage my Docker networks?
Not directly. NetBox models physical and virtual networks, IP assignments, and device connections. For Docker-specific management, use Portainer. You can document your Docker host IPs and networks in NetBox for reference.
Why does NetBox need two Redis instances?
One handles the message queue (background jobs, webhooks) with persistence enabled. The other is a cache (page rendering, API responses) that can be safely lost on restart. Separating them prevents cache eviction from disrupting job processing.
Related
Get self-hosting tips in your inbox
Get the Docker Compose configs, hardware picks, and setup shortcuts we don't put in articles. Weekly. No spam.
Comments