infra/docs/plans/2026-07-04-drone-logbook-design.md
Viktor Barzin 50778d47d3 drone-logbook: new stack — self-hosted Open DroneLog at dronelog.viktorbarzin.me
Viktor asked to self-host the DJI flight-log analyzer for his DJI Mini 4 Pro
(his fork ViktorBarzin/drone-logbook -> upstream arpanghosh8453/open-dronelog).
Upstream ghcr image with Keel auto-upgrade, DuckDB data on an encrypted
proxmox-lvm PVC (GPS traces = sensitive), NFS /sync-logs drop folder imported
every 8h, daily backup CronJob to /srv/nfs/drone-logbook-backup (vaultwarden
pattern), Authentik-gated ingress, PROFILE_CREATION_PASS from Vault via ESO.
Design + plan in docs/plans/; service-catalog updated.
2026-07-04 08:42:53 +00:00

5.8 KiB

Drone Logbook (Open DroneLog) — Design

Date: 2026-07-04 Status: Approved (Viktor, 2026-07-04) Owner request: "I have a DJI Mini 4 Pro. I'm interested in github.com/ViktorBarzin/drone-logbook" → self-host it in the cluster.

Goal

Self-host Open DroneLog (upstream of the ViktorBarzin/drone-logbook fork) at https://dronelog.viktorbarzin.me so Viktor can import DJI Fly flight logs from his DJI Mini 4 Pro and analyze them privately: telemetry charts, 3D map replay, per-flight and lifetime stats. All data stays in the cluster (single DuckDB database).

Decisions (interview, 2026-07-04)

Question Decision
Deployment form Self-hosted Docker web app in k8s (not desktop app, not hosted webapp)
Exposure Public dronelog.viktorbarzin.me, Authentik forward-auth (auth = "required")
Log ingestion Both manual web upload and a server-side auto-import drop folder from day one
Image source Upstream ghcr.io/arpanghosh8453/open-dronelog:latest — NOT the fork
Fork disposition Fork is 0 ahead / 372 behind, adds nothing; delete or park it. Only revive (sync + ADR-0002 GHA build) if Viktor starts modifying the code

Architecture

New Tier-1 stack stacks/drone-logbook/, modeled line-by-line on stacks/freshrss/ (the closest existing shape: single upstream-image app, own data volume, Keel-updated):

  • Namespace drone-logbook, tier 4-aux, label keel.sh/enrolled=true → Kyverno injects Keel poll annotations → auto-upgrades as upstream releases (project is actively maintained).
  • Deployment (1 replica, Recreate — DuckDB is single-writer/embedded):
    • image ghcr.io/arpanghosh8453/open-dronelog:latest (nginx frontend + Axum REST backend, port 80)
    • memory request=limit 512Mi (DuckDB import/analytics spikes), cpu request 25m, no cpu limit
    • standard KYVERNO_LIFECYCLE_V1 / KEEL_IGNORE_IMAGE / KEEL_LIFECYCLE_V1 lifecycle ignores
  • App data /data/drone-logbook (DuckDB db, cached DJI decryption keys, uploaded originals): proxmox-lvm-encrypted block PVC drone-logbook-data-encrypted, 2Gi, topolvm autoresize → 10Gi ceiling. Encrypted class because flight logs are GPS traces of home/travel — sensitive data defaults to proxmox-lvm-encrypted per the storage decision rule (.claude/CLAUDE.md). Embedded DBs stay off NFS (same rationale documented in the freshrss stack: NFS only for static files).
  • Backup CronJob drone-logbook-backup (mandatory for every proxmox-lvm app): daily 01:30 file copy of the data volume → NFS /srv/nfs/drone-logbook-backup (dated dirs, 30-day retention, Pushgateway metrics), pod-affinity co-scheduled with the app pod (RWO volume). 01:30 sits outside the 00:00/08:00/16:00 sync-import windows so the DuckDB file is quiescent; retained upload originals make even a torn copy recoverable by re-import. nfs-mirror (02:00) ships it to sda → Synology offsite. Vaultwarden pattern.
  • Sync drop folder: static NFS volume (modules/kubernetes/nfs_volume) 192.168.1.127:/srv/nfs/drone-logbook/sync-logs, mounted read-only at /sync-logs; SYNC_LOGS_PATH=/sync-logs, SYNC_INTERVAL="0 0 */8 * * *" (every 8 h). Any producer (Nextcloud sync, scp, a future phone pipeline) drops .txt logs there; the app imports them automatically. KEEP_UPLOADED_FILES=true keeps re-importable originals in the PVC.
  • Ingress via ingress_factory: name = "dronelog", auth = "required" (Authentik forward-auth), dns_type = "proxied". External Uptime Kuma HTTPS monitor comes automatically with the ingress annotation. Homepage tile (group "Media & Entertainment", icon mdi-quadcopter).
  • Secrets: Vault KV secret/drone-logbook (profile_creation_pass) → ExternalSecret (vault-kv ClusterSecretStore) → k8s secret drone-logbook-secrets → env PROFILE_CREATION_PASS. Gates profile create/delete even for other Authentik-logged-in users. No plan-time secret reads needed (no data "kubernetes_secret"). No DJI_API_KEY — bundled default is fine at personal import volume; add later if rate-limited.

Operational notes

  • DJI egress dependency: importing a new log file requires the pod to reach DJI's servers once (flight-log decryption key fetch; keys are then cached in the data dir). Remember this when egress enforcement lands (Security wave 1, beads code-8ywc).
  • The web UI is desktop-first; mobile is functional but basic.
  • NFS host prerequisite: /srv/nfs/drone-logbook/sync-logs (root:www-data, 2775 — same shape as sibling dirs) and /srv/nfs/drone-logbook-backup created on 192.168.1.127 and recorded in secrets/nfs_directories.txt. /srv/nfs is exported whole-tree, so no /etc/exports (scripts/pve-nfs-exports) change.
  • Backup story = the daily app-level backup CronJob (above) + the host daily-backup LVM-snapshot leg + original log files retained both in the drop folder and in the data volume (KEEP_UPLOADED_FILES=true).

Alternatives considered

  • Build from the fork (ghcr.io/viktorbarzin/... via GHA, ADR-0002): rejected for now — fork has zero custom commits; a build chain adds maintenance for no benefit. Revisit if code changes are wanted.
  • auth = "app" + app profile passwords (would enable the opendronelog-sync native uploader from anywhere): rejected — a single app password guarding GPS traces of home/travel on the open internet is weaker than Authentik; the sync drop folder covers automated ingestion instead.
  • Internal-only (.lan + VPN): rejected — Authentik-gated public matches the rest of the homelab and works without VPN while traveling.
  • NFS for the DuckDB data: rejected — embedded-DB-on-NFS locking risk; freshrss precedent keeps app DB data on proxmox-lvm.

Implementation

See 2026-07-04-drone-logbook-plan.md.