Tutorials

Uptime Kuma, PrivateBin and a Dashboard: Going Deeper

Chapter 17's extras set up properly: monitors that catch certificate expiry and a dead Pi-hole, PrivateBin behind HTTPS so its encryption works, and Homepage or Homarr as a front page for everything.

beginner ⏱ 60 min Be Your Own Cloud · Chapter 17 uptime-kumaprivatebinhomepagehomarr

Chapter 17 of Be Your Own Cloud adds three small services to close out Part 3. This page sets each one up in more detail, and builds out the dashboard the chapter leaves as optional — with two tested compose files, since the book doesn’t print one.

Uptime Kuma

Deploy it

mkdir -p /opt/stacks/uptime-kuma
cd /opt/stacks/uptime-kuma
File /opt/stacks/uptime-kuma/docker-compose.yml
services:
  uptime-kuma:
    image: louislam/uptime-kuma:2.5.5
    container_name: uptime-kuma
    restart: unless-stopped
    volumes:
      - ./data:/app/data
    ports:
      - '3001:3001'
Exactly as printed in Be Your Own Cloud, Chapter 17 , p. 75 · all of Chapter 17's code
docker compose up -d

Open http://192.168.1.50:3001, choose SQLite (Chapter 17 explains why), and create the admin account.

To give it a proper address, add a proxy host for status.home.yourdomain.com forwarding to 192.168.1.50, port 3001, with Websockets Support on — Uptime Kuma’s whole interface runs over a websocket, and without it the page loads and then sits there empty.

Monitors worth adding

Add New Monitor for each of these. Chapter 21 covers which ones matter most and adds the notifications.

  • Each service’s subdomain — type HTTP(s), URL https://vault.home.yourdomain.com and so on. Under Advanced, tick Certificate Expiry Notification: it warns you before a certificate lapses, not after.
  • Pi-hole answering — type DNS. Hostname vault.home.yourdomain.com, Resolver Server 192.168.1.50, port 53, record type A. This asks Pi-hole directly, so it fails if Pi-hole stops answering or loses your local records.
  • Things with no web page — type TCP Port, for example 192.168.1.50 port 53.

If subdomain monitors fail with “ENOTFOUND”

Uptime Kuma looks names up the way the server does, and the server doesn’t ask Pi-hole: Chapter 5’s netplan file gives it 192.168.1.1 and 1.1.1.1, and neither knows your *.home.yourdomain.com names. So an HTTP(s) monitor on https://vault.home.yourdomain.com can fail even when Vaultwarden is fine.

One fix is to send just this container’s lookups to Pi-hole. Add a dns: line to the uptime-kuma service in its compose file:

    dns:
      - 192.168.1.50

then docker compose up -d.

PrivateBin

Deploy it

mkdir -p /opt/stacks/privatebin
cd /opt/stacks/privatebin
File /opt/stacks/privatebin/docker-compose.yml
services:
  privatebin:
    image: privatebin/nginx-fpm-alpine:2.0.6
    container_name: privatebin
    restart: unless-stopped
    volumes:
      - ./data:/srv/data
    ports:
      - '8280:8080'
Exactly as printed in Be Your Own Cloud, Chapter 17 , p. 76 · all of Chapter 17's code

The folder has to belong to PrivateBin’s user before the first start, as Chapter 17 explains:

Run Terminal, in /opt/stacks/privatebin — before the first start
mkdir -p data
sudo chown 65534:82 data
Exactly as printed in Be Your Own Cloud, Chapter 17 , p. 76 · all of Chapter 17's code
docker compose up -d

Put it behind HTTPS — it needs it

PrivateBin encrypts each paste in your browser, and browsers only allow the encryption it uses on secure pages: HTTPS, or localhost. Open it as http://192.168.1.50:8280 from a laptop and it will refuse to create pastes. So give it a proxy host: paste.home.yourdomain.com → 192.168.1.50, port 8280, with your certificate and Force SSL on.

Using it well

When you create a paste, choose:

  • Expires — as short as the recipient needs. The default is a week.
  • Burn after reading — deleted the first time it’s opened. Good for passwords.
  • Password — optional, and sent separately from the link (a different app, or a phone call).

The part of the link after # is the decryption key. Browsers never send that part to the server, which is why even you, running the server, can’t read what’s stored.

A dashboard: Homepage or Homarr

Chapter 17 names both. They solve the same problem differently:

  • Homepage is configured with YAML files, fast, and read-only in the browser — you edit files to change it.
  • Homarr is configured by dragging things around in the browser, with its own accounts.

Pick one. Both compose files below follow the book’s conventions — their own folder, pinned versions, secrets in .env — and both were run in the test lab.

Homepage

Uses port 3000, which nothing else in the book’s port table uses.

mkdir -p /opt/stacks/homepage
cd /opt/stacks/homepage
services:
  homepage:
    image: ghcr.io/gethomepage/homepage:v2.4.0
    container_name: homepage
    restart: unless-stopped
    environment:
      # the addresses you'll open it on -- it refuses any other
      - HOMEPAGE_ALLOWED_HOSTS=dash.home.yourdomain.com,192.168.1.50:3000
    volumes:
      - ./config:/app/config
    ports:
      - '3000:3000'

HOMEPAGE_ALLOWED_HOSTS is required: Homepage answers only to the hostnames listed, and returns an error for anything else. In testing, a request for any other host got a 400. List the name you’ll use through the proxy, and the IP-and-port for direct access.

Start it, and it creates ./config with starter files. Your links go in config/services.yaml — create or replace it:

- Security:
    - Vaultwarden:
        href: https://vault.home.yourdomain.com
        description: Passwords
    - Pi-hole:
        href: http://192.168.1.50:8081/admin
        description: DNS and ad blocking

- Media:
    - Immich:
        href: https://immich.home.yourdomain.com
        description: Photos
    - Jellyfin:
        href: https://jellyfin.home.yourdomain.com
        description: Films and TV

Homepage picks up changes without a restart. The files in ./config are owned by root once the container creates them, so edit them with sudo.

Homarr

Uses port 7575.

mkdir -p /opt/stacks/homarr
cd /opt/stacks/homarr
echo "SECRET_ENCRYPTION_KEY=$(openssl rand -hex 32)" > .env
chmod 600 .env
services:
  homarr:
    image: ghcr.io/homarr-labs/homarr:v1.77.2
    container_name: homarr
    restart: unless-stopped
    environment:
      - SECRET_ENCRYPTION_KEY=${SECRET_ENCRYPTION_KEY}
    volumes:
      - ./appdata:/appdata
    ports:
      - '7575:7575'

The encryption key protects any passwords or API keys you later give Homarr for its widgets. Keep a copy in Vaultwarden: if .env is lost, Homarr can’t read what it stored.

docker compose up -d, open http://192.168.1.50:7575, and its first-run setup creates your admin account. Add apps and arrange the board from the browser.

Its own address

Either way, add a proxy host — dash.home.yourdomain.com → 192.168.1.50, port 3000 for Homepage or 7575 for Homarr, Websockets on — and set it as your browser’s home page.

Backups and updates

All three services keep everything in their folder under /opt/stacks, which Chapter 18 already backs up, and Chapter 19’s first restore drill uses PrivateBin on purpose. Update each by bumping its tag, after reading its release notes.

Official documentation

Stuck on a step? Get in touch.