All you need is two fresh servers
Ubuntu 22.04 or newer, internet access, and root. That is the entire shopping list. This page assumes you have never set up something like this before and explains what each step is doing as it goes.
Before you start
What you need
One or two servers
Running Ubuntu 22.04 or newer. One works and gives you everything except failover. Two is what this is designed around.
Four processors and four gigabytes of memory is comfortable for most workloads. nginx itself is famously light.
Root access on both
The installer has to add software and start services. If you can run
sudo, you have what you need.
Internet access
The installer downloads Docker, the code and the nginx sources. Both servers also need to be reachable from the internet on their own public addresses.
A domain name you control
For certificates, and for DNS failover later. You need to be able to add records at whoever runs your domain.
Ports that need to be open
| Port | Transport | Used for | Who needs to reach it |
|---|---|---|---|
80 | TCP | Ordinary web traffic, and certificate checks | Everyone |
443 | TCP, and UDP too | Secure web traffic. The UDP half is only needed if you turn on HTTP/3 | Everyone |
7443 | TCP | The management screen | Your staff only |
7444 | TCP | The two servers talking to each other | The other server only |
53 | UDP, and TCP too | DNS failover, if you use it. Lookups arrive on UDP and fall back to TCP when the answer is large | Everyone |
51820 | UDP | The tunnel, if you use it. Your workloads dial out to here, so nothing inbound is needed at their end | Your tunneled workloads |
You will also see port 5353, on UDP and TCP, if you go looking. That is where the
DNS part really listens, because a program without root cannot bind port 53. A firewall rule
the software manages sends port 53 to it. You never open 5353 yourself and you never test
against it.
Port 7443 should not be open to the whole internet
It is the management screen. The installer asks which networks may reach it and you should tell it. Without that, anybody who can reach the port gets the login page.
The install
Six steps, and two of them are just waiting
-
Get a terminal on the first server
On a Mac or on Linux, open the Terminal application. On Windows, open PowerShell. Then connect:
ssh root@203.0.113.10From here on, a line you type is shown on its own. Everything the server prints back is shown in the player beside this. You do not type the dollar sign if you see one.
-
Install the manager
One command. It fetches the code, sets up Docker if it is missing, and starts the management screen.
sudo git clone https://git.failoverlb.net/failoverlb.git /data/docker/failoverlb \ && sudo /data/docker/failoverlb/failoverlb_setup.sh \ --allowlist 198.51.100.25/32 \ --acme-email you@example.comThe allowlist is the list of networks allowed to open the management screen. Put your office public address followed by
/32. If you are not sure what it is, visit any website that reports your public address and use that.The email is where the certificate authority sends expiry warnings. It is optional. Use a shared mailbox rather than somebody's personal address.
-
Build nginx
The manager manages an nginx, it does not bring its own. This step takes the longest because it compiles nginx 1.30.4 from source against OpenSSL 3.5.7 with every module the screen knows how to configure.
sudo /data/docker/failoverlb/nginx-installer.sh installGo and make a coffee. It is a few minutes on a normal box.
Replayed from a real run on a clean Ubuntu 26.04 machine. Press play to watch it again, or click the bar to see it all at once.
-
Sign in for the first time
Open the address the installer printed, which looks like
https://203.0.113.10:7443.Your browser will warn you that the connection is not private. That is expected. The server made its own certificate during installation and no browser has been told to trust it. Continue past the warning. You can replace it with a real certificate later.
Find the first password in the log:
cd /data/docker/failoverlb sudo docker compose logs | grep -A3 "Made the first admin" -
Set up your authenticator app
After your password you are asked for a six digit code. Everybody with a local account has to set one up, because a password on its own is not enough to reach a screen that can move all of your traffic somewhere else.
Install any authenticator on your phone. Google Authenticator, Microsoft Authenticator, 1Password and Aegis all work. Add an account, point it at the square code, and type the number it shows.
Save your recovery codes
You are shown a list once and never again. Each one works a single time in place of a code from your app. They are how you get back in if your phone is lost or broken. Save them somewhere that is not your phone.
Real screens, stepped through. Use the arrows to move at your own pace.
-
Add the second server
On the first server, go to Cluster and press Add a node. You get a command with a token already in it. The token works once and expires in two hours.
Connect to the second machine and run it:
sudo git clone https://git.failoverlb.net/failoverlb.git /data/docker/failoverlb \ && sudo /data/docker/failoverlb/failoverlb_setup.sh \ --join 203.0.113.10:7444 \ --token <the token you copied> \ --allowlist 198.51.100.25/32Then build nginx on this machine too, exactly as before.
Do not copy the folder from the first server
It contains a settings file with that server's identity and its secret key, and the second machine would come up believing it is the first one. Install it fresh. The installer refuses to join when it spots this, and it is much easier not to do it.
The new node makes its own key pair. The private half never leaves that box.
Now do something with it
Your first site, from nothing to a padlock
Eight steps. Follow them with your own names in place of the example ones and you will have done most of the everyday jobs once.
A guided walkthrough of the real screens, not recorded video.
The order that works
- Make a pool with your application servers in it. Wait for them to go green before you go any further.
- Turn on health checks and point them at a page that really exercises the application.
- Make a site with the hostname people will type, set to proxy, pointing at that pool.
- Apply and check the plain http address works.
- Get a certificate from Let's Encrypt for that name.
- Turn on https and force it, then apply again.
- Add paths if part of the site goes somewhere else.
- Prove the failover works by stopping one backend and watching the pool.
Two habits worth building now
Save often, apply deliberately
Saving changes nothing for your visitors. Applying is what makes it real. So save as much as you like, and apply when you are ready. The banner at the top of the screen always tells you when something is saved and not yet live.
Apply in small steps
One change applied and checked is easy to understand. Nine changes applied together, one of which broke something, is an afternoon.
Day one
Eight things worth doing before you walk away
1. Set the allowlist properly
Check NFM_ADMIN_ALLOWLIST in .env on every node names only the networks you manage from.
2. Change the first password
And save your recovery codes somewhere that is not the phone you might lose.
3. Turn staging off, once
Certificates start pointed at the Let's Encrypt practice service on purpose. Switch it off in Settings once you have one working.
4. Take a backup
Before you have anything worth losing. It takes ten seconds and it teaches you where the button is.
5. Test the failover
Stop one node deliberately, in daylight, and watch what happens. A failover that has never been tried is a plan, not a capability.
6. Give people the smallest role
Viewer unless somebody genuinely needs more. It is easy to raise later.
7. Put a real name on the management screen
So nobody has to click past a browser warning every day and stop reading warnings entirely.
8. Write down where the backup lives
A backup nobody can find is not a backup.
If something goes wrong
The installer is safe to run again
Fix whatever it complained about and run exactly the same command a second time. It leaves alone anything it has already done and it never touches your settings file or your database.
That is the whole setup
Everything after this is optional: a firewall in front of your applications, failover between buildings, a tunnel to a backend with no public address. None of it is needed to serve a site.