FHEM on Ubuntu 24.04 on Azure User Guide
Overview
FHEM is a long-established, GPL-licensed home and building automation server written in Perl. Its browser dashboard, FHEMWEB, lets you monitor and control lights, climate, sensors, presence and more, and its rule engine (at, notify, DOIF and friends) automates them from timers, events and logic without writing application code. FHEM speaks a very wide range of smart-home protocols (Z-Wave, ZigBee, EnOcean, KNX, MQTT, Homematic and many others) through add-on modules, which makes it a popular central controller for self-hosted smart homes.
The cloudimg image installs FHEM 6.4 pinned to the official release, runs it as a dedicated unprivileged fhem system user, and - importantly - closes FHEM's biggest default security gap: FHEMWEB ships with no authentication. This image binds FHEMWEB to loopback only and puts an authenticated nginx front door in front of it, generating a unique admin password on the first boot of every VM. It also boots with a populated demo configuration so you see a working dashboard immediately, with no physical devices attached. Backed by 24/7 cloudimg support.
What is included:
- FHEM 6.4 (GPL-2.0), installed to
/opt/fhemand run asfhem.service - The FHEMWEB dashboard, bound to
127.0.0.1:8083and fronted by nginx on:80 - HTTP Basic auth (user
admin) with a per-VM password in a root-only file - A baked demo configuration: dummy climate sensors, lights, a thermostat and a presence device across several rooms, plus example
at/notifyautomations fhem.service+nginx.serviceas systemd units, enabled and active; the FHEM telnet CLI on127.0.0.1:7072(loopback-only)- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is comfortable for FHEM, which is light on resources. NSG inbound: allow 22/tcp from your management network and 80/tcp for the dashboard (front with TLS for public exposure - see Enabling HTTPS).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for FHEM by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name fhem \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name fhem --port 80 --priority 1010
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
systemctl is-active fhem nginx fhem-firstboot
All three report active. The listeners show the security posture at a glance - nginx is public on :80, while FHEMWEB (:8083) and the FHEM telnet CLI (:7072) are bound to loopback only:

ss -tln | grep -E ':80 |:8083 |:7072 '
Step 5 - Retrieve your dashboard password
The admin password is generated uniquely on the first boot of your VM and written to a root-only file:
sudo cat /root/fhem-credentials.txt
This file contains FHEM_ADMIN_USER (admin) and FHEM_ADMIN_PASSWORD, plus the dashboard URL. Store the password somewhere safe.

Step 6 - Check the health endpoint
nginx serves an unauthenticated health endpoint for load balancers and probes:
curl -s http://localhost/health
It returns ok.
Step 7 - Open the FHEMWEB dashboard
Browse to http://<vm-public-ip>/ and, when the browser prompts for HTTP Basic credentials, sign in as admin with the password from Step 5. FHEMWEB opens on the pre-loaded Living Room, showing the demo climate sensor, thermostat and light, plus a Home Overview panel that lists every demo device with live readings:

The room menu on the left groups devices; the Everything view lists them all. This is the whole-home overview across Living Room, Bedroom, Kitchen, Outdoor and Automation:

Step 8 - Inspect and control a device
Click any device name to open its detail page, where you can see its readings and internals, change its value with the set control, and edit its attributes. Here is the Living Room thermostat with its desired-temperature slider:

Step 9 - Review the demo automations
The Automation room collects the example rules the image ships with: two scheduled at timers (morning and night lighting scenes), a notify that turns the lights off when presence goes to absent, and a structure that groups the lights so they can be switched together:

Step 10 - Confirm the security posture
The dashboard is closed by default: an unauthenticated request is rejected with 401, and only succeeds with the per-VM password. FHEMWEB itself is never exposed to the network - nginx is the only public door.
curl -s -o /dev/null -w '%{http_code}\n' http://localhost/fhem/
That prints 401. With the per-VM credentials it returns 200:
curl -s -o /dev/null -w '%{http_code}\n' -u admin:<FHEM_ADMIN_PASSWORD> http://localhost/fhem/

Step 11 - Explore the demo devices and add your own
The demo devices are FHEM dummy devices, so they need no hardware. You can list them from the loopback telnet CLI, and use the same interface (or the dashboard) to define real devices once you attach a controller:
perl /opt/fhem/fhem.pl 7072 'list'

To connect real hardware, add the relevant FHEM module for your controller (for example a Z-Wave or ZigBee stick, or an MQTT broker) from the dashboard via Everything -> define, or edit /opt/fhem/fhem.cfg. The FHEM command reference documents every module.
Security posture
- FHEMWEB has no authentication of its own by default. This image never exposes it:
define WEB FHEMWEB 8083is used without theglobalkeyword, so FHEMWEB binds127.0.0.1only. The FHEM telnet CLI is likewise loopback-only on127.0.0.1:7072. - nginx is the only public surface, on
:80, enforcing HTTP Basic auth against/etc/nginx/.htpasswd(useradmin). It reverse-proxies FHEMWEB's long-poll live updates. - The password is unique per VM, minted by
fhem-firstboot.serviceon first boot into/etc/nginx/.htpasswdand the root-only/root/fhem-credentials.txt. No two deployments share a credential, and the image ships with no usable password baked in. - For any public exposure, terminate TLS in front of nginx (see below) so credentials are never sent in clear text.
Enabling HTTPS
The nginx reverse proxy terminates plain HTTP on port 80. For public exposure, put a certificate in front of it - add a DNS name for the VM and use the companion cloudimg nginx-ssl-certbot image as a TLS reverse proxy, or install certbot and extend the existing nginx site with a listen 443 ssl; server block. Keep FHEMWEB bound to loopback so the only public surface is the authenticated, TLS-terminated proxy.
Maintenance
- Configuration: edit devices and rules from the dashboard (they are saved to
/opt/fhem/fhem.cfg), or edit the file directly and reload. - Backups: back up
/opt/fhem(configuration, logs and state) to preserve your devices, rules and history. - Upgrades: FHEM self-updates from the dashboard command field with
update, followed byshutdown restart; the OS is patched separately. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.