homelab-codex-ws/services/gokapi
Oskar Kapala fbf9e7501d feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu
Nextcloud zostaje prywatny (mesh/kapala.org); Gokapi to osobny publiczny
serwis do wysylania linkow do plikow na zewnatrz (Firefox Send alt).
owner_node=vps, storage lokalny dysk (nie S3), E2E encryption ON, port
53842 bindowany tylko na TAILSCALE_BIND_IP (hairpin NAT przez npm@VPS,
nigdy 0.0.0.0). Cutover checklist w README (DNS, wildcard *.okit.pl na
npm@VPS, setup wizard) — nie zdeployowane w tym commicie.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-09 17:29:28 +02:00
..
docker-compose.yml feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu 2026-07-09 17:29:28 +02:00
env.example feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu 2026-07-09 17:29:28 +02:00
healthcheck.sh feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu 2026-07-09 17:29:28 +02:00
README.md feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu 2026-07-09 17:29:28 +02:00
service.yaml feat(gokapi): config publicznego file-share na VPS (share.okit.pl, E2E, Tailscale-bind za npm@VPS, disk-protection) — do deployu 2026-07-09 17:29:28 +02:00

Gokapi (publiczne udostępnianie plików)

Lekki self-hosted "Firefox Send" alternative — link do jednego pliku, na zewnątrz, z limitem pobrań/czasu. Osobny serwis od Nextclouda, celowo.

Nextcloud Gokapi
Rola twierdza — prywatna, mesh/kapala.org publiczne dzielenie — okit.pl
Dostęp Tailscale/LAN only, zero public ingress publiczny internet, przez npm@VPS
Host PIHA VPS (Hetzner, publiczny)
Użycie sync telefon/desktop, KB source "wyślij komuś link do pliku"

Host: VPS (Hetzner, 135.181.153.108) — publiczny serwis na publicznym hoście, węzły domowe nietknięte. owner_node: vps.

Stack

Kontener Obraz Rola
gokapi f0rc3/gokapi:v2.2.4 cała aplikacja (Go binary + wbudowana baza SQLite), port 53842

Wersja przypięta na v2.2.4 (aktualny stable na 2026-07-09, zweryfikowane przez github.com/Forceu/Gokapi releases + tagi f0rc3/gokapi na Docker Hub). TODO PRZY DEPLOYU: potwierdzić, czy nie wyszła nowsza wersja, zanim docker compose up.

Storage — lokalny dysk VPS (nie S3)

Decyzja Oskara: bez S3, dysk lokalny VPS. VPS ma tylko 80 GB SSD dzielone z npm/outline/joplin/ai-cluster/fleet-prometheus — więc ograniczenia rozmiaru + brak globalnego domyślnego expiry to jedyna ochrona dysku:

  • GOKAPI_MAX_FILESIZE=5120 (5 GB/plik; upstream default to 100 GB — za dużo na ten dysk).
  • GOKAPI_MIN_FREE_SPACE=2048 (2 GB headroom zanim Gokapi odmówi uploadu; upstream default 400 MB, za mało przy dzielonym dysku).
  • Gokapi NIE MA globalnego domyślnego expiry/limitu pobrań — to wybór per-upload w formularzu web. Nie da się tego wymusić przez env var ani config. Praktyka: przy każdym uploadzie ustawiać rozsądne wartości (np. 7 dni / 10 pobrań), żeby wygasające linki faktycznie czyściły dysk.

Szyfrowanie E2E — WŁĄCZONE (decyzja Oskara)

Gokapi ma 3 poziomy szyfrowania (żaden / lokalny / end-to-end). Wybór robi się w kroku "Encryption" wizardu /setup przy pierwszym starcie — nie ma env vara. Level 3 (E2E) = plik szyfrowany w przeglądarce przed uploadem, serwer nigdy nie widzi treści w plaintext. Uwaga upstream: implementacja szyfrowania nie była niezależnie audytowana; Firefox ma problemy z pobieraniem zaszyfrowanych plików (znane ograniczenie, nie nasz bug).

Klucz szyfrowania trafia do config.json w /app/configto jest część, którą trzeba backupować, inaczej utrata configu = utrata dostępu do już zaszyfrowanych plików.

Sieć — bind tylko na Tailscale, nigdy 0.0.0.0

Port 53842 binduje się wyłącznie na Tailscale IP VPS-a (TAILSCALE_BIND_IP=100.95.58.48), nigdy na 0.0.0.0. Publiczny adres Hetznera (135.181.153.108) w ogóle nie widzi tego portu — jedyna droga na zewnątrz to npm@VPS (TLS na 443) → share.okit.pl. npm i gokapi żyją na tym samym hoście jako osobne stacki compose; npm dociera do gokapi przez Docker hairpin NAT po tym samym realnym interfejsie (ten sam trik co fleet-prometheus/nextcloud127.0.0.1 by tu NIE zadziałało). GOKAPI_TRUSTED_PROXIES=172.16.0.0/12 mówi Gokapi, żeby ufał X-Forwarded-For z tego zakresu (podsieć mostka Docker), bo źródłowy IP po hairpinie to brama bridge'a, nie prawdziwy klient.

Backup

  • /opt/homelab/data/gokapi/data — pliki użytkowników. Ulotne z założenia (linki wygasają), nie wymaga backupu.
  • /opt/homelab/data/gokapi/configconfig.json + klucz szyfrowania E2E. To backupować — utrata = utrata dostępu do configu (hasło admina, ustawienia) i do zaszyfrowanych plików, jeśli klucz trzymany lokalnie. Sugerowana retencja: dołączyć do tej samej pętli nocnej co inne configi na VPS (mały rozmiar, plik+SQLite).

Cutover checklist (przy deployu — NIE teraz, ten PR to tylko config)

  1. git pull na VPS.
  2. mkdir -p /opt/homelab/data/gokapi/{data,config} na VPS.
  3. cp services/gokapi/env.example services/gokapi/.env, potwierdzić TAILSCALE_BIND_IP (tailscale ip -4 na żywym hoście — powinno być 100.95.58.48).
  4. Cloudflare: rekord A share.okit.pl135.181.153.108, DNS only (szara chmurka, bez proxy Cloudflare — spójne z resztą wpisów okit.pl/kapala.org w tym repo).
  5. Wildcard *.okit.pl na npm@VPSNAJPIERW SPRAWDZIĆ, czy już istnieje. Kontekst: wildcard *.okit.pl DNS-01 jest już zrobiony na npm@PIHA (cert #51, ważny do 2026-10-05, token Cloudflare npm-dns01-all-zones — Zone:DNS:Edit, All zones). Sesja docs/sessions/2026-07-07-okit-wildcard.md zostawiła to jako TODO: "Drugi npm na VPS (outline/joplin/agents tam) — analogiczny wildcard *.okit.pl?" — to jest ten moment, żeby to sprawdzić/zrobić. Jeśli brak: npm@VPS → SSL → New Certificate → Let's Encrypt → domeny *.okit.pl + okit.pl → DNS Challenge → Cloudflare → wkleić token npm-dns01-all-zones (ten sam token co PIHA, All-zones więc obejmuje okit.pl). Pułapka z poprzedniej sesji: literówka .okit.pl zamiast okit.pl w drugim polu dawała Internal Error.
  6. vhost w npm@VPS: nowy Proxy Host, domena share.okit.pl, Forward Hostname/IP = 100.95.58.48 (Tailscale IP VPS, TAILSCALE_BIND_IP), port 53842, SSL = cert wildcard *.okit.pl z kroku 5, Force SSL + HTTP/2.
  7. docker compose -f services/gokapi/docker-compose.yml up -d.
  8. Otworzyć https://share.okit.pl/setup i przejść wizard:
    • Database: SQLite (domyślnie, wbudowane).
    • Webserver: potwierdzić public URL https://share.okit.pl.
    • Authentication: Username/Password, ustawić prawdziwe hasło admina (nie ma tu env vara — to jedyny moment, żeby to zrobić w UI).
    • Storage: Local (nie S3 — decyzja Oskara).
    • Encryption: Level 3 / End-to-End (decyzja Oskara — E2E ON).
  9. Przy każdym uploadzie: ustawiać rozsądny expiry/limit pobrań ręcznie (patrz sekcja Storage wyżej — brak globalnego defaultu w Gokapi).
  10. ./healthcheck.sh z hosta VPS, potem z zewnątrz: curl -I https://share.okit.pl/.

Rejestracja w repo (zrobione w tym PR)

  • hosts/vps/services.yaml — wpis gokapi.
  • inventory/topology.yamlgokapi w liście serwisów vps.