# How to Self-Host Home Assistant With Docker or One Click (2026)

> Home Assistant Docker setup on a cloud server, step by step: the compose file, HTTPS and trusted proxies, the one-click way on xCloud, and safe updates.

**Home Assistant Docker** means running Home Assistant Container, the official image, on a Linux machine you control with Docker Compose. It gives you dashboards, automations and integrations without Home Assistant OS. On a cloud server, the work that matters is putting HTTPS in front and telling Home Assistant to trust that proxy.

Most Home Assistant Docker guides assume a mini PC at home, with host networking and USB sticks. This guide is for the other case: Home Assistant on a cloud server, reached over HTTPS from anywhere, for cloud services, MQTT and webhooks.

You will see the manual Docker Compose path on any Ubuntu server first, then the one-click way on xCloud, with what each one leaves on your plate. If containers are new to you, start with [**what Docker Compose is**](/what-is-docker-compose/).

![Home Assistant on a cloud server: the browser reaches HTTPS on the proxy, the proxy forwards to port 8123 on the server, and the container keeps everything in /config](/_landing/blog/self-host-home-assistant-image-1.png)

## TL;DR

- **Home Assistant Container** is the official Docker image, `ghcr.io/home-assistant/home-assistant`, served on port **8123**. With Docker, it needs Docker Engine 23.0.0 or later; Docker Desktop will not work ([**official install page**](https://www.home-assistant.io/installation/linux), as of November 2026).
- **On a cloud server**, skip the home-setup flags (`privileged`, host networking, D-Bus). They exist for local discovery, USB and Bluetooth, which a VPS cannot use.
- **The step most guides skip:** since Home Assistant 2026.8, reverse-proxy trust is set in **Settings → System → Network**, and an unconfirmed change reverts after 5 minutes. Until it is set, proxied requests are blocked.
- **Manual path:** Compose file, SSH tunnel for the first login, trusted proxies, then Caddy or NGINX for HTTPS.
- **One-click path:** pick **Home Assistant** under **One Click Apps** in xCloud, add a domain, and xCloud starts the container with HTTPS and the proxy trust already confirmed.
- **Either way, you own** version upgrades. Back up the whole `/config` folder before each one.

## The Step Most Docker Guides Skip: Trusting Your Reverse Proxy

Here's the part that trips people up. Home Assistant only accepts forwarded requests from a proxy you have named. Its [**HTTP integration docs**](https://www.home-assistant.io/integrations/http/) say requests from reverse proxies are blocked until you turn on **Trust X-Forwarded-For** and add the proxy to **Trusted proxies**.

Two things changed in 2026. Before Home Assistant 2026.8 you set this in `configuration.yaml`. The [**2026.8 release notes**](https://www.home-assistant.io/blog/2026/08/05/release-20268/) moved these web server settings, trusted proxies included, into the app, and the HTTP docs place them under **Settings → System → Network**. Saving restarts Home Assistant, and an administrator must confirm the new settings. If nobody confirms within 5 minutes, Home Assistant goes back to the old ones.

That creates a chicken-and-egg problem on a fresh cloud install. You cannot reach the setup page through your HTTPS domain until the proxy is trusted, and you cannot trust the proxy without reaching the setup page. The manual steps below solve it with an SSH tunnel.

xCloud's Home Assistant template handles it differently. Before the first start, it writes a confirmed network setting that trusts the local proxy, so the HTTPS address works the moment the install finishes. The template's notes say that without it, Home Assistant answers every proxied request with an HTTP 400 error. Here is the stack the template defines (as of November 2026). This comes from the template files; we did not run the one-click install end to end for this guide.

| Part | What xCloud's one-click install sets up |
|---|---|
| **Image** | The official `ghcr.io/home-assistant/home-assistant` image, pinned to **2026.9.4** by tag and digest |
| **Your data** | One `ha_config` volume mounted at `/config`: YAML files, users, integrations and the database |
| **Network** | Port 8123 is only reachable through your domain, not by server IP and port |
| **HTTPS** | NGINX in front of the app with a free SSL certificate |
| **Proxy trust** | Trust X-Forwarded-For on, with `127.0.0.1/32` and `172.16.0.0/12` as trusted proxies, already confirmed |
| **First boot** | A default `configuration.yaml` is written only if none exists, so a restored `/config` is never overwritten |
| **Health check** | Docker checks the web app every 30 seconds, after a 3-minute start-up window |
| **Baseline size** | 1 CPU core, 1 GB of RAM and 8 GB of disk |

## What You Need to Self-Host Home Assistant

Start with an honest check: a cloud server cannot see your home network. The [**official install page**](https://www.home-assistant.io/installation/linux) runs the container with host networking and privileged mode so it can find local devices and use Bluetooth. A VPS has none of those devices nearby.

| Requirement | What to plan for |
|---|---|
| **Server** | A 64-bit Linux server; Ubuntu LTS is the simplest choice. 1 CPU core and 1 GB of RAM is a workable start (xCloud's template baseline) |
| **Disk** | 8 GB or more; the history database grows with every sensor you add |
| **Docker** | Docker Engine 23.0.0 or later with the Compose plugin, per the [**official install page**](https://www.home-assistant.io/installation/linux). Docker Desktop will not work |
| **Ports** | 22 for SSH, 80 and 443 for HTTPS. Keep 8123 closed to the internet |
| **Domain** | An A record such as `ha.example.com` pointing at `SERVER_IP` |
| **Good fit** | Cloud integrations, MQTT brokers you can reach over the network, webhooks, REST clients, dashboards |
| **Poor fit** | Zigbee or Z-Wave USB sticks, Bluetooth, and devices found by local discovery |

If most of your devices only talk on your home network, run Home Assistant at home instead. A cloud install shines when your automations already live in the cloud.

## Option 1: Self-Host Home Assistant With Docker Compose

This path uses the official image on a fresh Ubuntu server. Commands use placeholders: replace `YOUR_USER`, `SERVER_IP` and `ha.example.com` with your own values. These steps follow the official Home Assistant and Caddy docs. The image tag below is published on GitHub's container registry, but we did not test the full flow end to end on a server.

### Step 1: Prepare the server and domain

Point the A record for your domain at `SERVER_IP`. Install Docker Engine from Docker's official Ubuntu instructions, then allow only ports 22, 80 and 443 in your firewall. Our [**VPS security guide**](/maximize-your-vps-security/) covers SSH keys and firewall basics.

### Step 2: Write the Compose file

Create a folder such as `/opt/homeassistant` and save this as `compose.yaml`. It starts from the official example and makes three changes for a cloud server: no privileged mode, no host networking, and a port that only listens on the server itself.

```yaml
services:
  homeassistant:
    container_name: homeassistant
    image: ghcr.io/home-assistant/home-assistant:2026.11.1
    volumes:
      - ./config:/config
      - /etc/localtime:/etc/localtime:ro
    ports:
      - "127.0.0.1:8123:8123"
    restart: unless-stopped
    stop_grace_period: 60s
    environment:
      TZ: America/New_York
```

Pin a release tag instead of `stable`, so a restart never jumps you to a new version. [**2026.11.1**](https://github.com/home-assistant/core/releases/tag/2026.11.1) was the latest release when we updated this (November 2026). Set `TZ` to your own time zone name.

```bash
cd /opt/homeassistant
docker compose up -d
docker compose logs -f homeassistant
```

The first start can take a few minutes while integrations load.

### Step 3: Create the owner account through an SSH tunnel

Home Assistant has no preset login: whoever opens the onboarding page first becomes the owner. Because port 8123 is not open to the internet, only you can reach it, through an SSH tunnel from your own computer:

```bash
ssh -L 8123:127.0.0.1:8123 YOUR_USER@SERVER_IP
```

Keep that session open, then visit `http://localhost:8123` in your browser and create the owner account.

### Step 4: Trust the reverse proxy

Still on the tunnel, go to **Settings → System → Network**. Turn on **Trust X-Forwarded-For** and add `172.16.0.0/12` under **Trusted proxies**. That range covers Docker's default private networks, and xCloud's own Home Assistant template trusts the same range. If the domain still returns a 400 error, check the Home Assistant log for the address the request came from and add that network instead. You can enter a single IP address or a network. If you enter a network, use its network address, such as `192.168.1.0/24`, not a host address such as `192.168.1.50/24`.

Saving restarts Home Assistant. Reload the page and **confirm** the new settings within 5 minutes, or they revert.

### Step 5: Add HTTPS with a reverse proxy

Any proxy that passes WebSockets works. Caddy is the shortest: install it from its official package, then put this in `/etc/caddy/Caddyfile`:

```
ha.example.com {
    reverse_proxy 127.0.0.1:8123
}
```

Run `sudo systemctl reload caddy`. Caddy requests a Let's Encrypt certificate on its own. Open `https://ha.example.com` and sign in with the owner account.

![Self-hosting Home Assistant: who does each job, manual Docker Compose vs one-click on xCloud](/_landing/blog/self-host-home-assistant-image-2.png)

### Troubleshooting the manual install

- **The domain shows "400: Bad Request" or the login page never loads.** The proxy is not trusted yet. Repeat Step 4 over the tunnel and confirm within 5 minutes.
- **An integration cannot find your devices.** It relies on local discovery, which a cloud server cannot do. Use a cloud or MQTT integration instead.
- **You looked for the add-on store.** Home Assistant's docs say the Container install has no access to apps (add-ons). Run extra services as their own containers.
- **The container restarts in a loop.** Read `docker compose logs homeassistant`. A broken YAML file in `config/` is the usual cause.

## Option 2: One-Click Home Assistant on xCloud

If you would rather skip the proxy and tunnel work, the one-click install does those steps for you. It needs an NGINX server; xCloud installs Docker during the app install if the server does not have it yet.

1. In the xCloud dashboard, click **Add New Site** → **One Click Apps** and search for **Home Assistant**.
2. Pick a compatible server or create a new one. The setup page shows the app's requirements.
3. Choose **Go Live** with your domain, or **Demo Site** to try it on a temporary URL, then click **Create**.
4. When the install finishes, open the site URL right away and create the owner account. The template sets no login for you: its install notes say whoever opens the URL first becomes the owner, so do not share the link before you do.

The [**One-Click App templates guide**](/docs/how-to-use-one-click-app-templates-in-xcloud/) walks through each screen. For plans and the managed server sizes, see [**Home Assistant hosting on xCloud**](/home-assistant-hosting/).

## Updates, Backups and Security After Install

### Back up the whole /config folder

Everything lives in `/config`: YAML, users, tokens, integrations and the history database. Back it up as one unit and restore it as one unit. On the manual install, a simple copy looks like this:

```bash
cd /opt/homeassistant
docker compose stop
sudo tar czf ha-config-$(date +%F).tar.gz config
docker compose start
```

Keep a copy off the server, and test a restore once. On xCloud, open the site's **Backup → Previous Backups** and click **Backup Now**, or schedule backups in **Backup Settings**. See [**how to back up and restore Docker apps**](/docs/backup-and-restore-docker-apps/).

### Update one release at a time, on purpose

Read the release notes for breaking changes first, then back up. On the manual install, change the tag in `compose.yaml` and run:

```bash
docker compose pull
docker compose up -d
```

On xCloud, **App Actions → Update** pulls the version named in the compose file again. Because the template pins an exact version, moving to a new release means changing the image tag and digest on the app's **Compose** page and clicking **Save & Redeploy**. Keep the `ha_config` volume as it is. The [**update and Compose guide**](/docs/update-a-one-click-app-and-edit-its-docker-compose-in-xcloud/) covers the details.

### Lock down the login

Turn on multi-factor authentication for the owner account in your Home Assistant profile, and create separate users for family members instead of sharing the owner login. On the manual install, keep port 8123 closed to the internet so the proxy is the only way in.

## What the One-Click Install Does Not Do

Here is the honest list, taken from the same template files and Home Assistant's docs:

- **No local devices.** It runs on an isolated Docker network, so local discovery, USB sticks (Zigbee, Z-Wave) and Bluetooth do not work.
- **No add-on store.** That is a limit of Home Assistant Container itself.
- **No automatic version upgrades.** The image is pinned, and existing installs stay on their version when the catalog changes.
- **It needs an NGINX server.** OpenLiteSpeed servers cannot run Docker apps.
- **Do not turn off Trust X-Forwarded-For** or remove the proxy ranges in **Settings → System → Network**, or every request through your domain will be rejected.

To undo the install, delete the site from xCloud. Take a backup first if you want to keep your configuration.

## Docker vs One-Click: Which to Choose

| | Manual Docker Compose | One-click on xCloud |
|---|---|---|
| **Software cost** | Free (Apache-2.0) | Free (Apache-2.0) |
| **Setup work** | Compose file, tunnel, proxy trust, Caddy or NGINX | A few form fields |
| **HTTPS and certificate** | You | Done for you |
| **Proxy trust** | You set and confirm it | Written and confirmed before first boot |
| **Version choice** | Any tag you pin | Pinned by the template; you change it in Compose |
| **Backups** | You script and test them | Scheduled Docker app backups, local or remote |
| **Local devices** | Not on a cloud server | Not on a cloud server |

The trade-off is the usual one: your time is the hidden cost. The manual path is the right call if you want to learn every layer or already run a proxy. The one-click path saves the hour you would spend on certificates and the 5-minute confirm dance. Our guide to [**self-managed vs managed hosting**](/self-managed-vs-managed-hosting/) goes deeper on that choice.

## Get Your Cloud Home Assistant Running Today

If you like owning every layer, the Compose file above is a solid start: pin the version, keep 8123 private, trust the proxy over a tunnel, and test a restore before you rely on it.

If you would rather skip the plumbing, deploy it from [**xCloud Home Assistant hosting**](/home-assistant-hosting/) and spend that time on automations instead. You can browse other self-hosted apps in [**One-Click Apps**](/one-click-apps/) or on [**Docker hosting**](/docker-hosting/), such as [**Node-RED**](/node-red-hosting/) for flow-based automations. For another app set up both ways, see our guide to [**self-hosting Nextcloud**](/self-host-nextcloud/) or [**self-hosting Vaultwarden**](/self-host-vaultwarden-password-manager/).

If you have found this blog helpful, feel free to [**subscribe to our blogs**](https://xcloud.host/blog/) for valuable tutorials, guides, knowledge, and tips on web hosting and server management. You can also join our [**Facebook community**](https://www.facebook.com/groups/xcloud.community) to share insights and engage in discussions.

## Frequently Asked Questions

### Can I run Home Assistant in Docker on a VPS?

Yes. Home Assistant Container runs on any Linux server with Docker Engine 23.0.0 or later. On a VPS it works for cloud services, MQTT, webhooks and dashboards, but it cannot reach devices on your home network, so local-only devices need a Home Assistant install at home.

### Why does Home Assistant block requests behind my reverse proxy?

Home Assistant blocks requests from a reverse proxy until you trust it. Go to **Settings → System → Network**, turn on **Trust X-Forwarded-For** and add your proxy's network to **Trusted proxies**. Confirm the change within 5 minutes, or Home Assistant puts the old settings back.

### Does Home Assistant in Docker support add-ons?

No. Home Assistant's own docs say the Container install does not have access to apps (add-ons). Run any extra service, such as an MQTT broker, as its own container next to Home Assistant.

### How much RAM does Home Assistant need in Docker?

The Container docs give no minimum. xCloud's one-click template asks for 1 CPU core, 1 GB of RAM and 8 GB of disk as a baseline. Long histories, many integrations and camera features need more, so watch memory as you grow.

### Does xCloud update Home Assistant for me?

No. The one-click install pins an exact Home Assistant version so a restart never changes it. To move to a new release, take a backup, then change the version in the app's Compose page and redeploy.
