Sh
Networking Azure

Sozu HTTP Reverse Proxy / Load Balancer on Ubuntu 24.04 on Azure User Guide

| Product: Sozu 2.2.0 on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Sozu on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Sozu (pronounced sou-zou) is an HTTP reverse proxy and load balancer written in Rust. It is fast, memory-safe, and — its defining feature — reconfigurable at runtime with no downtime: you add or remove clusters, frontends, backends and TLS certificates on a live proxy without dropping a single connection.

The image installs Sozu 2.2.0 from the pinned upstream crate, so the exact version is reproducible. Sozu runs under systemd as the unprivileged sozu user. Unattended security upgrades keep the base OS patched.

Serves a real response out of the box. The appliance ships a tiny self-contained local backend (a static server bound to 127.0.0.1:8000) and a default cluster that proxies to it, so an on-box curl http://localhost/ returns a real HTTP body through Sozu the moment the VM boots. You then point Sozu at your own backends with one config edit or a runtime CLI command.

Secure by design.

  • Sozu runs as the unprivileged sozu user and binds the privileged ports :80 and :443 using only the CAP_NET_BIND_SERVICE Linux capability — never as root.
  • The Sozu command/control channel is a local Unix socket only (/run/sozu/sozu.sock, mode 0750). It is never exposed on a TCP port, so the proxy cannot be reconfigured from the network. The sozu CLI over SSH is the sole admin path.
  • A per-VM self-signed TLS certificate is generated on first boot into /etc/sozu/tls/ — it is never baked into the image, so every VM has unique TLS material.

What is included:

  • Sozu 2.2.0 installed from the pinned upstream crate, run under systemd as the unprivileged sozu user (sozu.service)

  • An HTTP listener on :80 and an HTTPS listener on :443 (per-VM TLS), both proxying to a default cluster

  • A built-in local backend (sozu-backend.service on 127.0.0.1:8000) so the appliance answers a real request out of the box

  • A local Unix-socket-only command channel — the proxy is never controllable from the network

  • A per-VM TLS certificate generated on first boot, documented in /root/sozu-info.txt (0600)

Prerequisites

  • Active Azure subscription, SSH public key, VNet + subnet in target region

  • Subscription to the Sozu listing on Azure Marketplace

  • Network Security Group rules allowing TCP 22 (admin) and, for the traffic you want to proxy, TCP 80 and/or TCP 443

Recommended virtual machine size: Standard_B2s (2 vCPU, 4 GB RAM) for a light edge proxy. Higher throughput deployments should use Standard_D2s_v5 or larger.

Step 1: Deploy from the Azure Portal

Search Sozu in Marketplace, select the cloudimg publisher, and click Create. Configure the Network Security Group to allow TCP 80 and/or TCP 443 from the clients that will reach the proxy, and TCP 22 for administration.

Step 2: Deploy from the Azure CLI

RG="sozu-prod"; LOCATION="eastus"; VM_NAME="sozu1"
GALLERY_IMAGE_ID="/subscriptions/<sub-id>/resourceGroups/azure-cloudimg/providers/Microsoft.Compute/galleries/cloudimgGallery/images/sozu-ubuntu-24-04/versions/<version>"
SSH_KEY="$(cat ~/.ssh/id_rsa.pub)"
az group create --name "$RG" --location "$LOCATION"
az vm create \
  --resource-group "$RG" --name "$VM_NAME" \
  --image "$GALLERY_IMAGE_ID" \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values "$SSH_KEY" \
  --public-ip-sku Standard
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 80 --priority 1001
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 443 --priority 1002
az vm open-port --resource-group "$RG" --name "$VM_NAME" --port 22 --priority 1003

Step 3: First boot

On first boot the image generates a per-VM self-signed TLS certificate into /etc/sozu/tls/, writes /root/sozu-info.txt, then systemd starts the local backend and Sozu. This completes within a few seconds. SSH in as azureuser and read the appliance info:

sudo cat /root/sozu-info.txt

Step 4: Confirm the services are running

sozu.service runs under systemd as the unprivileged sozu user. ss confirms Sozu is listening on :80 and :443, and the local backend on loopback 127.0.0.1:8000.

systemctl is-active sozu.service sozu-backend.service
ps -o user= -C sozu | head -1
ss -tlnp | grep -E ':80 |:443 |127.0.0.1:8000 '

The Sozu service active under systemd and running as the unprivileged sozu user, with ss showing the HTTP listener on TCP 80, the HTTPS listener on TCP 443, and the built-in local backend on loopback 127.0.0.1 port 8000

Step 5: A real request flows through Sozu out of the box

The appliance proxies to its built-in local backend, so a request to http://localhost/ returns a real HTML body through Sozu. The default demo vhost sozu.appliance.local and the HTTPS listener (using the per-VM certificate) serve the same backend.

# Plain HTTP through Sozu on :80
curl -s http://localhost/ | head -3
# The documented demo vhost on :80
curl -s -H 'Host: sozu.appliance.local' http://localhost/ | grep -o 'cloudimg sozu appliance backend'
# HTTPS on :443 using the per-VM self-signed certificate
curl -sk --resolve sozu.appliance.local:443:127.0.0.1 https://sozu.appliance.local/ | grep -o 'cloudimg sozu appliance backend'

A real HTTP request served through Sozu out of the box: curl to localhost returns the built-in backend HTML page, the demo vhost on port 80 returns the backend marker, and an HTTPS request on port 443 using the per-VM self-signed certificate returns the same real backend body

Step 6: The control channel is a local Unix socket only

Sozu is administered with the sozu CLI over its command socket, which is a local Unix socket (/run/sozu/sozu.sock) — it is never exposed on a TCP port, so the proxy cannot be reconfigured from the network. sozu status queries the live proxy over that socket, and ss confirms the only network listeners are the proxy's own :80/:443 and SSH.

ls -l /run/sozu/sozu.sock
sudo sozu --config /etc/sozu/config.toml status
# No control port on the network — only :80, :443 (proxy) and :22 (ssh) listen off-loopback
ss -tlnp | awk 'NR>1 {print $4}' | grep -vE '^(127\.|\[::1\])'

The Sozu command socket shown as a local Unix socket at /run/sozu/sozu.sock, the sozu status command querying the live proxy over that socket and listing its workers, and ss confirming that the only non-loopback TCP listeners are the proxy ports 80 and 443 and SSH port 22 — the control channel is never on the network

Step 7: Review the per-VM TLS material and the secure-by-default config

A unique self-signed TLS certificate is generated on this VM at first boot. Nothing is baked into the image. The config shows the Unix-socket command channel and the default cluster wired to the local backend.

sudo openssl x509 -in /etc/sozu/tls/cert.pem -noout -subject -fingerprint -sha256
grep -E '^command_socket|^\[\[listeners\]\]|^protocol|^address' /etc/sozu/config.toml
sudo stat -c '%n %a %U:%G' /etc/sozu/tls/key.pem /root/sozu-info.txt

The per-VM self-signed TLS certificate subject and SHA256 fingerprint, the Sozu configuration showing the local Unix-socket command channel and the HTTP and HTTPS listeners, and the file permissions proving the private key is 0640 root sozu and the info file is 0600 root root

Step 8: Point Sozu at your own backend

Replace the built-in demo backend with your own. Edit /etc/sozu/config.toml: add a frontend for your hostname and a backend pointing at your application, then reload Sozu with no downtime. In this example we route the hostname app.example.com to a backend on 10.0.0.10:8080.

sudo tee -a /etc/sozu/config.toml >/dev/null <<'EOF'

[clusters.my-app]
protocol = "http"
load_balancing = "ROUND_ROBIN"
frontends = [
    { address = "0.0.0.0:80", hostname = "app.example.com" },
]
backends = [
    { address = "10.0.0.10:8080", backend_id = "app-1" },
]
EOF
sudo systemctl reload sozu

Sozu re-reads the configuration and applies the new routing on the running proxy. Add more backends to the backends array for load balancing, and choose the algorithm with load_balancing (ROUND_ROBIN, RANDOM, LEAST_LOADED, POWER_OF_TWO).

Step 9: Reconfigure a live proxy at runtime with the CLI

Sozu's signature feature is hot reconfiguration: add clusters, frontends and backends to a running proxy over the command socket, with no restart and no dropped connections. For example, add a cluster and a backend at runtime:

sudo sozu -c /etc/sozu/config.toml cluster add --id runtime-app --load-balancing-policy round_robin
sudo sozu -c /etc/sozu/config.toml frontend http add --address 0.0.0.0:80 --hostname runtime.example.com id runtime-app
sudo sozu -c /etc/sozu/config.toml backend add --id runtime-app --backend-id b1 --address 10.0.0.20:8080
sudo sozu -c /etc/sozu/config.toml frontend list

Persist runtime changes across restarts by saving the live state: sudo sozu -c /etc/sozu/config.toml state save -f /etc/sozu/state.json and set saved_state = "./state.json" in the config.

Step 10: Enable HTTPS for your own domain

The image ships a per-VM self-signed certificate so HTTPS works out of the box for testing. For production, install your CA-issued certificate and key, reference them from the HTTPS listener (or a specific HTTPS frontend) in /etc/sozu/config.toml, and reload. Replace the paths with your own PEM files:

sudo install -o root -g sozu -m 0640 /path/to/your-cert.pem /etc/sozu/tls/cert.pem
sudo install -o root -g sozu -m 0640 /path/to/your-key.pem  /etc/sozu/tls/key.pem
sudo systemctl reload sozu

Step 11: Security recommendations

  • Restrict the NSG. Allow TCP 80/443 only from the networks that should reach the proxy, and TCP 22 for administration only.

  • Keep the command channel local. The Sozu command socket ships as a local Unix socket; never point it at a TCP address. Administer over SSH with the sozu CLI.

  • Use your own TLS certificate in production. The per-VM certificate is self-signed for out-of-box testing; install a CA-issued certificate for public traffic.

  • Scope your frontends. Route only the hostnames you serve; a frontend only matches requests whose Host header equals its hostname.

  • Keep the OS patched. Unattended security upgrades remain enabled on the running VM.

Step 12: Support and Licensing

Sozu is developed by the Sozu project (Clever Cloud and contributors) and distributed under the GNU Affero General Public License v3.0 (AGPL-3.0). The full licence text ships on the image at /usr/share/doc/sozu/LICENSE. This cloudimg image installs the unmodified upstream Sozu 2.2.0. cloudimg provides the packaging, the secure default configuration, the per-VM TLS automation, security patching, and 24/7 support with a guaranteed 24 hour response SLA.

cloudimg is not affiliated with or endorsed by the Sozu project. Sozu is a mark of its respective owner and is used here only to identify the software.

Deploy on Azure

Find Sozu HTTP Reverse Proxy / Load Balancer on Ubuntu 24.04 LTS on the Azure Marketplace, published by cloudimg. Deploy from the Portal or the Azure CLI as shown above.

Need Help?

Email support@cloudimg.co.uk for deployment help, configuration questions, or licensing enquiries.