How to Install Home Assistant on Ubuntu 24.04 — Self-Hosted Smart Home on Your VPS
Home Assistant has become the de facto standard for serious smart home enthusiasts who refuse to hand over their device telemetry to Amazon, Google, or Samsung. Running it on a VPS gives you an always-on automation brain that reaches your cloud-connected devices (Nest, Tesla, Ring, Hue, Tuya) from anywhere, exposes dashboards on a proper domain with real TLS, and bridges to a home hub for local Zigbee and Z-Wave control. This guide walks you through installing Home Assistant Container on an Ubuntu 24.04 VPS, from first SSH connection to a hardened production deployment with HACS, a reverse proxy, backups, and the ecosystem of sibling containers that replace the Add-on Store.
Skip the setup? Deploy Home Assistant in one click with our pre-configured Smart Home image. Launch a Home Assistant VPS now and finish onboarding in under 10 minutes.
Table of Contents
What is Home Assistant?
Home Assistant is an open-source home automation platform written in Python that puts local control and privacy first. It started life in 2013 as a Raspberry Pi hobby project and has grown into one of the largest open-source communities on GitHub — the core repository has over 70,000 stars, with hundreds of active contributors shipping a release every three weeks. The project is released under the Apache 2.0 license and is backed by the Open Home Foundation, a non-profit that protects the long-term governance of the codebase.
Architecturally, Home Assistant is a Python async web application (built on aiohttp, not Flask, though it fills a similar role) that exposes a single-page web UI, a REST API, and a WebSocket API. Its power comes from over 3,000 integrations — modules that talk to everything from Philips Hue bulbs and Ecobee thermostats to Tesla vehicles, Starlink routers, Dyson vacuums, and Proxmox hypervisors. If a device has any kind of API, cloud account, or local protocol (MQTT, Zigbee, Z-Wave, Matter, Thread, Modbus, KNX), there is almost certainly a Home Assistant integration for it.
The platform shines where commercial smart home ecosystems fall short. Unlike Amazon Alexa Routines or Google Home Automations, Home Assistant lets you write arbitrarily complex automations that span vendors — for example, "when my Tesla starts charging and the solar production exceeds 3 kW, turn on the heat pump water heater and send me a Telegram message." It supports scripts, scenes, templates, blueprints, YAML, a graphical editor, and a rich dashboard system called Lovelace. Voice control is handled by Assist, a local pipeline that can replace Alexa or Google Assistant entirely when paired with a Wyoming satellite.
Home Assistant Editions Explained
Home Assistant ships in four flavors, which confuses newcomers. Here is the real difference:
| Edition | What It Is | Add-on Store | Supervisor | Best For |
|---|---|---|---|---|
| Home Assistant OS (HAOS) | A full Linux distro with Home Assistant, Supervisor, and Docker baked in | Yes | Yes | Dedicated Raspberry Pi, mini PC, or VM at home |
| Home Assistant Supervised | HA + Supervisor + Docker on top of your own Debian install | Yes | Yes | Advanced users on custom Debian hardware |
| Home Assistant Container | A single Docker image, run however you like | No | No | VPS, NAS, existing Docker hosts |
| Home Assistant Core | The raw Python package in a venv | No | No | Developers, constrained embedded systems |
For a VPS, Container is the right choice. You lose the Add-on Store, but you gain the ability to run Home Assistant alongside anything else on your box using plain Docker Compose. Everything the Add-on Store would install is just an official Docker image you bring up as a sibling container — we cover each one below.
Zigbee and Z-Wave caveat. A VPS has no USB ports, so you cannot plug in a SkyConnect, Sonoff, or Aeotec stick. If you want local radio control, keep a Raspberry Pi or HAOS VM at home running Zigbee2MQTT (or the Z-Wave JS server) and bridge it to your VPS over a WireGuard tunnel or a TLS-secured MQTT connection. The VPS remains the always-on brain; the Pi is just a radio. This hybrid topology is increasingly common and is what we assume throughout this guide.
Why Run Home Assistant on a VPS?
There are genuine reasons to prefer a VPS over a Pi-at-home install:
- Always on, always reachable — A VPS has 99.9%+ uptime, unmetered bandwidth, and a static IP. Your automations keep running during a home power cut, and your dashboards are reachable from any network without Dynamic DNS or port-forwarding the router.
- Proper TLS on a real domain — The Home Assistant mobile app, webhook integrations, and third-party services like IFTTT and Google Assistant require a public HTTPS URL with a valid certificate. On a VPS this is a five-minute Let's Encrypt job; at home it means carrier-grade NAT pain, DuckDNS certificates, or Nabu Casa Cloud's subscription.
- Runs cloud integrations beautifully — Nest, Tesla, Ring, Tuya, Hue Cloud, MyQ, Starlink, Withings, and hundreds of other integrations talk to vendor APIs from the cloud anyway. There is zero benefit to proxying those through a home Pi.
- Pairs with a local hub — MQTT over WireGuard or TLS bridges a home Zigbee2MQTT instance to the VPS with sub-100 ms latency. You get the best of both worlds: local radio at home, always-on brain in the cloud.
- Horizontally isolated from the LAN — A compromised smart plug on your home network cannot reach the VPS. The VPS only speaks to the home hub via a locked-down MQTT ACL or a WireGuard peer.
- Shared with your tenants and family — Give accounts to housemates, clients, or extended family without exposing your home router.
Home Assistant vs. Cloud Smart Home Alternatives
| Feature | SmartThings | Google Home | Home Assistant on VPS |
|---|---|---|---|
| Monthly cost | Free (Samsung account) | Free (Google account) | EUR 7.99/mo VPS |
| Integrations | ~200 | ~100 | 3,000+ |
| Local automations | Limited | No | Yes |
| Custom YAML logic | No | No | Yes |
| Data leaves your server? | Yes | Yes | No (cloud integrations excepted) |
| Mobile app with push | Yes | Yes | Yes (official + Companion) |
| Dashboards | Basic | Basic | Fully customizable (Lovelace) |
| HACS community add-ons | N/A | N/A | Yes |
Prerequisites
Before you begin, make sure you have:
- A VPS running Ubuntu 24.04 LTS with root or sudo access
- SSH access to your server
- At least 2 GB of RAM (4 GB recommended if you plan to add InfluxDB, Grafana, Node-RED, and ESPHome on the same box)
- At least 20 GB of disk space for Home Assistant, sibling containers, backups, and metric retention
- A domain name pointed at the VPS (for example,
home.example.com) — required for mobile app push notifications and cloud webhooks
Recommended Plan: CloudCore Starter>
Home Assistant itself idles at around 400 MB RAM and a few percent of a CPU core, but a realistic stack (HA + Mosquitto + Node-RED + InfluxDB + Grafana + Nginx) comfortably fits on the CloudCore Starter plan:>
- 4 vCPU cores
- 8 GB RAM
- 75 GB NVMe SSD
- Unmetered bandwidth
- From EUR 7.99/month>
If you plan to add transcoding workloads, voice pipelines, or heavy media automations, size up one tier.
Connect to your server:
ssh root@your-server-ipStep 1: Update System Packages
sudo apt update && sudo apt upgrade -yReboot if the kernel was updated, then reconnect.
Set the server's timezone — this matters because Home Assistant pulls the host timezone by default for sunrise/sunset calculations and scheduled automations:
sudo timedatectl set-timezone Europe/Berlin
timedatectlStep 2: Install Docker and Docker Compose
Home Assistant Container is a Docker image, so Docker is the only required dependency. The official Docker convenience script installs the engine, the CLI, and the Compose plugin in one shot.
curl -fsSL https://get.docker.com | shEnable and start the service:
sudo systemctl enable --now dockerVerify both components:
docker --version
docker compose versionExpected output:
Docker version 27.3.1, build ce12230
Docker Compose version v2.29.7Add your non-root user to the docker group so you do not need sudo for every command:
sudo usermod -aG docker $USER
newgrp dockerFor a complete Docker tutorial, see our How to Install Docker on Ubuntu 24.04 guide.
Step 3: Create the Home Assistant Compose Stack
We will use a single docker-compose.yml in /opt/homeassistant to manage the full stack. This keeps config, volumes, and backups in one predictable place.
sudo mkdir -p /opt/homeassistant/{config,mosquitto/config,mosquitto/data,mosquitto/log,nodered,esphome,influxdb,grafana}
cd /opt/homeassistantCreate the Compose file:
sudo tee /opt/homeassistant/docker-compose.yml > /dev/null <<'EOF'
services:
homeassistant:
container_name: homeassistant
image: ghcr.io/home-assistant/home-assistant:stable
restart: unless-stopped
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
- /run/dbus:/run/dbus:ro
environment:
- TZ=Europe/Berlin
ports:
- "8123:8123"
EOFA few notes on this minimal definition:
network_mode: hostvs. bridge with exposed port. Host networking is required at home for mDNS/SSDP discovery of Hue bridges, Sonos speakers, and Chromecasts on the LAN. On a VPS, those protocols do not apply — there is no LAN to discover. We use bridge mode with an explicit8123:8123port so Home Assistant coexists cleanly with other containers behind a reverse proxy../config:/configis where every piece of Home Assistant state lives:configuration.yaml, the SQLite database, secrets, automations, custom components. Back up this directory and you back up everything.ghcr.io/home-assistant/home-assistant:stableis the official image. Use:latestfor the bleeding-edge release train or pin to a specific version like:2026.4for reproducible deploys.
docker compose up -dWatch the first-run logs:
docker compose logs -f homeassistantThe first boot takes 60-90 seconds as Home Assistant generates its default config, builds its registry cache, and starts the HTTP server. You are ready when you see:
[homeassistant.core] Home Assistant initialized in 42.13s
[homeassistant.bootstrap] Home Assistant startedStep 4: First Onboarding
Browse to http://your-server-ip:8123 and you will land on the onboarding wizard.
Finish the wizard and you land on the default Overview dashboard. You now have a working Home Assistant.
Before going further, open Settings → System → General and note the default External URL is blank. We will fix that in the next step.
Step 5: Configure a Reverse Proxy with Nginx and TLS
Home Assistant speaks plain HTTP on port 8123. The mobile Companion app, Google Assistant integrations, and most webhooks require public HTTPS, so we put Nginx in front with a Let's Encrypt certificate.
Install Nginx and Certbot:
sudo apt install -y nginx certbot python3-certbot-nginxCreate the site configuration. The critical pieces are the WebSocket upgrade headers (Home Assistant's UI is pure WebSocket under the hood) and generous timeouts (long-lived streams for media, logbook, and live camera feeds).
sudo tee /etc/nginx/sites-available/homeassistant > /dev/null <<'EOF' server { listen 80; server_name home.example.com; return 301 https://$host$request_uri; }server { listen 443 ssl http2; server_name home.example.com;
ssl_certificate /etc/letsencrypt/live/home.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/home.example.com/privkey.pem;
# Security headers add_header X-Content-Type-Options nosniff; add_header X-Frame-Options SAMEORIGIN; add_header Referrer-Policy strict-origin-when-cross-origin;
client_max_body_size 100m;
location / { proxy_pass http://127.0.0.1:8123; proxy_http_version 1.1;
# WebSocket upgrade — required proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
# Long timeouts for streaming, logbook, and camera feeds proxy_read_timeout 3600s; proxy_send_timeout 3600s; proxy_buffering off; } } EOF
sudo ln -s /etc/nginx/sites-available/homeassistant /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx
Obtain the certificate:
sudo certbot --nginx -d home.example.comNow tell Home Assistant that it is sitting behind a proxy. Edit /opt/homeassistant/config/configuration.yaml and add:
http: use_x_forwarded_for: true trusted_proxies: - 127.0.0.1 - ::1 ip_ban_enabled: true login_attempts_threshold: 5
homeassistant: external_url: "https://home.example.com" internal_url: "https://home.example.com"
Restart the container:
docker compose restart homeassistantHome Assistant will now render the correct external URL in the onboarding flow, QR codes, and mobile app invite screens. The ip_ban_enabled and login_attempts_threshold settings add brute-force protection on top of Nginx.
For a complete Nginx reverse proxy walkthrough, see our How to Set Up Nginx as a Reverse Proxy guide.
Step 6: Set Up Core Integrations
Integrations are added from Settings → Devices & Services → Add Integration.
Cloud integrations (perfect for a VPS)
These talk to vendor APIs directly and require zero local network presence:
- Philips Hue (Cloud) — log in with your Hue Bridge remote account.
- Tesla Fleet API — monitor charging, climate, and location.
- Google Nest — thermostats, cameras, doorbells via the Device Access Console.
- Ring — doorbells, cameras, motion events.
- Tuya / SmartLife — thousands of generic Chinese devices.
- Ecobee — thermostat and remote sensors.
- Spotify, Plex, Jellyfin — media players.
- MET.no, OpenWeatherMap, Pirate Weather — weather.
HTTP, REST, and webhook integrations
Anything with a JSON endpoint can be consumed via the built-in rest and command_line platforms. Great for scraping status pages, home solar inverters exposed via REST, and custom sensors.
Local integrations via bridged MQTT
For anything strictly local (Zigbee bulbs, ESPHome nodes, Shelly relays), the standard pattern is: run a Mosquitto MQTT broker on the VPS, expose it to your home Pi over WireGuard, have Zigbee2MQTT and ESPHome on the Pi publish to that broker. Home Assistant subscribes and treats them as if they were locally attached. We set that up in the next step.
Step 7: Add MQTT, ESPHome, and Node-RED
Because Home Assistant Container has no Add-on Store, we add these as sibling services in the same Compose file. Edit /opt/homeassistant/docker-compose.yml:
services: homeassistant: # ... (unchanged from Step 3)mosquitto: container_name: mosquitto image: eclipse-mosquitto:2 restart: unless-stopped ports: - "1883:1883" - "9001:9001" volumes: - ./mosquitto/config:/mosquitto/config - ./mosquitto/data:/mosquitto/data - ./mosquitto/log:/mosquitto/log
nodered: container_name: nodered image: nodered/node-red:latest restart: unless-stopped ports: - "1880:1880" volumes: - ./nodered:/data environment: - TZ=Europe/Berlin
esphome: container_name: esphome image: ghcr.io/esphome/esphome:stable restart: unless-stopped ports: - "6052:6052" volumes: - ./esphome:/config environment: - TZ=Europe/Berlin
Create a minimal Mosquitto config with authentication:
sudo tee /opt/homeassistant/mosquitto/config/mosquitto.conf > /dev/null <<'EOF' listener 1883 listener 9001 protocol websocketspersistence true persistence_location /mosquitto/data/ log_dest file /mosquitto/log/mosquitto.log
allow_anonymous false password_file /mosquitto/config/passwd EOF
Create a user:
sudo docker run --rm -v /opt/homeassistant/mosquitto/config:/mosquitto/config \
eclipse-mosquitto:2 \
mosquitto_passwd -c -b /mosquitto/config/passwd hass your-strong-passwordBring the stack up:
cd /opt/homeassistant
docker compose up -dBack in Home Assistant: Settings → Devices & Services → Add Integration → MQTT. Enter:
- Broker:
mosquitto - Port:
1883 - Username / Password: the credentials you just created
Node-RED is reachable at http://your-server-ip:1880 — proxy it through Nginx too if you want it on a subdomain. It gives you a graphical flow-based automation editor that many users prefer to YAML for complex logic.
ESPHome Dashboard at port 6052 lets you compile and OTA-flash firmware to ESP32/ESP8266 boards. Since boards are flashed over Wi-Fi once they are joined, you do not need them physically attached to the VPS.
Step 8: Install HACS (Community Store)
HACS (the Home Assistant Community Store) is the third-party registry for community integrations, Lovelace cards, themes, and Python scripts. It replaces a large portion of what HAOS users get from the Add-on Store.
Open a shell inside the container:
docker exec -it homeassistant bashRun the HACS installer:
wget -O - https://get.hacs.xyz | bash -
exitRestart Home Assistant:
docker compose restart homeassistantThen in the UI: Settings → Devices & Services → Add Integration → HACS. You will be prompted to authorize HACS against a temporary GitHub device code. Paste the code on GitHub, confirm, and HACS will appear in the sidebar.
Highly recommended HACS add-ons
- Mushroom — a card pack with beautiful, dense, mobile-friendly tiles.
- Bubble Card — pop-up cards for quick actions without cluttering the main dashboard.
- card-mod — lets you inject CSS into any core or community card. Essential for theming.
- auto-entities — dynamically build card contents from filters (for example, "all lights that are currently on").
- apexcharts-card — gorgeous time-series charts for power, temperature, and sensor data.
- browser_mod — turn any browser into a controllable media/display device for wall tablets.
Step 9: Automations, Scripts, and Dashboards
Home Assistant's automation engine is a trigger / condition / action state machine:
- Triggers — time, state change, numeric threshold, webhook, sun event, MQTT topic, calendar, device trigger.
- Conditions — optional checks (only if someone is home, only after sunset, only on weekdays).
- Actions — call a service, send a notification, run a script, fire an event, wait, repeat, choose.
automations.yaml under /config. A simple example:- alias: "Porch light at sunset"
trigger:
- platform: sun
event: sunset
offset: "-00:15:00"
condition:
- condition: state
entity_id: person.owner
state: "home"
action:
- service: light.turn_on
target:
entity_id: light.porch
data:
brightness_pct: 80Scripts are reusable action sequences. Scenes are saved state snapshots ("Movie Night" = dim lights 20%, close blinds, turn TV on). Helpers (Settings → Devices & Services → Helpers) give you counters, timers, input booleans, template sensors, and groups without touching YAML.
Lovelace dashboards are pure YAML or visual-editor cards: entities, buttons, glance, grid, horizontal-stack, vertical-stack, conditional, picture-elements. Combine core cards with the HACS cards above and you get dashboards that rival commercial home-automation products.
The Home Assistant Companion apps for iOS and Android give you push notifications, geofencing, sensors from the phone (battery, activity, location), and a polished dashboard view. They require your public HTTPS URL from Step 5 — plain IP addresses and self-signed certificates will not work.
Step 10: Long-Term History with InfluxDB and Grafana
Home Assistant's default recorder keeps 10 days of state history in SQLite. That is enough for the Logbook and the History panel, but you will want longer retention for energy dashboards, seasonal comparisons, and device diagnostics.
Add InfluxDB 2 and Grafana to the Compose file:
influxdb: container_name: influxdb image: influxdb:2.7 restart: unless-stopped ports: - "8086:8086" volumes: - ./influxdb:/var/lib/influxdb2 environment: - DOCKER_INFLUXDB_INIT_MODE=setup - DOCKER_INFLUXDB_INIT_USERNAME=admin - DOCKER_INFLUXDB_INIT_PASSWORD=change-me-strong - DOCKER_INFLUXDB_INIT_ORG=home - DOCKER_INFLUXDB_INIT_BUCKET=homeassistant - DOCKER_INFLUXDB_INIT_RETENTION=52w - DOCKER_INFLUXDB_INIT_ADMIN_TOKEN=generate-a-long-token
grafana: container_name: grafana image: grafana/grafana:latest restart: unless-stopped ports: - "3000:3000" volumes: - ./grafana:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=change-me
Bring them up and enable the InfluxDB integration inside Home Assistant by editing configuration.yaml:
influxdb:
api_version: 2
ssl: false
host: influxdb
port: 8086
token: !secret influxdb_token
organization: home
bucket: homeassistant
tags:
source: HA
tags_attributes:
- friendly_name
default_measurement: unitsPut your token in /config/secrets.yaml:
influxdb_token: generate-a-long-tokenRestart Home Assistant. In Grafana (http://your-server-ip:3000, login admin / change-me), add an InfluxDB data source pointing at http://influxdb:8086, and you can start building dashboards with a year or more of retention.
Step 11: Backups and Restore
Home Assistant has a built-in backup engine at Settings → System → Backups. Create one on demand; it produces a .tar file containing the full /config directory. Download it — but since we are on a VPS, we want this automated and off-site.
Create /opt/homeassistant/backup.sh:
sudo tee /opt/homeassistant/backup.sh > /dev/null <<'EOF' #!/usr/bin/env bash set -euo pipefailSTAMP=$(date +%Y%m%d-%H%M%S) OUT=/opt/backups/homeassistant-$STAMP.tar.gz
mkdir -p /opt/backups docker compose -f /opt/homeassistant/docker-compose.yml stop homeassistant tar -czf "$OUT" -C /opt/homeassistant config docker compose -f /opt/homeassistant/docker-compose.yml start homeassistant
Keep the 7 newest local backups
ls -1t /opt/backups/homeassistant-*.tar.gz | tail -n +8 | xargs -r rm -fOff-site via rclone to Backblaze B2, S3, or any provider
rclone copy "$OUT" remote:homeassistant-backups/ EOF
sudo chmod +x /opt/homeassistant/backup.sh
Schedule it nightly at 03:00:
(crontab -l 2>/dev/null; echo "0 3 * /opt/homeassistant/backup.sh >> /var/log/ha-backup.log 2>&1") | crontab -Stopping Home Assistant while taring the config directory prevents SQLite corruption in the recorder database. A 2-3 second outage at 3 a.m. will not affect any automations.
Restore is symmetrical: stop the stack, extract the tarball over /opt/homeassistant/config, start the stack. You can also upload the .tar via Settings → System → Backups → Upload backup to restore from the UI on a fresh instance.
Security Hardening
Home Assistant has access to your cameras, locks, and vehicles. Treat it accordingly.
- Enable two-factor authentication per user: Profile → Security → Enable Multi-factor Authentication. Use any TOTP app.
- Use long-lived access tokens, not passwords, for API integrations. Revoke tokens under Profile → Security → Long-Lived Access Tokens when you rotate them.
- Configure
ip_ban_enabledandlogin_attempts_threshold— done in Step 5. - Do NOT use
trusted_networksfor public ranges. It bypasses authentication for listed IPs. Only use it for an internal WireGuard subnet (for example,10.99.0.0/24) if you want passwordless access from a trusted VPN. - Restrict outbound traffic with UFW if you are paranoid — but remember cloud integrations need egress to Google, Tesla, Nest, etc.
- Lock down the Companion app webhooks — they are per-device and invalidated when you remove the device.
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
:8123 returns connection refused | Container not started or port not mapped | docker compose ps then docker compose logs homeassistant. Confirm ports: - "8123:8123" in the Compose file. |
| Mobile Companion app cannot connect | Missing external URL, invalid TLS, or X-Forwarded headers blocked | Verify external_url in configuration.yaml, use_x_forwarded_for: true, and trusted_proxies include 127.0.0.1. Test https://home.example.com/manifest.json in a browser. |
| "400 Bad Request" at login page through proxy | trusted_proxies missing or wrong | Add the proxy IP (usually 127.0.0.1 and ::1) to http.trusted_proxies. Restart the container. |
| Integrations show "auth failed" repeatedly | OAuth redirect URL mismatch | In the vendor console (Google, Tesla, Nest), set redirect to https://home.example.com/auth/external/callback. |
| High CPU after upgrade | Recorder database migration or custom component loop | docker compose logs homeassistant \</td><td>grep -i error<code>. Consider purging the recorder: </code>service recorder.purge keep_days=7. |
| Restart loop | Bad YAML in configuration.yaml | docker run --rm -v /opt/homeassistant/config:/config ghcr.io/home-assistant/home-assistant:stable --script check_config. |
| "Failed to connect to broker" for MQTT | Password file not created or permissions wrong | Recreate mosquitto_passwd, confirm allow_anonymous false, check broker logs. |
| Graphs show gaps after a few hours | Recorder purge too aggressive | Increase recorder.purge_keep_days or rely on InfluxDB for long-term history. |
Viewing logs
docker compose logs -f homeassistant
docker compose logs -f mosquittoYou can also use the built-in log viewer at Settings → System → Logs, which filters by integration.
Updating Home Assistant
cd /opt/homeassistant
./backup.sh # always back up first
docker compose pull
docker compose up -dHome Assistant ships a new major release on the first Wednesday of every month. Read the release notes before upgrading — occasionally an integration is deprecated and needs a config change.
FAQ
Should I run Home Assistant Container on a VPS or HAOS at home?
If you have only cloud devices (Hue, Nest, Tesla, Ring, Tuya) — VPS, every time. No port forwarding, free TLS, always on. If your smart home is entirely local Zigbee, Z-Wave, or Matter-over-Thread, you need a device with a USB radio at home; put HAOS on a Pi 5 or a mini PC. The most powerful topology is both: HAOS on a Pi doing local radio duty, publishing to an MQTT broker on the VPS, with the VPS acting as the always-on brain and the public-facing interface.
How do I get Zigbee or Z-Wave devices on a VPS?
You cannot plug a USB stick into a VPS — full stop. The pattern is: install Zigbee2MQTT on a Pi at home with a SkyConnect or Sonoff dongle, point it at the Mosquitto broker running on the VPS over a WireGuard tunnel. Zigbee2MQTT publishes device state to MQTT, and Home Assistant auto-discovers every device. The same approach works for Z-Wave JS — run the Z-Wave JS Server on the Pi and connect to it remotely. Latency over a decent home-to-VPS link is 50-100 ms, which is indistinguishable from local for automation purposes.
Is HACS safe to use?
HACS itself is a widely-audited integration. The risk profile comes from the community code you install through it — each author's repository is separate. Stick to the most popular integrations (those with thousands of stars and active maintainers), read the repository before installing, and understand that custom components can do anything the core can do. For mission-critical automations (locks, security cameras), stay on first-party integrations only.
What about Nabu Casa Home Assistant Cloud?
Nabu Casa Cloud is the official paid service at USD 6.50/month that gives you remote access without running your own reverse proxy, plus turnkey Google Assistant and Alexa integration. It is a good option if you run Home Assistant at home on a Pi and do not want to deal with DNS/TLS/port forwarding. On a VPS this guide's setup already solves the remote access problem — you only need Nabu Casa if you specifically want the first-party Google/Alexa bridges, which otherwise require your own Google Cloud project. The money also directly funds the Open Home Foundation, which many users consider reason enough to subscribe.
How do I bridge local devices at home to the VPS?
The WireGuard + Mosquitto pattern is the canonical answer. Set up WireGuard between the VPS and your home Pi, tighten the Mosquitto ACL so only the Pi's WireGuard IP can publish to device topics, and run Zigbee2MQTT/ESPHome/Z-Wave JS at home publishing to the VPS broker. Home Assistant on the VPS subscribes and sees everything as if it were local. Our WireGuard guide walks through the tunnel setup.
Can I run voice assistants (Assist) on a VPS?
Yes, with caveats. The Assist pipeline — wake word, STT, intent, TTS — can run entirely in containers. The hard part is the audio endpoint: Wyoming satellites (ESP32-S3-BOX-3, M5 Atom Echo, a Raspberry Pi with a mic HAT) live at home and stream audio to the VPS over Wyoming protocol. You can run Piper (TTS) and Whisper (STT) on the VPS if you have 4+ GB of RAM to spare. For heavy Whisper models, offload to a GPU VPS or use cloud Whisper via the OpenAI integration.
How much bandwidth does Home Assistant use?
Very little. A typical setup with 50 devices, cloud integrations, and one user averages 50-200 MB of bandwidth per day. Camera streams (if you proxy them through Home Assistant) dominate — plan for 1-3 Mbps per 1080p stream. Our plans ship with unmetered bandwidth, so this is rarely a concern.
Next Steps
Now that Home Assistant is running on your VPS, here are recommended directions:
- Install AdGuard Home or Pi-hole alongside for network-wide ad blocking and DNS logging — integrates directly with Home Assistant dashboards.
- Bridge a home Pi for local Zigbee via Zigbee2MQTT over WireGuard, as described in the FAQ.
- Enable the Energy Dashboard — connect your utility meter integration or shelly EM devices, and get solar + grid + battery visualizations out of the box.
- Build a Glance wall tablet with browser_mod and an old tablet running Fully Kiosk Browser.
- Set up Frigate NVR in a sibling container for AI-powered object detection on your cameras.
- Explore blueprints — the community blueprint exchange has hundreds of ready-made automations (motion-activated lights, low-battery alerts, washing-machine-done notifications) you can import with one click.
Skip the Manual Install — Get Home Assistant Pre-Configured>
Our Smart Home VPS image comes with Home Assistant, Mosquitto, Node-RED, ESPHome, InfluxDB, Grafana, and Nginx pre-installed. Deploy in under a minute and skip straight to onboarding.>
- Home Assistant Container on the latest stable release
- Mosquitto broker with authentication already configured
- Nginx reverse proxy with Let's Encrypt automation
- Nightly backup script with off-site rclone targets
- WireGuard-ready for bridging a home Zigbee hub>
Deploy Your Smart Home VPS Now — CloudCore Starter plans from EUR 7.99/month.