Networking Azure

Nginx UI on Ubuntu 24.04 on Azure User Guide

| Product: Nginx UI on Ubuntu 24.04 LTS on Azure

Overview

This image runs Nginx UI, a web management interface for nginx. Nginx UI reads and writes the nginx configuration directly, so you can create and edit sites, streams and upstreams from a browser, issue and renew Let's Encrypt certificates, browse and analyse access and error logs, and test and reload the configuration without hand editing files over SSH. Every change is validated with nginx -t before it is applied, so a bad edit is caught before it reaches a running server.

The image ships nginx and Nginx UI together and the two are deliberately independent. nginx serves your sites on port 80 and 443 and is the thing under management. Nginx UI runs as its own service on port 9000 and manages it. Nginx UI is not itself served through nginx, so a configuration mistake that takes a site down never locks you out of the tool you need to fix it.

The image contains no account and no password. Nginx UI's normal first run opens a setup wizard where the first visitor creates the administrator, which is not safe on a public cloud image. Instead, on the first boot of every deployed VM a one shot service generates a password unique to that server, brings Nginx UI up bound to the loopback interface only, completes the setup locally, proves the new credential works and that guessable passwords are rejected, and only then exposes the service on port 9000. There is no window in which the setup wizard is reachable from the network, and no two cloudimg deployments share a password.

What is included:

  • Nginx UI 2.4.2 running as the nginx-ui service on port 9000
  • nginx 1.24.0 (Ubuntu 24.04 archive) running as the nginx service on port 80, under Nginx UI's management
  • Per VM first boot bootstrap: a unique administrator password generated on the server, written to a root only file
  • Setup completed over the loopback interface, so the first run wizard is never exposed to the network
  • Full nginx management: sites, streams, upstreams, configuration editor, Let's Encrypt certificates, log analysis
  • Configuration validated with nginx -t before every apply and reload
  • All packages from the Ubuntu archive plus the official upstream Nginx UI release, verified against its published SHA-512 digest
  • 24/7 cloudimg support

Nginx UI is published under the GNU Affero General Public License v3.0 and is shipped unmodified. The full licence text is retained on the image at /opt/nginx-ui/LICENSE.

Prerequisites

Before you deploy this image you need:

  • An active Microsoft Azure subscription where you can create virtual machines
  • An SSH key pair for administrator access to the VM
  • A virtual network and subnet in the target region
  • A network security group (NSG) that allows inbound TCP 22 from your administrator network, TCP 9000 from your administrator network only, and TCP 80 and TCP 443 from wherever your sites need to be reachable
  • The Azure CLI installed locally if you plan to deploy from the command line

Standard_B2s (2 vCPU / 4 GiB RAM) is a balanced default. Size the VM to the traffic your nginx sites will serve; Nginx UI itself is lightweight.

Step 1: Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, and search the Marketplace for Nginx UI by cloudimg. Select the listing and choose Create.

On the Basics tab pick your subscription and resource group, a region, and a VM size (Standard_B2s or larger). Under Administrator account select SSH public key, set the username, and paste your public key. Under Inbound port rules allow SSH (22) for administration. Add the management port (9000) and your site ports (80 and 443) afterwards, scoped to the right source ranges. Select Review + create, then Create.

First boot initialisation takes a few seconds after the VM reaches the Running state. Nginx UI is not reachable until it completes, which is by design.

Step 2: Deploy from the Azure CLI

The following block creates a VM from the cloudimg Nginx UI image into an existing VNet and subnet. Replace the placeholders with your own values.

az vm create \
  --resource-group <your-rg> \
  --name nginx-ui \
  --image <marketplace-image-urn> \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard

# The management interface. Scope this to your administrator network, never the internet.
az network nsg rule create --resource-group <your-rg> --nsg-name <your-nsg> \
  --name allow-nginx-ui --priority 1010 \
  --source-address-prefixes <your-admin-cidr> --destination-port-ranges 9000 \
  --access Allow --protocol Tcp

# The sites nginx serves.
az vm open-port --resource-group <your-rg> --name nginx-ui --port 80 --priority 1020
az vm open-port --resource-group <your-rg> --name nginx-ui --port 443 --priority 1030

Step 3: Connect as the Administrator over SSH

Connect to the VM with SSH as the administrator user you set at deploy time (azureuser by default on Ubuntu). The administrator account is SSH key only.

ssh azureuser@<vm-public-ip>

Step 4: Confirm Nginx UI and nginx are Running

Both services start automatically. Confirm they are active, check the listeners, and read the build provenance recorded on the image:

systemctl is-active nginx-ui.service nginx.service
sudo ss -tlnp | grep -E ':(9000|80|443) '
nginx-ui --version
nginx -v
cat /opt/nginx-ui/VERSION

Nginx UI listens on port 9000 and nginx listens on port 80. Nothing listens on 443 until you add a TLS site, which you can do from the interface in Step 8. The VERSION file records the exact upstream release and the SHA-512 digest the image was built from.

Both the nginx-ui and nginx services report active, Nginx UI 2.4.2 and nginx 1.24.0 are installed, the listeners show port 9000 for the management interface and port 80 for nginx, and the pinned build provenance records the upstream release tag and its verified SHA-512 digest

Step 5: Retrieve Your Sign In Credentials

First boot generated an administrator password unique to this server and wrote it to a root only file along with the URLs you need. Read it:

sudo stat -c '%a %U:%G %n' /root/nginx-ui-credentials.txt
sudo grep -E '^(NGINX_UI_ADMIN_USERNAME|NGINX_UI_URL|NGINX_SITE_URL)=' /root/nginx-ui-credentials.txt

The file is mode 600 and owned by root, so only an administrator who can already reach the server can read it. To display the password itself, read the whole file:

sudo cat /root/nginx-ui-credentials.txt

The first boot journal records exactly what happened: the setup was completed over the loopback interface, the credential was proven, and only then was the service exposed on port 9000.

The first boot journal shows Nginx UI started on 127.0.0.1 for the local bootstrap, the setup completed for the per VM admin over loopback, the credential proven and the setup window closed, then the service rebound to all interfaces, with the resulting root only credentials file listing the generated username, the management URL and the site URL

Step 6: Sign In to Nginx UI

Browse to http://<vm-public-ip>:9000/ and sign in with the username and password from Step 5.

The Nginx UI sign in page, showing the username and password fields, the login button, and the language and theme controls

After signing in you land on the server dashboard, which reports the nginx process state alongside live CPU, memory, storage, network and disk metrics for the VM.

The Nginx UI server dashboard showing server info with uptime, load average, operating system Ubuntu 24.04 and CPU count, memory and storage gauges, network statistics, and live CPU, network and disk IO charts

Change the password immediately. Open the user menu and set a password of your own. The generated password exists so the server is never unprotected on first boot; it is not intended to be your long term credential.

Step 7: Manage nginx Sites

Choose Manage Sites then Sites List. Nginx UI reads the site definitions straight from /etc/nginx/sites-available and shows their enabled state. A fresh image has one site, default, which serves the landing page you get on port 80.

From here you can Add a site, Edit one in the built in editor, Duplicate an existing site as a starting point, or enable and disable sites. Nginx UI runs nginx -t whenever you save and shows the result at the top of the page, so a syntax error is reported before the configuration is applied.

The Nginx UI Manage Sites list showing the default site as enabled, with a configuration file is test successful banner confirming nginx -t passed, and Edit, Duplicate and Delete actions available for each site

Step 8: Edit the nginx Configuration and Issue Certificates

Manage Configs exposes the whole of /etc/nginx as an editable tree: conf.d, modules-available, modules-enabled, sites-available and sites-enabled, plus nginx.conf itself. Edits are made in a syntax highlighted editor and validated before they are saved.

The Nginx UI Manage Configs page listing the nginx configuration tree including conf.d, modules-available, modules-enabled and sites-available with modify, rename and delete actions, and a configuration file is test successful banner

To serve a site over HTTPS, point a DNS name at the VM's public IP, make sure port 80 is reachable from the internet so the ACME HTTP challenge can complete, then use Certificates to request a Let's Encrypt certificate for that name. Nginx UI writes the certificate, wires it into the site, and renews it automatically. Add the port 443 NSG rule from Step 2 before you expose the site.

The Terminal entry in the sidebar opens an in browser root shell on the server. This is an upstream Nginx UI feature and is shipped unmodified. Treat access to port 9000 as equivalent to root SSH access, and restrict it accordingly in Step 10.

Step 9: Verify nginx Management from the Command Line

Everything the interface does is available through Nginx UI's API. This block signs in with your credentials, asks Nginx UI to report on the nginx it manages, lists the sites it can see, and runs nginx -t through the API:

. /usr/local/sbin/nginx-ui-api.sh
JWT=$(nui_login '<NGINX_UI_ADMIN_USERNAME>' '<NGINX_UI_ADMIN_PASSWORD>')
if [ -n "$JWT" ]; then
  echo "signed in OK"
  nui_get "$JWT" /api/nginx/status; echo
  nui_get "$JWT" /api/sites | head -c 300; echo
  curl -s -o /dev/null -w 'nginx -t via the API: HTTP %{http_code}\n' \
    -X POST -H "Authorization: $JWT" http://127.0.0.1:9000/api/nginx/test
else
  echo "sign in skipped: substitute the username and password from Step 5"
fi
sudo nginx -t

"running": true confirms Nginx UI is reading the live nginx process state, the site list confirms it is reading /etc/nginx, and the HTTP 200 confirms it can run a configuration test on demand.

Nginx UI reporting on the nginx it manages: the API returns running true for nginx status, lists the default site read from /etc/nginx, and returns HTTP 200 for a configuration test, matching the nginx -t syntax is ok and test is successful output on the server

Reload nginx after a change, from the interface or from the shell:

sudo nginx -t
sudo systemctl reload nginx
systemctl is-active nginx.service

Step 10: Security and Restricting the Management Port

The image ships no account, so there is no default credential to find. You can confirm the setup wizard is closed and that the generated password is the only one that works:

curl -s http://127.0.0.1:9000/api/install; echo
sudo /usr/local/sbin/nginx-ui-roundtrip.sh

{"lock":true,...} means the setup wizard is closed and cannot be used to claim the server. OK from the round trip means the per VM password authenticates, the resulting session can drive nginx, and every guessable password was rejected.

The setup wizard reports lock true so it cannot be used to claim the server, and the credential round trip returns OK, confirming the per VM password authenticates, the session identifies as the admin and can drive nginx, and guessable passwords are all rejected

For production, apply all of the following:

  • Restrict port 9000 to your administrator network in the NSG. Access to the management interface includes an in browser root terminal, so treat it as you would SSH. Never expose it to the internet.
  • Change the generated password from the user menu, and consider enabling two factor authentication or a passkey under the user settings.
  • Put the management interface behind your own TLS if you need to reach it across an untrusted network, or reach it over an SSH tunnel instead:
ssh -L 9000:127.0.0.1:9000 azureuser@<vm-public-ip>

Then browse to http://127.0.0.1:9000/ on your own machine, with port 9000 closed in the NSG entirely.

  • Keep the VM patched. Unattended upgrades are enabled, and you can apply updates on demand at any time.

Troubleshooting

The interface is not reachable on port 9000. Confirm the service is up and that first boot finished. First boot must complete before the port is opened, which is deliberate.

systemctl is-active nginx-ui.service
test -f /var/lib/cloudimg/nginx-ui-firstboot.done && echo "first boot completed"
sudo journalctl -u nginx-ui-firstboot.service --no-pager | tail -20

If the service is active and the sentinel exists, the problem is the network path: check the NSG rule for TCP 9000.

You have lost the administrator password. Reset it from the server. The command prints a newly generated password for the initial user:

sudo nginx-ui --config /usr/local/etc/nginx-ui/app.ini reset-password

A site is down after a configuration change. Nginx UI validates before applying, but if nginx is refusing to start, test the configuration and read the error:

sudo nginx -t
sudo journalctl -u nginx.service --no-pager | tail -20

Because Nginx UI is not served through nginx, the interface stays reachable on port 9000 while nginx is down, so you can fix the site from the browser.

Where things live.

ls -1 /etc/nginx/
ls -1 /usr/local/etc/nginx-ui/
cat /opt/nginx-ui/VERSION

nginx configuration is in /etc/nginx, Nginx UI's own configuration and database are in /usr/local/etc/nginx-ui, and nginx logs are in /var/log/nginx.

Support

cloudimg provides 24/7 support for this image. Contact support@cloudimg.co.uk with your Azure subscription ID and the VM name.

Nginx UI is an open source project published under the GNU Affero General Public License v3.0. Upstream documentation is at nginxui.com and the source is at github.com/0xJacky/nginx-ui. cloudimg is not affiliated with, endorsed by, or sponsored by the Nginx UI project or by F5, Inc.