Self-Hosting phpIPAM with Docker Compose
What Is phpIPAM?
phpIPAM started as a simple PHP application for tracking IP addresses and has grown into a mature, full-featured IPAM (IP Address Management) tool used by thousands of organizations. It handles subnet management, VLAN tracking, DNS integration, and automated network discovery — all through a clean web interface. If you’ve been tracking IP assignments in a spreadsheet, phpIPAM is the upgrade you need.
Unlike NetBox, which models your entire physical infrastructure (racks, cables, circuits), phpIPAM focuses specifically on IP address management. It’s lighter, simpler to set up, and doesn’t require you to document your whole data center to get value from it.
Prerequisites
- A Linux server (Ubuntu 22.04+ recommended)
- Docker and Docker Compose installed (guide)
- 512 MB of free RAM (phpIPAM + MariaDB)
- Port 80 or another available port on the host
- Basic understanding of subnetting and VLANs
Docker Compose Configuration
Create a directory for phpIPAM:
mkdir -p /opt/phpipam && cd /opt/phpipam
Create a docker-compose.yml:
services:
phpipam-web:
image: phpipam/phpipam-www:v1.7.4
container_name: phpipam-web
ports:
- "8085:80"
environment:
TZ: "UTC"
IPAM_DATABASE_HOST: phpipam-mariadb
IPAM_DATABASE_USER: phpipam
IPAM_DATABASE_PASS: ${DB_PASSWORD}
IPAM_DATABASE_NAME: phpipam
IPAM_DATABASE_WEBHOST: "%"
volumes:
- phpipam-logo:/phpipam/css/images/logo
- phpipam-ca:/usr/local/share/ca-certificates:ro
depends_on:
phpipam-mariadb:
condition: service_healthy
restart: unless-stopped
phpipam-cron:
image: phpipam/phpipam-cron:v1.7.4
container_name: phpipam-cron
environment:
TZ: "UTC"
IPAM_DATABASE_HOST: phpipam-mariadb
IPAM_DATABASE_USER: phpipam
IPAM_DATABASE_PASS: ${DB_PASSWORD}
IPAM_DATABASE_NAME: phpipam
IPAM_DATABASE_WEBHOST: "%"
SCAN_INTERVAL: "1h"
volumes:
- phpipam-ca:/usr/local/share/ca-certificates:ro
depends_on:
phpipam-mariadb:
condition: service_healthy
restart: unless-stopped
phpipam-mariadb:
image: mariadb:11.7
container_name: phpipam-mariadb
environment:
MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- phpipam-db:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
timeout: 10s
retries: 5
restart: unless-stopped
volumes:
phpipam-db:
phpipam-logo:
phpipam-ca:
Create the .env file:
cat > /opt/phpipam/.env << 'EOF'
# CHANGE BOTH OF THESE VALUES
DB_PASSWORD=change-this-strong-password
DB_ROOT_PASSWORD=change-this-root-password
EOF
Start the stack:
docker compose up -d
Initial Setup
1. Run the Installer
Open http://your-server-ip:8085 in your browser. You’ll see the phpIPAM installation page.
- Click New phpipam installation
- Select Automatic database installation
- Enter the MariaDB root credentials:
- MySQL server:
phpipam-mariadb - MySQL user:
root - MySQL password: the
DB_ROOT_PASSWORDfrom your.env
- MySQL server:
- Click Install database
- Log in with default credentials: Admin / ipamadmin
- Change the admin password immediately
2. Configure Subnets
Navigate to Subnets and add your network ranges:
- Create a section (e.g., “Home Lab”)
- Add subnets:
192.168.1.0/24,10.0.0.0/24, etc. - Within each subnet, add individual IP assignments
3. Enable Network Scanning
The phpipam-cron container runs automated discovery every hour (configurable via SCAN_INTERVAL). To configure scanning:
- Go to Administration > Scan agents
- Verify the default scan agent is active
- Mark subnets for discovery under Subnet > Edit > Scan agent
Configuration
Environment Variables
| Variable | Default | Purpose |
|---|---|---|
IPAM_DATABASE_HOST | 127.0.0.1 | MariaDB hostname |
IPAM_DATABASE_USER | phpipam | Database user |
IPAM_DATABASE_PASS | phpipamadmin | Database password |
IPAM_DATABASE_NAME | phpipam | Database name |
IPAM_DATABASE_PORT | 3306 | Database port |
IPAM_TRUST_X_FORWARDED | false | Trust reverse proxy headers |
IPAM_DISABLE_INSTALLER | false | Lock out installer after setup |
SCAN_INTERVAL | 1h | Network scan frequency (cron container only) |
TZ | UTC | Timezone for scheduling |
Scan Interval Options
| Value | Frequency |
|---|---|
5m | Every 5 minutes |
15m | Every 15 minutes |
30m | Every 30 minutes |
1h | Hourly (default) |
2h | Every 2 hours |
4h | Every 4 hours |
12h | Twice daily |
Post-Install Security
After completing setup, disable the installer to prevent unauthorized access:
environment:
IPAM_DISABLE_INSTALLER: "true"
Restart the web container after making this change.
Key Features
| Feature | Description |
|---|---|
| Subnet management | Hierarchical subnet tracking with CIDR notation |
| VLAN management | VLAN numbering and assignment to subnets |
| VRF support | Virtual routing and forwarding context |
| Network scanning | Automated ping-based host discovery |
| DNS integration | Forward and reverse DNS lookups for IPs |
| SNMP scanning | Device discovery via SNMP |
| NAT tracking | NAT translation documentation |
| API (REST) | Full CRUD API for automation |
| Rack management | Basic rack and device location tracking |
| PowerDNS integration | Direct zone management if using PowerDNS |
Advanced Configuration
Reverse Proxy With HTTPS
When running behind a reverse proxy, enable forwarded header trust:
environment:
IPAM_TRUST_X_FORWARDED: "true"
API Access
Enable the API under Administration > phpIPAM settings > Feature settings > API. Then create an API application under Administration > API:
# List subnets
curl -u admin:your-password \
http://localhost:8085/api/myapp/subnets/
# Get specific subnet
curl -u admin:your-password \
http://localhost:8085/api/myapp/subnets/1/
Docker Secrets
phpIPAM supports Docker secrets via the _FILE suffix:
environment:
IPAM_DATABASE_PASS_FILE: /run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt
Multiple Web Replicas
For high availability, run multiple phpipam-www containers behind a load balancer. Set $session_storage = "database" in config.php to share sessions across instances. Only run one phpipam-cron container to prevent duplicate scan jobs.
Reverse Proxy
Route through Nginx Proxy Manager or Caddy for HTTPS:
Caddy:
ipam.yourdomain.com {
reverse_proxy localhost:8085
}
See Reverse Proxy Setup for detailed configuration.
Backup
Critical Data
| Data | Location | Method |
|---|---|---|
| All IP assignments, subnets, VLANs | MariaDB phpipam database | mysqldump |
| Custom logo | phpipam-logo volume | File copy |
| Configuration | .env + docker-compose.yml | File copy |
Backup Script
#!/bin/bash
BACKUP_DIR="/opt/backups/phpipam/$(date +%F)"
mkdir -p "$BACKUP_DIR"
docker exec phpipam-mariadb mysqldump -u root -p"$DB_ROOT_PASSWORD" phpipam > "$BACKUP_DIR/phpipam.sql"
cp /opt/phpipam/.env "$BACKUP_DIR/"
cp /opt/phpipam/docker-compose.yml "$BACKUP_DIR/"
See Backup Strategy for the 3-2-1 approach.
Troubleshooting
Installer Shows “Could not connect to database”
Symptom: Installation step fails at database connection
Fix: Verify MariaDB is healthy and the root password is correct:
docker compose ps phpipam-mariadb
docker compose logs phpipam-mariadb
The MYSQL_ROOT_PASSWORD in your .env must match what the installer uses.
Automated Scans Not Running
Symptom: Network discovery shows no results after configuring subnets
Fix: Verify the cron container is running:
docker compose ps phpipam-cron
docker compose logs phpipam-cron
Ensure the subnet has a scan agent assigned (edit the subnet in the web UI).
”Permission denied” on Ping Scans
Symptom: Scan results show all hosts as down even when they’re up
Fix: phpIPAM needs NET_ADMIN and NET_RAW capabilities for ping. If your Docker setup restricts capabilities, add them explicitly:
cap_add:
- NET_ADMIN
- NET_RAW
White Screen After Login
Symptom: Login succeeds but page is blank
Fix: Usually a PHP session issue. Restart the web container:
docker compose restart phpipam-web
If behind a reverse proxy, ensure IPAM_TRUST_X_FORWARDED=true is set.
Resource Requirements
| Resource | Value |
|---|---|
| RAM | ~250 MB total (phpIPAM ~80 MB + MariaDB ~150 MB + Cron ~20 MB) |
| CPU | Low — lightweight PHP application |
| Disk | ~300 MB for containers + database grows with IP count |
| Network | Minimal; ICMP outbound needed for network scanning |
Verdict
For straightforward IP address management, phpIPAM hits the right balance between capability and simplicity. The web UI is clean, network scanning works out of the box, and the two-container architecture (web + cron) is easy to maintain. It does one job well — tracking IPs, subnets, and VLANs — without forcing you to model your entire data center.
If you need comprehensive infrastructure documentation (racks, cables, circuits, devices), NetBox is the more complete tool. See NetBox vs phpIPAM for a detailed comparison. For most homelabs where the main goal is “stop using a spreadsheet for IP assignments,” phpIPAM is the faster path.
FAQ
Can phpIPAM manage DNS records?
phpIPAM can look up forward and reverse DNS for tracked IPs, but it doesn’t serve DNS. It integrates with PowerDNS for direct zone management if you use both tools.
What’s the difference between phpIPAM and NetBox?
phpIPAM focuses on IP address management. NetBox is a full infrastructure documentation platform that includes IPAM plus device tracking, rack management, circuit documentation, and more. phpIPAM is lighter; NetBox is more comprehensive.
Is the phpipam-cron container required?
No — phpIPAM works without it. You lose automated network scanning, but all manual IP management features work. Add the cron container when you want automated host discovery.
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