Ubuntu 26.04 LTS Sysadmin Tools on Azure User Guide
Overview
This guide covers the deployment and configuration of Ubuntu Server 26.04 LTS Sysadmin Tools on Microsoft Azure using cloudimg's pre configured virtual machine image from the Azure Marketplace.
Ubuntu is a widely used Linux distribution produced by Canonical. Version 26.04 is a long term support (LTS) release, with standard security maintenance to 2031. What makes this image different from the standard Ubuntu Server 26.04 LTS image is the package profile: a named, version pinned set of 84 system administration packages, every one of them from Ubuntu's own archive, installed and ready. 65 come from main, which carries Canonical's full five year security commitment; 19 come from universe.
Be clear about what this is and what it is not. It is not a monitoring appliance, a hardened build, or a security product. It is the standard Ubuntu Server image with a documented toolbox already on it, saving you the apt install list you would otherwise type on every server you touch. There is no third party software, no vendor repository, and nothing on the image that Canonical does not publish.
Every daemon the profile adds is installed but disabled. rsync has its daemon mode, atop and sysstat have collectors, auditd has its dispatcher, at has atd, smartmontools has smartd — all present, all switched off. A freshly deployed machine listens on port 22 and nothing else. Turning a service on is a deliberate act you take, not a default you have to undo.
Just as deliberately, the daemons that the standard Ubuntu image already runs are left exactly as Canonical ships them. chrony still keeps time, cron still runs jobs, logrotate.timer still rotates logs, fstrim.timer still trims the disk. This variant does not quietly differ from stock Ubuntu in ways you would have to discover for yourself. The split was measured at build time against the stock image, not hand written, and the image ships the result so you can read it.
The image describes itself. Two files are generated from its own package database and its own measured unit state:
/usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.manifest— every package, its version, its component, and what was deliberately left out and why/usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.units— every systemd unit the profile touches, markedprofile-disabledorbase-stock
What's included:
- Ubuntu Server 26.04 LTS with 84 system administration packages preinstalled — 65 from
main, 19 fromuniverse, every one from the Ubuntu archive - Process and performance:
htop,atop,sysstat(sar,iostat,mpstat,pidstat),iotop,nmon,procps,psmisc,lsof,numactl - Tracing and debugging:
strace,ltrace,linux-tools-common - Storage and filesystems:
lvm2,mdadm,parted,gdisk,nvme-cli,hdparm,smartmontools,quota,acl,attr,cifs-utils,sshfs,ncdu - Terminal and editing:
tmux,screen,byobu,vim,nano,less,mc,tree - Search and text:
ripgrep(rg),fd-find(fdfind),bat(batcat),fzf,jq,moreutils,parallel - Transfer and archive:
rsync,curl,wget,unzip,zip,bzip2,xz-utils,zstd,pv,git - Network diagnostics:
iproute2,net-tools,ethtool,tcpdump,mtr-tiny,bind9-dnsutils(dig),whois,socat,netcat-openbsd,ipcalc - Hardware inventory:
dmidecode,pciutils(lspci),usbutils(lsusb),sysfsutils,cpu-checker - System hygiene and safety:
auditd,logrotate,cron,at,chrony,needrestart,apt-listchanges,unattended-upgrades,debsums,inotify-tools,molly-guard - A shipped manifest and unit disposition file derived from the image's own state, so the description cannot drift from what is installed
- Every available security update applied at build time, with
unattended-upgradesarmed so the machine keeps patching itself - AppArmor in enforcing mode, Gen2 Hyper V support, and 24/7 cloudimg support
What's deliberately NOT included:
- Offensive and dual use tooling.
nmap,hping3,masscan,zmap,ettercap,aircrack-ng,sqlmap,hydraand their relatives are excluded by design. They are yours to install if your work needs them; they are not something a general purpose image should ship by default, and they are a recurring source of antivirus false positives on cloud marketplaces. glances. A universe Python application that pulls a heavy dependency chain and enables its own service on127.0.0.1:61209the moment it is installed.htop,atopandsysstatcover the same ground without a listener.fioandiperf3. Both ship a systemd unit that listens on all interfaces by default (fio --serveron TCP 8765,iperf3on TCP 5201). Neither belongs on an image whose promise is that nothing but SSH is reachable.iperf3is on the sibling networking profile, where it is the point.ipmitoolandlm-sensors. Both are hardware bound. There is no BMC and there are no hardware sensors on an Azure virtual machine, so both would report nothing whilelm-sensorsenabled a unit andipmitoolrecommended a daemon.dstat. Not published on Ubuntu 26.04 at all; it was removed after Ubuntu 24.04.sarandatopare its replacements.
Platform: Microsoft Azure (Gen2 Hyper V, x64)
Default user: azureuser
Security posture
This image ships with no known credential. There is no default password and no baked in SSH key:
- The root account password is locked, so no one can log in as root with a password.
PermitRootLoginis set tono, so root has no SSH login path at all.PasswordAuthenticationis disabled, so every login is by key.- The only key that works is the public key you supply when you create the virtual machine. Azure injects it into
azureuserat first boot, so no two machines you launch ever share a secret. - The machine identity and the SSH host keys are regenerated uniquely on every instance.
- Every daemon the profile adds ships disabled and stopped. The off box listening set is exactly
{22}. - AppArmor is left enabled and enforcing, the Ubuntu default.
- No package on the image depends on Ubuntu Pro to receive its security fixes.
Prerequisites
Before deploying this image, ensure you have:
- An active Microsoft Azure subscription
- Access to the Azure Portal or Azure CLI
- An SSH key pair for Linux VM access
- Familiarity with Azure VM management
Recommended VM Size: Standard_B2s (2 vCPU, 4 GB RAM) or larger.
Disk size: the image ships as a 28 GiB OS disk. The 84 named packages total about 110 MB installed; a stock deployment uses about 3 GB and leaves around 26 GB free.
Step 1: Deploy the Virtual Machine
Option A: Azure Portal
- Sign in to the Azure Portal
- Search the Marketplace for Ubuntu 26.04 LTS Sysadmin Tools and select the cloudimg offering
- Click Create
- Choose your subscription, resource group and region
- Set the VM size to
Standard_B2sor larger - Under Administrator account, choose SSH public key, leave the username as
azureuser, and paste your public key - Under Inbound port rules, allow SSH (22) only, and restrict the source to your own management address range
- Review and create
Option B: Azure CLI
az vm create \
--resource-group my-resource-group \
--name ubuntu-sysadmin \
--image cloudimg:ubuntu-26-04-pkg-sysadmin:default:latest \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_rsa.pub \
--public-ip-sku Standard
Step 2: Connect via SSH
ssh azureuser@<vm-ip>
Replace <vm-ip> with your virtual machine's public IP address.
Step 3: Confirm the release and the profile
Check you have the release you expect:
grep -E '^(NAME|VERSION|ID|VERSION_ID|PRETTY_NAME)=' /etc/os-release
uname -srm
dpkg --print-architecture
Expected output:
PRETTY_NAME="Ubuntu 26.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="26.04"
VERSION="26.04.1 LTS (Resolute Raccoon)"
ID=ubuntu
Linux 7.0.0-1014-azure x86_64
amd64
Nothing is held back from updates, and the machine was fully patched at build time:
apt-mark showhold
echo "pending upgrades (phased updates included): $(apt-get -s -o APT::Get::Always-Include-Phased-Updates=true dist-upgrade 2>/dev/null | grep -c '^Inst ')"
apt-mark showhold printing nothing is the good result — it means no package is pinned away from its security updates.

Step 4: Read the shipped manifest
The image tells you what it is. The manifest is generated from the machine's own package database at build time, so it cannot drift from what is actually installed:
awk -F'\t' 'NF>=3{print $3}' /usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.manifest | sort | uniq -c
echo "total named by the profile: $(grep -vE '^#' /usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.manifest | grep -c .)"
Expected output:
65 main
19 universe
total named by the profile: 84
The header records the series and when it was generated:
head -6 /usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.manifest
# cloudimg ubuntu-26-04-pkg-sysadmin — shipped package profile
# Derived from the dpkg database at build time. Do not hand-edit.
# generated: 2026-09-22T12:12:22Z
# series: resolute (Ubuntu 26.04 LTS)
#
# [main] — Canonical five-year security commitment on 26.04 LTS
And the tail records what was left out, with the reason for each:
tail -8 /usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.manifest
# [excluded-by-contract]
# dstat not published on resolute (removed from noble, no rdeps)
# glances universe Python app; enabled service on 127.0.0.1:61209; heavy Recommends chain
# fio ships fio.service (fio --server) listening on all interfaces TCP 8765
# iperf3 ships iperf3.service on all interfaces TCP 5201; belongs to the networking profile
# ipmitool hardware-bound (no BMC on Azure); Recommends the openipmi daemon
# lm-sensors hardware-bound (no sensors on Azure); oneshot unit enabled on install
# plus every offensive or dual-use tool (nmap, hping3, masscan, aircrack-ng, hydra, ...)

Three name traps worth knowing
Three packages in this profile install a binary whose name is not the package name. This catches people out, so the image documents it:
| Package | Command you actually run |
|---|---|
bat |
batcat |
fd-find |
fdfind |
sysstat |
sar, iostat, mpstat, pidstat (there is no sysstat command) |
command -v batcat fdfind sar iostat
Also note that linux-tools-common is installed but ships no perf binary on Ubuntu 26.04 — perf lives in the linux-perf package, which you can add with apt install linux-perf if you need it.
Step 5: Confirm nothing is listening
This is the property the image exists for. Check it yourself:
ss -tln | awk '$1=="LISTEN"{print $1, $4}' | sort -u
Expected output:
LISTEN 0.0.0.0:22
LISTEN 127.0.0.53%lo:53
LISTEN 127.0.0.54:53
LISTEN [::]:22
The two 127.0.0.5x:53 rows are systemd-resolved, the stub DNS resolver that every Ubuntu machine runs. They are bound to loopback and are not reachable from the network. Filter them out and you get the set that actually matters:
ss -H -l -t -n | awk '{print $4}' | grep -vE '^(127\.|\[?::1\]?:|\[::ffff:127\.)' | sed -E 's/.*:([0-9]+)$/\1/' | sort -un | tr '\n' ' '
echo
That prints 22 and nothing else.

Step 6: Daemons — what is off, what is on, and why
The image ships a file recording the disposition of every systemd unit the profile touches. profile-disabled means this profile introduced it and shipped it switched off; base-stock means the standard Ubuntu image already ran it and this image left it alone.
echo "profile-introduced, shipped disabled: $(awk -F'\t' '$2=="profile-disabled"' /usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.units | grep -c .)"
echo "base-stock, left exactly as Ubuntu: $(awk -F'\t' '$2=="base-stock"' /usr/share/cloudimg/ubuntu-26-04-pkg-sysadmin.units | grep -c .)"
Check the daemons that could have opened a port:
for u in rsync.service atop.service auditd.service atd.service smartmontools.service quota.service; do
printf '%-26s %s\n' "$u" "$(systemctl is-enabled "$u" 2>/dev/null | head -1)"
done
Every one of them reports disabled. Now check the ones this image deliberately did not touch:
for u in chrony.service cron.service logrotate.timer fstrim.timer; do
printf '%-26s %s\n' "$u" "$(systemctl is-enabled "$u" 2>/dev/null | head -1)"
done
Every one of them reports enabled — exactly as on a standard Ubuntu Server 26.04 machine. Time synchronisation, scheduled jobs, log rotation and periodic disk trim all keep working. A "sysadmin tools" image that silently switched those off would be a worse machine, not a safer one.
Step 7: Check the patch level and the Ubuntu Pro position
Ubuntu Pro is Canonical's optional paid subscription. Some Ubuntu packages have security fixes that are published only to Pro's ESM repositories, which means a machine without a subscription can never apply them — and, crucially, apt reports nothing at all in that situation, so "0 upgradable" is not on its own evidence of anything.
This image ships unattached, and was verified at build time to carry zero fixes that need Pro:
pro status --format=json 2>/dev/null | python3 -c "import json,sys; print('pro attached:', json.load(sys.stdin).get('attached'))"
pro security-status --format=json 2>/dev/null | python3 -c "
import json,sys
d=json.load(sys.stdin); s=d.get('summary',{})
pa=[p for p in d.get('packages',[]) if p.get('status') in ('pending_attach','pending_becoming_available')]
print(' num_esm_infra_updates :', s.get('num_esm_infra_updates'))
print(' num_esm_apps_updates :', s.get('num_esm_apps_updates'))
print(' packages pending_attach:', len(pa))
print(' installed packages :', s.get('num_installed_packages'))"
Expected output:
pro attached: False
num_esm_infra_updates : 0
num_esm_apps_updates : 0
packages pending_attach: 0
installed packages : 743
Every package on this image can be patched for free, for the life of Ubuntu 26.04's standard support.

Step 8: Use the toolbox
Everything is already there. A few starting points:
uptime
sar -u 1 3
iostat -x 1 2
Find what is using disk, and what is using it now:
sudo du -xh --max-depth=1 /var 2>/dev/null | sort -h | tail -5
sudo iotop -b -n 1 2>/dev/null | head -8
ncdu is on the image too, for browsing the same information interactively — run sudo ncdu -x / when you have a terminal.
Inspect a process:
SSHD_PID="$(pgrep -n sshd || echo 1)"
echo "inspecting pid ${SSHD_PID}"
sudo lsof -p "${SSHD_PID}" 2>/dev/null | head -8
echo "(lsof lists the files and sockets that process holds open)"
Search a tree quickly:
rg --stats 'PermitRootLogin' /etc/ssh 2>/dev/null | tail -6
fdfind --max-depth 1 'conf$' /etc/ssh
Look at hardware and storage:
sudo dmidecode -s system-manufacturer
lspci | head -5
sudo smartctl --scan || echo "(no SMART-capable devices on a virtual disk — expected on Azure)"
Step 9: molly-guard, and why sudo reboot asks you a question
molly-guard is part of this profile on purpose. It intercepts halt, poweroff, reboot and shutdown and, when it detects that you are in an SSH session, asks you to type the hostname before it will proceed. It exists to stop you rebooting the wrong machine — the single most common way a remote administrator ruins an afternoon.
You can see the interception for yourself:
dpkg-divert --list | grep 'by molly-guard' | sort
What this means in practice:
- Interactive
sudo rebootover SSH will prompt you for the hostname. That is the feature working. sudo systemctl rebootis not intercepted and reboots immediately.systemctlis deliberately left un-diverted so you always have an un-prompted path.- Automation is unaffected.
molly-guardonly challenges when it detects an SSH session, socloud-init,unattended-upgradesand anything driven from systemd reboot normally.
Confirm the escape hatch is real:
readlink -f /sbin/reboot
command -v systemctl
/sbin/reboot resolves to the molly-guard shim; systemctl resolves to /usr/bin/systemctl, the real thing.
If you script reboots over SSH and want the direct path, use either of these:
# Example only — these actually reboot the machine.
sudo systemctl reboot
sudo reboot --force
If you would rather not have the guard at all, remove the package and the diversions go with it:
# Example only — run this if you do not want the reboot confirmation.
sudo apt-get remove -y molly-guard
Step 10: Turn a service on when you want it
Nothing the profile adds starts by itself. When you want one, enable it deliberately:
# Example only — run these when you actually want the service.
sudo systemctl enable --now auditd.service # kernel audit logging
sudo systemctl enable --now atd.service # one-off scheduled jobs via 'at'
sudo systemctl enable --now smartmontools.service # SMART monitoring (bare metal)
sudo systemctl enable --now atop.service # continuous performance history
rsync.service is the one to think twice about: enabling it starts rsync --daemon, which listens on TCP 873 on all interfaces. If you only use rsync over SSH — which is the normal case, and what rsync -e ssh does — you never need the daemon at all. If you do enable it, restrict the port in your network security group and configure /etc/rsyncd.conf before you start it.
Step 11: IPsec on this image
For the Dirty Frag class of kernel vulnerabilities (CVE-2026-43284, CVE-2026-43500) the image ships a mitigation at /etc/modprobe.d/dirtyfrag.conf that prevents the esp4, esp6, ipcomp, ipcomp6 and rxrpc modules from loading:
cat /etc/modprobe.d/dirtyfrag.conf
Expected output:
install esp4 /bin/false
install esp6 /bin/false
install ipcomp /bin/false
install ipcomp4 /bin/false
install ipcomp6 /bin/false
install rxrpc /bin/false
This profile contains no IPsec implementation, so the mitigation costs you nothing. But if you intend to terminate an IPsec tunnel on this virtual machine, you need those kernel modules and must remove the file:
# Only if you are terminating IPsec ON this VM.
sudo rm /etc/modprobe.d/dirtyfrag.conf
sudo reboot
You do not need to do this to sit behind an Azure VPN Gateway — the gateway terminates IPsec, not your VM. WireGuard and OpenVPN are also unaffected: neither uses kernel ESP.
Common Use Cases
- Jump host / bastion. One hop into a private subnet, with the diagnostic toolbox already on it and nothing but SSH exposed.
- Break glass diagnostic VM. Spin one up in a subnet that is misbehaving and start measuring immediately, instead of installing tools on a machine whose network you are trying to debug.
- Operations workstation.
tmuxorbyobuplusmc,ripgrep,fzfandbatas a persistent working environment for a team. - Storage and filesystem work.
lvm2,mdadm,parted,gdisk,nvme-cliandsmartmontoolsfor preparing, inspecting and moving volumes. - Baseline for a golden image. A known, documented starting set to build your own configuration on top of, with a manifest you can diff against.
Troubleshooting
Cannot connect via SSH
Confirm the network security group allows TCP 22 from your address, that the VM has a public IP, and that you are using the private key matching the public key you supplied at deployment. Password login is disabled by design.
sudo reboot is asking me to type the hostname
That is molly-guard, and it is intentional — see Step 9. Use sudo systemctl reboot for an un-prompted reboot, or remove the molly-guard package.
A tool is installed but the command is not found
Check the three name traps in Step 4 first: bat is batcat, fd-find is fdfind, and sysstat gives you sar and iostat rather than a sysstat command. perf is not installed — add linux-perf if you need it.
A service is installed but not running
That is the design. Every daemon the profile adds ships disabled. See Step 10 to enable one.
smartctl reports no devices
Expected on Azure. The virtual disk exposes no SMART data. smartmontools is on the image for the cases where you attach something that does, and for parity with bare metal runbooks.
nmap is not installed
Correct, and deliberate — see the exclusions in Step 4. Install it yourself with sudo apt install nmap if your work requires it.
An apt upgrade is asking which services to restart
That is needrestart, left at Ubuntu's own default. Answer the prompt, or run sudo NEEDRESTART_MODE=a apt upgrade to let it restart services automatically.
Package manager issues
sudo apt-get update
apt-cache policy | grep -E '(-security|-updates)' | head -5
A service is blocked and the logs mention AppArmor
AppArmor is enforcing, the Ubuntu default. Check sudo aa-status and the journal for DENIED entries before assuming a configuration problem.
Important Notes
- The profile is the product. The 84 packages are named in the shipped manifest with their versions and components. Nothing is hidden and nothing comes from outside the Ubuntu archive.
- Every daemon the profile adds is off; every daemon the base image ran is untouched. The split is recorded in the shipped unit disposition file.
rsync.servicelistens on TCP 873 if you enable it. Usersyncover SSH unless you specifically need the daemon.- No package on this image needs Ubuntu Pro to receive its security fixes. The image ships unattached.
- Universe packages are community maintained. While Ubuntu 26.04 is in standard support their security updates are published to
resolute-updatesandresolute-securitylike any other package. unattended-upgradesis enabled, so the machine continues to apply security updates after you deploy it.- The image ships no swap, which is the Azure requirement. Azure manages swap on the ephemeral resource disk.
Support
cloudimg provides 24/7 support for this image. For help with deployment, configuration or the package profile itself, contact support through the Azure Marketplace listing or visit www.cloudimg.co.uk.