Skip to content

phpIPAM

phpIPAM is an open-source web IP address management application (IPAM). Its goal is to provide light, modern and useful IP address management. It is php-based application with MySQL database backend, using jQuery libraries, ajax and HTML5/CSS3 features.

phpIPAM Screenshot

phpIPAM fulfils a non-sexy, but important role - It helps you manage your IP address allocation.

Why should you care about this?

You probably have a home network, with 20-30 IP addresses, for your family devices, your IoT devices, your smart TV, etc. If you want to (a) monitor them, and (b) audit who does what, you care about what IPs they're assigned by your DHCP server.

You could simple keep track of all devices with leases in your DHCP server, but what happens if your (hypothetical?) Ubiquity Edge Router X crashes and burns due to lack of disk space, and you loose track of all your leases? Well, you have to start from scratch, is what!

And that HomeAssistant config, which you so carefully compiled, refers to each device by IP/DNS name, so you'd better make sure you recreate it consistently!

Enter phpIPAM. A tool designed to help home keeps as well as large organisations keep track of their IP (and VLAN, VRF, and AS number) allocations.

phpIPAM Requirements

Ingredients

Already deployed:

Related:

Preparation

Setup data locations

We'll need several directories to bind-mount into our container, so create them in /var/data/phpipam:

mkdir /var/data/phpipam/databases-dump -p
mkdir /var/data/runtime/phpipam -p

Prepare phpIPAM environment

Create phpipam.env, and populate with the following variables

# Setup for github, phpipam application
OAUTH2_PROXY_CLIENT_ID=
OAUTH2_PROXY_CLIENT_SECRET=
OAUTH2_PROXY_COOKIE_SECRET=

# For MariaDB/MySQL database
MYSQL_ROOT_PASSWORD=imtoosecretformyshorts
MYSQL_DATABASE=phpipam
MYSQL_USER=phpipam
MYSQL_PASSWORD=secret

# phpIPAM-specific variables
MYSQL_ENV_MYSQL_USER=phpipam
MYSQL_ENV_MYSQL_PASSWORD=secret
MYSQL_ENV_MYSQL_DB=phpipam
MYSQL_ENV_MYSQL_HOST=db

# For backup
BACKUP_NUM_KEEP=7
BACKUP_FREQUENCY=1d

Additionally, create phpipam-backup.env, and populate with the following variables:

# For MariaDB/MySQL database
MYSQL_ROOT_PASSWORD=imtoosecretformyshorts
MYSQL_DATABASE=phpipam
MYSQL_USER=phpipam
MYSQL_PASSWORD=secret

# For backup
BACKUP_NUM_KEEP=7
BACKUP_FREQUENCY=1d

phpIPAM Docker Swarm config

Create a docker swarm config file in docker-compose syntax (v3), something like the example below:

Fast-track with premix! 🚀

"Premix" is a git repository which includes necessary docker-compose and env files for all published recipes. This means that you can launch any recipe with just a git pull and a docker stack deploy 👍.

🚀 Update: Premix now includes an ansible playbook, enabling you to deploy an entire stack + recipes, with a single ansible command! (more here)

version: '3'

services:

  db:
    image: mariadb:10
    env_file: /var/data/config/phpipam/phpipam.env
    networks:
      - internal
    volumes:
      - /var/data/runtime/phpipam/db:/var/lib/mysql

  app:
    image: pierrecdn/phpipam
    env_file: /var/data/config/phpipam/phpipam.env
    networks:
      - internal
      - traefik_public
    deploy:
      labels:
        # traefik common
        - "traefik.enable=true"
        - "traefik.docker.network=traefik_public"

        # traefikv1
        - "traefik.frontend.rule=Host:phpipam.example.com"
        - "traefik.port=80"
        - traefik.frontend.auth.forward.address=http://traefik-forward-auth:4181
        - traefik.frontend.auth.forward.authResponseHeaders=X-Forwarded-User
        - traefik.frontend.auth.forward.trustForwardHeader=true           

        # traefikv2
        - "traefik.http.routers.phpipam.rule=Host(`phpipam.example.com`)"
        - "traefik.http.routers.phpipam.entrypoints=https"
        - "traefik.http.services.phpipam.loadbalancer.server.port=80" 
        - "traefik.http.routers.api.middlewares=forward-auth"           

  db-backup:
    image: mariadb:10
    env_file: /var/data/config/phpipam/phpipam.env
    volumes:
      - /var/data/phpipam/database-dump:/dump
      - /etc/localtime:/etc/localtime:ro
    entrypoint: |
      bash -c 'bash -s <<EOF
      trap "break;exit" SIGHUP SIGINT SIGTERM
      sleep 2m
      while /bin/true; do
        mysqldump -h db --all-databases | gzip -c > /dump/dump_\`date +%d-%m-%Y"_"%H_%M_%S\`.sql.gz
        (ls -t /dump/dump*.sql.gz|head -n $$BACKUP_NUM_KEEP;ls /dump/dump*.sql.gz)|sort|uniq -u|xargs rm -- {}
        sleep $$BACKUP_FREQUENCY
      done
      EOF'
    networks:
      - internal

networks:
  traefik_public:
    external: true
  internal:
    driver: overlay
    ipam:
      config:
        - subnet: 172.16.47.0/24

Note

Setup unique static subnets for every stack you deploy. This avoids IP/gateway conflicts which can otherwise occur when you're creating/removing stacks a lot. See my list here.

Serving

Launch phpIPAM stack

Launch the phpIPAM stack by running docker stack deploy phpipam -c <path -to-docker-compose.yml>

Log into your new instance at https://YOUR-FQDN, and follow the on-screen prompts to set your first user/password.

Chef's notes 📓


  1. If you wanted to expose the phpIPAM UI directly, you could remove the traefik.http.routers.api.middlewares label from the app container 👍 

Tip your waiter (sponsor) 👏

Did you receive excellent service? Want to compliment the chef? (..and support development of current and future recipes!) Sponsor me on Github / Ko-Fi / Patreon, or see the contribute page for more (free or paid) ways to say thank you! 👏

Employ your chef (engage) 🤝

Is this too much of a geeky PITA? Do you just want results, stat? I do this for a living - I'm a full-time Kubernetes contractor, providing consulting and engineering expertise to businesses needing short-term, short-notice support in the cloud-native space, including AWS/Azure/GKE, Kubernetes, CI/CD and automation.

Learn more about working with me here.

Flirt with waiter (subscribe) 💌

Want to know now when this recipe gets updated, or when future recipes are added? Subscribe to the RSS feed, or leave your email address below, and we'll keep you updated.

Your comments? 💬