One morning I woke up and my smart bulbs weren't working. Due to an internet outage, they couldn't connect to cloud services, and even simple home automations had stopped. This situation clearly demonstrated the significant risk of building my entire smart home infrastructure dependent on third-party cloud services. The need to set up a cloud-independent smart home system, running in my own home, under my own control, arose that day.
Home Assistant is an open-source platform that meets this need. It can integrate with hundreds of smart devices on the market, and best of all, it offers the ability to control most devices over the local network. In this post, I will explain step-by-step how you can install Home Assistant on your own server using Docker Compose and how to implement basic security measures. My goal is to enable you to take full control of your home automation.
Why I Set Up My Own Home Assistant Server: The Importance of Cloud Independence
There are many products and platforms in the smart home device market, but almost all of them rely on a manufacturer's cloud service. This dependency means that your devices become unusable if your internet connection drops or if the manufacturer discontinues its cloud service. For example, when the cloud service of a smart plug brand I used for a while was down for a few days, all timers and remote access in my home completely stopped. Such experiences are unacceptable for those who, like me, love to keep control of their systems.
By setting up my own Home Assistant server, I also took a significant step towards data privacy and security. I've always had doubts about which data goes to whose servers, how it's stored, and with whom it's shared. A Home Assistant running on my own server processes all device data locally, eliminating these concerns. Furthermore, it ensures that my home automations continue to work seamlessly even without an internet connection. This way, simple but critical automations, such as my coffee machine starting automatically in the morning or my lights turning on in the evening, continue to operate unaffected by external factors. This freedom and security that comes with managing my own infrastructure has always been a priority for me.
ℹ️ The Advantage of Local Control
Home Assistant's greatest strength is its ability to control many devices over the local network. This means your devices can operate without needing the internet or cloud services. For example, Zigbee or Z-Wave devices connect directly to Home Assistant via a gateway, receiving commands quickly and securely. This both shortens response times and prevents you from being affected by potential cloud outages.
Hardware Selection and First Steps for Home Assistant Installation
Many hardware options are available for running Home Assistant. I usually prefer an old PC or a single-board computer like a Raspberry Pi. Each has its own advantages and disadvantages. Raspberry Pis stand out for their low power consumption, while an old PC offers more processing power and storage. My preference is usually an old mini PC lying idle or a virtual machine (VM) on a server. This allows me to utilize existing hardware and offers the flexibility to easily increase resources when needed. For instance, I once ran Home Assistant on a Raspberry Pi 3, but as I added more integrations and automations over time, I started experiencing performance issues. Following that, I switched to an old Intel NUC for a more stable experience.
As for the operating system, my choice is always Linux. Although there's a Home Assistant Operating System (HAOS) option specifically optimized for Home Assistant, I prefer distributions like Ubuntu Server or Debian to maintain my general Linux experience and use the server for other purposes. This allows me to comfortably host Nginx, Redis, or other side products on the server. Before installation, ensure your server has a static IP address and is accessible on your network. Also, sufficient storage space and at least 2GB of RAM are good starting points for Home Assistant to run smoothly. The server I use has 8GB RAM and a 256GB SSD, which gives me plenty of space for both Home Assistant and other services.
⚠️ Storage Space and Performance
One of the important factors affecting Home Assistant's performance is the storage unit. Especially if you are recording a large number of devices and sensor data, SD cards can slow down or fail over time. If possible, using an SSD is a much better choice for both performance and data integrity. If you are using a Raspberry Pi, booting from a USB SSD will significantly improve performance.
Home Assistant Installation Steps with Docker Compose
One of the most practical ways to run Home Assistant on my own server is by using Docker Compose. This method simplifies dependency management and allows me to run different services in an isolated manner. First, you need to install Docker and Docker Compose on your server. On Linux, this is usually done with the following commands:
# Docker installation
sudo apt update
sudo apt install apt-transport-https ca-certificates curl software-properties-common -y
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io -y
# Add current user to docker group (restart may be required)
sudo usermod -aG docker $USER
# Docker Compose installation (check for the latest version)
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
After Docker and Docker Compose are installed, we need to create a docker-compose.yml file for Home Assistant. This file defines how the Home Assistant container will be launched, which ports it will use, and which folders will be mapped for persistent storage. I usually create a directory like /opt/homeassistant and place the docker-compose.yml file there.
# /opt/homeassistant/docker-compose.yml
version: '3'
services:
homeassistant:
container_name: homeassistant
image: "ghcr.io/home-assistant/home-assistant:stable"
volumes:
- ./config:/config
- /etc/localtime:/etc/localtime:ro
environment:
- TZ=Europe/Istanbul # Set your own timezone
restart: unless-stopped
privileged: true # May be needed for USB devices (Zigbee/Z-Wave dongle)
network_mode: host # For automatic discovery of devices on the network
ports:
- 8123:8123 # Default web interface port for Home Assistant
After saving this docker-compose.yml file, we can start Home Assistant by running the following command in the same directory:
cd /opt/homeassistant
docker-compose up -d
Using network_mode: host allows Home Assistant to discover devices on the network more easily. However, this means the container directly uses the host's network interface, which can pose some security risks. For a more isolated structure, you can map specific ports with the ports definition, but in this case, additional settings may be required for device discovery. privileged: true may be necessary, especially to make hardware like Zigbee or Z-Wave USB dongles accessible from within the container. Once these steps are completed, I can access Home Assistant's web interface via http://<server_ip_address>:8123.
Basic Configuration and Integrations: Introducing Smart Devices
Once Home Assistant has successfully started, you'll be prompted to create a user account on your first access. After completing this step, Home Assistant will guide you to automatically discover smart home devices. In my experience, devices like the Philips Hue bridge, some smart plugs on the network (e.g., Shelly brand), and Chromecast are usually detected automatically. For devices not automatically discovered, I need to add them manually by navigating to "Settings > Devices & Services > Add Integration." At this point, knowing the local network IP addresses of the devices makes my job much easier.
For example, to set up a Zigbee network, I use a USB dongle (like a Conbee II or Sonoff Zigbee 3.0 dongle). After plugging this dongle into my server and enabling the privileged: true setting in my docker-compose.yml file, I can pair my Zigbee devices by adding the "ZHA" (Zigbee Home Automation) or "Zigbee2MQTT" integration to Home Assistant. I usually prefer Zigbee2MQTT because it offers broader device support and more detailed control. After installation, the configuration.yaml file is like the brain of Home Assistant. In this file, I define sensors, automations, dashboard elements, and other advanced settings.
Here's a simple configuration.yaml example (usually found inside the config folder):
# /opt/homeassistant/config/configuration.yaml
homeassistant:
name: My Home
latitude: 38.68971
longitude: 27.84869
elevation: 100
unit_system: metric
time_zone: Europe/Istanbul
currency: TRY
# Example sensor definition (this is a template sensor)
sensor:
- platform: template
sensors:
evin_sicakligi:
friendly_name: "Average Home Temperature"
value_template: "{{ states('sensor.mutfak_sicakligi') | float + states('sensor.salon_sicakligi') | float / 2 }}"
unit_of_measurement: "°C"
# Example automation definition
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml
The !include directives allow me to split automations, scripts, and scenes into separate files to keep the configuration.yaml file more organized. This way, I can easily manage the file structure even in complex setups. I make sure to regularly check Home Assistant's logs (usually accessible with the docker logs homeassistant command) to ensure integrations and devices are working correctly.
Remote Access and Security: Nginx Reverse Proxy and Let's Encrypt
Accessing Home Assistant when I'm on my home network is easy, but when I want to access it from outside, I need to take some security and configuration steps. Direct port forwarding often carries security risks and is not recommended. Instead, I use an Nginx reverse proxy to both enhance security and encrypt traffic using free SSL certificates from Let's Encrypt. This method also allows me to publish other web services on the same server via a single IP address and different domain names.
First, you need to install Nginx on your server:
sudo apt install nginx -y
Next, I create an Nginx configuration file for Home Assistant. This file tells Nginx to forward requests coming to a specific domain name to port 8123, where Home Assistant is running.
# /etc/nginx/sites-available/homeassistant
server {
listen 80;
server_name your_domain.com; # Enter your domain name here
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name your_domain.com; # Enter your domain name here
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem; # Certbot will create this
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem; # Certbot will create this
include /etc/letsencrypt/options-ssl-nginx.conf;
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
location / {
proxy_pass http://localhost:8123; # The address where Home Assistant is running
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;
proxy_http_version 1.1;
proxy_buffering off;
proxy_read_timeout 900; # For long-lived connections
proxy_send_timeout 900; # For long-lived connections
# For WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
After saving this file to the sites-available folder, I create a symbolic link to the sites-enabled folder and restart Nginx:
sudo ln -s /etc/nginx/sites-available/homeassistant /etc/nginx/sites-enabled/
sudo nginx -t # Configuration check
sudo systemctl reload nginx
For SSL certificates, I use Let's Encrypt and Certbot. Certbot, with its Nginx integration, automates the certificate acquisition and renewal processes:
sudo snap install core
sudo snap refresh core
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
sudo certbot --nginx -d your_domain.com # Enter your domain name
After these steps, I need to forward ports 80 and 443 from my home modem/router settings to my Nginx server. I should configure these settings in the router's NAT or Port Forwarding section. Also, I don't forget to add external_url and internal_url settings to Home Assistant's configuration.yaml file:
homeassistant:
# ... other settings ...
external_url: "https://your_domain.com"
internal_url: "http://192.168.1.100:8123" # Enter your local IP address
As additional security measures, I can add basic rate limiting settings to Nginx and run fail2ban on my server to monitor SSH and web login attempts. This provides an extra layer of protection against brute-force attacks. Using a strong password and two-factor authentication (2FA) is also essential for the security of my Home Assistant account.
Backup and Maintenance Strategies: Preventing Data Loss
As with any system, regularly backing up your Home Assistant installation is critically important. Having a rollback point, especially when adding new integrations or making major configuration changes, saves me from a lot of trouble in case of potential issues. My backup strategy usually consists of two main parts: Home Assistant's own backup tool and regular file backups performed at the server level.
Home Assistant offers a built-in backup (snapshot) feature for Supervised or OS installations. While this feature isn't directly accessible from the interface in a Docker Compose setup, regularly backing up the main configuration folder (/opt/homeassistant/config) is sufficient. This folder contains all your configuration files, your database (SQLite by default), and integration settings. I usually use a simple cron job to compress this folder with the tar command and then transfer it to another server or cloud storage using rsync.
Example backup script:
#!/bin/bash
BACKUP_DIR="/var/backups/homeassistant"
CONFIG_PATH="/opt/homeassistant/config"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="${BACKUP_DIR}/homeassistant_backup_${TIMESTAMP}.tar.gz"
mkdir -p "$BACKUP_DIR"
echo "Backing up Home Assistant configuration files..."
tar -czf "$BACKUP_FILE" -C "$CONFIG_PATH" .
if [ $? -eq 0 ]; then
echo "Backup completed successfully: $BACKUP_FILE"
# Clean up old backups (e.g., keep the last 7 backups)
find "$BACKUP_DIR" -type f -name "homeassistant_backup_*.tar.gz" -mtime +7 -delete
echo "Old backups cleaned."
else
echo "An error occurred during backup!"
fi
After saving this script as /usr/local/bin/backup_ha.sh and making it executable with chmod +x, I can schedule it to run weekly or daily using crontab -e:
0 3 * * * /usr/local/bin/backup_ha.sh > /dev/null 2>&1
On the maintenance side, keeping Home Assistant and Docker images up to date is important. I regularly update Home Assistant to the latest version by running docker-compose pull and docker-compose up -d commands. Additionally, I keep the server's operating system updated with sudo apt update && sudo apt upgrade -y. This helps close security vulnerabilities and allows me to benefit from new features. Regularly checking logs with journalctl -u docker.service or docker logs homeassistant helps me detect potential problems early. Especially if I make a mistake with settings like cgroup limits or memory.high, journald gives me the first signal.
Conclusion: Becoming the Smart Owner of My Own Home
Setting up my smart home system on my own server, independent of the cloud, satisfied my curiosity for technology and brought the peace of mind that comes with having full control over my home automations. External factors like internet outages or the discontinuation of a manufacturer's cloud service no longer affect my home's smart functions. The privacy and security of my data are entirely under my control, which is one of the biggest gains for me.
Top comments (1)
❤️🔥