chore: initial import
This commit is contained in:
216
steps.md
Normal file
216
steps.md
Normal file
@@ -0,0 +1,216 @@
|
||||
# steps.md
|
||||
|
||||
Log działań wykonywanych w ramach migracji `trade` → k3s + Gitea + GitOps (pull).
|
||||
Uwaga: **nie zapisuję sekretów** (hasła, tokeny, prywatne klucze) – jeśli pojawiają się w outputach narzędzi, są pomijane/redagowane.
|
||||
|
||||
## 2026-01-05
|
||||
|
||||
### Repo: inwentaryzacja i plan
|
||||
- Przejrzano strukturę repo (`apps/`, `devops/`, `services/`, `doc/`) i istniejące Compose stacki:
|
||||
- DB: `devops/db/docker-compose.yml`
|
||||
- App: `devops/app/docker-compose.yml`
|
||||
- Bootstrap (one-shot): `devops/tools/bootstrap/docker-compose.yml`
|
||||
- Sprawdzono Dockerfile:
|
||||
- API: `devops/api/Dockerfile`
|
||||
- Frontend: `devops/app/frontend/Dockerfile`
|
||||
- Ingestor: `devops/ingestor/Dockerfile`
|
||||
- Sprawdzono skrypty wersjonowania Compose (v1/v2…): `scripts/ops/*` + env: `devops/versions/v1.env`.
|
||||
- Dodano dokument planu migracji: `doc/migration.md`.
|
||||
|
||||
### Gitea: repo GitOps (MCP Gitea)
|
||||
- Utworzono repo `trade/trade-deploy` (public, `main`, auto-init).
|
||||
- Dodano szkielet Kustomize:
|
||||
- `kustomize/base/` (placeholder ConfigMap)
|
||||
- `kustomize/overlays/staging/` (`namespace: trade-staging`)
|
||||
- `kustomize/overlays/prod/` (`namespace: trade-prod`)
|
||||
- Dodano bootstrap manifesty Argo CD Application:
|
||||
- `bootstrap/argocd/application-trade-staging.yaml` (auto-sync + CreateNamespace)
|
||||
- `bootstrap/argocd/application-trade-prod.yaml` (CreateNamespace, bez auto-sync)
|
||||
- Dodano DB stack do `trade-deploy` (manifests + bootstrap):
|
||||
- Postgres/Timescale: `kustomize/base/postgres/*` + init SQL: `kustomize/base/initdb/001_init.sql`
|
||||
- Hasura: `kustomize/base/hasura/*` + job `hasura-bootstrap` (track tables/functions)
|
||||
- Staging: `kustomize/overlays/staging/pgadmin.yaml` + patch Hasury (console/dev mode)
|
||||
- Zaktualizowano `README.md` w `trade-deploy` o wymagane sekrety i port-forward.
|
||||
|
||||
### VPS: audyt stanu (MCP SSH)
|
||||
- Host: `qstack` (Debian), k3s działa; dostęp do klastra uzyskany przez `KUBECONFIG=/etc/rancher/k3s/k3s.yaml` (bez sudo).
|
||||
- Ingress: Traefik działa (LB na `77.90.8.171`, porty 80/443).
|
||||
- TLS: cert-manager działa; `ClusterIssuer/letsencrypt-prod` jest `Ready=True`.
|
||||
- Gitea jest zainstalowana w k3s (Helm release `gitea` w namespace `gitea`), Ingress na `rv32i.pl`, cert `rv32i-pl-tls` jest `Ready=True`.
|
||||
- GitOps controller (Argo CD / Flux): **nie znaleziono** (brak namespace `argocd` i `flux-system`).
|
||||
- Wdrożenia aplikacji `trade-*` w k3s: **nie znaleziono** (brak deploy/podów z nazwą `trade`).
|
||||
- Registry: endpoint `https://rv32i.pl/v2/` odpowiada (401 bez autoryzacji).
|
||||
|
||||
### Gitea: audyt stanu (MCP Gitea)
|
||||
- Zalogowany użytkownik: `u1` (admin).
|
||||
- Organizacja `trade` istnieje; są utworzone repozytoria (puste, bez commitów/branchy):
|
||||
- `trade/trade-api`
|
||||
- `trade/trade-frontend`
|
||||
- `trade/trade-ingestor`
|
||||
- `trade/trade-infra`
|
||||
- Repo `trade-deploy` (manifesty GitOps): **nie znaleziono**.
|
||||
|
||||
### VPS: Argo CD (MCP SSH)
|
||||
- Zainstalowano Argo CD przez Helm: release `argocd` w namespace `argocd` (`argo/argo-cd`).
|
||||
- Utworzono `Application` dla staging z `trade-deploy`:
|
||||
- zastosowano `bootstrap/argocd/application-trade-staging.yaml`
|
||||
- Argo utworzyło namespace `trade-staging` i zsynchronizowało placeholder ConfigMap `trade-deploy-info`.
|
||||
- Uwaga: jeśli port `8080` jest zajęty lokalnie (np. przez Hasurę), do port-forward użyj innego portu (np. `8090:443`).
|
||||
|
||||
### VPS: Gitea Actions runner (MCP SSH)
|
||||
- Wykryto wymaganie: `sudo` wymaga hasła, więc runner postawiony w k3s (bez instalacji binarki na hoście).
|
||||
- Utworzono namespace `gitea-actions` oraz zasoby dla `act_runner` (DinD sidecar + runner):
|
||||
- manifest w `trade-deploy`: `bootstrap/gitea-actions/act-runner.yaml`
|
||||
- sekret `act-runner-registration-token` utworzony w klastrze z tokena rejestracyjnego pobranego z Gitei (API admin; token nie trafia do gita)
|
||||
- Naprawiono start Dockera w sidecar:
|
||||
- początkowo próba po unix-sockecie powodowała konflikt (`docker.sock` jako katalog)
|
||||
- finalnie ustawiono `DOCKER_HOST=tcp://127.0.0.1:2375` (runner ↔ dind po localhost), co uruchomiło runnera poprawnie.
|
||||
|
||||
### Uwaga: seed sekretów (blokada narzędzia)
|
||||
- Przy próbie seedowania sekretów do `trade-staging` przez MCP SSH pojawił się trwały timeout na każde polecenie (`ssh-mcp/exec`), więc ten krok został opisany w `trade-deploy/README.md` do wykonania ręcznie na VPS.
|
||||
|
||||
### VPS: dostęp SSH kluczem (wymagane hasło)
|
||||
- Użytkownik poprosił o używanie naszego klucza prywatnego dla VPS: `k/qstack/qstack`.
|
||||
- Klucz jest zaszyfrowany hasłem (passphrase). Bez podania passphrase nie da się go użyć w trybie nieinteraktywnym (`ssh`/`ssh-keygen` zwraca błąd o niepoprawnym passphrase / brak `ssh-askpass`).
|
||||
- Żeby kontynuować automatyzację z tej sesji są 2 opcje:
|
||||
1) dostarczyć passphrase poza czatem (np. lokalnie w pliku w `tokens/`, gitignored) i używać `SSH_ASKPASS`, albo
|
||||
2) wygenerować osobny klucz bez passphrase jako “deploy key” tylko do automatyzacji i dodać jego publiczną część do `~user/.ssh/authorized_keys` na VPS.
|
||||
|
||||
### Następne kroki (do zrobienia)
|
||||
- Wybrać GitOps controller (Argo CD vs Flux) i zainstalować w k3s.
|
||||
- Utworzyć repo `trade-deploy` i dodać strukturę Helm/Kustomize (staging/prod).
|
||||
- Postawić runner CI (Gitea Actions `act_runner` lub alternatywa) i dodać pipeline build+push obrazów.
|
||||
- Dopiero potem: manifesty K8s dla `trade-api`/`trade-frontend`/`trade-ingestor` + DB/Hasura + joby migracji.
|
||||
|
||||
## 2026-01-06
|
||||
|
||||
### VPS: SSH kluczem projektu (passphrase)
|
||||
- Użyto klucza prywatnego `k/qstack/qstack` do połączenia z VPS przez `ssh` (z `SSH_ASKPASS` czytającym passphrase z `tokens/vps-ssh.json`, plik gitignored).
|
||||
- Skrypt `tokens/ssh-askpass.sh` był tworzony tymczasowo i został usunięty po użyciu (żeby nie ryzykować przypadkowego commita).
|
||||
|
||||
### Doprecyzowanie dostępu i bezpieczeństwo repo
|
||||
- Dopisano w `doc/migration.md` bieżący status VPS/k3s oraz komendy do Argo CD (port-forward na `8090`) i logów runnera.
|
||||
- Zaktualizowano `.gitignore`, żeby ignorować sekrety/klucze lokalne: `tokens/*`, `k/`, `argo/pass`, `gitea/token`.
|
||||
|
||||
### k3s: seed sekretów (staging)
|
||||
- Utworzono sekrety w namespace `trade-staging` (wartości wygenerowane losowo, nie logowane):
|
||||
- `trade-postgres` (`POSTGRES_*`)
|
||||
- `trade-hasura` (`HASURA_GRAPHQL_ADMIN_SECRET`, `HASURA_JWT_KEY`)
|
||||
- `trade-pgadmin` (`PGADMIN_DEFAULT_*`)
|
||||
|
||||
### Argo CD: deploy DB stack (staging)
|
||||
- Wymuszono refresh aplikacji Argo `trade-staging` (annotation `argocd.argoproj.io/refresh=hard`).
|
||||
- Status: `trade-staging` = `Synced` / `Healthy`.
|
||||
- Workloady w `trade-staging` działają:
|
||||
- `StatefulSet/postgres` = `postgres-0 Running`
|
||||
- `Deployment/hasura` = `Running`
|
||||
- `Deployment/pgadmin` = `Running`
|
||||
- `Job/hasura-bootstrap` = `Completed` (log: `[hasura-bootstrap] ok`)
|
||||
|
||||
### Portainer: dlaczego nie widać k3s (wyjaśnienie)
|
||||
- Portainer uruchomiony jako kontener Docker domyślnie widzi tylko środowisko Docker; k3s używa `containerd`, więc nie zobaczysz „podów” w `docker ps` ani w Portainerze jako kontenerów Dockera.
|
||||
- Żeby Portainer widział „wnętrze” k3s trzeba dodać środowisko typu `Kubernetes` w Portainer UI albo postawić Portainera bezpośrednio w klastrze (rekomendowane).
|
||||
|
||||
### Portainer (opcja A): wdrożenie w k3s + Ingress `portainer.rv32i.pl`
|
||||
- Dodano do GitOps repo `trade/trade-deploy` paczkę Kustomize: `kustomize/infra/portainer` (Namespace+RBAC+PVC+Deployment+Service+Ingress).
|
||||
- Dodano Argo CD `Application` dla Portainera: `bootstrap/argocd/application-portainer.yaml`.
|
||||
- Zastosowano `Application` na VPS i potwierdzono status: `portainer` = `Synced` / `Healthy`.
|
||||
- Ingress utworzony na host `portainer.rv32i.pl` (Traefik).
|
||||
- cert-manager utworzył `Certificate/portainer-rv32i-pl-tls`, ale ACME jest `pending` dopóki DNS `portainer.rv32i.pl` nie wskazuje na `77.90.8.171` (brak rekordu A w momencie sprawdzania).
|
||||
|
||||
### Portainer: DNS + TLS + odblokowanie „New Portainer installation timed out”
|
||||
- Potwierdzono, że rekord A `portainer.rv32i.pl` istnieje na autorytatywnych DNS (`dns*.home.pl`) i rozwiązuje się na publicznych resolverach.
|
||||
- Zrestartowano `Deployment/portainer` w namespace `portainer`, żeby odblokować ekran inicjalizacji (komunikat “timed out for security purposes”).
|
||||
- cert-manager miał „zawieszone” HTTP-01 self-check przez cache NXDOMAIN w klastrze; zrestartowano `Deployment/coredns` w `kube-system`, po czym certyfikat stał się `Ready=True` (`Certificate/portainer-rv32i-pl-tls`).
|
||||
|
||||
### Registry: token do Gitea Packages + docker login
|
||||
- Na VPS (z poziomu poda Gitei) wygenerowano token `read:package,write:package` dla użytkownika `u1`:
|
||||
- polecenie: `gitea admin user generate-access-token --username u1 --scopes "read:package,write:package" --raw`
|
||||
- token zapisany lokalnie w `tokens/gitea-registry.token` (gitignored; wartość nie jest logowana).
|
||||
- Wykonano `docker login rv32i.pl` (bez logowania tokena).
|
||||
- Zaktualizowano `.dockerignore`, żeby nie wysyłać do build context katalogów z sekretami/kluczami (`tokens/*`, `k/`, `gitea/`, `argo/`).
|
||||
|
||||
### Obrazy: build + push (trade-api, trade-ingestor)
|
||||
- Zbudowano i wypchnięto obrazy do Gitea registry:
|
||||
- `rv32i.pl/trade/trade-api:k3s-20260106013603`
|
||||
- `rv32i.pl/trade/trade-ingestor:k3s-20260106013603`
|
||||
- Tag zapisany lokalnie w `tokens/last-image-tag.txt` (gitignored).
|
||||
|
||||
### GitOps: manifesty k3s dla API + ingestor (trade-deploy)
|
||||
- Dodano do repo `trade/trade-deploy`:
|
||||
- `kustomize/base/api/deployment.yaml` + `kustomize/base/api/service.yaml`
|
||||
- `kustomize/base/ingestor/deployment.yaml`
|
||||
- aktualizacja `kustomize/base/kustomization.yaml` (dopięcie nowych zasobów).
|
||||
- Konfiguracja:
|
||||
- `trade-api` używa `HASURA_GRAPHQL_URL=http://hasura:8080/v1/graphql` i sekretów `trade-hasura` + `trade-api` (admin).
|
||||
- `trade-ingestor` startuje w trybie `INGEST_VIA=hasura` (bez tokenów API) i używa `trade-hasura` + `trade-ingestor-tokens` (RPC).
|
||||
|
||||
### k3s: seedy sekretów + weryfikacja (staging)
|
||||
- Utworzono w `trade-staging`:
|
||||
- `Secret/gitea-registry` (imagePullSecret do `rv32i.pl`)
|
||||
- `Secret/trade-api` (`API_ADMIN_SECRET`, wygenerowany losowo; nie logowany)
|
||||
- `Secret/trade-ingestor-tokens` (plik `heliusN.json`; wartość nie logowana)
|
||||
- Argo CD `Application/trade-staging` po refresh: `Synced` / `Healthy`.
|
||||
- Pody w `trade-staging` uruchomione: `trade-api` i `trade-ingestor` (`Running`).
|
||||
- Logi:
|
||||
- `trade-api` startuje i maskuje sekrety (`***`).
|
||||
- `trade-ingestor` pobiera ceny i ingestuje ticki; URL RPC jest redagowany (`api-key=***`).
|
||||
|
||||
### Ingest przez API + tokeny read/write
|
||||
- Zmieniono `trade-ingestor` na `INGEST_VIA=api` (pisze do `trade-api` zamiast bezpośrednio do Hasury); manifest w `trade/trade-deploy`: `kustomize/base/ingestor/deployment.yaml`.
|
||||
- Utworzono tokeny w `trade-api`:
|
||||
- `write` (dla ingestora) oraz `read` (dla klientów UI/odczytu)
|
||||
- tokeny zapisane jako K8s Secrets (wartości nie logowane):
|
||||
- `trade-staging/Secret/trade-ingestor-tokens`: `alg.json` (write) + `heliusN.json` (RPC)
|
||||
- `trade-staging/Secret/trade-read-token`: `read.json` (read)
|
||||
- Wymuszono rollout `Deployment/trade-ingestor` i potwierdzono w logach:
|
||||
- `ingestVia: "api"`, `writeUrl: "http://trade-api:8787/v1/ingest/tick"`, `auth: "bearer"`.
|
||||
- Potwierdzono, że `trade-api /v1/ticks` działa z tokenem `read` (bez ujawniania tokena).
|
||||
|
||||
### Frontend: deploy na k3s (staging) + Ingress `trade.rv32i.pl`
|
||||
- Zbudowano i wypchnięto obraz do Gitea registry:
|
||||
- `rv32i.pl/trade/trade-frontend:k3s-20260106013603`
|
||||
- Dodano manifesty do `trade/trade-deploy`:
|
||||
- `kustomize/base/frontend/deployment.yaml` + `kustomize/base/frontend/service.yaml`
|
||||
- staging: `kustomize/overlays/staging/frontend-ingress.yaml` (host `trade.rv32i.pl`)
|
||||
- aktualizacje `kustomize/base/kustomization.yaml` i `kustomize/overlays/staging/kustomization.yaml`.
|
||||
- Utworzono sekret `trade-staging/Secret/trade-frontend-tokens` (pliki `frontend.json` + `read.json`; wartości nie logowane).
|
||||
- Argo CD `Application/trade-staging`: `Synced` / `Healthy`; `Deployment/trade-frontend` = `Running`, `/healthz` działa.
|
||||
- TLS dla `trade.rv32i.pl` jest `pending` dopóki DNS `trade.rv32i.pl` nie wskazuje na `77.90.8.171` (w razie cache NXDOMAIN: restart `kube-system/coredns` jak wcześniej).
|
||||
|
||||
### DNS: `trade.rv32i.pl` (weryfikacja)
|
||||
- Sprawdzono rekord A `trade.rv32i.pl` na autorytatywnych DNS (`dns*.home.pl`) oraz na publicznych resolverach: **brak odpowiedzi** (rekord nie był jeszcze widoczny na NS), więc cert-manager trzyma `trade-rv32i-pl-tls` w stanie `pending` (NXDOMAIN).
|
||||
- Uwaga: jeśli w panelu DNS dodasz rekord i nadal masz `NXDOMAIN`, sprawdź czy host nie ma literówki (np. `rade` zamiast `trade`) i czy rekord jest zapisany jako A/CNAME dla właściwej nazwy `trade.rv32i.pl`.
|
||||
|
||||
### DNS/TLS: `trade.rv32i.pl` (finalizacja)
|
||||
- Użytkownik potwierdził rekord A `trade.rv32i.pl` → `77.90.8.171` na autorytatywnych DNS (`dns.home.pl`).
|
||||
- Na VPS potwierdzono:
|
||||
- `Ingress/trade-frontend` ma host `trade.rv32i.pl`.
|
||||
- `Certificate/trade-rv32i-pl-tls` = `Ready=True`.
|
||||
- `https://trade.rv32i.pl` odpowiada `HTTP 401` (basic auth) – czyli Ingress + TLS działają.
|
||||
|
||||
### Weryfikacja wdrożenia (MCP SSH)
|
||||
- `argocd/Application`: `trade-staging` i `portainer` = `Synced` / `Healthy`.
|
||||
- `trade-staging`: wszystkie workloady `Running` (Postgres/Hasura/pgAdmin/trade-api/trade-ingestor/trade-frontend).
|
||||
- `trade-ingestor` ma `INGEST_VIA=api` oraz `INGEST_API_URL=http://trade-api:8787` (ingest przez API z tokenem write).
|
||||
|
||||
### Portainer: odblokowanie ekranu `timeout.html`
|
||||
- Zrestartowano `Deployment/portainer` w namespace `portainer`, żeby ponownie pojawił się kreator inicjalizacji (admin user/password).
|
||||
|
||||
### Gitea: lista repo w organizacji `trade`
|
||||
- `trade/trade-api`
|
||||
- `trade/trade-deploy`
|
||||
- `trade/trade-doc`
|
||||
- `trade/trade-frontend`
|
||||
- `trade/trade-infra`
|
||||
- `trade/trade-ingestor`
|
||||
|
||||
## 2026-01-06
|
||||
|
||||
### Zmiana: log działań w `doc/`
|
||||
- Przeniesiono log działań z `steps.md` → `doc/steps.md` (zgodnie z nową zasadą: wszystko projektowe ląduje w `doc/`).
|
||||
|
||||
### Superproject: decyzja + plan (do akceptacji)
|
||||
- Zaproponowano `trade/trade-infra` jako repo główne (superproject) spinające subrepo (API/ingestor/frontend/deploy/doc).
|
||||
- Plan refaktoru opisany w `doc/migration.md` (sekcja „Metoda superproject”).
|
||||
- Użytkownik zaakceptował `trade/trade-infra` jako superproject; do decyzji pozostało: `submodules` vs `subtree` (rekomendacja: submodules, jeśli chcemy zachować niezależne repo + pinowanie wersji).
|
||||
Reference in New Issue
Block a user