Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
25 KiB
Wdrożenie na VM103
Stan na 2026-09-19: na VM103 działa łańcuch prawdziwej aktualizacji przez sidecar executor (sekcja „Prawdziwe aktualizacje”). Pierwsza aktualizacja: jackett v0.24.2601-ls30 → v0.24.2624-ls33 (18:06, verify ok). Aplikacja bez „Real updates” zostaje w trybie na sucho.
| Adres | https://upgrade.mariuszpacek.pl (traefik, web-secured, certyfikat http, wildcard DNS na 192.168.0.139) |
| Dostęp | z LAN i z internetu, tylko po zalogowaniu Keycloakiem (realm home, usługa auth = oauth2-proxy jako forwardAuth Traefika; sekcja „Logowanie”) |
| Manifest | /opt/homelab/compose/homelab-upgrade/compose.yaml (kopia deploy/compose.yaml) |
| Obraz | git.mariuszpacek.pl/mariusz.pacek/homelab-upgrade:<tag> z rejestru Gitei, budowany przez Gitea Actions (etykieta org.opencontainers.image.revision = sha commita) |
| Dashboard | kafelek „Upgrade” w grupie Infra na https://dash.mariuszpacek.pl z etykiet homepage.* na server (homepage czyta je przez swoje połączenie z Dockerem; jego pliki nie są zmieniane) |
| Stopka | gałąź i numer buildu CI (foundations · build 6; na master sam numer), pełny sha w podpowiedzi; z argumentów builda BRANCH, BUILD_NUMBER, REVISION → /api/build |
| Tagi | <sha> (pełny, do wycofania), <gałąź> (master, foundations), latest tylko z master |
| Dane | /srv/appdata/homelab-upgrade/data (SQLite + WAL, właściciel uid 1000, chmod 700) |
| Kontenery | server (sieci default + proxy), driver (sieci default + docker + executor; wyjście do rejestrów i adresów aplikacji; nie widzi plików projektów compose), docker-proxy (docker.sock tylko do odczytu, przepuszcza tylko GET na kontenery; sieć docker bez wyjścia), executor (jedyny zapisujący: root bez capabilities, docker.sock, /opt/homelab/compose; sieć executor bez wyjścia), model (claude CLI właściciela, uid 1000, bez socketu i plików projektów; sieci default + executor) |
| Kopie manifestów | /srv/appdata/homelab-upgrade/backups/<projekt>/<id>/ (root, katalogi 0700, pliki 0600) |
| Rekord vzdump | /srv/appdata/homelab-upgrade/host/vzdump.json (pisze timer na Proxmoksie, driver czyta tylko do odczytu) |
server i driver: użytkownik 1000, system plików tylko do odczytu (poza /data i /tmp), bez capabilities, bez portu na hoście, bez docker.sock. docker-proxy ma docker.sock tylko-do-odczytu i przepuszcza wyłącznie GET na /containers (POST=0). Jego system plików nie jest tylko do odczytu, bo entrypoint przy starcie zapisuje haproxy.cfg (przy read_only kontener restartował się w pętli).
Port 8080 na hoście VM jest zajęty przez inną usługę, dlatego appka nie publikuje portu: traefik łączy się z kontenerem przez sieć proxy.
Aktualizacja
Obieg: git push → Gitea Actions (.gitea/workflows/ci.yaml): npm run check, a na master, foundations i tagach wydań v… także build i push obrazu do rejestru Gitei → wdrożenie tylko ręcznie, przyciskiem albo przez API. Arcane nie zarządza tym projektem.
Wydanie: tag v<rok>.<miesiąc>.<numer> (np. v2026.10.1) na commicie z master, najlepiej jako release w Gitei; CI buduje obraz :v2026.10.1 (i :<sha>). Stopka pokazuje wtedy v2026.10.1 · build N.
Wdrożenie: Gitea → repo → Actions → deploy → Run workflow (gałąź master), pole version: tag wydania, pełny sha albo latest (ostatni master); force tylko świadomie. To samo przez API/MCP: dispatch_workflow z workflow_id: deploy.yaml, ref: master, inputs: { version, force }; wynik i log w runie.
Workflow (.gitea/workflows/deploy.yaml) działa tylko z definicji na master: sprawdza format wersji, pobiera obraz i uruchamia skrypt z tego obrazu (/app/deploy/update.sh --install) na katalogu /opt/homelab/compose/homelab-upgrade przez socket Dockera. update.sh:
- odmawia (kod 3), gdy instancja silnika jest w stanie
running(run na bramce lub w kolejce restart przeżywa, przerwany węzeł wznawia się w UI przyciskiem „Retry the step”); - robi spójną kopię bazy przez działający serwer (
/data/queue.sqlite.before-deploy-<czas>, zostaje 5 najnowszych); bez kopii odmawia (kod 5); - z
--installwgrywacompose.yamliupdate.shz obrazu (poprzedni compose zostaje jakocompose.yaml.previous, diff w logu); docker compose pull(gdy obrazu nie ma: przywraca compose i kończy bez restartu) iup -d;- czeka do 90 s na
healthyserwera i executora oraz na stabilne pozostałe usługi; gdy nowa wersja nie wstaje, wraca do poprzedniego obrazu (lokalny tag:rollback) i poprzedniegocompose.yaml, nie zmienia.envi kończy się kodem 1.
--force pomija krok 1 i pozwala na brak kopii z kroku 2. Wycofanie to ponowne wdrożenie starszej wersji tym samym przyciskiem. Stare obrazy zostają na VM.
Awaryjnie, gdy Gitea lub runner nie działa, ten sam skrypt ręcznie na VM103:
cd /opt/homelab/compose/homelab-upgrade
./update.sh # tag z .env (domyślnie latest)
./update.sh v2026.10.1 # inna wersja (tag, gałąź albo pełny sha) i zapamiętanie jej w .env
./update.sh --force # pomija blokadę „trwa krok / węzeł runu” i brak kopii bazy
Ręczny update.sh nie wgrywa compose.yaml; po zmianie deploy/compose.yaml wdrażaj przyciskiem albo skopiuj plik.
Przy zmianie schematu bazy nowa wersja migruje bazę przy starcie (migracje są transakcyjne; nowszej bazy niż kod odmawia otwarcia). Wycofanie do starszego obrazu po zmianie schematu nie zadziała, bo starszy kod odmówi otwarcia nowszej bazy: wtedy przywraca się kopię queue.sqlite.before-deploy-* z kroku 2.
Logowanie (Keycloak)
Usługa auth (oauth2-proxy, deploy/compose.yaml) stoi przed aplikacją: Traefik pyta ją o każde zapytanie (forwardAuth); bez sesji przeglądarka idzie do https://login.mariuszpacek.pl/realms/home, po powrocie wpuszczane są tylko adresy z AUTH_ALLOWED_EMAILS. Sesja trwa 7 dni (odświeżana co godzinę), wylogowanie: https://upgrade.mariuszpacek.pl/oauth2/sign_out. Publiczne zostają tylko manifest.webmanifest i icon.svg.
Jednorazowo w Keycloaku (realm home):
- Clients → Create client: typ OpenID Connect, Client ID
homelab-upgrade; Client authentication on, Standard flow on, Direct access grants off. - Valid redirect URIs
https://upgrade.mariuszpacek.pl/oauth2/callback, Web originshttps://upgrade.mariuszpacek.pl. - Client scopes →
homelab-upgrade-dedicated→ Add mapper → By configuration → Audience: Included Client Audiencehomelab-upgrade, Add to access token on (oauth2-proxy sprawdza audience). - Credentials → skopiuj Client secret.
W /opt/homelab/compose/homelab-upgrade/.env na VM103 (root, 600):
AUTH_CLIENT_SECRET=<client secret z Keycloaka>
AUTH_COOKIE_SECRET=<openssl rand -base64 32 | tr -- '+/' '-_'>
AUTH_ALLOWED_EMAILS=<adres e-mail konta w Keycloaku>
Bez tych trzech wartości docker compose odmawia (wdrożenie kończy się bez restartu, update.sh przywraca poprzedni compose.yaml).
Jednorazowa konfiguracja
- Rejestr: działa od razu (Packages w Gitei są domyślnie włączone;
https://git.mariuszpacek.pl/v2/odpowiada 401). - Token (Gitea → Settings → Applications):
write:packagedla CI. Tokenów nie wklejamy do repo ani logów.read:packagedla VM103 nie jest potrzebny, dopóki pakiet jest publiczny (pull anonimowy działa). - Sekret repo
REGISTRY_TOKEN(repo → Settings → Actions → Secrets): tokenwrite:package. - Runner (
deploy/runner/, na VM103 w/opt/homelab/compose/gitea-runner/; dane w/srv/appdata/gitea-runner/data). Token rejestracyjny: repo → Settings → Actions → Runners → Create new runner (token na poziomie repo zamiast całej instancji). Runner madocker.sock, czyli praktycznie root na VM: rejestruj go tylko dla tego repo. docker loginna VM103: pomijamy, bo pull jest anonimowy. Gdyby pakiet stał się prywatny:docker login git.mariuszpacek.pl -u mariusz.pacektokenemread:package.- Przełączenie z lokalnego obrazu: skopiuj
deploy/compose.yamlideploy/update.shdo/opt/homelab/compose/homelab-upgrade/, po pierwszym zielonym buildzie uruchom./update.sh <sha>. Później oba pliki wgrywa workflow deploy.
Ograniczenia, które warto znać: job dostaje repo z http://192.168.0.139:13080 (port Gitei na VM), bo whitelist traefika nie obejmuje sieci jobów; docker push idzie z demona VM, więc źródłowy adres to 192.168.0.139 z whitelisty Gitei.
Awaryjnie: build ręczny bez rejestru
Na hoście Proxmox: git archive --format=tar.gz -o /tmp/src.tar.gz HEAD, przenieś plik na VM103 (sha256 do porównania). Na VM103:
cd /srv/appdata/homelab-upgrade/build && rm -rf src && mkdir src && tar -xzf src.tar.gz -C src
cd src && docker build --pull=false -t git.mariuszpacek.pl/mariusz.pacek/homelab-upgrade:manual --build-arg REVISION=<sha> .
cd /opt/homelab/compose/homelab-upgrade && TAG=manual docker compose up -d
Notatki wydań i kontrola po aktualizacji (per aplikacja)
Notatki wydań nie są ustawieniem: są w skillu projektu (Apps → aplikacja → Skill), w wierszu „Release notes” tabeli „Źródła”, np. | Release notes | https://nextcloud.com/changelog/ · https://github.com/nextcloud/server/releases |. Link github.com/<owner>/<repo>/releases driver czyta przez API GitHuba (tylko wydania między działającą wersją a kandydatem), każdy inny link jako stronę; do 4 źródeł. Z takim wierszem skok powyżej progu auto trafia najpierw do modelu (release_notes), a właściciel widzi w decyzji jego ocenę. Bez wiersza jest zwykły STOP. 10 z 15 skilli w config/skills/ ma już taki wiersz (brakuje w deluge, dockge, gitea, homepage i keycloak: tam major dostaje zwykły STOP, dopóki wiersz nie zostanie dopisany w skillu).
Jedno ustawienie w Apps → aplikacja, domyślnie wyłączone:
- Post-upgrade check executor:
sonnet/opus= po udanymverifymodel sprawdza, czy aktualizacja wymaga czynności poinstalacyjnych (czyta ocenę notatek, skill i stan usługi; co robić po aktualizacji, można dopisać w skillu). Model wykona tylko to, co dopuszczaconfig/agent-exec.json(dokładne komendy, bez wildcardów); reszta trafia do właściciela jako STOPmigration_required. Dziś lista ma tylko komendy Nextclouda: kontrola odbiorcza ze skilla (tylko odczyt:php occ statusz--output=jsoni bez,php occ config:app:get core lastcron,php occ app:list,pidof crondw usłudzecron) oraz to, co po upgrade brakuje w bazie (php occ db:add-missing-indices,db:add-missing-columns,db:add-missing-primary-keys; użytkownikwww-data, usługaapp). Model widzi listę przezhl exec-rulesi nie zgaduje. Dla pozostałych aplikacji ten krok tylko wypisze, co zrobić ręcznie.
Schemat bazy przechodzi na v10 (v8 dodał post_upgrade_executor, v9 zdejmuje niepotrzebną release_notes_source, v10 dodaje niepodłączony jeszcze katalog i instancje nowego silnika workflow); starszy obraz jej nie otworzy, więc przed wdrożeniem kopia queue.sqlite*.
Dry run: jak testować
- W appce (https://upgrade.mariuszpacek.pl) otwórz aplikację (Apps → nazwa) i kliknij „Dry run”. Run niczego nie zmienia: czyta działającą wersję, rejestr i release notes, a przed kopią i apply kończy się na „Dry run finished”.
- Przebieg widać na stronie runu (graf i historia); gdy run czeka na decyzję, jest na Overview i przychodzi push.
- Konfigurację aplikacji (
app_config) zmienia się na jej stronie: włączenie, prógauto, wzorzec tagów, URL i status do sprawdzenia, wykonawcy modeli, podpowiedź, notatka, „Real updates”. Usługa, obraz i pozycja są tylko do odczytu.config/apps.jsonsłuży tylko do zasiania nowych wpisów.
Znane ograniczenia tego etapu:
dockgeigrafanamają w compose sam digest, bez tagu.docker pspokazuje jednak w poluImagelokalny tag wskazujący ten sam obraz (np.louislam/dockge:1.5.0, sprawdzone 2026-09-19), więcstatusmoże przejść dalej zamiast zatrzymać się naversion_unknown. Taki tag to nazwa nadana obrazowi przy pobraniu, nie to, co stoi w compose. Pewną wersję da portimage_version.- Nazwa projektu compose musi być nazwą katalogu (domyślna w compose). Projekt z własnym
name:wcompose.yamlda błąd „no container of service …”. manifest_sha256jestnull: ten tryb nie czytacompose.yaml. Kroki zmieniające (backup, apply) będą potrzebowały dostępu do plików projektów, a to decyzja właściciela.homeassistantstartuje wyłączony (config/apps.json); od 2026-09-23 nie ma już listy aplikacji pod absolutnym STOP, więc właściciel włącza go (i traefik, mqtt, unifi) flagąenabledna stronie aplikacji.- Driver nie czyta plików projektów, ale proxy z
CONTAINERS=1pozwala nainspect, który pokazuje zmienne środowiskowe kontenerów. Dopóki nie ma boksu, driver jest kodem zaufanym. - Driver ma ruch wychodzący do całej sieci (nie tylko do rejestrów); zawężenie to zadanie boksu.
Prawdziwe aktualizacje (executor)
Decyzje właściciela i zasady: docs/DESIGN.md, „Executor”. Każda aplikacja ma workflow update-<app> (kopia szablonu z domain/workflow-update.ts): odczyt wersji, wybór obrazu, release notes, kopia, apply_dry_run, apply, verify, sprawdzenie przez model; zmiana powyżej progu auto, brak kopii, nieudany verify itd. zatrzymują run na bramce z decyzją właściciela (Overview). Run „Real” wymaga „Real updates” w konfiguracji aplikacji.
Jednorazowe przygotowanie (każdy zapis za zgodą właściciela)
- Kopia bazy (migracja v2 dodaje
app_config.apply; starszy obraz nie otworzy nowszej bazy):cd /srv/appdata/homelab-upgrade/data && for f in queue.sqlite*; do cp -p "$f" "$f.before-v2"; done - Katalogi na VM103:
install -d -o root -g root -m 0700 /srv/appdata/homelab-upgrade/backups install -d -o root -g root -m 0755 /srv/appdata/homelab-upgrade/host - Timer na Proxmoksie (pliki z
deploy/proxmox/): skrypt co godzinę czyta najnowszą kopię VM103 zvm-storage(pvesh) i zapisuje ją przez guest agenta dohost/vzdump.json(plik 0644, bez sekretów).install -m 0755 homelab-upgrade-vzdump-record /usr/local/sbin/ install -m 0644 homelab-upgrade-vzdump.service homelab-upgrade-vzdump.timer /etc/systemd/system/ systemctl daemon-reload && systemctl enable --now homelab-upgrade-vzdump.timer systemctl start homelab-upgrade-vzdump.service # pierwszy zapis od razu deploy/compose.yamlideploy/update.shdo/opt/homelab/compose/homelab-upgrade/, potem./update.sh foundations.update.shczeka też na zdrowy executor.- Whitelisty traefika: driver łączy się z adresami aplikacji jako
172.16.0.1(brama sieciproxypo maskaradzie). W jackett i ombi nieaktualny wpis172.18.0.1/16zamieniono 2026-09-19 na172.16.0.1/32(kopie.compose.yaml.before-whitelist-20260919T121215Z); orca odpowiada 401 (basic auth aplikacji), tak jak z LAN. Nowa aplikacja z whitelistą potrzebuje tego samego wpisu, inaczejverifydostanie 403.
Włączenie i przebieg
- Apps → aplikacja → „Real updates” → Save. To jedyne miejsce konfiguracji: executor ma
EXECUTOR_PROJECTS: "*"(wszystkie projekty poza absolutnym STOP i samym homelab-upgrade). Jawna lista wcompose.yamlzawęziłaby to; aplikacja spoza niej kończy się STOP wstatus. Przed zmianą preflight sprawdza adres aplikacji: gdy już wtedy odpowiada inaczej niż „Expected HTTP status” (np. 403 z whitelisty), łańcuch staje przed kopią i apply, bo verify mógłby tylko cofnąć zmianę. - Strona aplikacji → „Real run” (albo harmonogram w trybie Real). Wersja w progu
autoprzechodzi sama: kopia,apply_dry_run(diff: tylkoservices.<usł>.image),apply,verify, sprawdzenie przez model. - Bramki (Overview → „Decide”): „Approve the update” — Proceed = reszta runu sama, Skip = nic się nie zmienia; „Update check failed” / „Repair failed” — Roll back przywraca
compose.yamlz kopii, Skip zostawia jak jest. Rollback cofa tylko manifest, nie dane: Nextcloud, radarr, sonarr, bazarr i jellyfin migrują bazę przy starcie i na starszym obrazie mogą nie wstać („downgrading is not supported”). Wtedy naprawa to nowszy obraz i dokończenie migracji (Nextcloud:occ upgrade,occ maintenance:mode --off). - Po zmianie: kopia w
backups/<projekt>/<id>/, log executora (docker compose logs executor: projekt, usługa, hash przed i po).
Grupy (DESIGN.md, „Grupy”): Apps pokazuje składniki projektu razem (grafana, pod nim └ influxdb); każdy ma własny przełącznik „Real updates”, próg i adres. Usługi na tym samym obrazie (nextcloud app + cron) zmieniają się razem. Nowe wpisy z config/apps.json (np. składniki baz) driver dopisuje przy starcie, nie ruszając istniejących wierszy. gitea-db (postgres:14) i nextcloud-redis (redis:7-alpine) są wyłączone: najpierw trzeba w manifeście przypiąć konkretną działającą wersję.
2026-09-19, Nextcloud 31.0.12 → 31.0.14: verify po 30 s widział health: starting i 404 (migracja bazy przy starcie), a automatyczny rollback przywrócił 31.0.12 na dane 31.0.14.1, więc kontener restartował się w pętli. Naprawa: app i cron na nextcloud:31.0.14-apache@sha256:07ec73cc… (kopia manifestu backups/nextcloud/manual-20260919T184504Z), occ upgrade, occ maintenance:mode --off. Od tej wersji verify czeka na start i nie cofa sam.
Ręczny powrót do dowolnej kopii: STOP w kolejce → rollback, albo z kroku z backup_id w wejściu. Wyłączenie wszystkiego: odznacz „Real updates” (kroki zmieniające kończą się wtedy bez zmian) albo usuń EXECUTOR_URL z drivera (cały driver wraca do trybu na sucho).
Model, powiadomienia, noc
Jednorazowo (właściciel)
- Katalog logowania modelu na VM103:
install -d -o 1000 -g 1000 -m 0700 /srv/appdata/homelab-upgrade/claude. - Logowanie
claude(Twoim kontem, raz; dane zostają w tym katalogu):Wygasłe logowanie kończycd /opt/homelab/compose/homelab-upgrade && docker compose exec -it model-claude /opt/claude/bin/claude # w CLI: /login, potem /exitrepairbłędemauth_failed(push); wtedy powtórz ten krok. - Katalog logowania Codeksa na VM103:
install -d -o 1000 -g 1000 -m 0700 /srv/appdata/homelab-upgrade/codex. - Logowanie
codex(Twoim kontem, raz; dane zostają w tym katalogu):Bez tego kroku profile Codeksa kończą się błędemcd /opt/homelab/compose/homelab-upgrade && docker compose run --rm model-codex /opt/codex/bin/codex login --device-authauth_failed. - Home Assistant: w
/opt/homelab/compose/homelab-upgrade/.envdopisz (nigdy do repo):HA_URL=http://192.168.0.139:8123 HA_TOKEN=<długoterminowy token z profilu HA> HA_NOTIFY=notify.<twoja_usługa>update.shzmienia w.envtylko linięTAG=. - Harmonogram: każdy workflow ma własny cron (strona aplikacji albo Workflows → Schedule); starego
NIGHTLY_ATjuż nie ma. Staryhomelab-nightly-update.timerna Proxmoksie wyłącz dopiero wtedy, gdy harmonogramy nowego silnika działają:systemctl disable --now homelab-nightly-update.timer. ./update.shpo każdej zmianie.env.
Jak działa
- Nieudany
verify→model.repair: model przezhlogląda i naprawia jedną aplikację, potem kod wykonuje jeszcze razverify; gdy i to nie pomoże, run czeka na bramce (rollback albo zostaw). hl execw repair jest domyślnie wyłączony. Dokładne dopuszczenia (project,service,useralbonull, pełneargv) wpisuje się do wersjonowanegoconfig/agent-exec.json; nie ma wildcardów anish -c.- Skill aplikacji (Apps → aplikacja → Skill) to fakty dla modelu; warto tam wpisać wymagania wersji (np. „Nextcloud 32 wymaga MariaDB ≥ 10.6”).
- Push (driver, Home Assistant), gdy run czeka na decyzję, gdy się nie powiedzie i gdy run „Real” się skończy; bez
HA_URL/HA_TOKENtylko do logu.
Arcane i repo compose
Repozytorium ssh://git@git.mariuszpacek.pl:2244/mariusz.pacek/homelab-compose.git jest prywatne, na master, zawiera 20 katalogów projektów z samym compose.yaml, archiwum to_delete/dockge oraz .gitignore; pliki .env i sekrety nie są śledzone. Główny checkout VM103: /srv/appdata/homelab-upgrade/git/repo. Dziesięć compose używających env_file w formacie raw skonwertowano przez tools/compose-env-compat.py; pełny wynik docker compose config porównano ściśle, wartości lokalne pozostały bez zmian.
Arcane v2.13.1 działa pod https://arcane.mariuszpacek.pl. Projekty używają Git Sync w trybie Deploy (w UI: Pull), ścieżka <projekt>/compose.yaml, syncDirectory=false, interwał 5 minut. Autosync jest włączony dla wszystkich 19 projektów; stosy Arcane i homelab-upgrade są wyłączone, a upgrade-lab działa bezpośrednio. Wszystkie manifesty projektów zawierają etykietę com.getarcaneapp.arcane.updater: "false". Arcane sam wykonuje redeploy projektu po zmianie compose, więc executor w trybie git nie uruchamia pull/up.
Początkowe synchronizacje 18 projektów (i Trilium, dołączonego 2026-09-30) zachowały SHA plików env i nie zmieniły startów kontenerów; Arcane może utworzyć pusty .env. Źródła nie wymagały restartu podczas importu. Test Jackett przez API executora potwierdził ścieżkę komentarz → commit 47c2b7f → push → udany sync Arcane i HTTP 301; rollback executora wykonał git revert, przywrócił pierwotny SHA i zakończył się powodzeniem.
config/workflow-schedules.json rozkłada starty w strefie Europe/Warsaw (czas polski): poniedziałek Bazarr 19:00, Jackett 21:00; wtorek Radarr 19:00, Sonarr 21:00; środa Deluge 19:00, Ombi 21:00; czwartek Homepage 19:00, OrcaSlicer 21:00; piątek Gitea 18:00, baza 19:00, Keycloak 20:00, baza 22:00; sobota Home Assistant 18:00, Nextcloud 20:00, baza 22:00, Redis 23:00; niedziela Trilium 16:00, Grafana 18:00, Jellyfin 20:00. InfluxDB i Dockge są wyłączone.
Konfiguracja prywatna /srv/appdata/homelab-upgrade/git-config/deployments.json jest montowana jako /git-config tylko do odczytu, a GIT_DEPLOYMENTS_FILE=/git-config/deployments.json. Schemat v1: repoPath=/git/repo, branch=master, sshKeyPath=/git-ssh/id_ed25519, knownHostsPath=/git-ssh/known_hosts; projekty mają tryb direct albo git, webhookUrl i opcjonalny redeployWebhookUrl. Executor ma checkout do zapisu, katalog git-ssh tylko do odczytu oraz sieci executor i default; git i OpenSSH są częścią obrazu. Klucz executora z prawem zapisu znajduje się w /srv/appdata/homelab-upgrade/git-ssh/id_ed25519, klucz Arcane tylko do odczytu w /srv/appdata/arcane/git-ssh/id_ed25519. known_hosts przypina trzy publiczne algorytmy Gitei porównane z plikiem .pub kontenera. Nie umieszczaj tokenów ani webhook URL zawierających sekrety w dokumentacji, repo ani logach.
Kod obsługuje apply, migrate, rollback i hl write/up; istniejący verify nadal rozstrzyga powodzenie. Brudny checkout, rozbieżny SHA lub sekrety inline blokują publikację. Zmiany env zapisuje się lokalnie przed pushem i przy odrzuconej publikacji przywraca; rollback zmian wyłącznie env używa osobnego webhooka redeploy. Rollback Git cofa automatycznie tylko commity manifestu zmieniające pojedynczy plik; pozostałe wymagają ręcznego przeglądu.
Właściciel potwierdził konfigurację konta Arcane przez Keycloak dla pacekm90@gmail.com; tej konfiguracji nie weryfikowano niezależnie w tej sesji. Wcześniejsze lokalne konto pacekm90 było tymczasowe; nie dokumentować hasła. Callback OIDC Arcane: https://arcane.mariuszpacek.pl/auth/oidc/callback.
Dockge został zatrzymany (down, bez -v). Jego katalogi compose/appdata oraz 29 starych kopii (łącznie 31 ścieżek) przeniesiono na VM do /srv/appdata/to_delete/20260930; niczego nie usunięto. Wszystkie 20 wpisów harmonogramu zapisano i porównano przez API z planem.
Poprawka wydajności podglądów harmonogramów została wdrożona z przetestowanego drzewa roboczego na obrazie homelab-upgrade:git-arcane-20260930-r4; executor pozostaje na homelab-upgrade:git-arcane-20260930-r2. Publikacja kodu w Git uruchamia sprawdzenie i budowę obrazu w CI; wdrożenie obrazu na VM wymaga osobnego uruchomienia update.sh. Weryfikacja: npm run check — 104 pliki, 1240 testów PASS; API harmonogramów po naprawie około 0,34 s zamiast blokowania serwera. Tymczasowy token instalacyjny Gitei unieważniono i sprawdzono HTTP 401.
Wycofanie
cd /opt/homelab/compose/homelab-upgrade && docker compose down # dane zostają w /srv/appdata/homelab-upgrade/data
Pełne usunięcie: dodatkowo rm -r /opt/homelab/compose/homelab-upgrade /srv/appdata/homelab-upgrade i docker image rm $(docker images -q 'git.mariuszpacek.pl/mariusz.pacek/homelab-upgrade'). Inne projekty nie są dotknięte.
Uwagi
- Kroki zmieniające (backup, apply, rollback) idą wyłącznie przez executor (DESIGN.md, „Executor”); proxy dla drivera zostaje tylko GET. Reszta boksu (ruch wychodzący drivera, modele) jest nadal otwarta.
- Przed wystawieniem poza LAN trzeba dodać logowanie (DESIGN.md: „logowanie do przemyślenia”).