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.

  1. Click New phpipam installation
  2. Select Automatic database installation
  3. Enter the MariaDB root credentials:
    • MySQL server: phpipam-mariadb
    • MySQL user: root
    • MySQL password: the DB_ROOT_PASSWORD from your .env
  4. Click Install database
  5. Log in with default credentials: Admin / ipamadmin
  6. Change the admin password immediately

2. Configure Subnets

Navigate to Subnets and add your network ranges:

  1. Create a section (e.g., “Home Lab”)
  2. Add subnets: 192.168.1.0/24, 10.0.0.0/24, etc.
  3. 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:

  1. Go to Administration > Scan agents
  2. Verify the default scan agent is active
  3. Mark subnets for discovery under Subnet > Edit > Scan agent

Configuration

Environment Variables

VariableDefaultPurpose
IPAM_DATABASE_HOST127.0.0.1MariaDB hostname
IPAM_DATABASE_USERphpipamDatabase user
IPAM_DATABASE_PASSphpipamadminDatabase password
IPAM_DATABASE_NAMEphpipamDatabase name
IPAM_DATABASE_PORT3306Database port
IPAM_TRUST_X_FORWARDEDfalseTrust reverse proxy headers
IPAM_DISABLE_INSTALLERfalseLock out installer after setup
SCAN_INTERVAL1hNetwork scan frequency (cron container only)
TZUTCTimezone for scheduling

Scan Interval Options

ValueFrequency
5mEvery 5 minutes
15mEvery 15 minutes
30mEvery 30 minutes
1hHourly (default)
2hEvery 2 hours
4hEvery 4 hours
12hTwice 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

FeatureDescription
Subnet managementHierarchical subnet tracking with CIDR notation
VLAN managementVLAN numbering and assignment to subnets
VRF supportVirtual routing and forwarding context
Network scanningAutomated ping-based host discovery
DNS integrationForward and reverse DNS lookups for IPs
SNMP scanningDevice discovery via SNMP
NAT trackingNAT translation documentation
API (REST)Full CRUD API for automation
Rack managementBasic rack and device location tracking
PowerDNS integrationDirect 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

DataLocationMethod
All IP assignments, subnets, VLANsMariaDB phpipam databasemysqldump
Custom logophpipam-logo volumeFile copy
Configuration.env + docker-compose.ymlFile 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

ResourceValue
RAM~250 MB total (phpIPAM ~80 MB + MariaDB ~150 MB + Cron ~20 MB)
CPULow — lightweight PHP application
Disk~300 MB for containers + database grows with IP count
NetworkMinimal; 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.

Comments