We
Developer Tools Azure

WeTTY on Ubuntu 24.04 on Azure User Guide

| Product: WeTTY on Ubuntu 24.04 LTS on Azure

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.service running 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.service for 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_B2s VM (2 vCPU, 4 GiB) or larger.

Step 1: Deploy from the Azure Portal

  1. Open the WeTTY on Ubuntu 24.04 LTS offer on Azure Marketplace and select Get It Now, then Create.
  2. Choose your subscription, resource group and region.
  3. Set the VM size to Standard_B2s or larger, and provide your SSH public key for the azureuser administrator.
  4. On the Networking tab, allow inbound 443 (HTTPS) from the clients that will reach the terminal, and 22 (SSH) for administration.
  5. 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

WeTTY, nginx and the first boot service all active, nginx listening on port 443, WeTTY listening only on the Unix socket /run/wetty/wetty.sock with 750/770 wetty permissions, running WeTTY 3.2.0 on Node.js 22

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:

The WeTTY browser terminal after signing in with the per VM password, showing the cloudimg message of the day and an interactive shell prompt

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:

The WeTTY browser terminal running uname, whoami and uptime and showing their real output in an interactive session

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:

The WeTTY browser terminal listing the filesystem and checking service status, demonstrating full administrative shell access from the browser

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

The WeTTY, nginx and first boot units enabled, the first boot marker present, and an intact OS patch baseline with no held packages

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.