The CloudSOE Bastion Host image is a hardened SSH jump host on Ubuntu: fail2ban brute-force protection, the AIDE file-integrity checker (its database is initialised on your VM at first boot), ntpd-rs time sync, and a full Active Directory join toolchain (sssd, realmd, adcli, Kerberos, Samba) preinstalled but unconfigured. There are no baked-in credentials — access is your SSH key, nothing else.
What you’ll need
- An Azure subscription
- An SSH public key (password login is disabled in the image)
- About five minutes
Step 1 — Create the VM
- Find the CloudSOE Bastion Host offer in the Azure Marketplace and click Create.
- Choose a resource group, region and VM name.
- Pick a small size — a bastion forwards SSH traffic, so
Standard_B2s(or evenStandard_B1s) is plenty for most teams. - Under Administrator account, select SSH public key, pick a username (e.g.
azureuser) and paste your key. - Place it in the virtual network that contains your private VMs, attach a public IP, and make the public IP Static for production — your team’s SSH configs will reference this address.
Step 2 — Open exactly one port
In the VM’s network security group, allow inbound:
| Port | Protocol | Purpose |
|---|---|---|
| 22 | TCP | SSH — restrict to your office/VPN ranges |
That’s the whole table. A bastion’s value is its tiny attack surface: no other inbound rule belongs here, and port 22 should be limited to known source ranges, never Any. On the private VMs’ NSGs, allow port 22 only from the bastion’s subnet or private IP.
Step 3 — Let first boot finish
On the very first boot the bastion-firstboot service initialises the AIDE integrity database — a fingerprint of your VM’s files that later checks compare against. It runs in the background and can take a few minutes; the bastion is usable immediately. Check it:
ssh <admin-user>@<public-ip>
systemctl status bastion-firstboot
fail2ban starts automatically at boot and begins watching the SSH log:
sudo fail2ban-client status sshd
Step 4 — Jump to a private VM
The whole point of a bastion — reach VMs that have no public IP (use private addresses for the hop; an Azure VM often cannot reach its own public IP from inside the VNet anyway):
ssh -J <admin-user>@<bastion-public-ip> <user>@<private-vm-ip>
-J (ProxyJump) tunnels through the bastion without leaving your private key on it. Don’t copy private keys to the bastion, and prefer ProxyJump over agent forwarding (-A) — with ProxyJump the bastion never sees your agent at all. Make it permanent with an SSH config block — see tips & tricks.
Next steps
- Configure the bastion — Active Directory join, fail2ban tuning, AIDE checks
- Tips & tricks — ProxyJump config, session recording, keeping AIDE current