WeTTY on Ubuntu 24.04 on Azure User Guide
Overview
WeTTY is an open source terminal in the browser. It serves a real, fully interactive shell over HTTP or HTTPS, backed by SSH, so anyone with a browser gets a genuine command line on the server with no desktop SSH client, no downloaded key file and no local setup. The web front end is a complete xterm terminal, so editors, pagers, colours, resizing and long running commands all behave exactly as they do in a native terminal, and every browser session is a normal SSH login under the hood.
The cloudimg image runs WeTTY as a systemd service that listens only on a private Unix socket (/run/wetty/wetty.sock, no TCP port at all), and fronts it with nginx over HTTPS on port 443 (port 80 redirects to 443). Behind the browser sign in, WeTTY opens an SSH session to the local server as your own administrator account (the admin username you chose at deployment), so every browser session is a real login on the VM.
Secure by default: no known or default credential ships and no extra login account is added to the operating system. On the first boot of every instance a wetty-firstboot.service oneshot generates a unique 32 character browser password (stored by nginx only as a hash), a per VM SSH key that WeTTY uses to open the shell as your admin account, and a per VM self signed TLS certificate, and only then starts WeTTY and nginx. The browser password is written 0600 root:root to /root/wetty-credentials.txt. The WeTTY key is accepted only from the VM itself (from="127.0.0.1,::1"), and SSH password authentication stays disabled for every account.
What is included:
- WeTTY 3.2.0 (MIT) installed from npm on a Node.js 22 LTS runtime
wetty.servicerunning the terminal on the Unix socket/run/wetty/wetty.sock, which only nginx can connect to- nginx reverse proxy terminating HTTPS on port 443, WebSocket aware, with an HTTP to HTTPS redirect
- A per VM browser password generated at first boot and enforced by nginx
- A per VM SSH key that opens the browser shell as your own admin account, accepted only from loopback
- Per VM self signed TLS certificate generated at first boot in
/etc/ssl/cloudimg/ wetty-firstboot.servicefor first boot credential and certificate generation- SSH password authentication disabled for every account
- Ubuntu 24.04 LTS base, fully patched, unattended security upgrades enabled
- 24/7 cloudimg support, 24h response SLA
Prerequisites
- An Azure subscription and permission to deploy a virtual machine.
- An SSH key pair to administer the VM as
azureuser. - Inbound TCP 443 (and optionally 80) open to the clients that will use the browser terminal, and TCP 22 for administration.
- A
Standard_B2sVM (2 vCPU, 4 GiB) or larger.
Step 1: Deploy from the Azure Portal
- Open the WeTTY on Ubuntu 24.04 LTS offer on Azure Marketplace and select Get It Now, then Create.
- Choose your subscription, resource group and region.
- Set the VM size to
Standard_B2sor larger, and provide your SSH public key for theazureuseradministrator. - On the Networking tab, allow inbound 443 (HTTPS) from the clients that will reach the terminal, and 22 (SSH) for administration.
- Review and create. When deployment finishes, note the VM's public IP address.
Step 2: Deploy from the Azure CLI
Accept the marketplace image terms once per subscription if prompted, then create the VM:
az vm image terms accept --urn cloudimg1647283583153:wetty-ubuntu-24-04:default:latest
az group create --name wetty-rg --location eastus
az vm create \
--resource-group wetty-rg \
--name wetty-vm \
--image cloudimg1647283583153:wetty-ubuntu-24-04:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
az vm open-port --resource-group wetty-rg --name wetty-vm --port 443 --priority 900
Step 3: Connect via SSH and read the per VM password
Administer the VM as azureuser with your SSH key, then read the browser terminal password that first boot generated for this instance:
ssh azureuser@<vm-ip>
The per VM password lives in a root only file. Read it:
sudo cat /root/wetty-credentials.txt
You will see the browser sign in, the per VM password, the account the shell opens as, and the browser URL:
WETTY_URL=https://<vm-ip>/
WETTY_WEB_USER=wetty
WETTY_WEB_PASSWORD=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
WETTY_SHELL_USER=azureuser
NOTE=Open the WeTTY URL in a browser and sign in as WETTY_WEB_USER with WETTY_WEB_PASSWORD.
WETTY_SHELL_USER is the admin username you chose when you deployed the VM.
Step 4: Verify the services are running
WeTTY and nginx are managed by systemd. Confirm both are active, that nginx listens on 443, and that WeTTY listens only on its Unix socket, which is closed to every local user except nginx:
systemctl is-active wetty nginx wetty-firstboot
sudo ss -tlnp | grep ':443 '
sudo ss -xlp | grep wetty.sock
sudo stat -c '%n %a %U:%G' /run/wetty /run/wetty/wetty.sock
wetty --version ; node --version

Step 5: Secure by default
There is no default password and no extra login account. The browser password is generated uniquely on this VM at first boot, nginx keeps only its hash, and the plain value is in a root only file. WeTTY opens the shell with a per VM key that your admin account accepts only from the VM itself, and SSH password authentication is off:
sudo stat -c '%n perms=%a owner=%U:%G' /root/wetty-credentials.txt /etc/nginx/cloudimg-wetty.htpasswd
grep cloudimg-wetty-browser-terminal ~/.ssh/authorized_keys | cut -c1-60
sudo sshd -T | grep -i '^passwordauthentication'
You should see the credentials file 600 root:root, the WeTTY key restricted with restrict,pty,from="127.0.0.1,::1" (no forwarding of any kind, loopback only), and passwordauthentication no. The browser terminal always opens as your admin account: nginx ignores any attempt to choose another account through the URL or request headers.
Step 6: Open WeTTY in your browser and sign in
In a browser, go to https://<vm-ip>/. The image ships a per VM self signed certificate, so accept the browser warning (or install your own certificate, see Step 11). The browser asks you to sign in: use wetty and the per VM password from Step 3. WeTTY then opens a real shell as your admin account, with the cloudimg message of the day:

Step 7: Use the browser terminal
The session is a genuine interactive shell. Run any command and see real output, exactly as you would in a native terminal:

Step 8: Administer the server from the browser
The browser shell runs as your admin account, which has sudo, so you can administer the whole server from the browser terminal. Treat the browser password with the same care as your SSH key:

Step 9: The stack, nginx and HTTPS
nginx terminates HTTPS on port 443 and proxies to WeTTY on loopback, upgrading the WebSocket the terminal relies on. Port 80 redirects to HTTPS:
nginx -v
curl -ks -o /dev/null -w 'GET /wetty (443, no password) -> HTTP %{http_code}\n' https://127.0.0.1/wetty
curl -s -o /dev/null -w 'GET / (port 80) -> HTTP %{http_code}\n' http://127.0.0.1/
You should see HTTP 401 for the HTTPS request without the browser password (the sign in is enforced) and HTTP 301 for the port 80 redirect.
Step 10: Persistence and the patch baseline
The units are enabled so the browser terminal survives a reboot, the first boot marker confirms the per VM password, key and certificate were generated, and the OS security baseline has no held packages:
sudo systemctl is-enabled wetty nginx wetty-firstboot
test -f /var/lib/cloudimg/wetty-firstboot.done && echo "first boot complete"
sudo apt-mark showhold

Step 11: Enable a trusted TLS certificate
The image ships a per VM self signed certificate so HTTPS works out of the box. For a production deployment, point a DNS name at the VM and install a trusted certificate with certbot:
sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com --email admin@your-domain.example.com --agree-tos --no-eff-email
certbot updates the nginx configuration to use the issued certificate and sets up automatic renewal.
Managing the service
sudo systemctl status wetty --no-pager
sudo systemctl restart wetty
To follow the WeTTY logs live, run sudo journalctl -u wetty -f. To rotate the browser password yourself, run printf 'wetty:%s\n' "$(openssl passwd -apr1)" | sudo tee /etc/nginx/cloudimg-wetty.htpasswd >/dev/null && sudo systemctl reload nginx and record the new value. If you remove the cloudimg-wetty-browser-terminal line from your admin account's authorized_keys, the browser terminal can no longer open a shell.
Support
This image is published by cloudimg with 24/7 support and a 24 hour response SLA. WeTTY is open source software licensed under the MIT License; this image bundles it with a hardened, fully patched base and secure by default configuration. For help with the image or the deployment, contact cloudimg support.