Set up strongMan on Ubuntu 22.04 — a Web UI for strongSwan VPN solution

Kenneth KOFFI
5 min readNov 18, 2023

--

from Unsplash

Recently, I explored the WireGuard VPN solution and was pleasantly surprised by its user-friendly setup. Setting up a VPN server with a sleek graphical interface took just a few commands. Given that I use strongSwan at my workplace, I envisioned having a similar graphical interface for it. A quick Google search revealed that such a project already exists: StrongMan-a graphical web UI designed for StrongSwan. Excited to try it out, I encountered some difficulties getting it to run smoothly on my Ubuntu 22.04 host. In this write-up, I’ll share with you the process I went through to get it up and running.

Install strongSwan

First, update your local package cache using apt:

sudo apt update

Then install the software by typing:

sudo apt install strongswan strongswan-pki strongswan-swanctl -y
  • strongswan-pki package comes with a utility called pki to generate a Certificate Authority and server certificates.
  • strongswan-swanctl package comes with the Versatile IKE Control Interface (VICI) plugin

strongMan connects to the IKE daemon via VICI protocol, so you need to make sure that the VICI plugin is loaded:

sudo ipsec listplugins | grep -i vici

You should have an output as below:

vici:
CUSTOM:vici

Install the dependencies

Install python:

sudo apt install python3-pip -y

Install virtualenv:

sudo python3 -m pip install virtualenv

Make alias for python:

sudo ln -s /usr/bin/python3 /usr/bin/python

Install strongMan

Run the following commands to install strongMan:

git clone https://github.com/strongswan/strongMan.git
cd strongMan
sudo ./setup.py install

If things went smoothly, you will get an output as below:

Start strongMan installation
- Virtualenv
- Requirements
- Database migration
Delete strongMan/db.sqlite3
[Errno 2] No such file or directory: '/root/strongMan/strongMan/db.sqlite3'
- Static files

Please be aware that the [Errno 2] No such file or directory: '/home/ubuntu/strongMan/strongMan/db.sqlite3' message in the preceding output is not a critical error; think of it more like a log entry. There's no need to worry. Initially, it might seem confusing-I fell for it myself the first time, thinking there was an issue. However, it's just a benign notification, and everything is actually functioning properly.

Set the environment to production

Replace strongMan.settings.local by strongMan.settings.production in the run.py file. Otherwise, you might get a Invalid HTTP_POST header error.

Invalid HTTP_POST header

You can use your fav code editor or simply do it from the command line using:

sed -i 's/strongMan.settings.local/strongMan.settings.production/g' run.py

Configuration loader

To guarantee data consistency between strongMan and strongSwan, we need to make sure that the configuration loader script will be executed on the startup of strongSwan.

Put the following line into “strongswan-starter.service”. Replace “pathTostrongMan” with the path, where you installed strongMan.

ExecStartPost=/pathTostrongMan/configloader.py

Sample of the /lib/systemd/system/strongswan-starter.service file:

[Unit]
Description=strongSwan IPsec IKEv1/IKEv2 daemon using ipsec.conf
After=network-online.target

[Service]
ExecStart=/usr/sbin/ipsec start --nofork
ExecReload=/usr/sbin/ipsec reload
Restart=on-abnormal
ExecStartPost=/root/strongMan/configloader.py

[Install]
WantedBy=multi-user.target

Reload for changes to take effect:

sudo systemctl daemon-reload
sudo systemctl restart strongswan-starter.service

Add a systemd service

If you want to run strongMan permanently in the background, you can install strongMan as a systemd service.

sudo ./setup.py add-service

Check if it’s working:

sudo systemctl status strongMan

You might get an output as below:

● strongMan.service - strongMan gunicorn service
Loaded: loaded (/etc/systemd/system/strongMan.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2023-11-18 11:29:54 UTC; 8s ago
Main PID: 28150 (python)
Tasks: 8 (limit: 2309)
Memory: 211.1M
CPU: 2.680s
CGroup: /system.slice/strongMan.service
├─28150 /root/strongMan/env/bin/python run.py
├─28152 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>
├─28153 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>
├─28154 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>
├─28155 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>
├─28156 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>
├─28157 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>
└─28158 /root/strongMan/env/bin/python /root/strongMan/env/bin/gunicorn --workers 6 --bind 0.0.0.0:1515 --env DJANGO_SETTINGS_MODULE=strongMan.s>

Nov 18 11:29:54 strongman systemd[1]: Started strongMan gunicorn service.
Nov 18 11:29:55 strongman python[28152]: [2023-11-18 11:29:55 +0000] [28152] [INFO] Starting gunicorn 20.0.4
Nov 18 11:29:55 strongman python[28152]: [2023-11-18 11:29:55 +0000] [28152] [INFO] Listening at: http://0.0.0.0:1515 (28152)
Nov 18 11:29:55 strongman python[28152]: [2023-11-18 11:29:55 +0000] [28152] [INFO] Using worker: sync
Nov 18 11:29:55 strongman python[28153]: [2023-11-18 11:29:55 +0000] [28153] [INFO] Booting worker with pid: 28153
Nov 18 11:29:55 strongman python[28154]: [2023-11-18 11:29:55 +0000] [28154] [INFO] Booting worker with pid: 28154
Nov 18 11:29:55 strongman python[28155]: [2023-11-18 11:29:55 +0000] [28155] [INFO] Booting worker with pid: 28155
Nov 18 11:29:55 strongman python[28156]: [2023-11-18 11:29:55 +0000] [28156] [INFO] Booting worker with pid: 28156
Nov 18 11:29:55 strongman python[28157]: [2023-11-18 11:29:55 +0000] [28157] [INFO] Booting worker with pid: 28157
Nov 18 11:29:55 strongman python[28158]: [2023-11-18 11:29:55 +0000] [28158] [INFO] Booting worker with pid: 28158

You now have strongMan service listening on http://your-server-IP:1515. Likewise, you can now log in to the web UI with:

  • Username: John
  • Password: Lennon@1940
StrongMan login page

That’s it!

Bonus

If you’re a fan of Ansible and embrace the concept of Infrastructure as Code, I have a playbook ready to effortlessly automate the entire installation process for you.

- name: Install strongMan
hosts: all
tasks:
- name: Update cache
become: true
ansible.builtin.apt:
update_cache: true

- name: Install strongswan
become: true
ansible.builtin.apt:
name:
- strongswan
- strongswan-pki
- strongswan-swanctl
state: present

- name: Install python3 and virtualenv
become: true
ansible.builtin.apt:
name:
- python3
- python3-virtualenv
- python3-pip
state: present

- name: Create a symbolic link
become: true
ansible.builtin.file:
src: /usr/bin/python3
dest: /usr/bin/python
state: link

- name: Clone strongMan repo
ansible.builtin.git:
repo: 'https://github.com/strongswan/strongMan.git'
dest: "{{ ansible_env.HOME }}/strongMan"
force: true

- name: Install strongMan
become: true
ansible.builtin.command:
cmd: sudo ./setup.py install
chdir: "{{ ansible_env.HOME }}/strongMan"

- name: Set the environment to production
ansible.builtin.replace:
path: "{{ ansible_env.HOME }}/strongMan/run.py"
regexp: 'strongMan\.settings\.local'
replace: 'strongMan.settings.production'

- name: Configuration loader
become: true
ansible.builtin.lineinfile:
path: /lib/systemd/system/strongswan-starter.service
insertafter: '^Restart=on-abnormal\n'
line: 'ExecStartPost={{ ansible_env.HOME }}/strongMan/configloader.py'
notify: Restart strongswan-starter service

- name: Add strongMan service
become: true
ansible.builtin.command:
cmd: sudo ./setup.py add-service
chdir: "{{ ansible_env.HOME }}/strongMan"
notify: Restart strongMan service

handlers:
- name: Restart strongswan-starter service
become: true
ansible.builtin.systemd_service:
state: restarted
daemon_reload: true
name: strongswan-starter.service

- name: Restart strongMan service
become: true
ansible.builtin.systemd_service:
state: restarted
daemon_reload: true
name: strongMan.service

What’s next?

Now that you have strongMan installed, take a look at this article of mine to learn how to set up an IKEv2 Point-to-Site VPN with it.

Thank you for reading this article all the way to the end! I hope you found the information and insights shared here to be valuable and interesting. Get in touch with me on LinkedIn

I appreciate your support and look forward to sharing more content with you in the future. Until next time!

References

Originally published at https://theko2fi.github.io on November 18, 2023.

--

--

Kenneth KOFFI
Kenneth KOFFI

Written by Kenneth KOFFI

Administrateur systèmes avec une appétence pour le Cloud et le DevOps