One of the reasons we share what we do is that others might benefit from our experience. This is hopefully one of those blog posts, which explains how we made something work. More specifically, it explains how we installed the Omada Software Controller on a Raspberry Pi using Docker, set the SMTP options to send emails through Gmail, and finally set up an HTTPS certificate for the portal.

You’ll need to be moderately confident if you’re following these instructions, although if you’re confident enough to be trying to set up a managed network you should be fine.


Some of our networking equipment (and we’re slowly moving towards all of our networking equipment) is managed using something called Software Defined Networking. We’ve got a few reasons for this, but the upshot of this decision is that somewhere on our network we need something to orchestrate what’s going on. This is the “controller”, and since we’re using things in TP-Link’s Omada family, we need an Omada controller.

Purchasing a dedicated hardware appliance to do this job is on our list as part of some future upgrades, but to get things started we installed the Omada Software Controller on the PC on our tech desk. This had a few problems, primarily around the system going to sleep or restarting to install updates. This meant that the controller would occasionally disconnect for a few minutes, or disconnect entirely until someone manually restarted it.

We could have worked around this by adjusting schedules and configuring the application to boot on startup, but we’d still be left with one PC doing some things it wasn’t really meant to be doing in the first place.

Fortunately, there’s a solution which didn’t involve buying a new thing. We had a spare Raspberry Pi kicking around, and you can turn one into a controller. So we did. Here’s how.

Get the Raspberry Pi ready

A clean machine makes things easier. If you already have a working Raspberry Pi feel free to skip these, but we included them for completeness.

Install a clean version of Raspberry Pi OS

We installed a completely clean version of Raspberry Pi OS Lite. We chose the Lite version because the whole thing was going to be running headless. Out of the box, Raspberry Pi OS has SSH disabled, so we did use a keyboard, mouse and monitor for initial setup.

Change the password

It’s good policy to not use the default username and password. You should change your password using the passwd command. The pi user remains the same.

Enable SSH

To allow us to manage the Raspberry Pi remotely, use the sudo raspi-config command to enable SSH (under “interfaces”). At this point we switched to using SSH from another machine, so we could more easily paste in commands, but you can continue to use directly attached devices if you want.

Update software

Updated software is good. Update your software using sudo apt update and sudo apt upgrade.

Get the controller running in Docker

There isn’t a version of Omada Software Controller which runs natively on a Raspberry Pi. Fortunately, Docker can solve this problem and someone has already created an image that does the hard work.

Install Docker

Docker and its install script play nicely out of the box with Raspberry Pi. Install Docker using these commands:

$ curl -fsSL -o
$ sh

As always, double-check that you trust what a script is doing before running it.

We had to reboot (shutdown -r now) to get the Docker daemon to start cleanly.

Fire up the Software Controller container

This is mostly based on the instructions in the Docker Hub image, with an important tweak from a Github issue.

Create and start the Software Controller container using the following command:

$ docker run -d \
  --name omada-controller \
  --restart unless-stopped \
  --net host \
  -e MANAGE_HTTP_PORT=8088 \
  -e PORTAL_HTTP_PORT=8088 \
  -e SHOW_SERVER_LOGS=true \
  -e SHOW_MONGODB_LOGS=false \
  -e SSL_CERT_NAME="tls.crt" \
  -e SSL_KEY_NAME="tls.key" \
  -e TZ=Etc/UTC \
  -e TLS_1_11_ENABLED=true \
  -v omada-data:/opt/tplink/EAPController/data \
  -v omada-work:/opt/tplink/EAPController/work \
  -v omada-logs:/opt/tplink/EAPController/logs \

Docker should then do its thing of downloading the various bits and pieces it needs, creating a new container and hooking it up to the network. Instructions on what the various environment variables do are on Docker Hub.

It didn’t affect us, but it’s worth knowing that many of these variables are only used the first time the controller starts, and then their values are stored in the database.

You will need to wait for the controller to finish booting, and first time around this can take several minutes. If you’re curious, docker logs --follow omada-controller will let you see what’s going on inside the container.

Head to the controller in a browser

Since your Raspberry Pi doesn’t have a browser (assuming it’s the Lite OS, or you’re connected via SSH) you’ll need to open a browser and visit the controller’s webpage. Swap out this IP for your own.

If you run into an insecure content warning, don’t panic. You can usually click “advanced” or similar to get an option to continue regardless. If you’re on Chrome, you might need to type the magic word thisisunsafe into the warning page. Don’t worry if you don’t see anything appearing, once you finish typing it should carry on.

Set up the controller

Once you’re connected, you should be guided to set up the controller for the first time. This will cover creating accounts, adopting devices, creating networks and so-on.

Set up SMTP for Gmail

This was a bit of a tricky one, because of a problem with the latest version of JDK. Fortunately, we setTLS_1_11_ENABLED=true in the setup process for the container, so we work around that particular bug.

Because we’re using Google Workspace, we could use Gmail’s SMTP relay service to make this step easier. If you don’t use Google Workspace you will probably need to use the regular SMTP server, and tweak the following steps accordingly.

Get your email credentials

You’ll need an account to send emails from. We decided to create a new user in Google Workspace just for the Omada controller, although you can reuse one if you prefer.

The credentials you’ll need are the full email address, and the password.

Sign in at least once

You’ll need to sign in to Gmail at least once as the new user to accept the terms and conditions and activate the account.

Configure routing in Gmail

Visit the Gmail routing setup in Workspace Admin.

Configure the routing rule to only send from users in your domain, require SMTP authentication and not to require TLS.

Configure SMTP in the controller

Within the Omada controller, head to Admin in the menu, followed by Controller, and then find the section labelled “Mail Server“.

Tick the box to enable the email server, then configure as follows:

  • SMTP:
  • Port: 465
  • SSL: Enabled
  • Authentication: Enabled
  • Username: The (full) new email address you created for this account
  • Password: The password for this account
  • Sender Address: The email address as above

You can then enter your own email address under “Test SMTP Server” and click “Send”. After a few seconds, you should get a “Success” message.

Save the changes using the link at the bottom of the page.

Set up an HTTPS certificate

Since we want to use our controller to guide people through a network portal, we need to make sure browsers don’t balk at invalid certificates. It’s also good practice to make sure certificates are properly in place and you’re not just bypassing browser security.

If you’re happy to keep telling your browser to ignore the unsafe warning and have no plans to use the portal, you can stop here. Otherwise, let’s get HTTPS up and working.

Set up a fixed IP

Before you can get a certificate, you’ll need your controller to be accessible at a specific domain. To do this, it needs a fixed IP address on your internal network.

The exact method for doing this depends very much on your existing network configuration, but you will need to assign a static IP address to the Raspberry Pi in your DHCP configuration. Make a note of this IP, you’ll need it for the next step.

Set up a domain name

You can’t get a certificate for an IP address, so you’ll need to create a domain name for your controller and point it at the IP of your controller. We put all our internal things in a .intra subdomain, eg You can use whatever domain you like (as long as you control it).

Heads up: Your DNS servers may be implementing DNS rebinding protection, which can break this behaviour if they drop local IP responses.

Get a certificate

To get a certificate we used the free tier of ZeroSSL. Certificates generated through this expire every 90 days, so we’re happy to re-evaluate this in future, but for now we’re just rotating them every few months. You need to generate a new certificate for your domain name, and auto-generate the CSR. The Omada Controller isn’t capable of creating its own CSR

For validating the internal domain, you’ll need to make another DNS change.

Combine the certificate and key

The Omada controller only supports uploading one file, so you need to combine the certificate and key. The invocation to do this on Linux or Mac is below, if you’re on Windows I’m afraid you’ll need to solve this on your own:

$ openssl pkcs12 -export -out certificate_out.pfx -inkey private.key -in certificate.crt

When prompted, add your own password. At the end of this you should have a new certificate_out.pfx file, ready to be fed to the controller.

Upload the certificate and configure the controller

In the Omada controller menu, head to “Settings” and then “Controller”. Under the “HTTPS Certificate” section you will need to import the pfx file you created in the last step and then add the keystore password you entered in the last step. There is no private key password.

In the next section “Access Control”, set the “Controller Hostname/IP” to the new domain name you created. Make sure you leave the port settings intact.

Save all your settings, and restart the controller so they take effect.

Tadaa! 🎉

You’re done! You should now be able to visit the new domain you set up (at the right port) and end up at your controller’s sign-in page with a valid certificate.

If this was useful, we’d love to hear. If not, we’d love to hear that as well. Drop an email to [email protected] with your comments!