Skip to content

TutorialsSelf-hosted apps

How to run Home Assistant Container with Docker on a server

Run Home Assistant Container with Docker Compose on a server, reach it over WireGuard or Caddy HTTPS with trusted proxies, and back up and update it safely.

  • Intermediate
  • 35 min read
  • Updated

Tested on: Ubuntu 24.04 LTS, Ubuntu 26.04 LTS, Debian 12, Debian 13

This guide is not available in your language yet, so it is shown in English.

On this page
  1. Prerequisites
  2. What works on a remote server
  3. Step 1 — Create the Compose file
  4. Step 2 — Close the firewall and start Home Assistant
  5. Step 3 — Onboard through an SSH tunnel
  6. Step 4 — Trust Caddy as a reverse proxy
  7. Step 5 — Publish Home Assistant over HTTPS with Caddy
  8. Step 6 — Reach your home devices over WireGuard
  9. Back up and restore
  10. Update Home Assistant
  11. Troubleshooting
  12. 400: Bad Request when you open the domain
  13. Network settings reverted after a few minutes
  14. Port 8123 cannot be reached from your browser
  15. Devices at home are not discovered
  16. Home Assistant does not start after editing configuration.yaml
  17. Next steps

Home Assistant is an open-source home automation platform with thousands of integrations, a visual automation editor and customisable dashboards. The Home Assistant Container installation runs the core application from the official image ghcr.io/home-assistant/home-assistant with Docker.

Running it on a rented server instead of a box at home changes what it can do: there are no USB radios and no local network to discover devices on. In return you get a hub that is always online, reachable from anywhere, and that can control your home over a VPN. This guide sets up Home Assistant Container with Docker Compose as documented by the project, onboards it through an SSH tunnel, publishes it over HTTPS with Caddy and the required trusted proxy settings, connects it to your home with WireGuard, and covers backups and updates.

Prerequisites

Home Assistant publishes hardware minimums only for the Home Assistant OS virtual machine (2 GB of RAM and 2 vCPUs), not for Container. The suggested values below are a conservative starting point:

ResourceMinimum (official)Suggested starting point
RAMNot published for Container (2 GB for the OS virtual machine)2 GB
CPUNot published for Container (2 vCPUs for the OS virtual machine)2 vCPUs
DiskNot published for Container20 GB SSD; the history database and backups grow over time

What works on a remote server

FeatureHome Assistant OS at homeContainer on a remote server
Automations, dashboards, integrationsYesYes
Apps (formerly add-ons) and the SupervisorYesNo; run extra services as separate containers
Backups from the interfaceYesYes
USB radios (Zigbee, Z-Wave, Thread) and BluetoothYes, with local hardwareNo; there is no local hardware
Automatic discovery of home devicesYes, on the home networkNo; add devices by IP address over the VPN

Home Assistant also notes that Thread and Z-Wave are controlled by apps, so Container has no out-of-the-box support for them.

Step 1 — Create the Compose file

Create a project folder with a config subfolder, then the Compose file:

Bash
sudo mkdir -p /opt/homeassistant/config
sudo chown -R $USER:$USER /opt/homeassistant
cd /opt/homeassistant
nano compose.yaml

Paste the official example with the config path filled in, and set TZ to your time zone:

YAML
services:
  homeassistant:
    container_name: homeassistant
    image: "ghcr.io/home-assistant/home-assistant:stable"
    volumes:
      - /opt/homeassistant/config:/config
      - /etc/localtime:/etc/localtime:ro
      - /run/dbus:/run/dbus:ro
    restart: unless-stopped
    stop_grace_period: 60s
    privileged: true
    network_mode: host
    environment:
      TZ: Europe/Amsterdam

network_mode: host lets Home Assistant use the server's network directly, which many integrations expect. It also means port 8123 is a normal host port, so ufw does filter it, unlike ports published by Docker.

Step 2 — Close the firewall and start Home Assistant

Allow only SSH so that port 8123 stays closed to the internet, then start the container:

Bash
sudo ufw allow OpenSSH
sudo ufw enable
docker compose up -d
docker compose ps
docker compose logs -f homeassistant

Wait until the log stops showing setup messages, then press Ctrl+C. Check that Home Assistant answers locally:

Bash
curl -I http://127.0.0.1:8123
sudo ss -tlnp | grep 8123

curl prints HTTP headers, and ss shows Home Assistant listening on all addresses, which ufw now blocks from outside.

Step 3 — Onboard through an SSH tunnel

The first person to open Home Assistant creates the owner account. Do this through a tunnel. On your own computer, run:

Bash
ssh -L 8123:127.0.0.1:8123 admin@203.0.113.10

Open http://localhost:8123, select Create my smart home, and enter a name, a lowercase username and a strong password. Home Assistant warns that the owner credentials cannot be recovered, so store them in a password manager. Then set your home location, which also sets the time zone, unit system and currency, choose what anonymous data to share (sharing is off by default), and select Finish.

Turn on multi-factor authentication right away: open your user profile, go to the Security tab and enable the authenticator app module.

Step 4 — Trust Caddy as a reverse proxy

Home Assistant blocks requests from reverse proxies unless you allow them. With host networking, Caddy on the same server connects from 127.0.0.1 (or ::1). Since version 2026.8 these settings live in the interface, not in configuration.yaml:

  1. Go to Settings → System → Network and find the HTTP server section.
  2. Turn on Trust X-Forwarded-For.
  3. Add 127.0.0.1 and ::1 to Trusted proxies.
  4. Turn on Enable IP banning and set Login attempts before ban to a low number, such as 5.
  5. Save. Home Assistant restarts, and you must confirm the new settings afterwards; otherwise it reverts to the previous settings after 5 minutes.

If you upgrade an older installation that still has an http: block in configuration.yaml, Home Assistant imports it into these settings once and then shows a repair asking you to remove the block.

Step 5 — Publish Home Assistant over HTTPS with Caddy

Open the web ports and add a site block to /etc/caddy/Caddyfile. Caddy proxies WebSocket connections, which the Home Assistant frontend uses, without extra settings:

Caddyfile
ha.example.com {
    reverse_proxy 127.0.0.1:8123
}
Bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo systemctl reload caddy
curl -I https://ha.example.com

You should get an HTTP response with a valid certificate. Under Settings → System → Network, set the Home Assistant URL for the internet to https://ha.example.com, so links and the companion apps use it.

Step 6 — Reach your home devices over WireGuard

Home Assistant on a server can only control devices it can reach over the network. The usual pattern is a site-to-site VPN: the server runs WireGuard, and a router or small device at home joins as a peer that routes your home subnet, for example 192.168.1.0/24. Set this up with How to set up a WireGuard VPN server, adding the home subnet to that peer's allowed IPs.

From the server, check that a home device answers, then add its integration in Home Assistant by IP address:

Bash
ping -c 3 192.168.1.10

Automatic discovery (mDNS, SSDP) does not cross a routed VPN, so devices are not found on their own; most integrations let you enter the address manually. You can also use the VPN to open Home Assistant from your phone instead of publishing it with Caddy. Allow the port only on the VPN interface:

Bash
sudo ufw allow in on wg0 to any port 8123 proto tcp

Back up and restore

Everything Home Assistant knows lives in the config folder, /opt/homeassistant/config: configuration.yaml, the hidden .storage folder with dashboards and integrations, and the history database.

Backups from the interface. Go to Settings → System → Backups, select Backup now and then Manual backup, or set up automatic backups, which also delete old ones. Download the emergency kit and keep it safe; it holds the key you need to restore encrypted backups. On Container, local backups are written to /opt/homeassistant/config/backups, inside the folder they protect, so copy them elsewhere or add a network or cloud backup location in the same screen.

Folder backup. Stop the container, archive the whole config folder, and start it again:

Bash
sudo mkdir -p /opt/backups
cd /opt/homeassistant
docker compose stop
sudo tar czf /opt/backups/homeassistant-config-$(date +%F).tar.gz -C /opt/homeassistant config
docker compose start

Copy /opt/backups to another machine with rsync or scp.

Restore. In the interface, open Settings → System → Backups, select a backup and choose Restore. On a fresh installation, the welcome screen lets you upload a backup instead of creating a new home. To restore the folder archive, stop the container, move the current folder aside and unpack the archive:

Bash
cd /opt/homeassistant
docker compose down
sudo mv config config.old
sudo tar xzf /opt/backups/homeassistant-config-2026-10-09.tar.gz -C /opt/homeassistant
docker compose up -d

Update Home Assistant

Read the release notes first, especially the Backward-incompatible changes section, and make a backup. Then pull the new image and recreate the container, as the Container documentation describes:

Bash
cd /opt/homeassistant
docker compose pull homeassistant
docker compose up -d
docker image prune

Afterwards, check Settings → System → Repairs and the logs. The stable tag always points to the latest stable release. To control updates, replace it with a specific version tag, for example 2026.10.0, which also lets you go back to a previous release.

Before restarting after manual YAML changes, validate the configuration:

Bash
docker exec homeassistant python -m homeassistant --script check_config --config /config

Troubleshooting

400: Bad Request when you open the domain

Home Assistant does not trust the proxy. Repeat Step 4 and make sure both 127.0.0.1 and ::1 are in the trusted proxies, then check the log with docker compose logs homeassistant for a message about a request from a reverse proxy.

Network settings reverted after a few minutes

After saving the HTTP server settings, Home Assistant restarts and waits for an administrator to confirm them. If nobody confirms within 5 minutes, it restores the previous settings. Save again and confirm.

Port 8123 cannot be reached from your browser

That is intended: ufw blocks it. Use the SSH tunnel, the VPN, or the Caddy domain. If you expected access over WireGuard, check that the wg0 rule exists with sudo ufw status.

Devices at home are not discovered

Discovery protocols do not cross the VPN. Check that the server can reach the device with ping, then add the integration manually with the device's IP address. If ping fails, the home subnet is missing from the WireGuard peer's allowed IPs or the home router does not route it.

Home Assistant does not start after editing configuration.yaml

A YAML error stops the configuration from loading. Run the check_config command from the update section, fix the reported lines, and start the container again with docker compose up -d.

Next steps

Frequently asked questions

What is the difference between Home Assistant OS and Home Assistant Container?

Home Assistant OS is a complete operating system with the Supervisor, which manages apps (formerly add-ons) and one-click updates. Home Assistant Container is the same core application in a Docker image: it has no apps, and you update it by pulling a new image.

Can I use Zigbee or Z-Wave sticks with Home Assistant on a remote server?

Not directly. USB radios and Bluetooth must be plugged into the machine that runs Home Assistant, and a data-centre server has no access to your home. Use network-based devices and integrations, reached over a VPN to your home network.

Why does Home Assistant return 400 Bad Request behind Caddy?

Home Assistant blocks requests from reverse proxies it does not trust. Open Settings, System, Network, turn on Trust X-Forwarded-For in the HTTP server section and add 127.0.0.1 and ::1 as trusted proxies, then confirm the new settings after the restart.

Does Home Assistant Container support backups?

Yes. The backup integration creates and restores backups on all installation types. On Container, local backups are stored in the backups folder inside the config directory, so copy them off the server or add a remote backup location.

Which HyperDC servers can run Home Assistant?

Home Assistant Container runs on a HyperDC Linux VPS, VDS or dedicated server with root access and Docker Engine 23 or newer. It is most useful there as a central hub for network and cloud integrations reached over a VPN.

Jelszó létrehozása

Please confirm