feat(kb): SPLIT gokapi -> service + decision + runbook
kb/services/gokapi.md (Stack, Backup, Rejestracja w repo) kb/decisions/gokapi-storage-e2e-siec.md (storage lokalny zamiast S3, szyfrowanie E2E, bind tylko na Tailscale) kb/runbooks/gokapi-cutover.md (cutover checklist) Tresc sekcji nietknieta; kontrola multizbioru linii == oryginal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
0a8a668b05
commit
d2401ef566
54
kb/decisions/gokapi-storage-e2e-siec.md
Normal file
54
kb/decisions/gokapi-storage-e2e-siec.md
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
---
|
||||||
|
okf: "0.1"
|
||||||
|
type: decision
|
||||||
|
visibility: private
|
||||||
|
status: active
|
||||||
|
updated: 2026-07-09
|
||||||
|
links:
|
||||||
|
- ../services/gokapi.md
|
||||||
|
- ../runbooks/gokapi-cutover.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gokapi — decyzje: storage, szyfrowanie E2E, siec
|
||||||
|
|
||||||
|
## 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/config` — **to 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`/`nextcloud` — `127.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.
|
||||||
|
|
||||||
51
kb/runbooks/gokapi-cutover.md
Normal file
51
kb/runbooks/gokapi-cutover.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
okf: "0.1"
|
||||||
|
type: runbook
|
||||||
|
visibility: private
|
||||||
|
status: active
|
||||||
|
updated: 2026-07-09
|
||||||
|
links:
|
||||||
|
- ../services/gokapi.md
|
||||||
|
- ../decisions/gokapi-storage-e2e-siec.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# Gokapi — cutover checklist
|
||||||
|
|
||||||
|
## 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.pl` → `135.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@VPS** — **NAJPIERW 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/`.
|
||||||
|
|
||||||
51
kb/services/gokapi.md
Normal file
51
kb/services/gokapi.md
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
---
|
||||||
|
okf: "0.1"
|
||||||
|
type: service
|
||||||
|
visibility: private
|
||||||
|
status: active
|
||||||
|
updated: 2026-07-09
|
||||||
|
links:
|
||||||
|
- ../decisions/gokapi-storage-e2e-siec.md
|
||||||
|
- ../runbooks/gokapi-cutover.md
|
||||||
|
---
|
||||||
|
|
||||||
|
# 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`.
|
||||||
|
|
||||||
|
## Backup
|
||||||
|
|
||||||
|
- `/opt/homelab/data/gokapi/data` — pliki użytkowników. **Ulotne z
|
||||||
|
założenia** (linki wygasają), nie wymaga backupu.
|
||||||
|
- `/opt/homelab/data/gokapi/config` — `config.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).
|
||||||
|
|
||||||
|
## Rejestracja w repo (zrobione w tym PR)
|
||||||
|
|
||||||
|
- `hosts/vps/services.yaml` — wpis `gokapi`.
|
||||||
|
- `inventory/topology.yaml` — `gokapi` w liście serwisów `vps`.
|
||||||
|
|
@ -1,119 +0,0 @@
|
||||||
# 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/config` — **to 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`/`nextcloud` — `127.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/config` — `config.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.pl` → `135.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@VPS** — **NAJPIERW 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.yaml` — `gokapi` w liście serwisów `vps`.
|
|
||||||
Loading…
Reference in a new issue