How to deploy a phpIPAM server with external MySQL database on AWS RDS
As usual this is just a somewhat niche thing that I found myself working on and that had me struggling for a bit there. The main obstacle being the fact that the automatic configuration offered by phpIPAM didn’t work as expected. So I had to grind a little harder then usual but in the end everything worked as expected.
What is phpIPAM
phpIPAM is an open-source web-based IP address management platform which simplify IP address management for network administrators in your organisation. — Random Blog Article
At Simbase we use it as a lightweight tool to assign private IP addresses to simcards when they are provisioned.
Because of the nature of the job it performs, it can only work with relational databases. It supports MySQL and MariaDB out of the box. In this case I’ve decided to go with MySQL.
Internal or external DB
When you deploy your phpIPAM you can decide whether you want to use a local db instance running alongside the server itself or if you want to specify an external instance. In our case, due to the importance of maintaining the service active, we decided to opt for a highly-available multi AZ instance on AWS RDS, pretty much the gold-standard.
Deployment approach
I’m a big Docker fan. I love how complex deployments can be simplified by running a container. And nothing makes me happier than finding an official image on the Docker Hub that is actively maintained.
Step by step guide
I’m going to leave out any details concerning VPCs, security groups, VPNs, etc. I’m going to assume that you know how to connect your server instance to your db, and that you can access your server instance via SSH.
Step 1: Create your RDS database (or other)
Wherever you create your database, you will need to have an host, a username and a password. The types of DB accepted are MariaDB and MySQL.
When you create a “database instance” on a service like AWS RDS, you’re not quite yet creating the database that hosts the table that will help you persist your data. But rather you’re creating a virtual machine that runs the software that enables you to create your own database.
This virtual machine already contains a few other databases used to store permissions and other system-level informations that are necessary for the service to run successfully.
If you delete any of the existing databases or the tables they contain and you don’t have a backup or snapshot, you’ll have to dump the current db and spin up a new one.
By default an RDS MySQL database will come with the sys, mysql, performance_schema, information_schema
databases.
Step 2: Configure your MySQL database
At this point it matters little if your MySQL database is running in an RDS instance or on a donkey’s back. Once you’re connected to it the commands will run exactly the same.
The first thing to do is to connect to the MySQL instance via CLI:
If you don’t have
mysql
installed, you can follow the steps outlined here.
mysql -h database.endpoint.url -u username -p
# if it works it will show this prompt:
mysql>
Congratulations, you’re in the mysql console. Here you communicate to the database engine in pure SQL. Let’s see if we’re int the right place:
mysql>show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| performance_schema |
| mysql |
| sys |
+--------------------+
4 rows in set (0.00 sec)
Great. The next steps are creating a new database, setting up the permissions so that our user can create and update tables, and last but not least, applying the SCHEMA.sql file provided by phpIPAM.
These are exactly the same operations that would be performed under the hood by the phpIPAM automatic installation process, with the exception that it doesn’t work. — Me
Step 2.1: Create the database in the database server
Im calling the database phpipam. It will be called the same in all following examples.
mysql>create database phpipam;
Step 2.2: Create a user with credentials matching your remote DB and update permissions
mysql>CREATE USER 'username'@'your-ip-address' IDENTIFIED BY 'password';
mysqq>GRANT ALL ON phpipam.* TO 'username'@'your-ip-address';
In this example I’m accessing the database through an EC2 instance which is in the same VPC as the RDS instance. Instead of your-ip-address
I entered the private IP of the EC2 instance, but I also had to make sure that the db and the EC2 had access to each other’s firewall.
If your resources are not in a VPC, your-ip-address
will be your public IP.
Step 3.3: Apply schema to database
Quit the MySQL console and return to your command line from which you ran the previous mysql
command.
Create a new file and paste inside the contents of the SCHEMA.sql file. This file contains a long list of SQL statements that will configure all the db tables for you. You can apply this commands remotely to your database with the followng command:
mysql -h database.endpoint.url -u username -p phpipam < SCHEMA.sql
Alright, that should be it on the db setup and configuration side!
Step 3: Launch the instance that will host the phpIPAM server and install Docker
I’m working with Ubuntu here. I find the Docker convenience script to be in fact super convenient. If you are using some other distro make sure that you have docker and “docker compose” working (not “docker-compose” which is deprecated).
Step 2: The compose.yml file
I use VIM to edit files in the shell. I thought it’d be tedious to report all the VIM commands so I’m omitting them.
Create a /var/script
folder and navigate there (or anywhere else you’re comfortable working in your Linux instance).
In that folder we’re gonna place the compose.yml
file from the example in the Docker Hub page and make just a small change. Instead of leaving the environment variables inside it, we’re moving them out to an .env
file.
This here is the edited version of compose.yml
.
As you can see, instead of environment
we have env_file
that refers to a file named .env
. The next step is to make that file:
Security
Go back to the CLI and write:
sudo chmod 600 .env
This will allow only users with root-level privileges to have read/write access to the file.
There are indeed safer, more articulate, approaches to security. But I’m not going to delve into them as they’re not the focus of this article.
Just to give you some inspiration in case this is important to you:
- store your sensitive strings on a service like AWS Secrets Manager
- Write a launch script in bash, that fetches those strings. Of course you’ll have to assign a role to your EC2 instance that allow it to get to those secrets.
- Within the same script, launch the phpIPAM docker container using
docker run
instad ofdocker compose
, and pass those strings in the form of variables as environment variables into the container with the-e
flag. - Of course the first layer of security should always be around firewalls and private networks.
Step 3: Launching the service and first login
Back to your CLI:
docker compose up --build -d
The --build
flag is just to ensure that you’re loading any new environment variables. Otherwise you’d be running a previous version of the container.
The -d
flag stands for “detached” and it just makes it so you maintain the use of your terminal. If you want to see the logs you can look into the docker logs
command.
Ok, great! The service should be running, let’s go take a look!
If you access your host machine’s IP address from your browser you should see this:
Everything is already configured so you can click on “Working Installation”.
The phpIPAM server should check the connection to the db, and once it establishes it you’ll be redirected to the login page:
Login the first time with:
- Username: admin
- Password: ipamadmin
You will be forced to change the password at the first login.
Congratulations!! You made it!
If you ever are in need to reset the admin password, just follow the instructions on this page.