Files
homelab-updaterandClaude Opus 5.5 136f9d2fb0
ci / check (push) Successful in 1m30s
ci / publish (push) Successful in 1m22s
feat(deploy): deploy a release by hand from Gitea Actions
A deploy workflow, started only by hand (or through the API) and only
from master, pulls the chosen image (release tag, sha or latest) and
runs that image's own update.sh against VM103's compose directory
through the Docker socket. update.sh now copies the database through the
running server first, installs the image's compose.yaml and update.sh
with --install, and restores the previous compose file together with
the previous image when the new version does not come up. CI also
builds release tags v*.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 09:30:19 +02:00

24 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 tylko LAN: middleware ipwhitelist 192.168.0.1/24,10.0.0.0/16; appka nie ma logowania
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:

  1. 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”);
  2. robi spójną kopię bazy przez działający serwer (/data/queue.sqlite.before-deploy-<czas>, zostaje 5 najnowszych); bez kopii odmawia (kod 5);
  3. z --install wgrywa compose.yaml i update.sh z obrazu (poprzedni compose zostaje jako compose.yaml.previous, diff w logu);
  4. docker compose pull (gdy obrazu nie ma: przywraca compose i kończy bez restartu) i up -d;
  5. czeka do 90 s na healthy serwera i executora oraz na stabilne pozostałe usługi; gdy nowa wersja nie wstaje, wraca do poprzedniego obrazu (lokalny tag :rollback) i poprzedniego compose.yaml, nie zmienia .env i 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.

Jednorazowa konfiguracja

  1. Rejestr: działa od razu (Packages w Gitei są domyślnie włączone; https://git.mariuszpacek.pl/v2/ odpowiada 401).
  2. Token (Gitea → Settings → Applications): write:package dla CI. Tokenów nie wklejamy do repo ani logów. read:package dla VM103 nie jest potrzebny, dopóki pakiet jest publiczny (pull anonimowy działa).
  3. Sekret repo REGISTRY_TOKEN (repo → Settings → Actions → Secrets): token write:package.
  4. 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 ma docker.sock, czyli praktycznie root na VM: rejestruj go tylko dla tego repo.
  5. docker login na VM103: pomijamy, bo pull jest anonimowy. Gdyby pakiet stał się prywatny: docker login git.mariuszpacek.pl -u mariusz.pacek tokenem read:package.
  6. Przełączenie z lokalnego obrazu: skopiuj deploy/compose.yaml i deploy/update.sh do /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 udanym verify model 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 dopuszcza config/agent-exec.json (dokładne komendy, bez wildcardów); reszta trafia do właściciela jako STOP migration_required. Dziś lista ma tylko komendy Nextclouda: kontrola odbiorcza ze skilla (tylko odczyt: php occ status z --output=json i bez, php occ config:app:get core lastcron, php occ app:list, pidof crond w usłudze cron) oraz to, co po upgrade brakuje w bazie (php occ db:add-missing-indices, db:add-missing-columns, db:add-missing-primary-keys; użytkownik www-data, usługa app). Model widzi listę przez hl exec-rules i 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ć

  1. 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”.
  2. Przebieg widać na stronie runu (graf i historia); gdy run czeka na decyzję, jest na Overview i przychodzi push.
  3. Konfigurację aplikacji (app_config) zmienia się na jej stronie: włączenie, próg auto, 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.json służy tylko do zasiania nowych wpisów.

Znane ograniczenia tego etapu:

  • dockge i grafana mają w compose sam digest, bez tagu. docker ps pokazuje jednak w polu Image lokalny tag wskazujący ten sam obraz (np. louislam/dockge:1.5.0, sprawdzone 2026-09-19), więc status może przejść dalej zamiast zatrzymać się na version_unknown. Taki tag to nazwa nadana obrazowi przy pobraniu, nie to, co stoi w compose. Pewną wersję da port image_version.
  • Nazwa projektu compose musi być nazwą katalogu (domyślna w compose). Projekt z własnym name: w compose.yaml da błąd „no container of service …”.
  • manifest_sha256 jest null: ten tryb nie czyta compose.yaml. Kroki zmieniające (backup, apply) będą potrzebowały dostępu do plików projektów, a to decyzja właściciela.
  • homeassistant startuje 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ą enabled na stronie aplikacji.
  • Driver nie czyta plików projektów, ale proxy z CONTAINERS=1 pozwala na inspect, 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)

  1. 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
    
  2. 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
    
  3. Timer na Proxmoksie (pliki z deploy/proxmox/): skrypt co godzinę czyta najnowszą kopię VM103 z vm-storage (pvesh) i zapisuje ją przez guest agenta do host/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
    
  4. deploy/compose.yaml i deploy/update.sh do /opt/homelab/compose/homelab-upgrade/, potem ./update.sh foundations. update.sh czeka też na zdrowy executor.
  5. Whitelisty traefika: driver łączy się z adresami aplikacji jako 172.16.0.1 (brama sieci proxy po maskaradzie). W jackett i ombi nieaktualny wpis 172.18.0.1/16 zamieniono 2026-09-19 na 172.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, inaczej verify dostanie 403.

Włączenie i przebieg

  1. Apps → aplikacja → „Real updates” → Save. To jedyne miejsce konfiguracji: executor ma EXECUTOR_PROJECTS: "*" (wszystkie projekty poza absolutnym STOP i samym homelab-upgrade). Jawna lista w compose.yaml zawęziłaby to; aplikacja spoza niej kończy się STOP w status. 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ę.
  2. Strona aplikacji → „Real run” (albo harmonogram w trybie Real). Wersja w progu auto przechodzi sama: kopia, apply_dry_run (diff: tylko services.<usł>.image), apply, verify, sprawdzenie przez model.
  3. Bramki (Overview → „Decide”): „Approve the update” — Proceed = reszta runu sama, Skip = nic się nie zmienia; „Update check failed” / „Repair failed” — Roll back przywraca compose.yaml z 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).
  4. 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)

  1. Katalog logowania modelu na VM103: install -d -o 1000 -g 1000 -m 0700 /srv/appdata/homelab-upgrade/claude.
  2. Logowanie claude (Twoim kontem, raz; dane zostają w tym katalogu):
    cd /opt/homelab/compose/homelab-upgrade && docker compose exec -it model-claude /opt/claude/bin/claude
    # w CLI: /login, potem /exit
    
    Wygasłe logowanie kończy repair błędem auth_failed (push); wtedy powtórz ten krok.
  3. Katalog logowania Codeksa na VM103: install -d -o 1000 -g 1000 -m 0700 /srv/appdata/homelab-upgrade/codex.
  4. Logowanie codex (Twoim kontem, raz; dane zostają w tym katalogu):
    cd /opt/homelab/compose/homelab-upgrade && docker compose run --rm model-codex /opt/codex/bin/codex login --device-auth
    
    Bez tego kroku profile Codeksa kończą się błędem auth_failed.
  5. Home Assistant: w /opt/homelab/compose/homelab-upgrade/.env dopisz (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.sh zmienia w .env tylko linię TAG=.
  6. Harmonogram: każdy workflow ma własny cron (strona aplikacji albo Workflows → Schedule); starego NIGHTLY_AT już nie ma. Stary homelab-nightly-update.timer na Proxmoksie wyłącz dopiero wtedy, gdy harmonogramy nowego silnika działają: systemctl disable --now homelab-nightly-update.timer.
  7. ./update.sh po każdej zmianie .env.

Jak działa

  • Nieudany verify → model.repair: model przez hl ogląda i naprawia jedną aplikację, potem kod wykonuje jeszcze raz verify; gdy i to nie pomoże, run czeka na bramce (rollback albo zostaw).
  • hl exec w repair jest domyślnie wyłączony. Dokładne dopuszczenia (project, service, user albo null, pełne argv) wpisuje się do wersjonowanego config/agent-exec.json; nie ma wildcardów ani sh -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_TOKEN tylko do logu.

Arcane i repo compose

Repozytorium ssh://git@git.mariuszpacek.pl:2244/mariusz.pacek/homelab-compose.git jest prywatne, na master, zawiera 19 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 18 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 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 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”).