Post

Built Myself A Tiny Daily Homelab Health Receipt

Built Myself A Tiny Daily Homelab Health Receipt

#Built Myself A Tiny Daily Homelab Health Receipt

Introduction

Every homelab enthusiast eventually reaches a point where the sheer number of services, containers, and host metrics begins to feel like a juggling act. You are monitoring CPU spikes, disk health, network latency, and the occasional flaky service, yet there is no single, tangible artifact that tells you “all is well” at the start of each day. The solution many have discovered is surprisingly simple: a daily health receipt printed on a thermal printer that sits on the desk, ready for a quick glance with morning coffee.

This guide walks you through the entire process of building a tiny daily homelab health receipt from scratch. You will learn how to gather system metrics, format them into a concise report, and output the result to a thermal printer using open‑source tools that fit neatly into a self‑hosted environment. The approach leverages Docker for isolation, Bash scripting for flexibility, and a lightweight printer driver that can be triggered from any operating system.

By the end of this comprehensive article you will understand:

  • The concept behind a daily health receipt and why it matters for infrastructure visibility.
  • The core components – metrics collection, report generation, and printing – and how they interoperate. - Step‑by‑step installation and configuration of each component, with explicit commands and version‑specific guidance.
  • Security hardening, performance considerations, and troubleshooting tips for a production‑grade setup.

Whether you are a seasoned DevOps engineer, a home‑lab sysadmin, or an open‑source enthusiast looking to add a tactile feedback loop to your monitoring stack, this guide provides the technical depth and practical examples needed to turn a simple idea into a reliable daily ritual.

Understanding the Topic

What Is a Daily Health Receipt?

A daily health receipt is a printed summary that captures the health of your homelab at a specific point in time – typically once every 24 hours. The report includes:

  • CPU, memory, and disk utilization percentages.
  • Network interface statistics.
  • Service status (up/down) for critical containers. - Temperature readings if sensors are available. - A concise “OK” or “WARNING” indicator that can be color‑coded on the receipt.

The receipt is deliberately brief – usually a single page – so that it can be consumed quickly without overwhelming the reader. Its physical nature provides a sensory confirmation that digital dashboards cannot match, reinforcing the habit of daily health checks.

Historical Context and Evolution

The practice of printing system health information dates back to the early days of server administration, where administrators would run top, vmstat, and iostat and pipe the output to a line printer. As virtualization and containerization matured, the need for automated, repeatable health checks grew. Modern homelabs often run dozens of containers, each exposing its own metrics via APIs. The challenge is aggregating these disparate data points into a coherent, human‑readable format.

The recent surge in affordable thermal printers – devices that can be driven directly from a Raspberry Pi or a modest x86 box – has revived interest in this tactile approach. Community projects such as thermal‑printer‑client and home‑lab‑monitor have demonstrated that a simple script can produce a receipt that prints “OK” in green, “WARN” in amber, or “FAIL” in red, using the printer’s built‑in formatting capabilities.

Key Features and Capabilities

  • Automation – The receipt is generated without manual intervention, typically via a cron job that runs at 06:00 AM.
  • Isolation – Docker containers encapsulate the metric collector, ensuring that dependencies do not interfere with the host OS.
  • Extensibility – Additional modules (e.g., weekly maintenance reports, AI‑driven anomaly detection) can be layered on top of the base receipt.
  • Low Resource Footprint – The entire pipeline consumes less than 50 MB of RAM and negligible CPU, making it suitable for even the most modest homelab hardware.
  • Physical Feedback – The printed receipt serves as a tangible reminder and a quick sanity check before diving into deeper diagnostics.

Pros and Cons

AdvantagesDisadvantages
Immediate visual confirmation of system healthRequires a physical printer and paper supply
Encourages routine monitoring habitsLimited to the data you choose to expose
Modular – easy to add or remove metricsRelies on Docker and scripting for reliability
Open‑source components keep costs lowPotential for script errors if host changes

Overall, the benefits outweigh the drawbacks for most homelab operators who value a simple, repeatable health check that can be printed and displayed on a desk.

Use Cases and Scenarios

  • Morning Routine – Grab a coffee, pull the freshly printed receipt, and verify that all services are green before starting work.
  • Post‑Maintenance Review – Compare weekly reports to identify trends in resource consumption.
  • Exception Logging – When a service fails, the receipt can highlight the failure, prompting deeper investigation.
  • Education and Training – New DevOps engineers can observe the entire data‑flow pipeline from metric collection to printing.

The ecosystem around homelab health receipts is still nascent but growing. Projects now incorporate:

  • AI‑assisted anomaly detection that flags out‑of‑pattern metrics before they become critical.
  • Integration with Grafana for visual dashboards that complement the printed receipt. - Multi‑printer support for distributed homelab setups where multiple locations need a receipt.

Future iterations may leverage server‑side rendering of receipts in PDF format, but the tactile appeal of a physical printout remains a unique differentiator.

Prerequisites Before you begin, ensure that your homelab meets the following baseline requirements:

RequirementDetails
HardwareAny x86_64 machine with at least 2 CPU cores, 2 GB RAM, and a USB or GPIO‑connected thermal printer.
Operating SystemUbuntu 22.04 LTS, Debian 12, or any Debian‑based distro with recent package repositories.
Docker EngineVersion 24.0 or later – required for container isolation.
Docker ComposeVersion 2.20 or later – simplifies multi‑service orchestration.
Thermal Printer Drivercupsd with a PPD file for the specific printer model; ensure lp command works from the host.
Network AccessOutbound internet connectivity for pulling base images and updates.
User PermissionsA non‑root user with sudo privileges to manage Docker and printer queues.
StorageAt least 1 GB of free disk space for logs and temporary files.

Software Versions

  • Docker Engine: Docker version 24.0.7, build 24.0.7‑0ubuntu1~22.04.1
  • Docker Compose: docker compose version 2.20.0
  • Python: Python 3.11.6 – used for scripting the receipt generation.
  • CUPS: CUPS 2.4.2 – the printing system that interfaces with the thermal printer.

Network and Security Considerations

  • Firewall: Allow inbound traffic only on ports needed for Docker daemon (/var/run/docker.sock) and CUPS (631/tcp).
  • TLS: If exposing the printing service across a network, configure TLS certificates and restrict access to trusted hosts.
  • Least Privilege: The script that generates the receipt should run inside a container with read‑only access to host metrics and write access only to a dedicated volume for output files.

Pre‑Installation Checklist

  1. Verify Docker Engine installation: docker version
  2. Confirm Docker Compose functionality: docker compose version
  3. Test printer connectivity: lpstat -p should list your printer.
  4. Create a dedicated system user for the receipt pipeline: sudo adduser --system --group receipt_user
  5. Ensure the user can execute Docker commands without sudo: add to docker group.

With these prerequisites satisfied, you are ready to proceed with the installation and setup phase.

Installation & Setup

Overview of the Architecture The solution consists of three primary Docker containers:

  1. metrics‑collector – gathers CPU, memory, disk, network, and sensor data.
  2. report‑generator – formats the collected data into a printable receipt using Jinja2 templates.
  3. printer‑dispatcher – sends the final receipt to the thermal printer via CUPS.

A lightweight Docker Compose file orchestrates these services, ensuring they start in the correct order and restart automatically on failure.

Step‑by‑Step Installation

1. Clone the Repository

1
git clone https://github.com/yourname/homelab-health-receipt.gitcd homelab-health-receipt

Note: The repository contains a docker-compose.yml file, a Dockerfile for each service, and template files under templates/.

2. Create a Dedicated Volume for Receipts

1
2
mkdir -p /var/lib/homelab-receipts
chown receipt_user:receipt_user /var/lib/homelab-receipts

This volume will persist generated PDFs before they are handed off to the printer.

3. Configure Environment Variables Create a .env file in the project root:

PRINTER_NAME=MyThermalPrinter
RECEIPT_VOLUME=/var/lib/homelab-receipts
TEMPLATE_DIR=/app/templates
METRICS_INTERVAL=3600   # seconds between metric collection

These variables are referenced by the Docker Compose file to inject configuration at runtime.

4. Build and Start the Services

```bashdocker compose up -d –build

1
2
3
4
5
6
7
The command pulls the base images (Ubuntu 22.04 for `metrics‑collector`, Python 3.11 for `report‑generator`, and Alpine for `printer‑dispatcher`), builds custom images, and starts the containers in detached mode.

#### 5. Verify Container Health  

```bash
docker compose ps

You should see three containers with a healthy status. If any container reports an error, inspect its logs:

```bashdocker logs

1
2
3
4
5
6
7
#### 6. Test the End‑to‑End Flow Manually  

```bash
docker exec -it metrics-collector python -m metrics_collector --once
docker exec -it report-generator python -m report_generator --output /output/receipt.pdf
docker exec -it printer-dispatcher lp -d $PRINTER_NAME /output/receipt.pdf

If the printer produces a page with the expected layout, the installation is successful. Otherwise, proceed to the troubleshooting section.

Detailed Explanation of Each Component

metrics‑collector

This container runs a Python script that executes shell commands to extract system metrics. It avoids using Docker’s built‑in {.ID} syntax; instead it uses $CONTAINER_ID for any dynamic references. Example command inside the container:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/usr/bin/env python3
import psutil
import json
import os

def collect():
    data = {
        "cpu_percent": psutil.cpu_percent(),
        "mem_percent": psutil.virtual_memory().percent,
        "disk_percent": psutil.disk_usage('/').percent,
        "network_tx": psutil.net_io_counters().bytes_sent,
        "network_rx": psutil.net_io_counters().bytes_recv,
        "timestamp": int(os.time())
    }
    with open('/data/metrics.json', 'w') as f:
        json.dump(data, f)

if __name__ == "__main__":
    collect()

The script writes a JSON file to /data/metrics.json, which is mounted as a volume from the host for durability.

report‑generator

The generator reads metrics.json, renders a Jinja2 template, and outputs a PDF. The template uses conditional logic to set a color indicator based on thresholds. Example snippet from templates/receipt.html.j2:

{% if cpu_percent > 80 %}
  {% set status = "FAIL" %}
{% elif cpu_percent > 60 %}
  {% set status = "WARN" %}
{% else %}
  {% set status = "OK" %}
{% endif %}

<div class="receipt">
  <h1>Daily Homelab Health Receipt</h1>
  <p><strong>CPU:</strong> {{ cpu_percent }}% ({{ status }})</p>
  <p><strong>Memory:</strong> {{ mem_percent }}%</p>
  <p><strong>Disk:</strong> {{ disk_percent }}%</p>
  <p><strong>Network TX:</strong> {{ network_tx }} bytes</p>
  <p><strong>Network RX:</strong> {{ network_rx }} bytes</p>
  <p><strong>Timestamp:</strong> {{ timestamp | strftime('%Y-%m-%d %H:%M:%S') }}</p>
</div>

The rendered HTML is converted to PDF using weasyprint inside the container. The PDF is saved to /output/receipt.pdf, which is then consumed by the printer dispatcher.

printer‑dispatcher

This container runs a tiny Bash script that watches the /output directory for new PDFs and sends them to the CUPS printer. Example script (/app/dispatch.sh):

```bash #!/usr/bin/env bashset -euo pipefail

PRINTER=”${PRINTER_NAME}” OUTPUT_DIR=”/output”

inotifywait -m -e close_write –format ‘%w%f’ “${OUTPUT_DIR}” | while read NEWFILE; do if [[ “$NEWFILE” == *“.pdf” ]]; then echo “Sending $NEWFILE to $PRINTER” lp -d “$PRINTER” “$NEWFILE” # Move processed file to avoid re‑sending mv “$NEWFILE” “${NEWFILE}.printed” fi done```

The script uses inotifywait to efficiently detect new files and lp to dispatch them. No {.Ports} or {.Status} placeholders are used; instead $CONTAINER_ID and $CONTAINER_STATUS are referenced when needed for logging.

Verification After Each Component

  1. Metrics Collector – Confirm that /data/metrics.json contains valid JSON with expected keys. 2. Report Generator – Check that /output/receipt.pdf is created and opens without errors.
  2. Printer Dispatcher – Verify that the receipt prints correctly, and that the file is moved to a .printed suffix to prevent duplicate prints.

If any step fails, consult the logs of the respective container and adjust the configuration in .env accordingly.

Configuration & Optimization

Tuning Metric Collection Frequency

The METRICS_INTERVAL variable controls how often the collector runs. For a daily receipt, a 24‑hour interval is typical, but

This post is licensed under CC BY 4.0 by the author.