Easegress on Ubuntu 24.04 on Azure User Guide
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
easegresssystem user -
The
egctladministration client on the system path, plusegbuilder -
A working HTTPServer on port 80 with three pipelines applied on first boot
-
A
/demoroute 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
/healthzprobe suitable for an Azure load balancer health check -
Remote administration on
/apis/v2behind 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
azureuseradministrative 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
- In the Azure Portal choose Create a resource and search the Marketplace for Easegress on Ubuntu 24.04 LTS by cloudimg.
- Choose your subscription, resource group and region, and set the VM size to Standard_B2s or larger.
- Set the administrator username to
azureuserand upload your SSH public key. - On the Networking tab allow inbound 22 and 80 from the addresses you trust.
- 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)'

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

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

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)"

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/v2route 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.