Architecture: palinks

arch-palinks Architecture

architecture active palinks

Diagram

Components

Component Purpose Notes
Rails 8.1 app Link-in-bio dashboard — CRUD, favorites, drag-and-drop, click tracking, filter tabs Puma on port 3000, Tailscale funnel terminates TLS
PostgreSQL (CNPG) Primary database CloudNativePG operator on k3s, auto-migrations on deploy
k3s + kustomize Container orchestration and deployment Deployment parity with landscaping-assistant
Woodpecker CI Build, push to Harbor Triggered on push to main
Harbor registry Container image storage Images pushed by Woodpecker, pulled by k3s
Hetzner edge node Reverse proxy for custom domain (palinks.app) 178.156.129.142, Caddy auto-TLS, Tailscale mesh to k3s
palinks-ios Turbo Native iOS shell HotwireNative + Fastlane, TestFlight/App Store distribution

Key Decisions

  • Rails 8.1 — server-rendered app, Puma on port 3000, no reverse proxy inside cluster (Tailscale funnel terminates TLS)
  • Custom domain live — palinks.app routes through Hetzner edge (Caddy + Tailscale mesh), DNS A records at GoDaddy
  • iOS via Turbo Native — WKWebView wraps the Rails app, ~40 lines of Swift, most updates are web-only
  • No Keycloak auth today — auth/roles/visibility designed (spikes done) but deferred until after App Store launch
  • CNPG for PostgreSQL — operator-managed database on k3s, consistent with other platform apps
  • JSONB metadata — escape hatch for fast iteration; promote to columns when patterns stabilize
  • Deployment parity — auto-migrations, secrets-based config match landscaping-assistant patterns

Current Access

Method URL Status
Custom domain palinks.app Active — primary access
Tailscale hostname palinks.tail5b443a.ts.net Active — secondary/internal access
Dev tunnel dev-tunnel-palinks.tail5b443a.ts.net Active — local docker-compose dev
  • project-palinks — project page
  • arch-godaddy-tofu — DNS provider architecture
  • Canonical repo docs at docs/architecture.md — diagrams and data model details
  • iOS docs at docs/ios.md — build, deploy, and config