Raspberry Pi Zero W Home IoT Server: Build a Headless Sensor Dashboard (Part 1)
Flash a microSD card and turn a Raspberry Pi Zero W v1.3 into a headless home IoT server. This build covers Raspberry Pi OS Lite, Wi-Fi and SSH setup, DHT11 wiring, Linux IIO, a lightweight Python metrics API, and a responsive dashboard.
Live demo: Raspberry Pi Zero W dashboard. This is a hands-on build log from a Raspberry Pi Zero W v1.3, not a claim that every Pi setup behaves identically.
What you will build. A headless Raspberry Pi home IoT server that reads a DHT11 sensor, reports basic Pi health, and serves a responsive dashboard over your local network. The design keeps the sensor API on loopback and uses Caddy to serve the website.Why turn a Pi Zero W into an IoT hub?
A Pi Zero W is a useful always-on Linux host for a small home automation project: it can collect readings, run a local MQTT broker, and serve a website without needing a monitor. Its limits matter too. It has modest memory and CPU, so I use it for lightweight services and a handful of devices rather than a large database, heavy containers, or high-rate data processing.
This is Part 1 of a two-part Raspberry Pi IoT series. Here we get the hardware, sensor, and dashboard working locally. Part 2 covers remote HTTPS access, dynamic DNS, page-view counts, a guestbook, and the next steps toward an embedded-device hub.
Parts and tools
- Raspberry Pi Zero W v1.3 with microSD card and a stable power supply
- Raspberry Pi OS Lite (32-bit), configured for Wi-Fi and SSH during imaging
- DHT11 sensor, jumper wires, and a 6.9 kΩ pull-up resistor between DATA and 3.3 V
- Windows, macOS, or Linux computer with an SSH client
Flash Raspberry Pi OS Lite to the microSD card
Start with a blank microSD card and a computer with an SD card reader. Flashing erases the selected card, so copy off any files you need first. Install Raspberry Pi Imager from the official Raspberry Pi software page, insert the card, and launch Imager.
- Choose Raspberry Pi Zero W as the device if Imager asks you to select a model.
- Choose Raspberry Pi OS Lite (32-bit). The Lite image has no desktop environment, which suits a headless server and conserves storage and memory.
- Select the microSD card carefully as the storage target. Double-check its size and drive before writing; the selected card will be erased.
- Open the OS customisation settings before writing. Set a hostname, create the Linux username and a strong password, configure the Wi-Fi network name and password, and select the correct wireless country and time zone.
- Enable SSH in the same settings. For a first setup, password authentication is straightforward; SSH keys are preferable once you have confirmed you can connect.
- Review the settings, write the image, wait for verification to finish, then safely eject the card.
Insert the card into the Pi Zero W and power it up. Give the first boot a few minutes. From a computer on the same Wi-Fi network, connect using the hostname you configured, for example ssh your-user@your-hostname.local. If local name discovery does not work on your computer, check the router's connected-device list for the Pi's address and SSH to that IPv4 or IPv6 address instead. Confirm SSH works on the home network before moving on to sensors or remote access.
Imager labels can change between releases, but the key choices remain the same: the correct Pi model, a 32-bit Lite image, Wi-Fi credentials, a known user, and SSH enabled. Raspberry Pi's official headless setup guide describes this pre-configuration workflow.
Keep the services simple
Browser on home network
│ HTTPS / HTTP
▼
Caddy: static site + same-origin API routes
├── /api/metrics → Python service on 127.0.0.1:8765
└── website files under /var/www/home-pi
│
└── Linux IIO → DHT11 on BCM GPIO17
ESP8266 / ESP32 nodes ── local MQTT ──► future sensor integrationsThe Python process listens only on 127.0.0.1. The browser talks to Caddy, and Caddy proxies the metrics path to Python. This keeps a development API port from becoming another public internet service. Caddy's documentation describes the static file and reverse-proxy building blocks used here.
Wire the DHT11 carefully
On this Pi, I used physical pin 1 for 3.3 V, physical pin 11 for BCM GPIO17 data, and physical pin 6 for ground. The 6.9 kΩ resistor pulls DATA up to 3.3 V. Physical pin numbers and BCM GPIO numbers are different: physical pin 11 is BCM GPIO17. Physical pin 9 is ground; GPIO9 is a signal pin.
Pi physical pin 1 (3.3 V) ───────── DHT11 VCC
Pi physical pin 11 (BCM GPIO17) ─── DHT11 DATA
│
6.9 kΩ
│
Pi physical pin 1 (3.3 V) ─────────┘
Pi physical pin 6 (GND) ─────────── DHT11 GNDElectrical note: Power down before moving wires. Raspberry Pi GPIO is 3.3 V logic. Do not send a 5 V data signal into a GPIO pin. Check supply voltage between a known 3.3 V pin and a known ground pin before troubleshooting software.
Why I switched from Python bit-banging to the Linux driver
My first attempt used the Adafruit CircuitPython DHT library. The sensor read successfully from an ESP12F, but on the Pi the Python library repeatedly reported “A full buffer was not returned.” A DHT sensor encodes data in narrow pulse timings; Linux scheduling can interrupt a userspace timing loop. A working ESP test proved that the sensor could respond, but it did not prove the Pi wiring or timing was sound.
The Trixie kernel on my Pi included the Linux DHT11 IIO driver and Raspberry Pi OS included the dht11 device-tree overlay. I enabled it for BCM GPIO17 in /boot/firmware/config.txt:
[all]
dtoverlay=dht11,gpiopin=17After reboot, I found the IIO device under /sys/bus/iio/devices. Readings were exposed as milli-units; for example, 27800 represented 27.8 °C and 44600 represented 44.6% relative humidity. Some reads still timed out, so the dashboard reports sensor errors instead of pretending a failed sample is current data.
ls -la /sys/bus/iio/devices
cat /sys/bus/iio/devices/iio:device0/name
cat /sys/bus/iio/devices/iio:device0/in_temp_input
cat /sys/bus/iio/devices/iio:device0/in_humidityrelative_inputDevice numbering can differ. Identify the device by its name before hard-coding a path in an application. The kernel driver is useful for DHT11/DHT22-compatible sensors, but it does not make a low-cost DHT11 a laboratory instrument. Place it away from direct sun, heaters, and airflow from the Pi, and treat occasional invalid samples as normal.
Build the dashboard without a heavy runtime
A small Python service returns JSON for temperature, humidity, CPU load, CPU temperature, memory, disk use, operating-system details, and uptime. A background worker samples the sensor slowly; the website polls the local API and displays connection status. The frontend uses static HTML and a compiled stylesheet, so the Pi does not need to run a JavaScript build tool in production.
This pattern is reusable: use the Pi for local collection and presentation, and use microcontrollers for distributed sensing. The Pi Zero W has no built-in analog-to-digital converter, so an analog soil-moisture or light sensor needs an external ADC or a microcontroller such as an ESP8266/ESP32 to read it and publish the result.
Useful projects to build next
- Room climate logger: add a better calibrated temperature/humidity sensor and store periodic readings.
- Plant monitor: let an ESP32 read soil moisture and publish measurements to the Pi over MQTT.
- Network heartbeat board: show whether ESP devices are online and when they last reported.
- Workshop monitor: track temperature, humidity, and door state, then show trends and alert on thresholds.
- Energy awareness: display readings from a certified, isolated energy monitor; do not connect mains voltage directly to Pi GPIO.
For each project, begin with read-only telemetry. Verify sensor units, timestamps, lost Wi-Fi behavior, and recovery after a reboot before adding alerts or controls.
What this first build taught me
- Test each layer separately: wiring, kernel device, Python/API, Caddy route, and browser.
- On a Linux Pi, a kernel sensor driver can be more reliable than tight userspace pulse timing.
- Keep small services on loopback and expose one deliberate web entry point.
- A dashboard should label stale or missing sensor data clearly.
Continue: Part 2: Make the Raspberry Pi dashboard reachable over HTTPS and add community features.
Comments (0)
Sign in or create an account to leave a comment.
No comments yet.