Deployment Guide
Deploy Rackd in production
This guide covers various deployment methods for Rackd in production environments.
Docker Deployment
Basic Docker Run
# Create data directory
mkdir -p /opt/rackd/data
# Run container
docker run -d \
--name rackd \
-p 8080:8080 \
-v /opt/rackd/data:/data \
-e DATA_DIR=/data \
ghcr.io/martinsuchenak/rackd:latest
Docker with Environment Variables
docker run -d \
--name rackd \
-p 8080:8080 \
-v /opt/rackd/data:/data \
-e DATA_DIR=/data \
-e LOG_LEVEL=info \
-e LOG_FORMAT=json \
-e ENCRYPTION_KEY=your-64-hex-char-key \
-e INITIAL_ADMIN_USERNAME=admin \
-e INITIAL_ADMIN_PASSWORD=your-secure-password \
ghcr.io/martinsuchenak/rackd:latest
Docker Compose
Create docker-compose.yml:
version: '3.8'
services:
rackd:
image: ghcr.io/martinsuchenak/rackd:latest
container_name: rackd
restart: unless-stopped
ports:
- "8080:8080"
volumes:
- ./data:/data
environment:
- DATA_DIR=/data
- LOG_LEVEL=info
- LOG_FORMAT=json
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
- INITIAL_ADMIN_USERNAME=${INITIAL_ADMIN_USERNAME:-admin}
- INITIAL_ADMIN_PASSWORD=${INITIAL_ADMIN_PASSWORD}
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/healthz"]
interval: 30s
timeout: 5s
retries: 3
nginx:
image: nginx:alpine
container_name: rackd-nginx
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- rackd
Create .env file:
ENCRYPTION_KEY=your-64-hex-char-key
INITIAL_ADMIN_USERNAME=admin
INITIAL_ADMIN_PASSWORD=your-secure-password
Deploy:
docker-compose up -d
Docker Networking for Discovery
The default Docker bridge network NATs all container traffic, which breaks Layer-2 discovery features: no ARP visibility (MAC addresses and vendors), and broadcast protocols (mDNS/NetBIOS/LLDP) cannot cross the bridge — only unicast TCP/ICMP probing works.
For full discovery capability, run rackd with host networking and bind the API to loopback behind your TLS reverse proxy:
services:
rackd:
image: ghcr.io/martinsuchenak/rackd:latest
container_name: rackd
restart: unless-stopped
network_mode: host # share the host network namespace
volumes:
- ./data:/data
environment:
- DATA_DIR=/data
- LISTEN_ADDR=127.0.0.1:8080 # only the local proxy can reach the API
- ENCRYPTION_KEY=${ENCRYPTION_KEY}
- INITIAL_ADMIN_USERNAME=${INITIAL_ADMIN_USERNAME:-admin}
- INITIAL_ADMIN_PASSWORD=${INITIAL_ADMIN_PASSWORD}
No ports: mapping is used (or needed) with host networking. Alternative
without host networking: configure SNMP credentials — SNMP is UDP unicast
and works from bridged containers, yielding hostnames, interfaces and MACs.
Nomad Deployment
The Nomad job file is available at deploy/nomad.hcl.
Prerequisites
- Configure host volume in Nomad client:
# nomad.hcl
client {
host_volume "rackd-data" {
path = "/opt/nomad/rackd-data"
read_only = false
}
}
- Set Nomad variables:
nomad var put nomad/jobs/rackd \
api_auth_token="your-secure-token" \
mcp_auth_token="your-mcp-token"
Deploy
nomad job run deploy/nomad.hcl
Systemd Service
Binary Installation
# Download and install
curl -LO https://github.com/martinsuchenak/rackd/releases/latest/download/rackd-linux-amd64
sudo mv rackd-linux-amd64 /usr/local/bin/rackd
sudo chmod +x /usr/local/bin/rackd
# Create user and directories
sudo useradd -r -s /bin/false rackd
sudo mkdir -p /var/lib/rackd /etc/rackd
sudo chown rackd:rackd /var/lib/rackd
Service Configuration
Create /etc/systemd/system/rackd.service:
[Unit]
Description=Rackd IPAM and Device Inventory
After=network.target
Wants=network.target
[Service]
Type=simple
User=rackd
Group=rackd
ExecStart=/usr/local/bin/rackd server
Restart=always
RestartSec=5
Environment=DATA_DIR=/var/lib/rackd
Environment=LISTEN_ADDR=:8080
Environment=LOG_LEVEL=info
EnvironmentFile=-/etc/rackd/rackd.env
# Security
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/rackd
[Install]
WantedBy=multi-user.target
Create /etc/rackd/rackd.env:
ENCRYPTION_KEY=your-64-hex-char-key
INITIAL_ADMIN_USERNAME=admin
INITIAL_ADMIN_PASSWORD=your-secure-password
Enable and start:
sudo systemctl daemon-reload
sudo systemctl enable rackd
sudo systemctl start rackd
Reverse Proxy Setup
When running behind a reverse proxy, set TRUST_PROXY=true and
TRUSTED_PROXIES to the proxy address (e.g. 127.0.0.1) so rackd honors
forwarded headers only from that peer for rate limiting and audit logging,
and bind LISTEN_ADDR to loopback so the API is only reachable through the
proxy.
Nginx
Create /etc/nginx/sites-available/rackd:
server {
listen 80;
server_name rackd.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name rackd.example.com;
ssl_certificate /etc/ssl/certs/rackd.crt;
ssl_certificate_key /etc/ssl/private/rackd.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Traefik
Create traefik.yml:
api:
dashboard: true
entryPoints:
web:
address: ":80"
websecure:
address: ":443"
certificatesResolvers:
letsencrypt:
acme:
email: [email protected]
storage: acme.json
httpChallenge:
entryPoint: web
providers:
docker:
exposedByDefault: false
Update Docker Compose with Traefik labels:
services:
rackd:
labels:
- "traefik.enable=true"
- "traefik.http.routers.rackd.rule=Host(`rackd.example.com`)"
- "traefik.http.routers.rackd.entrypoints=websecure"
- "traefik.http.routers.rackd.tls.certresolver=letsencrypt"
TLS/HTTPS
Let’s Encrypt with Certbot
# Install certbot
sudo apt install certbot python3-certbot-nginx
# Obtain certificate
sudo certbot --nginx -d rackd.example.com
# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet
Self-Signed Certificate
# Generate certificate
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
-keyout rackd.key -out rackd.crt \
-subj "/CN=rackd.example.com"
# Install
sudo cp rackd.crt /etc/ssl/certs/
sudo cp rackd.key /etc/ssl/private/
sudo chmod 600 /etc/ssl/private/rackd.key
Production Considerations
Security
- Use strong authentication tokens
- Enable HTTPS in production
- Restrict network access with firewall rules
- Run with non-root user
- Regular security updates
Performance
- Allocate sufficient memory (minimum 256MB)
- Use SSD storage for database
- Monitor disk space usage
- Configure log rotation
Backup Strategy
#!/bin/bash
# backup-rackd.sh
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup/rackd"
DATA_DIR="/var/lib/rackd"
mkdir -p $BACKUP_DIR
sqlite3 $DATA_DIR/rackd.db ".backup $BACKUP_DIR/rackd_$DATE.db"
gzip $BACKUP_DIR/rackd_$DATE.db
# Cleanup old backups (keep 30 days)
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete
Log Management
Configure log rotation in /etc/logrotate.d/rackd:
/var/log/rackd/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 644 rackd rackd
postrotate
systemctl reload rackd
endscript
}
Monitoring
Health Checks
Rackd provides a health check endpoint:
curl http://localhost:8080/api/datacenters
Prometheus Metrics
Add monitoring labels to Docker Compose:
services:
rackd:
labels:
- "prometheus.io/scrape=true"
- "prometheus.io/port=8080"
- "prometheus.io/path=/metrics"
Basic Monitoring Script
#!/bin/bash
# monitor-rackd.sh
URL="http://localhost:8080/api/datacenters"
TIMEOUT=5
if curl -f -s --max-time $TIMEOUT $URL > /dev/null; then
echo "Rackd is healthy"
exit 0
else
echo "Rackd health check failed"
exit 1
fi
Uptime Monitoring
Configure external monitoring with services like:
- Pingdom
- UptimeRobot
- StatusCake
Monitor these endpoints:
/api/datacenters- API health/- Web UI availability
Troubleshooting
Common Issues
Permission denied on data directory
sudo chown -R rackd:rackd /var/lib/rackdPort already in use
sudo netstat -tlnp | grep :8080Database locked
# Check for stale processes ps aux | grep rackd
Logs
# Systemd logs
sudo journalctl -u rackd -f
# Docker logs
docker logs -f rackd
# Nomad logs
nomad alloc logs -f <alloc-id>