Your NAS is already running 24/7, has redundant storage, and is significantly more reliable than a Raspberry Pi. There's no reason to run a dedicated device for Home Assistant when a Docker container on your NAS can do the same job — and restart automatically after power cuts, updates, or reboots without any intervention from you.
This guide shows how to deploy it in a way that is correct, minimal, and easy to recover.
Prerequisites
- Synology NAS with Docker (or Container Manager) installed
- Portainer running (optional but recommended for visual management)
- SSH access or File Station access
Step 1: Create the Config Directory
Home Assistant stores all your automations, integrations, and device pairings in its /config directory. This must live on your NAS, outside the container, so it survives container updates and replacements.
Via SSH:
mkdir -p /volume1/docker/homeassistant/configOr create the same path using Synology File Station.
Step 2: Deploy the Stack
This project uses Docker Compose files committed to Git. The Home Assistant stack lives in this folder.
If you are deploying via Portainer:
- Log into Portainer → Stacks → + Add stack
- Name it
home-assistant - Switch to Upload and upload the
docker-compose.yamlfrom this folder, or paste its contents into the web editor - Click Deploy the stack
If you are deploying directly from the NAS via SSH:
cd /path/to/this/repo/home-assistant
docker compose up -dThe Compose File — What Each Setting Does and Why
services:
homeassistant:
image: ghcr.io/home-assistant/home-assistant:stable
container_name: homeassistant
hostname: homeassistant
security_opt:
- no-new-privileges:true
healthcheck:
test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8123/"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
network_mode: host
volumes:
- /volume1/docker/homeassistant/config:/config:rw
environment:
TZ: Asia/Jerusalem
restart: unless-stoppednetwork_mode: host
Home Assistant uses mDNS and Zeroconf to auto-discover devices (smart bulbs, Chromecasts, Apple TV, etc.) on your local network. These protocols do not cross Docker's default bridge network. Host networking is the correct and supported solution, not a workaround.
restart: unless-stopped
The container restarts automatically after the NAS reboots or if the process crashes — but it stays stopped if you deliberately stop it. Using always instead would restart the container even after an intentional docker stop, which is the wrong behaviour.
TZ: Asia/Jerusalem
Setting the timezone via an environment variable is portable across all NAS platforms. The older pattern of bind-mounting /etc/localtime from the host can break on non-Synology systems or when DST changes are handled differently by the host OS.
security_opt: no-new-privileges:true
Prevents any process inside the container from gaining more privileges through setuid/setgid binaries. Correct default for any container that doesn't explicitly need privilege escalation.
No privileged: true
The original tutorial enables privileged: true unconditionally. This grants the container full root access to the host kernel — effectively the same as running without any container isolation. Home Assistant does not need this for normal operation. If you have a USB Zigbee or Z-Wave stick, use a devices: entry (commented out in the compose file) to expose only that specific device.
Step 3: Access Home Assistant
Once the container is running and the healthcheck passes:
http://<NAS-IP>:8123Follow the onboarding flow to create your owner account, set your location, and connect your first devices.
Recovery
Because your config lives at /volume1/docker/homeassistant/config and your compose definition is committed here in Git, recovery after a disk swap or NAS replacement is:
# On the new NAS, after restoring /volume1/docker/homeassistant/config from backup:
git clone <this-repo>
cd Nas-Config/home-assistant
docker compose up -dThat's it. All automations, device pairings, and integrations are in the config directory. Nothing is stored inside the container.
Adding a Zigbee/Z-Wave USB Stick
Uncomment and adjust the devices block in docker-compose.yaml:
devices:
- /dev/ttyUSB0:/dev/ttyUSB0To find the correct device path on your Synology:
ls /dev/tty*Plug the stick in, run the command again, and the new entry is your device. No privileged: true required.
Using a Reverse Proxy (Caddy, Nginx, etc.)
If you access Home Assistant via a reverse proxy (e.g. Caddy routing homeassistant.yourdomain.com to localhost:8123), Home Assistant will reject the requests by default. There is no environment variable to override this — it must be configured in configuration.yaml.
Add the following to /volume1/docker/homeassistant/config/configuration.yaml:
http:
use_x_forwarded_for: true
trusted_proxies:
- 127.0.0.1use_x_forwarded_for: true
Tells Home Assistant to read the real client IP from the X-Forwarded-For header set by the proxy, rather than treating all requests as coming from the proxy itself.
trusted_proxies
The list of IPs Home Assistant will accept proxy headers from. Since Caddy runs on the same host with network_mode: host, 127.0.0.1 is sufficient. If your reverse proxy runs in a Docker bridge network instead, also add its subnet (e.g. 172.17.0.0/16).
After saving, restart the container:
docker restart homeassistant