Application Infrastructure Azure

Easegress on Ubuntu 24.04 on Azure User Guide

| Product: Easegress on Ubuntu 24.04 LTS on Azure

Overview

This guide covers the deployment and configuration of Easegress on Ubuntu 24.04 on Azure using cloudimg Azure Marketplace images. Easegress is an open source cloud native traffic orchestration system: a single Go binary that runs 24/7 under systemd and sits in front of your applications as a programmable API gateway and reverse proxy. It matches incoming requests against declarative routing rules and passes each one through a pipeline of composable filters that can proxy to backend pools, load balance across them, validate credentials, rewrite headers, apply rate limiting and circuit breaking, and mirror or mock traffic.

The image installs the latest stable Easegress release, resolved at build time from the official GitHub releases and verified against the upstream checksums.txt before extraction, then baked reproducibly into the image (the exact version, release tag and tarball digest are recorded in /opt/easegress/VERSION). Easegress runs under systemd as the unprivileged easegress system user, which is granted the CAP_NET_BIND_SERVICE capability so it can bind port 80 without running as root.

Configuration is declarative and applied at runtime. Easegress uses two main object kinds: an HTTPServer (which port to listen on and which path goes to which pipeline) and a Pipeline (an ordered flow of filters). You apply them with the egctl command line client against the administration API, and they take effect immediately without restarting the gateway or redeploying anything.

A working gateway ships in the image. On first boot this image applies an HTTPServer on port 80 plus three pipelines, so you have real traffic flowing the moment the instance is up: an unauthenticated /healthz probe, a /demo route that is genuinely proxied and round robin load balanced across two backends, and an /apis/v2 route that gives you remote administration behind authentication.

Secure by default, with no credential in the image. The Easegress administration API is bound to 127.0.0.1:2381 and its embedded configuration store to 127.0.0.1:2379 and 127.0.0.1:2380, so nothing administrative is reachable from the network directly. The only network path to administration is the gateway's own /apis/v2 route, which is gated by an Easegress Validator filter in basic authentication mode against a bcrypt credential generated uniquely on this instance's first boot. No credential and no gateway state ever ships inside the image.

What is included:

  • The latest stable Easegress release (single Go binary), run under systemd as the unprivileged easegress system user

  • The egctl administration client on the system path, plus egbuilder

  • A working HTTPServer on port 80 with three pipelines applied on first boot

  • A /demo route that is proxied through a live pipeline and round robin load balanced across two local upstream servers, so you can see real traffic orchestration immediately

  • An unauthenticated /healthz probe suitable for an Azure load balancer health check

  • Remote administration on /apis/v2 behind a per instance basic authentication credential, with the administration API itself bound to loopback only

  • The per instance credential written to /root/easegress-credentials.txt (readable by root only) and stored as a bcrypt hash in /etc/easegress/admin.htpasswd

  • The Apache 2.0 licence notice retained at /opt/easegress/LICENSE

Prerequisites

  • An Azure subscription with permission to deploy virtual machines

  • A network security group allowing inbound TCP 22 (SSH) and TCP 80 (the gateway data plane) from the addresses you trust

  • An SSH key pair for the azureuser administrative account

  • A VM size of Standard_B2s or larger

Ports 2379, 2380 and 2381 are deliberately bound to loopback and must never be opened in your network security group.

Step 1: Deploy from the Azure Portal

  1. In the Azure Portal choose Create a resource and search the Marketplace for Easegress on Ubuntu 24.04 LTS by cloudimg.
  2. Choose your subscription, resource group and region, and set the VM size to Standard_B2s or larger.
  3. Set the administrator username to azureuser and upload your SSH public key.
  4. On the Networking tab allow inbound 22 and 80 from the addresses you trust.
  5. Review and create. The gateway is configured on first boot and is usually serving traffic within a minute of the VM reporting Running.

Step 2: Deploy from the Azure CLI

az group create --name easegress-rg --location eastus

az vm create \
  --resource-group easegress-rg \
  --name easegress-vm \
  --image cloudimg:easegress-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

az vm open-port --resource-group easegress-rg --name easegress-vm --port 22 --priority 1001
az vm open-port --resource-group easegress-rg --name easegress-vm --port 80 --priority 1002

Then connect over SSH, replacing the address with your VM's public IP:

ssh azureuser@<vm-ip>

Step 3: Verify the Easegress service

Confirm the gateway and its local upstreams are running, and check which ports are listening. Note that the administration API on 2381 and the embedded store on 2379 and 2380 are bound to 127.0.0.1 only.

sudo systemctl is-active easegress.service nginx.service
sudo cat /opt/easegress/VERSION
sudo ss -ltn | grep -E ':(80|2379|2380|2381|9095|9096)'

The Easegress version and build provenance including the release tag and verified tarball digest, easegress.service and nginx.service both reporting active, the service running as the non root easegress user, and ss showing Easegress listening on port 80 for the data plane with the administration API on 2381 and the embedded store on 2379 and 2380 all bound to 127.0.0.1 only

Step 4: Inspect the live gateway objects

Easegress is administered with egctl. Because the administration API listens on loopback, running egctl on the VM itself needs no credential. List everything the gateway currently has loaded:

sudo egctl get all

You should see the cloudimg-gateway HTTPServer plus the three pipelines: healthz-pipeline, demo-pipeline and admin-pipeline. To see which request path is routed to which pipeline, read the HTTPServer object:

sudo egctl get httpserver cloudimg-gateway -o yaml

The output of egctl get all showing the cloudimg-gateway HTTPServer alongside the healthz-pipeline, demo-pipeline and admin-pipeline objects with their ages, and the HTTPServer routing rules showing the healthz path, the apis v2 path prefix and the demo path prefix each mapped to their backend pipeline

Step 5: See real traffic being orchestrated

This is the part that proves the gateway is genuinely routing traffic rather than simply holding a port open. The /demo route is proxied through demo-pipeline, whose Proxy filter load balances across two separate local upstream servers using the round robin policy. Send four requests and watch them alternate:

for i in 1 2 3 4; do curl -s http://127.0.0.1/demo/ | head -1; done

Each request is answered by a different upstream in turn, which is the load balancer doing its job. You can read the pipeline that does it:

sudo egctl get pipeline demo-pipeline -o yaml

The unauthenticated health probe is served by a ResponseBuilder filter, so it answers without touching any upstream. This is the endpoint to point an Azure load balancer health probe at:

curl -s -o /dev/null -w 'healthz: HTTP %{http_code}\n' http://127.0.0.1/healthz
curl -s http://127.0.0.1/healthz

Four consecutive curl requests to the demo route returning alternating responses from cloudimg backend A and cloudimg backend B proving round robin load balancing, the demo pipeline YAML showing the Proxy filter with a roundRobin load balance policy over two upstream servers, and the unauthenticated healthz probe returning HTTP 200

Step 6: Understand the access gate and your per instance credential

The administration API is not on the network. The only way in from outside the VM is the gateway's /apis/v2 route, which is protected by an Easegress Validator filter in basic authentication mode. Your credential was generated on this instance's first boot and is recorded here:

sudo grep -E '^easegress\.(admin_user|host|gateway|healthz|demo_route|admin_api)=' /root/easegress-credentials.txt

The password itself is in the same file under easegress.admin_password. Read it when you need it:

sudo awk -F= '/^easegress.admin_password=/{print $2}' /root/easegress-credentials.txt

Confirm the gate actually rejects what it should. A request with no credential, a wrong password, or an unknown user must all be refused with 401, and only the real credential is admitted:

curl -s -o /dev/null -w 'no credential:     HTTP %{http_code}\n' http://127.0.0.1/apis/v2/status/members
curl -s -o /dev/null -w 'wrong password:    HTTP %{http_code}\n' -u '<EASEGRESS_ADMIN_USER>:definitely-wrong' http://127.0.0.1/apis/v2/status/members
curl -s -o /dev/null -w 'unknown user:      HTTP %{http_code}\n' -u 'nosuchuser:<EASEGRESS_ADMIN_PASSWORD>' http://127.0.0.1/apis/v2/status/members
curl -s -o /dev/null -w 'real credential:   HTTP %{http_code}\n' -u '<EASEGRESS_ADMIN_USER>:<EASEGRESS_ADMIN_PASSWORD>' http://127.0.0.1/apis/v2/status/members

Confirm for yourself that the administration API really is unreachable off loopback. This must fail to connect:

LAN_IP=$(hostname -I | awk '{print $1}')
CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 5 "http://${LAN_IP}:2381/apis/v2/status/members" || true)
echo "admin API on ${LAN_IP}:2381 -> HTTP ${CODE} (000 means the connection was refused, which is what you want)"

The access gate results showing a request with no credential, a wrong password and an unknown user each rejected with HTTP 401 while the per instance credential is admitted with HTTP 200, the authenticated response listing the real cluster member with its loopback API address, the per instance credential file with the password masked, and the bcrypt credential store with the hash masked

Step 7: Administer the gateway remotely

From your workstation you can drive the administration API through the authenticated route. Replace the address with your VM's public IP and use the credential from Step 6:

curl -u '<EASEGRESS_ADMIN_USER>:<EASEGRESS_ADMIN_PASSWORD>' http://<vm-ip>/apis/v2/status/members

Because this path traverses the public network, treat it as you would any administrative endpoint: restrict port 80 in your network security group to the addresses you administer from, and put a trusted TLS certificate in front of it before using it in production (see Step 10).

If you prefer not to expose administration at all, remove the admin-pipeline route from the HTTPServer and use an SSH tunnel instead, which reaches the loopback API directly:

ssh -L 2381:127.0.0.1:2381 azureuser@<vm-ip>

Step 8: Point the gateway at your own backends

The demo route exists so the image arrives working. To put your own service behind Easegress, edit the shipped objects file and re apply it. The file is plain YAML with one document per object:

sudo cat /opt/easegress/objects.yaml

Change the two servers entries under demo-pipeline to your own upstreams, then apply the change. egctl apply updates objects in place, so the gateway picks up the new routing immediately with no restart:

sudo nano /opt/easegress/objects.yaml
sudo egctl apply -f /opt/easegress/objects.yaml

You can also define objects ad hoc without touching the file. Use egctl apply rather than egctl create so the command is repeatable: create fails with a 409 conflict if the object already exists, whereas apply creates it the first time and updates it thereafter.

sudo egctl apply -f - <<'YAML'
name: my-api-pipeline
kind: Pipeline
flow:
  - filter: my-proxy
filters:
  - name: my-proxy
    kind: Proxy
    pools:
      - loadBalance:
          policy: roundRobin
        servers:
          - url: http://10.0.0.4:8080
          - url: http://10.0.0.5:8080
YAML

Confirm it was accepted, then route a path to it by adding a rule to the HTTPServer in /opt/easegress/objects.yaml and re applying that file:

sudo egctl get pipeline my-api-pipeline -o yaml

For a simple proxy you can skip the two object model entirely and use the convenience command, which creates the HTTPServer and its pipeline together. Delete any previous object of the same name first so the command is repeatable:

sudo egctl delete httpserver my-service 2>/dev/null || true
sudo egctl create httpproxy my-service --port 8081 --rule='/api*=http://10.0.0.4:8080'

Step 9: Add filters to a pipeline

The value of a pipeline is the filters you compose into it. Easegress ships a large filter set including Proxy, Validator (headers, JWT, OAuth2, signature and basic authentication), RateLimiter, CircuitBreaker, RequestAdaptor, ResponseAdaptor, ResponseBuilder, CORSAdaptor, Mock and WASMHost. List what this build supports:

sudo egctl api-resources

The admin-pipeline in this image is a working two filter example: a Validator that enforces basic authentication, followed by a Proxy that forwards the request onward only if the validator passed. Read it as a template for your own gated routes:

sudo egctl get pipeline admin-pipeline -o yaml

To add basic authentication to a route of your own, generate a credential file and reference it from a Validator filter placed before your Proxy filter in the pipeline flow.

Step 10: Terminate TLS (production)

The image serves plain HTTP on port 80 so that the gateway works immediately without a certificate or a domain name. For production, put your own certificate in front of the traffic. Easegress can terminate TLS itself: set https: true on the HTTPServer and supply your certificate and key, either inline or through an AutoCertManager object that obtains certificates from an ACME provider such as Let's Encrypt.

Point a DNS record at your VM's public IP first, then configure the HTTPServer with https: true, your certificate material, and port 443, and open 443 in your network security group. Until TLS is in place, restrict port 80 in your network security group to addresses you trust rather than leaving it open to the internet.

Step 11: Server components

Component Location Purpose
easegress-server /usr/local/bin/easegress-server The gateway itself, a single Go binary
egctl /usr/local/bin/egctl The administration client
Server configuration /etc/easegress/easegress.yaml Node name, loopback API address, data and log directories
Gateway objects /opt/easegress/objects.yaml The HTTPServer and pipelines applied on first boot
Credential store /etc/easegress/admin.htpasswd The bcrypt hash for the /apis/v2 route
Per instance credential /root/easegress-credentials.txt The generated username, password and endpoints
Configuration store /var/lib/easegress Embedded etcd holding the live objects
Logs /var/log/easegress and journalctl -u easegress Gateway logs
Version provenance /opt/easegress/VERSION Release tag and verified tarball digest
Licence /opt/easegress/LICENSE The Apache 2.0 notice

Step 12: Managing the Easegress service

sudo systemctl status easegress.service --no-pager
sudo journalctl -u easegress.service --no-pager | tail -20

To restart the gateway after a change to /etc/easegress/easegress.yaml:

sudo systemctl restart easegress.service

Changes made with egctl do not need a restart. They are stored in the embedded configuration store and applied to live traffic immediately.

Step 13: Security recommendations

  • Restrict port 80 in your network security group to the addresses that need it, and never open 2379, 2380 or 2381.

  • Terminate TLS before putting the gateway in front of production traffic (Step 10), and treat the /apis/v2 route as administrative.

  • Rotate the administration credential when you need to by writing a new bcrypt entry in place. Substitute your own password for <new-password>. Write the file in place rather than deleting and recreating it, because the validator watches the file and will lose track of it if the file is replaced:

sudo htpasswd -B -b /etc/easegress/admin.htpasswd egadmin '<new-password>'

The change takes effect within a few seconds, with no restart needed.

  • Remove the demo route once your own backends are configured, so the image's example upstreams are not reachable.

  • Keep the instance patched. Unattended upgrades are enabled in the image.

  • The per instance credential file is readable by root only. Nothing in the image is shared between deployments: the credential and the gateway state are generated fresh on each instance's first boot.

Step 14: Support and Licensing

Easegress is open source software licensed under the Apache License 2.0. The licence notice is retained on the image at /opt/easegress/LICENSE. cloudimg is not affiliated with or endorsed by the Easegress project; this image packages the unmodified open source release.

Your cloudimg subscription covers the image, its configuration and 24/7 support.

Deploy on Azure

Find Easegress on Ubuntu 24.04 LTS by cloudimg on the Azure Marketplace.

Need Help?

Contact cloudimg support at support@cloudimg.co.uk.