Complete guide for deploying Bootimus in various environments with networking and storage configurations.
- Quick Start
- Docker Deployment
- Binary Deployment
- Networking Configuration
- Storage Configuration
- Database Options
- Remote Updates & Privacy
- Production Deployment
# Create data directory
mkdir -p data
# Run with SQLite (no database container needed)
docker run -d \
--name bootimus \
--cap-add NET_BIND_SERVICE \
-p 69:69/udp \
-p 8080:8080/tcp \
-p 8081:8081/tcp \
-v $(pwd)/data:/data \
garybowers/bootimus:latest
# Check logs for admin password
docker logs bootimus | grep "Password"
# Access admin interface
open http://localhost:8081# Download binary
wget https://github.com/garybowers/bootimus/releases/latest/download/bootimus-amd64
chmod +x bootimus-amd64
# Create data directory
mkdir -p data
# Run (SQLite mode - no database required)
./bootimus-amd64 serve
# Admin panel: http://localhost:8081
# Admin password shown in startup logs# Clone repository
git clone https://github.com/garybowers/bootimus
cd bootimus
# Start with PostgreSQL
docker-compose up -d
# View logs
docker-compose logs -f bootimusThe Docker Compose stack includes:
- Bootimus server: Main PXE/HTTP boot server
- PostgreSQL: Database for client/image management
- Health checks: Automatic service monitoring
- Persistent storage: Data volumes for ISOs and database
Bootimus automatically creates subdirectories:
/data/isos/- ISO image files and extracted boot files (in subdirectories per ISO)/data/bootloaders/- Custom bootloader files (optional)/data/bootimus.db- SQLite database (if using SQLite mode)
By default, containers use an internal bridge network with port forwarding:
networks:
bootimus_net:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
gateway: 172.20.0.1- Bootimus server:
172.20.0.3 - PostgreSQL:
172.20.0.2 - Access from host: Via port forwarding (e.g.,
localhost:8081)
For production PXE environments, you may want the container directly on your LAN with a static IP.
ip addr show # Linux
# Look for your primary interface (e.g., eth0, ens33, enp0s3)Uncomment the host_bridge network sections:
services:
bootimus:
networks:
# Comment out internal bridge
# bootimus_net:
# ipv4_address: 172.20.0.3
# Enable host bridge
host_bridge:
ipv4_address: 192.168.1.100 # Your desired static IP
environment:
BOOTIMUS_SERVER_ADDR: 192.168.1.100 # Set static server address
networks:
# Uncomment and configure for your LAN
host_bridge:
driver: macvlan
driver_opts:
parent: eth0 # Your network interface
ipam:
config:
- subnet: 192.168.1.0/24 # Your LAN subnet
gateway: 192.168.1.1 # Your LAN gateway
ip_range: 192.168.1.100/32 # Container static IPUpdate these values for your network:
parent: Your host's network interface (e.g.,eth0,ens33)subnet: Your LAN subnet (e.g.,192.168.1.0/24)gateway: Your router's IP (e.g.,192.168.1.1)ip_range: The static IP for Bootimus (e.g.,192.168.1.100/32)BOOTIMUS_SERVER_ADDR: Same as the static IP
docker-compose down
docker-compose up -d# From another machine on the LAN
curl http://192.168.1.100:8081
# Ping the container
ping 192.168.1.100- Macvlan networking: Container appears as a separate device on your LAN
- Host cannot reach container: The host machine cannot directly communicate with macvlan containers. Use a separate VM/container for admin access, or create a macvlan interface on the host.
- DHCP conflicts: Ensure the static IP is outside your DHCP range or reserved in your DHCP server
- Firewall rules: Container bypasses host firewall - configure container firewall separately if needed
If you need to access the macvlan container from the host machine:
# Create a macvlan interface on the host
sudo ip link add macvlan0 link eth0 type macvlan mode bridge
sudo ip addr add 192.168.1.101/32 dev macvlan0
sudo ip link set macvlan0 up
sudo ip route add 192.168.1.100/32 dev macvlan0
# Now you can access the container from the host
curl http://192.168.1.100:8081- OS: Linux (amd64, arm64, armv7)
- Privileges: Root required for port 69 (TFTP), or use non-privileged ports
- Disk: 10GB+ for ISO storage
- Memory: 512MB minimum, 2GB+ recommended
# Download binary for your architecture
wget https://github.com/garybowers/bootimus/releases/latest/download/bootimus-amd64
# Make executable
chmod +x bootimus-amd64
# Move to system location
sudo mv bootimus-amd64 /usr/local/bin/bootimus
# Create data directory
sudo mkdir -p /opt/bootimus/data
# Create systemd service
sudo nano /etc/systemd/system/bootimus.service[Unit]
Description=Bootimus PXE/HTTP Boot Server
After=network.target
[Service]
Type=simple
User=root
WorkingDirectory=/opt/bootimus
ExecStart=/usr/local/bin/bootimus serve --data-dir /opt/bootimus/data
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable bootimus
sudo systemctl start bootimus
# Check status
sudo systemctl status bootimus
# View logs
sudo journalctl -u bootimus -f/opt/bootimus/data/
├── isos/ # ISO files
│ ├── ubuntu-24.04.iso # ISO file
│ ├── ubuntu-24.04/ # Extracted boot files
│ │ ├── vmlinuz
│ │ ├── initrd
│ │ └── casper/
│ │ └── filesystem.squashfs
│ └── debian-12.iso
├── bootloaders/ # Custom bootloaders (optional)
├── bootimus.db # SQLite database (if using SQLite)
└── .admin_password # Generated admin password
- ISOs: 1-10GB per ISO
- Extracted files: 100MB-3GB per ISO
- Database: < 100MB
- Recommended: 50GB+ for multiple ISOs
- Use SSD: Faster boot times for clients
- Regular backups: Backup database and ISOs
- Monitor disk space: Set up alerts for low disk space
- Clean old ISOs: Remove unused ISOs to free space
SQLite is enabled by default - no configuration required!
# Run with SQLite (default)
./bootimus serve
# Database automatically created at: <data_dir>/bootimus.dbBenefits:
- Zero configuration
- Single file database
- Perfect for single-server deployments
- Easy backups (just copy the file)
Limitations:
- Lower concurrency than PostgreSQL
- Single-server only (no clustering)
For enterprise deployments with high concurrency:
# bootimus.yaml
db:
host: postgres.example.com
port: 5432
user: bootimus
password: secretpassword
name: bootimus
sslmode: requireexport BOOTIMUS_DB_HOST=postgres.example.com
export BOOTIMUS_DB_PORT=5432
export BOOTIMUS_DB_USER=bootimus
export BOOTIMUS_DB_PASSWORD=secretpassword
export BOOTIMUS_DB_NAME=bootimus
export BOOTIMUS_DB_SSLMODE=require
./bootimus serveBenefits:
- High concurrency
- Multi-server deployments
- Advanced replication
- Better performance at scale
Requirements:
- PostgreSQL 12+ server
- Network connectivity to database
- Additional infrastructure
Bootimus is self-hosted and does not phone home in the background. It ships with a full catalogue of distro and tool profiles embedded in the binary, so it is fully functional with no outbound internet access.
The only time Bootimus contacts an external service is when an operator
explicitly triggers a profile/tool update — via the "Check for Updates"
buttons in the admin UI, the bootimus profiles update CLI command, or the
POST /api/profiles/update and POST /api/tools/update endpoints. Each of
those performs an unauthenticated GET of a static JSON file on GitHub
(raw.githubusercontent.com/garybowers/bootimus/main/...) and sends no system
information or identifiers.
To guarantee no remote contact ever happens (e.g. air-gapped deployments), run with remote updates disabled:
bootimus serve --disable-remote-profiles
# or in bootimus.yaml: disable_remote_profiles: true
# or via env: BOOTIMUS_DISABLE_REMOTE_PROFILES=trueSee the Distro Profiles guide for full details.
docker run -d \
--name bootimus \
--restart unless-stopped \
--cap-add NET_BIND_SERVICE \
-p 69:69/udp \
-p 8080:8080/tcp \
-p 8081:8081/tcp \
-v /opt/bootimus/data:/data \
garybowers/bootimus:latestversion: '3.8'
services:
bootimus:
image: garybowers/bootimus:latest
container_name: bootimus
restart: unless-stopped
cap_add:
- NET_BIND_SERVICE
ports:
- "69:69/udp"
- "8080:8080/tcp"
- "8081:8081/tcp"
volumes:
- ./data:/data
- ./bootimus.yaml:/app/bootimus.yaml
environment:
- BOOTIMUS_DB_HOST=postgres
- BOOTIMUS_DB_PASSWORD=secretpassword
depends_on:
- postgres
postgres:
image: postgres:17-alpine
container_name: bootimus-db
restart: unless-stopped
environment:
- POSTGRES_USER=bootimus
- POSTGRES_PASSWORD=secretpassword
- POSTGRES_DB=bootimus
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:Bootimus uses sensible defaults and requires minimal configuration.
- Command-line flags (highest priority)
- Environment variables (prefixed with
BOOTIMUS_) - Configuration file (
bootimus.yaml)
# bootimus.yaml
tftp_port: 69
http_port: 8080
admin_port: 8081
data_dir: ./data # Base data directory
server_addr: "" # Auto-detected if not specified
bind_interface: "" # Tie all listeners to one NIC, e.g. eth0 (Linux only; all interfaces if not specified)
# Database configuration (optional)
# If no db.host is specified, SQLite is used automatically
db:
host: localhost # Leave empty for SQLite
port: 5432
user: bootimus
password: bootimus
name: bootimus
sslmode: disable# Server settings
export BOOTIMUS_TFTP_PORT=69
export BOOTIMUS_HTTP_PORT=8080
export BOOTIMUS_ADMIN_PORT=8081
export BOOTIMUS_DATA_DIR=/var/lib/bootimus/data
export BOOTIMUS_SERVER_ADDR=192.168.1.100
# Database settings (PostgreSQL only)
export BOOTIMUS_DB_HOST=postgres # Empty = SQLite
export BOOTIMUS_DB_PORT=5432
export BOOTIMUS_DB_USER=bootimus
export BOOTIMUS_DB_PASSWORD=secret
export BOOTIMUS_DB_NAME=bootimus
export BOOTIMUS_DB_SSLMODE=disable
./bootimus serve# Run as root
sudo ./bootimus serve
# Or use Docker with NET_BIND_SERVICE capability
docker run --cap-add NET_BIND_SERVICE ...
# Or use non-privileged port
./bootimus serve --tftp-port 6969# Check SQLite database
ls -la data/bootimus.db
# For PostgreSQL, test connection
psql -h localhost -U bootimus -d bootimus
# Check PostgreSQL logs
docker logs bootimus-db# Verify macvlan configuration
docker network inspect bootimus_host_bridge
# Check IP address assignment
docker exec bootimus ip addr show
# Verify routing
ip route | grep 192.168.1.100
# Check firewall
sudo iptables -L -n | grep 192.168.1.100# Check disk usage
df -h /opt/bootimus/data
# Find large files
du -sh /opt/bootimus/data/*
# Clean up old ISOs
rm /opt/bootimus/data/isos/old-image.iso
# Scan for new ISOs to update database
curl -u admin:password -X POST http://localhost:8081/api/scan- Read Image Management Guide for ISO handling
- See Admin Console Guide for management
- Configure DHCP Server for PXE booting