kitestacks-homelab/homelab-mastery/architecture/services.md
kenpat 1e8319ee75 docs: comprehensive homelab-mastery rewrite with full build guides
Complete documentation suite for KiteStacks covering all 11 services across
2-host active-active architecture. Includes beginner track (with AI, 8 files)
and advanced track (without AI, 7 files) with time estimates, real troubleshooting
cases, and command-by-command explanations. Updates certifications roadmap to
reflect July 7 2026 A+ Core 2 exam goal.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-19 01:08:43 -05:00

12 KiB

KiteStacks — Complete Service Reference

Every service that runs in KiteStacks: what it does, where it lives, how to manage it, and what commands to use. This is the day-to-day operations reference.

Last Updated: 2026-06-19


Quick Reference — All Containers on monk

docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
Container Purpose Public URL
homepage Portal / main website www.kitestacks.com
authentik SSO identity provider auth.kitestacks.com
authentik-worker Authentik background jobs
authentik-ldap LDAP interface for Authentik
authentik-ldap-proxy LDAP proxy
forgejo Git platform gitforge.kitestacks.com
kite-openwebui AI chat ai.kitestacks.com
kite-litellm LLM proxy gateway
karakeep Bookmarks links.kitestacks.com
karakeep-chrome Headless browser for Karakeep
karakeep-meilisearch Search engine for Karakeep
kavita eBook reader kavita.kitestacks.com
grafana Monitoring dashboards grafana.kitestacks.com
uptime-kuma Status page status.kitestacks.com
bookstack Wiki / docs wiki.kitestacks.com
bookstack-db MariaDB for BookStack
osticket-app Help desk tasks.kitestacks.com
osticket-db MySQL for OSTicket
portainer Docker management UI portainer.kitestacks.com
cloudflared Tunnel connector
prometheus Metrics collector
node-exporter Host metrics exporter
blackbox-exporter HTTP probe monitor
kitestacks-metrics-api System stats API for portal
ntfy Push notifications
flux GitOps controller

Service Deep Dives

homepage — Portal

What it is: Custom-built static website served by nginx. Directory: ~/kitestacks-live/docker/kitestacks-portal/ Public files: ./public/index.html — edit this to change what the portal shows Config: ./nginx.conf — nginx routing rules

# Restart portal
cd ~/kitestacks-live/docker/kitestacks-portal
docker compose restart homepage

# Edit the portal
nano public/index.html

# View nginx logs
docker logs homepage -f

Ports: 3005:3000 (host:container). Cloudflare Tunnel uses container port 3000 directly.


authentik — SSO Identity Provider

What it is: Self-hosted OAuth2/OIDC identity provider. Handles all logins for every service. Directory: ~/kitestacks-live/docker/authentik/ Database: Shared PostgreSQL on kscloud1 at 100.123.x.x:5432, database authentik Redis: Shared Redis on kscloud1 at 100.123.x.x:6379

cd ~/kitestacks-live/docker/authentik

# Start all Authentik services
docker compose up -d

# Check health (wait for "healthy" before testing SSO)
docker inspect --format '{{.State.Health.Status}}' authentik
docker inspect --format '{{.State.Health.Status}}' authentik-worker

# Run a Django management command (admin tasks, user management)
docker exec authentik ak shell

# View logs
docker logs authentik -f
docker logs authentik-worker -f

SSO apps configured in Authentik:

  • Grafana, Forgejo, Kavita, Karakeep, Open WebUI, Portainer, BookStack

Key Authentik admin panel: https://auth.kitestacks.com/if/admin/

Important: OAuth2 code TTL is set to 10 minutes (increased from default 1 minute) to allow monk's Authentik to finish starting up after a reconnect before codes expire.


forgejo — Git Platform

What it is: Self-hosted Git. Stores all homelab code, configs, and documentation. Directory: ~/kitestacks-live/docker/forgejo/ Database: Shared PostgreSQL on kscloud1, database forgejo, user forgejo Data volume: ./data/ (repositories, avatars, attachments)

cd ~/kitestacks-live/docker/forgejo

# Start
docker compose up -d

# Admin commands
docker exec -u git forgejo forgejo admin user list
docker exec -u git forgejo forgejo admin user create --username newuser --password pass --email e@mail.com --admin

# View logs
docker logs forgejo -f

# API token for automation
# Token: stored in .env — used by kitestacks-metrics-api for activity feed

API base URL: https://gitforge.kitestacks.com/api/v1/ Local access (via Cloudflare): gitforge.kitestacks.com


kite-openwebui — AI Chat

What it is: Self-hosted ChatGPT-like interface connected to LiteLLM proxy. Directory: ~/kitestacks-live/docker/kite-openwebui/ Backend: kite-litellm — routes to OpenRouter (many models, free tier available)

cd ~/kitestacks-live/docker/kite-openwebui
docker compose up -d
docker logs kite-openwebui -f
docker logs kite-litellm -f

SSO: Authentik OIDC — "Sign in with Authentik" on login page.


karakeep — Bookmarks

What it is: Bookmark manager and read-it-later tool. Saves full page content. Directory: ~/kitestacks-live/docker/karakeep/ Depends on: karakeep-chrome (headless Chromium for page capture) + karakeep-meilisearch (search)

cd ~/kitestacks-live/docker/karakeep
docker compose up -d

# SSO callback URL: https://links.kitestacks.com/api/auth/callback/custom
# (NextAuth.js uses "custom" as the provider ID, not "authentik")

SSO: Authentik OAuth2 — redirect URI must be /api/auth/callback/custom (not /callback/authentik)


kavita — eBook Reader

What it is: eBook, manga, and comic library. Directory: ~/kitestacks-live/docker/kavita/ Book files: ./library/books/ — add books here, then scan library in Kavita UI Config/DB: ./config/kavita.db (SQLite)

cd ~/kitestacks-live/docker/kavita
docker compose up -d
docker logs kavita -f

# If you change OIDC settings, use the Kavita UI at kavita.kitestacks.com/settings
# Do NOT edit kavita.db directly for OIDC config — Kavita overwrites it on restart
# Use SSH port-forward to access kscloud1's Kavita directly if needed:
# ssh -L 5099:localhost:5000 kenpat@kscloud1-tailscale-ip
# Then visit http://localhost:5099

SSO: Authentik OIDC — Authority URL must end with trailing slash: https://auth.kitestacks.com/application/o/kavita/


grafana — Monitoring Dashboards

What it is: Visualizes metrics collected by Prometheus. Directory: ~/kitestacks-live/docker/grafana/ Provisioning: ./provisioning/ — auto-loads datasource (Prometheus) and dashboard (Node Exporter Full) Data: Named Docker volume grafana-data

cd ~/kitestacks-live/docker/grafana
docker compose up -d
docker logs grafana -f

Dashboards auto-loaded:

  • Node Exporter Full (id 1860) — CPU, RAM, disk, network for both monk and kscloud1
  • Switch between hosts using the "instance" variable at top of dashboard

SSO: Authentik OAuth2. Local admin login also works.


uptime-kuma — Status Page

What it is: Uptime monitoring with a public status page. Directory: ~/kitestacks-live/docker/uptime-kuma/ Database: Named Docker volume uptime-kuma (SQLite kuma.db) Status page slug: homelabhttps://status.kitestacks.com/status/homelab

cd ~/kitestacks-live/docker/uptime-kuma
docker compose up -d
docker logs uptime-kuma -f

# To push kuma.db to kscloud1 after changes (monk → kscloud1):
# See scripts/sync-kuma.sh (or follow the sqlite backup pattern)

Monitors configured: All 11 public services + kscloud1 ping + Monk ping + Samurai ping.

Conky widget: Reads kscloud1's Uptime Kuma directly via Tailscale IP at http://100.123.x.x:3001/api/status-page/homelab. This means the widget shows kscloud1's health, not monk's — which is what matters for production status.


bookstack — Wiki

What it is: Self-hosted documentation wiki with a clean UI. Directory: ~/kitestacks-live/docker/bookstack/ Database: MariaDB container bookstack-db Config: .env file (APP_URL, DB settings, OIDC config)

cd ~/kitestacks-live/docker/bookstack
docker compose up -d
docker logs bookstack -f

# BookStack API (used to push docs from Forgejo):
# Token created via: DB injection + bcrypt hash for API key
# Token ID/secret stored in .env

SSO: Authentik OIDC. Key config:

  • OIDC_ISSUER=https://auth.kitestacks.com/application/o/bookstack/
  • OIDC_ISSUER_DISCOVER=true
  • Cache dir must be writable: chown -R abc:users /config/www/framework/cache/

osticket-app — Help Desk

What it is: OSTicket help desk and ticketing system. Directory: ~/kitestacks-live/docker/osticket/ Database: MySQL container osticket-db URL: tasks.kitestacks.com (took over from OpenProject)

cd ~/kitestacks-live/docker/osticket
docker compose up -d
docker logs osticket-app -f

SMTP: Configured for smtp.gmail.com:587 using kitestacks.helpdesk@gmail.com. App password stored in ost_email table (smtp_auth_creds=1 for all email entries). Confirmed working: Email delivery verified 2026-06-19.


portainer — Docker Management

What it is: Web UI for managing Docker containers on both monk and kscloud1. Directory: ~/kitestacks-live/docker/portainer/ URL: portainer.kitestacks.com

cd ~/kitestacks-live/docker/portainer
docker compose up -d

SSO: Authentik OAuth2 (AuthenticationMethod=3). User kenpat7177@gmail.com pre-created as admin. Security: Authentik PolicyBinding restricts Portainer app to homelab-admin group only.


cloudflared — Tunnel Connector

What it is: Creates the outbound tunnel to Cloudflare. This is what makes all public services reachable without opening ports on the router. Directory: ~/kitestacks-live/docker/cloudflared/ Token: Read from .env file as TUNNEL_TOKEN (never hardcoded in docker-compose.yml)

cd ~/kitestacks-live/docker/cloudflared
docker compose up -d
docker logs cloudflared -f

# To rotate the token (runs on both monk and kscloud1):
# ~/kitestacks-homelab/scripts/rollout-cloudflared-token.sh '<new-token>'

Tunnel ID: 5e60ea8e-a543-49b6-bab5-325f39441e00 Account: Cloudflare dashboard → Zero Trust → Networks → Tunnels


prometheus + node-exporter — Metrics

What it is: Prometheus collects time-series metrics. node-exporter exposes host stats. Directory: ~/kitestacks-live/docker/prometheus/ Config: ./prometheus.yml — defines scrape targets

cd ~/kitestacks-live/docker/prometheus
docker compose up -d
docker logs prometheus -f

# Scrape targets configured:
# - node-exporter:9100 (monk, via Docker DNS)
# - 5.78.x.x:9100     (kscloud1, via public IP — node-exporter exposed on 0.0.0.0)

Common Operations

Restart a single service

cd ~/kitestacks-live/docker/<service-name>
docker compose restart <container-name>

View live logs

docker logs <container-name> -f
# -f = follow (live tail). Ctrl+C to stop.

Update a service to latest image

cd ~/kitestacks-live/docker/<service-name>
docker compose pull
docker compose up -d

Check all container health at once

docker ps --format "table {{.Names}}\t{{.Status}}"

Enter a container's shell

docker exec -it <container-name> bash
# or sh if bash isn't available:
docker exec -it <container-name> sh

Check disk and memory usage

docker system df        # Docker disk usage
free -h                 # RAM usage
df -h                   # Disk usage

Push a kuma.db update to kscloud1

# 1. Make changes to monk's Uptime Kuma (add monitors, etc.)
# 2. Backup monk's db:
docker run --rm -v uptime-kuma:/src:ro -v /tmp:/out python:3-alpine \
  python3 -c "import sqlite3; s=sqlite3.connect('/src/kuma.db'); b=sqlite3.connect('/out/kuma.db.push'); s.backup(b); b.close(); s.close()"
# 3. Transfer and restore on kscloud1:
gzip -c /tmp/kuma.db.push | ssh -i ~/.ssh/id_ed25519_kscloud1 kenpat@100.123.x.x \
  "gunzip > /home/kenpat/kuma.db.push"
# Then on kscloud1: stop uptime-kuma, restore via same sqlite.backup() pattern, restart