I built a NAS from spare parts — an MSI X99A Raider motherboard, a 6-core Intel Xeon CPU, 128 GB ECC DDR4 RAM, a 10G NIC, and an HBA card for the HDDs. The HDDs are configured in ZFS RAID-Z2, allowing the system to tolerate up to two simultaneous disk failures. The operating system is installed on two SSDs configured in RAID10 for redundancy.
Is it overkill for a homelab? Maybe. But I want to store my documents, family photos, and other personal data reliably, without relying on any cloud provider.
Why TrueNAS?
I think TrueNAS is an excellent choice. It offers an intuitive web interface, straightforward setup, and clear configuration options — making it ideal for homelab environments as well.
Recently, I purchased an APC UPS. While ZFS (RAID-Z2) provides strong data integrity and fault tolerance, it doesn’t protect against sudden power loss. I didn’t want to leave it to chance, so I integrated the UPS to ensure the NAS can gracefully shut down when the battery level is low.
To achieve this, I installed NUT (Network UPS Tools) on one of my Raspberry Pis, connecting the UPS via USB. The Raspberry Pi acts as the UPS server and communicates with the TrueNAS system over the network.
Configuring UPS Integration in TrueNAS
After setting up NUT on the Raspberry Pi, I logged into the TrueNAS admin interface and navigated to
System → Services → UPS (pencil icon) to configure the UPS client.
In the configuration form, I entered:
- An identifier for the UPS connection
- The IP address, port, and credentials for the NUT observer user
Once saved, I activated the UPS service and enabled auto-start.
This setup allows the NUT client on the TrueNAS server to monitor the UPS and automatically shut down the NAS when the UPS battery level becomes critically low.
Monitor UPS with Home Assistant
TrueNAS can run containerized applications using Docker Compose under the hood.
Some applications are available directly from the TrueNAS catalog (and only require minimal configuration), but you can also deploy custom “freestyle” applications, where you define everything manually.
If you install a catalog app but need more granular control, you can convert it to a freestyle application, giving you direct access to the underlying Docker Compose configuration.
Traefik
Because I already had multiple applications running on my TrueNAS system, I wanted to route their traffic based on hostnames rather than remembering port numbers. To achieve this, I installed Traefik as a reverse proxy using the following configuration:
networks:
proxy:
driver: bridge
external: true
services:
traefik:
command:
- '--api.insecure=true'
- '--providers.docker=true'
- '--providers.docker.network=proxy'
- '--entrypoints.web.address=:80'
environment:
TZ: Europe/Brussels
group_add:
- 568
hostname: proxy.homelab.arpa
image: docker.io/library/traefik:v3
networks:
- proxy
ports:
- mode: ingress
protocol: tcp
published: 8080
target: 80
- mode: ingress
protocol: tcp
published: 8088
target: 8080
- mode: ingress
protocol: tcp
published: 8443
target: 443
pull_policy: always
restart: always
volumes:
- type: bind
source: /run/docker.sock
target: /var/run/docker.sock
Before installation, I created the Docker bridge network for Traefik to communicate with other containers:
docker network create --driver=bridge proxy
I then attached the Traefik container to this network.
For simplicity, I’m currently running without TLS, so I enabled insecure API access and allowed Traefik’s Docker provider to automatically discover containers. The Docker socket is mounted as a bind volume, giving Traefik visibility into running containers.
Using pull_policy: always
ensures the container automatically updates to the latest Traefik v3 image on restart.
Home Assistant
Below is an excerpt from the Home Assistant Docker Compose configuration:
networks:
homeassistant:
driver: bridge
proxy:
driver: bridge
external: true
services:
home-assistant:
labels:
- traefik.enable=true
- traefik.http.routers.homeassistant.entrypoints=web
- traefik.http.routers.homeassistant.rule=Host(`homeassistant.homelab.arpa`)
- traefik.http.routers.homeassistant.service=homa-svc
- traefik.http.services.homa-svc.loadbalancer.server.port=30103
networks:
- proxy
- homeassistant
postgres:
...
networks:
- homeassistant
I installed Home Assistant from the TrueNAS catalog and then converted it to a custom app (via the three-dot menu → Convert to custom app). This allowed me to edit its Docker Compose configuration directly, as shown above.
I attached the proxy network so Traefik could route traffic to the container, and created an additional homeassistant network for internal communication with the PostgreSQL database. This separation keeps database traffic isolated from the proxy network.
Next, I added Traefik labels to enable routing based on hostname.
However, after setting everything up, accessing the Home Assistant dashboard returned an HTTP 400 (Bad Request) error. The fix was documented here:
Home Assistant (400 Bad Request) Docker + Proxy – Solution
To resolve the issue, I updated Home Assistant’s configuration file located at
/mnt/.ix-apps/app_mounts/home-assistant/config/configuration.yaml
:
http:
use_x_forwarded_for: true
trusted_proxies:
- <Subnet of the proxy Docker network, e.g. 172.27.0.0/24 or Traefik’s IP>
After restarting the Home Assistant service, the dashboard loaded correctly.
Monitoring
With everything connected, I created a Home Assistant card to display the UPS status.
Here’s the YAML configuration for the dashboard card:
type: vertical-stack
title: Server Room Rack UPS
cards:
- type: history-graph
entities:
- name: Status
entity: sensor.rack_ups_1_status
hours_to_show: 4
- type: horizontal-stack
cards:
- type: gauge
entity: sensor.rack_ups_1_load
name: UPS Load
severity:
green: 0
yellow: 70
red: 90
- type: gauge
entity: sensor.rack_ups_1_battery_charge
name: Battery Charge
severity:
green: 50
yellow: 20
red: 0
This dashboard displays the UPS status (e.g., on battery, charging, etc.), current battery level, and load percentage in real time.
Summary:
This setup provides a robust and self-contained NAS system with:
- Fault-tolerant ZFS RAID-Z2 storage
- Power-loss protection through UPS integration
- Automated monitoring and alerting via Home Assistant
- Flexible hostname-based routing through Traefik
It’s a powerful, reliable homelab configuration — and best of all, it’s completely under my control.
Top comments (0)