Skip to main content
  1. Posts/

·4 mins

yaml #

title: “How to Build a ‘Poop Tracker’: The Ultimate Self-Hosted Health Dashboard” date: 2026-07-25T00:51:38+08:00 draft: false tags: [“selfhosted”, “vps”, “linux”, “technology”] summary: “Inspired by a viral r/selfhosted post about tracking toilet habits, learn how to build your own private health dashboard using Docker, Grafana, and custom API endpoints.” #


## The Community Spark: Taking Self-Hosting to the Bathroom

A recent viral post on Reddit's `r/selfhosted` community titled, *"I got tired of having to go the toilet - so I built an app to do it,"* took the community by storm. While the title was tongue-in-cheek, the underlying premise was deadly serious: the modern self-hoster wanted a frictionless way to track digestive health metrics. 

Why rely on cloud-connected health apps that harvest your data when you can spin up a local Docker container? The community rallied around the concept of a highly private, self-hosted "bathroom tracker." 

## Synthesized Community Perspectives

The Reddit thread generated intense debate, splitting users into two distinct camps:

### The "Dashboard-Driven" Camp
The loudest consensus was that tracking bodily functions isn't just a joke—it's practical health data. Users noted that conditions like IBS, Crohn’s, or dietary intolerances require meticulous tracking. Cloud apps lack privacy, so self-hosting is the only logical path. The community agreed that a simple web form accessible via a smartphone, combined with a time-series database, is the "holy grail" of personal health tracking.

### The Automation Advocates
A fascinating sub-debate emerged around *how* to log the data. Purists argued for manual entry, but automation enthusiasts proposed using cheap passive sensors. Ideas included toilet seat pressure switches connected to ESP32 microcontrollers, or even leveraging OpenCV to estimate time spent. The community ultimately agreed that while automated sensors are cooler, manual entry offers richer dietary correlation data.

## Deep-Dive Actionable Guide: Building Your Self-Hosted Tracker

To turn this viral concept into reality, you need a lightweight, privacy-respecting stack. Here is a step-by-step guide to deploying a self-hosted toilet tracker using **Docker**, **InfluxDB**, and **Grafana**.

### Step 1: Deploy the Docker Stack
Create a `docker-compose.yml` file to spin up your time-series database and visualization dashboard.

```yaml
version: '3.8'
services:
  influxdb:
    image: influxdb:2.7
    ports: ["8086:8086"]
    volumes: ["./influxdb_data:/var/lib/influxdb2"]
    environment:
      - DOCKER_INFLUXDB_INIT_MODE=setup
      - DOCKER_INFLUXDB_INIT_USERNAME=admin
      - DOCKER_INFLUXDB_INIT_PASSWORD=supersecretpass
      - DOCKER_INFLUXDB_INIT_BUCKET=bathroom

  grafana:
    image: grafana/grafana:latest
    ports: ["3000:3000"]
    volumes: ["./grafana_data:/var/lib/grafana"]
    depends_on: [influxdb]

Run docker-compose up -d to initialize your stack.

Step 2: Create the Ingestion Endpoint #

You don’t need a complex Node.js backend. Use a simple Python script acting as a webhook receiver to ingest data into InfluxDB.

from flask import Flask, request
from influxdb_client import InfluxDBClient, Point
from influxdb_client.client.write_api import SYNCHRONOUS

app = Flask(__name__)
client = InfluxDBClient(url="http://localhost:8086", token="YOUR_TOKEN", org="admin")
write_api = client.write_api(write_options=SYNCHRONOUS)

@app.route('/log', methods=['POST'])
def log_event():
    data = request.json
    point = Point("bathroom_visit").tag("type", data.get("type", "solid")) \
        .field("duration", data.get("duration", 1)) \
        .field("comfort", data.get("comfort", 5))
    write_api.write(bucket="bathroom", record=point)
    return {"status": "success"}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Use an app like HTTP Shortcuts on Android or Apple Shortcuts on iOS to send POST requests with your custom payload directly to this Flask server.

Pros & Cons: Manual vs. Automated Tracking #

FeatureManual Entry (Webhook/Forms)Automation (ESP32/Sensors)
Privacy100% local100% local
Data GranularityHigh (Diet notes, comfort levels)Low (Duration only)
WAF (Wife/Partner Factor)LowHigh (Requires hardware tinkering)
Implementation TimeQuick (Under 1 hour)Slow (Requires soldering/coding)

The consensus? Use manual entry. The minimal friction of pressing a button on your phone is worth the rich contextual data (e.g., rating discomfort from 1-10) that a pressure sensor simply cannot capture.

The Verdict / Expert Advice #

Building a self-hosted “poop tracker” is the ultimate rite of passage for the modern homelabber. It answers a genuine health need while ensuring sensitive, biological data never leaves your local network.

Recommendations by User Persona:

  • For the Tinkerer: Start with the Docker Compose stack above. It takes minimal effort and provides immediate visual feedback in Grafana.
  • For the Developer: Fork the Flask API and build a lightweight PWA (Progressive Web App) so you have a native-feeling icon on your phone’s home screen.
  • For the Privacy Maximalist: Ensure your Docker stack is not exposed to the internet. Use WireGuard or Tailscale to securely send updates to your homelab while on vacation or out of the house.

Frequently Asked Questions (FAQ) #

Is it safe to self-host health data? #

Yes, provided you configure it correctly. By keeping services behind your home firewall and avoiding port forwarding, your data remains strictly local.

Do I need a powerful server to run this? #

No. The combined InfluxDB and Grafana stack consumes less than 200MB of RAM, making it perfect for a Raspberry Pi Zero.

Can I use this setup to track other health metrics? #

Absolutely. You can modify the Flask script to ingest mood ratings, water intake, or workout durations into separate InfluxDB measurements.

How can I trigger the webhook easily from my phone? #

On iOS, use the native “Shortcuts” app to create a button that sends a POST request. On Android, HTTPS Shortcuts is highly recommended by the self-hosted community.