Developer Tools Azure

OliveTin on Ubuntu 24.04 on Azure User Guide

| Product: OliveTin on Ubuntu 24.04 LTS on Azure

Overview

OliveTin gives you a clean web interface of buttons, where each button runs one predefined shell command that an administrator has approved in advance. Instead of handing people SSH access to run ad hoc commands, you define a curated set of actions in a single YAML file, and users simply click to run them and watch the live output stream back to the page. It is a natural fit for home labs and operations teams who want to let less technical users, or their future selves, safely trigger routine jobs such as restarting a service, checking disk space, pinging a host or kicking off a backup, from a browser or a phone.

Because every button is a real shell command running on the server, the entire value of OliveTin depends on it being locked down. An OliveTin that is reachable without authentication is, in effect, remote command execution. The cloudimg image is built around that fact: OliveTin itself is bound to the loopback interface and never exposed directly, an nginx reverse proxy terminating TLS with HTTP Basic Auth is the only network facing surface, a unique administrator password is generated on the first boot of every VM, the command runner process runs as a dedicated unprivileged user rather than as root, and only a small set of safe, non destructive actions ship out of the box.

The cloudimg image ships OliveTin 3000.17.1 as a single static Go binary on a hardened, fully patched Ubuntu 24.04 LTS base, managed by systemd. Backed by 24/7 cloudimg support.

What is included:

  • OliveTin 3000.17.1, the official release, running as a dedicated non root olivetin system user, managed by systemd
  • An nginx reverse proxy on port 443 terminating TLS with a self signed certificate regenerated per VM at first boot, enforcing HTTP Basic Auth, with port 80 redirecting to HTTPS and an unauthenticated /healthz probe for load balancers
  • OliveTin bound to the loopback interface only (127.0.0.1:1337), never exposed to the network
  • A per VM administrator password generated on first boot and recorded in a root only file, with no shipped default login
  • A small set of safe, non destructive default actions (check disk usage, show memory, show uptime, ping a host from a fixed allow list, and restart a demo service via a narrow scoped sudo rule)

OliveTin is free and open source software licensed under the GNU Affero General Public License version 3.

Prerequisites

  • An Azure subscription and either the Azure portal or the Azure CLI (az)
  • An SSH key pair to administer the VM
  • A network security group that allows inbound TCP 443 (and 80 for the HTTPS redirect) from the clients that need the web interface, plus TCP 22 from your admin location

Step 1 - Deploy from the Azure Marketplace

Find the cloudimg OliveTin on Ubuntu 24.04 LTS offering in the Azure Marketplace, choose the recommended Standard_B2s size, attach it to your virtual network, and allow inbound TCP 443 and 22. OliveTin is a tiny Go binary and runs comfortably on Standard_B2s.

Step 2 - Deploy from the Azure CLI

The commands below create a resource group, the VM from the cloudimg image, and inbound rules for HTTPS and the HTTPS redirect. Replace the image URN or plan details with the ones shown on the Marketplace listing page.

az group create --name olivetin-rg --location uksouth

az vm create \
  --resource-group olivetin-rg \
  --name olivetin \
  --image <marketplace-image-urn-from-listing> \
  --size Standard_B2s \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

az vm open-port --resource-group olivetin-rg --name olivetin --port 443 --priority 900
az vm open-port --resource-group olivetin-rg --name olivetin --port 80 --priority 910

# When the VM is running, note its public IP address:
az vm show -d --resource-group olivetin-rg --name olivetin --query publicIps -o tsv

Step 3 - Confirm the services are running

SSH in as azureuser and confirm the command runner, the reverse proxy and the first boot job are healthy. OliveTin is served by nginx, which proxies to the OliveTin binary on the loopback interface, and a one shot first boot service generates the per VM secrets.

systemctl is-active olivetin nginx olivetin-firstboot.service

Expected output (the first boot service reports active once it has completed on the first boot of the VM):

active
active
active

You can confirm the pinned version that shipped:

cat /opt/olivetin/VERSION

The olivetin and nginx services reporting active, the OliveTin binary reporting version 3000.17.1, and the baked version and sha256 recorded in the VERSION file

Step 4 - Confirm the network shape

OliveTin binds to the loopback interface only. nginx, listening on ports 80 and 443, is the sole network facing surface and reverse proxies to it. Confirm the listeners:

ss -tln | grep -E ':1337|:80 |:443 '

You will see OliveTin on 127.0.0.1:1337 (loopback only) and nginx on 0.0.0.0:80 and 0.0.0.0:443.

OliveTin listening on 127.0.0.1:1337 loopback only, with nginx listening on port 80 and port 443 as the only network facing surface

Step 5 - Retrieve the per VM administrator password

Every VM generates its own administrator password on first boot and writes it into the nginx HTTP Basic Auth file, recording the login details in a root only file. Read it over SSH:

sudo cat /root/olivetin-credentials.txt

You will see the web URL, the administrator user (admin) and the generated password. These values are unique to your VM. The file is mode 0600 and owned by root.

Step 6 - Confirm authentication is enforced

The reverse proxy refuses unauthenticated requests and only serves OliveTin to a caller that passes HTTP Basic Auth. The unauthenticated /healthz probe is the one exception, provided for load balancers. Confirm all three:

curl -sk -o /dev/null -w 'anonymous: %{http_code}\n' https://127.0.0.1/
curl -sk -o /dev/null -w 'authenticated: %{http_code}\n' -u '<OLIVETIN_ADMIN_USER>:<OLIVETIN_ADMIN_PASSWORD>' https://127.0.0.1/
curl -sk -o /dev/null -w 'healthz: %{http_code}\n' https://127.0.0.1/healthz

An unauthenticated request is refused with 401, an authenticated request returns 200, and the health probe returns 200 without a login:

anonymous: 401
authenticated: 200
healthz: 200

Three curl calls proving authentication is enforced: an unauthenticated request returns 401, an authenticated request with the per VM credential returns 200, and the unauthenticated healthz probe returns 200

Step 7 - Sign in to the web UI

Browse to your VM over HTTPS. The image ships a self signed certificate generated per VM, so your browser will warn once; accept it (or place your own certificate in front for production).

https://<your-vm-public-ip>/

Your browser prompts for HTTP Basic Auth. Enter admin and the password from the credentials file. You land on the OliveTin Actions dashboard, showing the shipped safe actions as buttons.

The OliveTin Actions dashboard signed in as admin, showing the shipped safe action buttons: Check disk usage, Show memory usage, Show system uptime, Ping a host and Restart demo service

Step 8 - Run an action

Click any action button to run its command. OliveTin executes the predefined command on the server and streams the output back into an execution dialog. Click Check disk usage and you will see the real df output, with the execution marked Completed.

The OliveTin execution dialog for the Check disk usage action, showing the status Completed and the real df command output listing the root filesystem size and usage

Every execution is recorded. Open the Logs view to see the history of who ran what and when, with each entry linking to its full output.

The OliveTin Logs view listing an executed Check disk usage action with its timestamp, the user admin, and a Completed status

Step 9 - Trigger an action from the API

OliveTin exposes the same actions over a simple JSON API, so you can drive them from scripts, cron or another service. Authenticate with the same HTTP Basic Auth credential. This triggers the check_disk action and waits for its output:

curl -sk -u '<OLIVETIN_ADMIN_USER>:<OLIVETIN_ADMIN_PASSWORD>' \
  -H 'Content-Type: application/json' \
  -d '{"actionId":"check_disk"}' \
  https://127.0.0.1/api/olivetin.api.v1.OliveTinApiService/StartActionAndWait

The response is a JSON logEntry containing the command exitCode and its output. Actions that take arguments pass them as an array, for example the shipped ping_host action:

curl -sk -u '<OLIVETIN_ADMIN_USER>:<OLIVETIN_ADMIN_PASSWORD>' \
  -H 'Content-Type: application/json' \
  -d '{"actionId":"ping_host","arguments":[{"name":"host","value":"1.1.1.1"}]}' \
  https://127.0.0.1/api/olivetin.api.v1.OliveTinApiService/StartActionAndWait

The check_disk action triggered over the OliveTin JSON API returning exit code 0 and the df command output, alongside the credentials file showing it is root only 0600 with the admin user and URL

Step 10 - Add your own actions

Actions are defined in /etc/OliveTin/config.yaml. Each action gives a title, a stable id used by the API, and the shell command to run. Every action is a real shell command run on the server, so add actions with care. Constrain any argument to a fixed list of choices rather than accepting free form input, keep destructive commands off the appliance, and never widen the reverse proxy authentication.

A minimal safe action looks like this:

actions:
  - title: Show running containers
    id: docker_ps
    shell: docker ps
    icon: box
    onclick: execution-dialog
    timeout: 15

OliveTin runs as the unprivileged olivetin user. If an action genuinely needs elevated privileges, grant exactly that one command through a narrow rule in /etc/sudoers.d/, exactly as the shipped Restart demo service action does, rather than running OliveTin as root. After editing the config, restart the service and OliveTin reloads it:

sudo systemctl restart olivetin

The Diagnostics view helps you confirm the running configuration and generate a support report.

The OliveTin Diagnostics view showing the get support section, the SSH helper status for the olivetin user, and the server diagnostics generator

Security model - no default login

The cloudimg image ships with no known credentials. Before capture, the HTTP Basic Auth file is emptied and the credentials file is reset to a placeholder. On the first boot of every VM, a one shot first boot service regenerates the self signed TLS certificate, generates a fresh random administrator password, writes it into the nginx Basic Auth file as a bcrypt hash, and proves end to end that an unauthenticated request is refused, an authenticated request succeeds, and a shipped action executes and returns its output, before recording the login in the root only credentials file.

Defence in depth means the OliveTin binary is bound to loopback and is never reachable from the network directly; nginx is the only public surface and forwards the authenticated identity to OliveTin as a request header that a client cannot spoof; and OliveTin is configured to deny any request that is not an authenticated administrator, so even a request that reached the loopback port without going through nginx would be refused. To rotate the administrator password at any time:

sudo htpasswd -B /etc/nginx/olivetin.htpasswd admin

Corresponding source (AGPL-3.0)

OliveTin is distributed under the GNU Affero General Public License version 3. The complete corresponding source for the version in this image is published by the OliveTin project at github.com/OliveTin/OliveTin, and the exact release and its sha256 digest are recorded on the VM at /opt/olivetin/VERSION. The cloudimg image adds only configuration and an nginx reverse proxy; it does not modify the OliveTin source.

Support

Every cloudimg deployment is paired with this guide and backed by 24/7 cloudimg support. If you have any questions about running OliveTin on Azure, contact the cloudimg team.