Canadian cloud in Montréal · VMs from 8.50 CAD/month

Load balancer: several servers behind one address

A load balancer takes traffic on its own address and shares it across your machines. Pools and health checks, an HTTPS listener with an automatic certificate, path routing, maintenance without downtime: a complete setup, at 0.010 CAD an hour.

One incoming stream shared by a load balancer across three machines, one drained

One machine behind a domain name is simple until the day it needs a restart for an update, or the load outgrows it. A load balancer takes traffic on its own address and spreads it across several machines: you take one out for maintenance, the others keep serving.

The FFxF load balancer is a managed service. You describe where traffic goes; FFxF runs the load balancer, obtains its Let's Encrypt certificates and keeps it up to date. This guide sets one up end to end, with the actual output of a load balancer in service.

1. How it fits together

  • A pool groups the machines serving the same thing, each with a port: web for the site, api for the API.
  • A listener is an entry port on the load balancer's address, HTTP, HTTPS or TCP, with a default pool.
  • Rules send a hostname or a path prefix to another pool: /api/ to api, the rest to web.

The target machines share a private network with the load balancer. They need no public address, and their firewalls can close 80 and 443 to the Internet: the private network is never filtered.

2. Create the load balancer

In the console, under Load balancers, give it a name and pick your machines' private network. The same through the API:

bash
curl -s -X POST https://api.ffxf.net/v1/load-balancers \
     -H "Authorization: Bearer $FFXF_TOKEN" \
     -H "Idempotency-Key: $(uuidgen)" \
     -H "Content-Type: application/json" \
     -d '{"name": "pilote", "vpc": 15}'

{"data":{"id":1,"name":"pilote","status":"pending","billing":{"mode":"hourly","rate":"0.010","currency":"CAD"}}}

A load balancer is billed by the hour, 0.010 CAD, about 7.30 CAD for a full month. It is ready within minutes: its status goes from pending to active, and it gets an IPv4 and an IPv6 address. Pools and listeners can be set up meanwhile.

3. A pool and its targets

For this demo, a single machine of the private network, at 10.50.0.2, runs three small HTTP servers on ports 8081, 8082 and 8083. In production these would be separate machines; the load balancer treats them the same way.

bash
curl -s -X POST https://api.ffxf.net/v1/load-balancers/1/pools \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"name": "web", "protocol": "http", "health_type": "http", "health_path": "/"}'

curl -s -X PUT https://api.ffxf.net/v1/load-balancers/1/pools/1/targets \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"targets": [{"vm": 150, "port": 8081}, {"vm": 150, "port": 8082}]}'

A machine is named by its number, the one shown in the console and the API. The load balancer checks each target every 5 seconds, here with an HTTP request on /: three failures take it out of the pool, two successes bring it back. A second pool, api, points at port 8083.

4. An HTTPS listener and DNS

bash
curl -s -X POST https://api.ffxf.net/v1/load-balancers/1/listeners \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"port": 443, "protocol": "https", "default_pool": 1, "redirect_https": true}'

With redirect_https, port 80 redirects to HTTPS. For the certificate, point your name at the load balancer: an A record to its IPv4, an AAAA to its IPv6. As soon as the name points the right way, the load balancer requests its certificate from Let's Encrypt; in our demo it was active about thirty seconds after the listener was created.

5. Routing by path

bash
curl -s -X PUT https://api.ffxf.net/v1/load-balancers/1/listeners/1/rules \
     -H "Authorization: Bearer $FFXF_TOKEN" -H "Content-Type: application/json" \
     -d '{"rules": [
           {"hostname": "app.example.com", "pool": 1},
           {"hostname": "app.example.com", "path_prefix": "/api/", "pool": 2}
         ]}'

The order you send does not matter: the load balancer evaluates rules most specific first (hostname and path, then hostname alone, then path alone), and the first match wins. The console's Routing tab shows them in that order, followed by the "Otherwise" line that leads to the default pool.

6. Check it

bash
$ for i in 1 2 3 4; do curl -s https://app.example.com/; done
pilote 8081
pilote 8082
pilote 8081
pilote 8082
$ curl -s https://app.example.com/api/
pilote 8083
$ curl -s -o /dev/null -w "%{http_code} %{redirect_url}\n" http://app.example.com/
301 https://app.example.com/

Requests alternate between the two targets of the web pool, /api/ goes to the other pool, and HTTP is redirected. On the application side, the visitor's address arrives in the X-Forwarded-For header, with X-Forwarded-Proto and X-Forwarded-Port.

7. Maintenance without downtime

Before updating a machine, click Drain next to it in the Pools tab (or send {"drain": true} through the API). It gets no new connections, current ones finish, and the change is live within about ten seconds. Once the update is done, Restore brings it back.

A target that fails without warning is taken out by the health checks, and the Pools tab shows it as down. If every target of a pool fails, the load balancer answers 503 instead of leaving visitors waiting.

8. Who can connect

Only 80, 443 and your listeners' ports are open on the load balancer's address. Each listener accepts allowed sources: a TCP 5432 listener in front of a database pool can accept your office address only. While an HTTPS listener exists, port 80 stays open to everyone, because Let's Encrypt validates certificates there.

9. Statistics and usage

The Statistics tab charts requests by response class, traffic and concurrent sessions over 1 hour, 24 hours or 7 days. The overview gives the cost for the current month and the activity of the last minute.

Traffic through the load balancer is counted on the target machines, as if they had served it themselves: it uses their included bandwidth. In the demo, two 10 MB downloads through the load balancer added 20,972,166 bytes to the target machine's counter.

10. From an AI agent

The FFxF MCP server exposes the same steps: create_load_balancer, upsert_pool, set_targets, upsert_listener and set_rules. An agent can build the whole load balancer from one sentence; its instructions ask it to state the price before ordering, then to tell you which DNS records to create.

Checklist

  • Machines in one private network, each service on a known port.
  • One pool per service, with a health check that really tests the application.
  • An HTTPS listener with redirection from port 80.
  • DNS pointed, then the certificate active in the Certificates tab.
  • Ports 80 and 443 of the targets closed to the Internet by their firewall.
  • Drain before every maintenance.

Every call is detailed in the load balancer documentation, and the targets' firewall in protecting a VM with the cloud firewall.

An IPv6 VM linked through a translation gateway to the IPv4 Internet

IPv6-only VPS: 2 CAD less, IPv4 still in reach

No public IPv4, 2 CAD less a month, and GitHub still in reach: a demo of an IPv6-only VPS, and of the gateway that links it to the IPv4 Internet.

Read the article 6 min read

Mesh of network nodes around an IPv6 address block

IPv6 on a VPS: addresses, reverse DNS, firewall

IPv6 is no longer optional: it drives mail deliverability, access from mobile networks, and search visibility. Here is the full configuration.

Read the article 8 min read

Support & discussions

Technical questions, incident reports, or infrastructure discussions, the team is reachable on Discord, Telegram, X, Instagram, Reddit, and IRC.