Zoraxy
Overview
Zoraxy is a general-purpose, self-hosted HTTP reverse proxy and network toolkit that you manage entirely from a web interface. From one management UI you publish and route many sites through a single entry point, terminate TLS with automatic certificate renewal, balance load across upstreams, apply access control by IP or country, forward raw TCP and UDP streams, and monitor uptime.
Zoraxy also bundles a set of network utilities: an mDNS scanner, an IP scanner, a port scanner, traceroute and ping, and wake on LAN. The SecureAnyCloud image serves Zoraxy 3.3.3 on a hardened Ubuntu 24.04 LTS base, patched at build time. Zoraxy is itself the reverse proxy, so it owns ports 80 and 443 for your proxied sites. The web management UI listens separately on port 8000.
The image is secure by default. It ships with no administrator account, so the first time you open the management UI you create your own admin with your own password. A fresh node identity is generated per instance on first boot, and no shared or default login ever ships in the image.
What you get:
- Zoraxy 3.3.3, a single self-contained Go binary, managed by systemd.
- The web management UI on
:8000and the reverse proxy on:80and:443. - No default administrator. You create your own admin on the first visit.
- An embedded key-value store, so there is no external database to run.
- Automatic HTTPS with ACME certificate renewal and DNS challenge support.
- A reverse proxy with HTTP/2, websockets, load balancing and virtual directories.
- Access control by IP or country, a TCP and UDP stream proxy and an uptime monitor.
- Network tools: an mDNS scanner, an IP scanner, a port scanner, traceroute and wake on LAN.
- A dedicated Azure data disk at
/opt/zoraxyfor configuration, certificates and state. zoraxy.serviceas an enabled systemd unit.- 24/7 SecureAnyCloud support.
Prerequisites
Before you deploy this image, make sure you have:
- An active Azure subscription, an SSH key pair, and a VNet and subnet in the target region.
- A VM size. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point. Size up for more concurrent connections.
- NSG inbound rules that allow
22/tcpfrom your management network,8000/tcpfor the management UI, and80/tcpand443/tcpfor the sites you publish through the reverse proxy. Restrict8000/tcpto trusted networks, because it is the administrative interface.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Zoraxy by SecureAnyCloud, and select Create.
On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80), then add custom rules for 443 and 8000.
Review the dedicated data disk on the Disks tab, then choose Review + create and Create.
Step 2 - Deploy from the Azure CLI
Accept the Marketplace terms once per subscription, then create the VM:
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:zoraxy-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name zoraxy \
--image sac1647283583153:zoraxy-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku StandardThen open the management UI port and the reverse proxy port:
az vm open-port --resource-group <your-rg> --name zoraxy --port 8000 --priority 900
az vm open-port --resource-group <your-rg> --name zoraxy --port 443 --priority 910Step 3 - Confirm the service is running
SSH in as azureuser and confirm that Zoraxy is active. The management UI listens on port 8000. The reverse proxy listens on ports 80 and 443 for the sites you publish.
systemctl is-active zoraxy zoraxy-firstbootsudo ss -tlnp | grep -E ':8000 |:80 |:443 ' | awk '{print $1, $4}'findmnt -no SOURCE,TARGET,FSTYPE /opt/zoraxyStep 4 - The first visit info note
Zoraxy ships with no administrator account. On the first boot of every VM, a one-shot service writes an instance info note that records the management URL and the create-admin instruction. The note contains no password, because you set your own on the first visit. Read it with sudo:
sudo cat /root/zoraxy-credentials.txtConfirm from the command line that the server is healthy and that no admin is baked into the image. The version endpoint returns 200, and the account count is 0 until you create your own admin:
curl -s -o /dev/null -w 'GET /api/info/x -> HTTP %{http_code}\n' http://127.0.0.1:8000/api/info/xcurl -s http://127.0.0.1:8000/api/auth/userCount; echoStep 5 - Create your admin on first visit
Browse to http://<vm-public-ip>:8000/. Because the image ships with no administrator, Zoraxy opens on its Account Setup page. Choose a username and a strong password, confirm the password, and select Confirm.
This one screen is where you secure the instance. There are no default credentials to change, because none ship.
Step 6 - The management dashboard
After you create your admin, sign in to the management UI. The status page confirms that the server is online and which port it is serving on, and it shows request and network activity. The left navigation groups every feature: Reverse Proxy, Access and Connections, Security, Services, Networking and more.
Step 7 - Publish a site through the reverse proxy
Open Reverse Proxy, then HTTP Proxy to manage the hosts you route. Select Create Proxy Rule (or HTTP Proxy, then the new rule form). Enter the matching hostname (for example app.example.com), the upstream destination (for example 192.168.1.10:8080), and whether the upstream uses TLS.
Save the rule. Zoraxy immediately routes matching requests to that upstream, adding websockets and HTTP/2 automatically.
Step 8 - Use the built-in network tools
Zoraxy is also a network toolkit. Open Networking, then Network Tools. From the management UI you can discover services with the mDNS scanner, find devices on the local network with the IP scanner, check open ports with the port scanner, and trace routes or ping hosts.
Step 9 - Verify the stack
Confirm the Zoraxy version, that the service is enabled, that the management UI responds, and that the dedicated data disk is mounted:
/usr/local/bin/zoraxy -versionsystemctl is-enabled zoraxycurl -s -o /dev/null -w 'GET /login.html -> HTTP %{http_code}\n' http://127.0.0.1:8000/login.htmldf -h /opt/zoraxy | tail -1Step 10 - Where your data lives
Your reverse proxy rules, issued and self-signed certificates, access rules, logs and the node identity all live on a dedicated Azure data disk mounted at /opt/zoraxy, separate from the OS disk. This disk is captured into the image and re-provisioned on every VM, and you can snapshot and resize it independently. Confirm the mount and the free space:
df -h /opt/zoraxy | tail -1sudo ls /opt/zoraxyStep 11 - Enable HTTPS with ACME (optional)
Zoraxy can obtain and renew TLS certificates for you. In the management UI, open Security, then TLS / SSL certificates and ACME Client. Set your contact email and request a certificate for a domain that resolves to this VM.
Zoraxy serves the HTTP challenge on port 80, so keep 80/tcp open in the NSG. It then serves your site over HTTPS on port 443 and renews the certificate automatically before it expires. You can also upload your own certificate if you manage TLS elsewhere.
Security notes
- The management UI serves on port 8000. Restrict
8000/tcpin the NSG to trusted networks, and consider putting the management UI behind your own VPN. The reverse proxy itself faces the network on ports 80 and 443 for the sites you publish. - The image ships with no administrator. You create the first admin on the first visit, so there are no shared or default credentials to rotate. A fresh node identity is generated per instance on first boot, so no cryptographic identity is shared across deployments.
- Zoraxy runs as root because it binds the privileged ports 80 and 443 and drives network tools. Publish only the upstreams you intend to expose, and use the access control rules to limit who can reach them.
- Keep the VM patched. The image is patched at build time and ships with unattended security upgrades enabled.
Support
SecureAnyCloud images come with 24/7 support. If you have questions about this Zoraxy image or need help with your deployment, contact us through the SecureAnyCloud website.
Deploy on Azure
Launch Zoraxy on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
This image runs Zoraxy, a self-hosted reverse proxy with a full web management interface. Instead of editing configuration files by hand, you define virtual hosts, upstream targets, redirect rules, access control lists and TLS certificates from a browser, and Zoraxy applies them live.
Zoraxy is distributed under the GNU Affero General Public License version 3. It is installed from the official prebuilt single Go binary at /usr/local/bin/zoraxy, with a copy of the licence at /usr/share/doc/zoraxy/LICENSE. There is no external database. Zoraxy keeps its state in an embedded key-value store.
The service runs under systemd and starts on boot. All state lives under /opt/zoraxy, which is a dedicated and independently resizable EBS data volume. The state includes the configuration store, the node identity, the certificate store, request logs and plugins.
The security model, which differs from a stock Zoraxy install
Two ports carry your traffic and are the only application ports this image expects to be open:
- 80: proxied sites over HTTP. Redirects to HTTPS unless a rule opts out.
- 443: proxied sites over HTTPS.
The management console is bound to the loopback address 127.0.0.1:8000 and is deliberately not published. It is not in the security group and cannot be reached from outside the instance at all. You open it through an SSH tunnel from your own workstation, which Step 4 walks through. This closes off the most common failure mode for a self-hosted proxy, which is an administrative console left facing the internet.
Every instance generates its own administrator password at first boot and writes it to /root/zoraxy-credentials.txt with mode 0600. It registers the password through the application's own first-run account window before that window closes. No credential, account store, node identity, proxy rule, TLS private key or certificate authority account key is baked into the image, so two instances launched from it never share a secret.
Two upstream defaults are switched off in this image, because neither is appropriate for a machine image. The first is the mDNS scanner and transponder, which would otherwise probe and advertise on your network. The second is the built-in static web server, which upstream starts automatically on port 5487 across all interfaces with directory listing enabled. You can turn both back on from the console.
Prerequisites
Before you deploy this image, make sure you have:
- An Amazon Web Services account where you can launch EC2 instances.
- IAM permissions to launch instances, create security groups and subscribe to AWS Marketplace products.
- An EC2 key pair in the target Region for SSH access to the instance.
- A VPC and subnet in the target Region, with a security group that allows inbound port 22 from your management network, and ports 80 and 443 from wherever your proxied sites should be reachable.
- An SSH client on your workstation, which you also use to tunnel to the management console.
- Optional: the AWS CLI (version 2) installed locally, if you plan to deploy from the command line.
Launch the Instance from the AWS Marketplace
Sign in to the AWS Management Console, open the EC2 service, and select Launch instance. Under Application and OS Images, choose AWS Marketplace AMIs and search for Zoraxy. Select the SecureAnyCloud listing and choose Select, then Continue on the subscription summary.
Pick an instance type of m5.large or larger. Choose your EC2 key pair under Key pair (login). Under Network settings, select your VPC and subnet, and create or select a security group that opens port 22 from your management network and ports 80 and 443 for your proxied traffic. Do not open port 8000. The management console is bound to loopback and does not listen on the instance's public address.
Select Launch instance. First-boot initialisation completes a few seconds after the instance state becomes Running and the status checks pass.
Launch the Instance from the AWS CLI
The following command launches an instance from the SecureAnyCloud Zoraxy Marketplace AMI into an existing subnet and security group. Replace <ami-id> with the AMI ID shown on the Marketplace listing, <key-name> with your EC2 key pair name, <subnet-id> with your subnet ID, and <security-group-id> with a security group that opens ports 22, 80 and 443 as described above.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <key-name> \
--subnet-id <subnet-id> \
--security-group-ids <security-group-id> \
--block-device-mappings '[{"DeviceName":"/dev/sda1","Ebs":{"VolumeSize":30,"VolumeType":"gp3"}}]' \
--metadata-options 'HttpTokens=required,HttpEndpoint=enabled' \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=zoraxy}]'Wait for the instance to reach the running state and pass both status checks before you continue.
Connect to Your Instance
Connect over SSH on port 22 using the login user for your operating system variant.
Connecting to your instance
- Ubuntu 24.04: SSH login user is ubuntu
ssh -i /path/to/your-key.pem ubuntu@<public-ip>The login banner tells you where this instance's credentials are and how to reach the console.
Confirm that the service is running and check the version:
STATE=$(systemctl is-active zoraxy.service)
echo "zoraxy.service is ${STATE}" [ "${STATE}" = "active" ] || exit 1
VER=$(/usr/local/bin/zoraxy -version | head -1)
echo "${VER}" case "${VER}" in *3.3.3*)
echo "version check passed" ;; *)
echo "unexpected version"; exit 1 ;; esacReal output from a running instance:
zoraxy.service is active Zoraxy - Version 3.3.3 version check passedConfirm what is listening, and in particular that the management console is on loopback only:
LISTEN=$(sudo ss -tlnH | awk '{print $4}' | sort)
echo "${LISTEN}" case "${LISTEN}" in *"127.0.0.1:8000"*)
echo "management console is bound to loopback" ;; *)
echo "management console is not on loopback"; exit 1 ;; esac case "${LISTEN}" in *"0.0.0.0:8000"*|*"[::]:8000"*|*"*:8000"*)
echo "management console is publicly bound"; exit 1 ;; esac case "${LISTEN}" in *":5487"*)
echo "the static web server is running"; exit 1 ;; *)
echo "the built in static web server is off, as shipped" ;; esacReal output from a running instance:
*:443 *:80 0.0.0.0:22 127.0.0.1:8000 127.0.0.53%lo:53 127.0.0.54:53 [::]:22 management console is bound to loopback the built in static web server is off, as shippedPorts 80 and 443 are your proxied data plane. Port 8000 is bound to 127.0.0.1 and is unreachable from anywhere but the instance itself.
Confirm that the dedicated data volume is mounted:
findmnt -no SOURCE,TARGET,FSTYPE /opt/zoraxy
findmnt -no TARGET /opt/zoraxy | grep -qx /opt/zoraxy || exit 1 echo "/opt/zoraxy is a dedicated filesystem"Real output from a running instance:
/dev/nvme1n1 /opt/zoraxy ext4 /opt/zoraxy is a dedicated filesystemRetrieve the Credentials and Open the Management Console
This instance's administrator credentials were generated on this machine at first boot. List the keys held in the credentials file:
sudo grep -oE '^[A-Za-z._]+=' /root/zoraxy-credentials.txt
sudo stat -c 'perms=%a owner=%U:%G' /root/zoraxy-credentials.txtReal output from a running instance:
zoraxy.admin.user= zoraxy.admin.pass= ZORAXY_ADMIN_URL= ZORAXY_PUBLIC_URL= perms=600 owner=root:rootTo read the values, including the password, run the following command on the instance. Only root can read the file.
sudo cat /root/zoraxy-credentials.txtThe management console listens on 127.0.0.1:8000 and is not reachable from the internet. From your own workstation, open an SSH tunnel to it:
ssh -i /path/to/your-key.pem -L 8000:127.0.0.1:8000 ubuntu@<public-ip>Leave that session open and browse to http://127.0.0.1:8000/ on your workstation. Sign in with the username and password from the credentials file.
After you sign in, you land on the status view. It shows the proxy service state, the port it is serving on, request counters and network throughput, with the full feature menu down the left-hand side.
Verifying the console rejects the wrong callers
Before you rely on the console, check that it is protected. An unauthenticated call to an administrative endpoint is redirected to the login page and never answered with data:
CODE=$(curl -s -o /dev/null -w '%{http_code}' -m 10 http://127.0.0.1:8000/api/proxy/list)
echo "unauthenticated GET /api/proxy/list returned HTTP ${CODE}" case "${CODE}" in 200)
echo "the management API answered an unauthenticated caller"; exit 1 ;; "")
echo "no response from the management API"; exit 1 ;; *)
echo "the management API refused the unauthenticated request, as expected" ;; esacReal output from a running instance:
unauthenticated GET /api/proxy/list returned HTTP 307 the management API refused the unauthenticated request, as expectedNow check that this instance's own credential works. The following command reads the username and password from the root-only credentials file when it runs and never prints them. Zoraxy protects its console with a session cookie plus a cross-site request forgery token, so the login exchange fetches the token first.
WORK=$(mktemp -d) JAR="${WORK}/jar"
CSRF=$(curl -s -m 10 -c "${JAR}" http://127.0.0.1:8000/login.html \
| sed -n 's/.*name="zoraxy\.csrf\.Token" content="\([^"]*\)".*/\1/p' | head -1) [ -n "${CSRF}" ] || { echo "could not read the login page token"; rm -rf "${WORK}"; exit 1; }
USER=$(sudo grep '^zoraxy.admin.user=' /root/zoraxy-credentials.txt | cut -d= -f2-)
PASS=$(sudo grep '^zoraxy.admin.pass=' /root/zoraxy-credentials.txt | cut -d= -f2-) [ -n "${USER}" ] && [ -n "${PASS}" ] || { echo "could not read the credentials"; rm -rf "${WORK}"; exit 1; }
RESP=$(curl -s -m 15 -b "${JAR}" -c "${JAR}" -H "X-CSRF-Token: ${CSRF}" \
--data-urlencode "username=${USER}" \
--data-urlencode "password=${PASS}" \
http://127.0.0.1:8000/api/auth/login) case "${RESP}" in *'"OK"'*) echo "the management login accepted this instance's own credential" ;; *) echo "the management login rejected the credential"; rm -rf "${WORK}"; exit 1 ;; esac
CODE=$(curl -s -o /dev/null -w '%{http_code}' -m 10 -b "${JAR}" http://127.0.0.1:8000/api/proxy/list) rm -rf "${WORK}" echo "authenticated GET /api/proxy/list returned HTTP ${CODE}" [ "${CODE}" = "200" ] || exit 1Real output from a running instance:
the management login accepted this instance's own credential authenticated GET /api/proxy/list returned HTTP 200Create Your First Reverse Proxy Rule
In the console, open Reverse Proxy, then Create Proxy Rule. Enter the hostname you intend to publish under Matching Keyword / Domain. Under Target IP Address or Domain Name with port, enter the address of the service you want to sit behind it, for example 127.0.0.1:3000. Tick Proxy Target require TLS Connection only if the upstream itself speaks HTTPS. Select Create Endpoint.
The rule appears in HTTP Proxy. There you can toggle it on and off, attach virtual directories, add tags, and open the detail editor for headers, rate limiting, sticky sessions and access rules. Subdomains and wildcards are supported, and a comma-separated list adds alias hostnames to the same rule.
Point a DNS record for that hostname at your instance's public IP address, and the site is live on ports 80 and 443.
Proving a real request travels through the proxy
The image ships a self-test that exercises the whole path end to end. It stands up a temporary upstream on the loopback interface carrying a random marker, creates a proxy rule for it through the authenticated API, requests it through the public data plane on port 80, and checks that the marker comes back. It removes the temporary rule and the temporary upstream before it exits.
sudo /usr/local/sbin/zoraxy-selftest.shReal output from a running instance:
1/4 unauthenticated admin API refused (HTTP 307) 2/4 wrong password refused, no session granted (HTTP 307) 3/4 per-instance credential authenticates, admin API reachable (HTTP 200) 4/4 reverse-proxy round-trip served the upstream body through port 80 SELFTEST OK - admin API protected, per-instance credential valid, proxy round-trip liveConfirm that the self-test left nothing behind:
LEFT=$(sudo find /opt/zoraxy/conf/proxy -name '*selftest*' 2>/dev/null | wc -l | tr -d ' ')
echo "temporary self test rules remaining: ${LEFT}" [ "${LEFT}" = "0" ] || exit 1
echo "the self test removed its temporary rule"Real output from a running instance:
temporary self test rules remaining: 0 the self test removed its temporary ruleEnable HTTPS for Your Sites
Open Security, then TLS / SSL certificates. You can upload an existing certificate and private key for a domain, paste them directly, or let Zoraxy obtain one for you.
For an automatically issued certificate, open Security, then ACME Client. Choose your certificate authority, enter the domain and the contact email address, and request the certificate. The domain must already resolve to this instance, and port 80 must be reachable from the internet so that the challenge can complete. Zoraxy renews certificates automatically before they expire, and you can configure the renewal policy on the same page.
Until a certificate exists for a hostname, Zoraxy serves it with a self-signed fallback certificate that it generates on this instance. No certificate and no certificate authority account key ships in the image.
Restrict Who Can Reach Your Sites
Open Access & Connections, then Access Control. Every proxy rule uses the default access rule unless you assign it another one, so you can apply one policy to every site or write a rule per site.
Each rule carries a blacklist, a whitelist and a quick ban list. You can block or allow by IP address, by IP range, or by the country estimated from the requester's address. Country estimation is based on IP geolocation and is not exact, so treat it as a coarse control. Create a new rule with Access Rule Editor and attach it to a site from the rule's detail editor in HTTP Proxy.
Trusted Proxy, on the same menu, tells Zoraxy which upstream addresses it should trust for the X-Forwarded-For header. Set it if the instance itself sits behind a load balancer or CDN. Otherwise your access rules see the intermediary's address instead of the real client's.
Operations and Maintenance
Service control
sudo systemctl status zoraxy
sudo systemctl restart zoraxyReading the service log
sudo journalctl -u zoraxy.service -n 100 --no-pagerZoraxy also keeps its own request and system logs under /opt/zoraxy/log/. The console shows them under Others, then Utilities.
Where the state lives
Everything Zoraxy needs is under /opt/zoraxy on the dedicated data volume:
- /opt/zoraxy/sys.db: account store, settings and the session key
- /opt/zoraxy/sys.uuid: node identity and the cross-site request forgery signing key
- /opt/zoraxy/conf/: proxy, redirect, stream and access rules, plus the certificate store
- /opt/zoraxy/log/: request and system logs
- /opt/zoraxy/plugins/: installed plugins, empty as shipped
Backup
Stop the service so the embedded store is quiesced, archive the data volume contents, then start the service again. Run the following on the instance, and substitute a destination of your own:
sudo systemctl stop zoraxy
sudo tar -czf /var/backups/zoraxy-$(date +%F).tar.gz -C /opt zoraxy
sudo systemctl start zoraxyThe archive contains your certificates and your account store, so treat it as a secret and store it accordingly. For a full disaster recovery position, take an EBS snapshot of the /opt/zoraxy volume instead. You can restore the snapshot to a new instance directly.
Resizing the data volume
The data volume is independent of the operating system disk. Modify it in the EC2 console or with aws ec2 modify-volume. Then grow the filesystem on the instance with sudo resize2fs against the device that findmnt /opt/zoraxy reports.
Changing the administrator password
Sign in to the console, open the account menu at the top right, and change the password there. If you lose the credential entirely, the shipped binary can reset the account store. Stop the service and run the binary's account reset from the working directory. Then start the service and create a new administrator on the next visit.
Enabling the features shipped switched off
A flag on the service unit disables the mDNS scanner. To re-enable it, edit ExecStart in /etc/systemd/system/zoraxy.service, remove -mdns=false, then run sudo systemctl daemon-reload && sudo systemctl restart zoraxy.
The static web server is disabled per instance. Re-enable it from Services, then Static Web Server. There you can also keep it pinned to the loopback interface and publish it through a proxy rule instead of exposing it directly.
Troubleshooting
The console will not load in your browser. The console is bound to loopback. Check that the SSH tunnel from Step 4 is still open, and that you are browsing to http://127.0.0.1:8000/ on your workstation instead of the instance's public address. Opening port 8000 in the security group does not help, because nothing is listening on the public interface.
A proxied site redirects to HTTPS and you did not expect it. Zoraxy redirects port 80 to port 443 by default. To serve a host on port 80 directly, open the rule's detail editor in HTTP Proxy and allow plain HTTP access for that host.
A proxied site returns a gateway error. The upstream address in the rule is not answering. Check that the service you pointed at is running and listening on the address and port in the rule, and that the instance can reach it.
A certificate request fails. The domain must resolve to this instance, and port 80 must be reachable from the internet for the challenge. Check the DNS record and the security group, then retry from ACME Client.
The service will not start. Read the log with sudo journalctl -u zoraxy.service -n 100 --no-pager. A common cause is another process that already holds port 80 or 443 on the instance.
Support
SecureAnyCloud provides 24/7 technical support for this image by email at sales@secureanycloud.com and by live chat on secureanycloud.com. Our engineers help with deployment, proxy rule design, upstream and load-balancing configuration, TLS and certificate troubleshooting, access control and data volume resizing.
Zoraxy itself is an open source project by tobychui, licensed under the GNU Affero General Public License version 3. Product documentation and the source are at github.com/tobychui/zoraxy.
Deploy on AWS
Launch Zoraxy on AWS with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com