Commit Graph
41 Commits
Author SHA1 Message Date
forust a6af69dca0 fix(k8s): Recreate singletons and trim requests for scheduler headroom
ci / lint-actionlint (push) Successful in 1s
ci / lint-shellcheck (push) Successful in 2s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-compose (push) Successful in 3s
ci / test-backend (push) Successful in 8s
ci / test-frontend (push) Successful in 11s
ci / validate (push) Successful in 3s
renovate-ci / validate-renovate (push) Successful in 13s
ci / lint-dockerfiles (push) Successful in 2s
ci / scan-deps (push) Successful in 18s
ci / build (push) Successful in 1m30s
RollingUpdate with default maxSurge needs a spare pod the single node does not have (99% CPU requested), so multi-workload restarts end Pending and verify times out. Recreate on all replicas:1 Deployments (immich-server and bentopdf keep RollingUpdate at replicas 2). Also trims CPU/memory requests toward measured use (adguard, authentik, gitea, netbox, uptime-kuma, netbird-server) and gives traefik requests/limits so it is no longer BestEffort.
2026-09-28 22:36:46 +02:00
forust 11e92fdf4e fix(deploy): bound ssh hangs and retry the stage on transport loss
A connection that died silently used to hang until the job timeout, and
the stage was never re-run. One flaky TCP session cost a whole
45-minute apply, and the symptom - a job that stops mid-output with no
error - is what made the last few deploy failures expensive to read.

ServerAliveInterval/CountMax cap how long a dead peer goes unnoticed at
~60s, ConnectTimeout caps setup. Only exit 255 - ssh's own transport
failures - is retried, up to three attempts with a growing gap. A stage
that fails on its own merits exits with the remote's status, so a real
failure surfaces its own log immediately instead of being repeated three
times over 45 minutes. The stages are declarative applies, so re-running
one that had already committed is harmless.

The stage environment now goes through `env` as separate argv entries
rather than one interpolated string, so nothing in REPO, DEPLOY_SHA or
DEPLOY_SNAPSHOT_DIR is re-split by the remote shell.

Verified against a stubbed ssh: clean run attempts once, a single
transport failure recovers on attempt 2 and exits 0, three failures give
up preserving 255, and a stage failing with 1 or 7 attempts once and
passes the code through unchanged.

Also records why USERBOT_IMAGE stays on the prod tag: render_pinned
rewrites only plain `image:` lines, and this ref is what the panel
injects into the per-instance Deployments it creates, so those instances
track the tag rather than the panel's own resolved digest. The two
panel-created instances currently in the cluster are digest-pinned, so
the panel does accept one either way; the tag is the choice, not a
limitation.
2026-09-27 18:26:25 +02:00
forust 9b91b5847e fix(compose): stop pointing at the tag the build dropped
These five stacks still asked for :latest, but the build stopped pushing
it - on main it only pushes main and prod, on dev only dev. Every one of
these images therefore resolved only because the registry still had a
stale :latest from before that change, and the next time one of them was
actually built the reference would have dangled.

Named for dtek-notif: of the seven, only that one still resolved at
:prod, because it is the only image not rebuilt since the build dropped
:latest - and it is the only one of these five stacks the deploy does not
manage (no `active` marker, and its file is docker-compose.yaml, which
the COMPOSE_STACKS glob does not even match). Touching
dtek_notif/docker-compose.yaml matches dtek_notif/* in the build's
changed-service detector, so pushing this builds it and publishes
:prod for it too.

Verified the other six resolve at :prod in the registry.
2026-09-27 18:11:45 +02:00
forust ac0f845da6 fix(deploy): stop the panel from pointing at a tag the build dropped
ci / lint-compose (push) Successful in 3s
ci / lint-actionlint (push) Successful in 1s
ci / lint-shellcheck (push) Successful in 2s
ci / lint-prettier (push) Successful in 3s
ci / lint-ruff (push) Successful in 1s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / scan-deps (push) Successful in 15s
ci / test-backend (push) Successful in 7s
ci / test-frontend (push) Successful in 11s
renovate-ci / validate-renovate (push) Successful in 12s
ci / validate (push) Successful in 3s
ci / build (push) Successful in 37s
USERBOT_IMAGE named userbot:latest, but the build stopped pushing latest when
images became :prod. render_pinned resolves every gcr.forust.xyz reference it
finds in a manifest, not just the ones it rewrites, so that env var made the
whole apply abort with "cannot resolve userbot:latest; applying nothing".

Naming it :prod also makes the build job rebuild userbot, which is what
restores forust/userbot:prod - the tag is listed in the registry but its
manifest 404s, so the image: field in userbots.yaml had nothing to resolve
either.

Found by resolving every digest apply-k8s will need before spending a run on
it: 6 of 8 resolved, and both failures were userbot.
2026-09-27 16:14:43 +02:00
forustandClaude Opus 4.8 3a05d86e3e ci: run svelte-check, which was already a dependency with no script
svelte-check sits in devDependencies at ^4.7.3 and nothing in the repository
ever invoked it, so the type errors it reports had no path to a human. Point a
script at it and run it in the frontend job, and it is clean: 0 errors, 0
warnings.

It shares the one `npm ci` with the test step. A second install would have
doubled the slowest part of the job to learn exactly the same thing.

The lockfile is untouched, because scripts are not part of what it pins.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-27 10:24:18 +02:00
forustandClaude Opus 4.8 0ae0df7473 style: format the last 10 files that ruff format disagreed with
ruff.toml has declared `quote-style = "single"` and line-length 120 since the
lint job landed, and 118 of 128 files follow it. The panel backend and the
netbox configuration were written in black/prettier style instead, so a
`ruff format --check` would have failed on them from the start.

Bring them onto the style the repository already declares, which is what makes
the check adoptable at all. Formatting only: apart from quote style the diff is
multi-line expressions joined where they fit inside 120 columns.

Both suites still pass afterwards (25 pytest, and ruff check is clean).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-27 10:19:23 +02:00
forustandClaude Opus 4.8 0691536f28 fix(deploy): roll out our images by digest instead of a moving tag
`kubectl rollout undo` restores the previous ReplicaSet's pod template
verbatim. While that template names a tag, the rollback does not roll back
the image: the tag has already moved, so the reverted pod pulls the very
build that just failed and the cluster stays broken. The safety net added
in 1505b63 therefore could not recover from a bad image.

Pin the digest at apply time. A digest is not knowable when a manifest is
written, so render_pinned resolves it on the way into the cluster and the
digest is never committed. Git keeps a readable `:prod`, Renovate keeps
seeing exactly the manifests it saw before, and the previous revision of
each workload now holds the digest that was actually serving, so undo
restores those exact bytes.

imagePullPolicy is dropped from the manifests rather than set to
IfNotPresent: a reference that is not `:latest` already defaults to it, and
that is what the Kubernetes docs ask for alongside a digest.

An unresolvable image is fatal instead of a warning, because carrying on
would quietly apply a mutable tag again.

restart_stale_images keeps its comparison but is no longer how a rebuild
reaches the cluster -- the pinned template rolls out on its own now. What
is left is a drift check for hand-run `kubectl set image`, so it matches
the container by repository: a pod's status now reports `repo@sha256:...`
while the manifest still says `:prod`.

The build job stops pushing `:latest` altogether, which removes the tag
that a dev branch could otherwise move under a prod deploy.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-09-27 10:09:06 +02:00
forust a9eabfba02 fix(userbot): include internal-certificate in kustomize base 2026-09-23 15:52:32 +02:00
forust bc1e69ebe0 feat(tls): internal CA wildcard for *.internal routes
ci / lint-prettier (push) Successful in 2s
ci / lint-ruff (push) Successful in 0s
ci / lint-yaml (push) Successful in 2s
ci / lint-dockerfiles (push) Successful in 1s
ci / validate (push) Successful in 1s
ci / build (push) Skipped
ci / deploy-userbot-panel (push) Skipped
Selfsigned root (10y) + internal-ca issuer; per-namespace
internal-wildcard-tls certs referenced by all -local routers.
Root public cert committed for client trust stores.
2026-09-23 14:45:05 +02:00
forust d9f1c8325a feat(userbot): prereqs at startup, SPA path guard, provision lock
ci / lint-prettier (push) Failing after 8s
ci / lint-ruff (push) Successful in 4s
ci / lint-yaml (push) Failing after 7s
ci / lint-dockerfiles (push) Successful in 4s
ci / validate (push) Successful in 5s
deploy / redeploy (push) Failing after 0s
ci / build (push) Has been skipped
ci / deploy-userbot-panel (push) Has been skipped
- ensure_prerequisites runs on startup, not per-request; kube config
  errors surface as 503 PanelError
- serialize provisioning with a lock; drop per-endpoint prereq checks
- guard SPA fallback against path traversal (relative_to)
- add backend tests for auth flow, k8s service, spa routing; ci comment
  for legacy userbot deployments
2026-09-06 20:39:12 +02:00
forust 861d89d36a ci(deploy): split runtime by k8s/active marker
services marked k8s/active are applied via kubectl; the rest via docker
compose. inactive services with k8s/ keep only routing manifests
(external Services, EndpointSlices, Ingresses) to reach docker backends.
headscale/nextcloud routing moved to k8s/routing/.

validations: compose config --quiet + kubectl apply --dry-run=client.
namespace manifests applied first. pull_policy:build stacks get
build+push before up so the registry image stays fresh.
2026-09-06 20:39:12 +02:00
forust 71cddd6a91 feat(userbot): add Kubernetes control panel
Manage Telegram instances through Kubernetes with legacy adoption for forust and anna. Build and deploy the panel image alongside the runtime.
2026-09-06 20:39:12 +02:00
forust 9b3a7aadb4 fix: resolve pyrogram imports by adding venv and pyright config
lint / prettier (push) Successful in 7s
lint / ruff (push) Successful in 4s
lint / yamllint (push) Successful in 6s
lint / hadolint (push) Successful in 4s
validate / yaml (push) Successful in 5s
validate / k8s (push) Successful in 5s
- Create .venv with pyrofork and all dependencies installed
- Add pyrightconfig.json at workspace root and in userbot/
- Enable pyright as language server for Python in Zed settings
- Update uv.lock with resolved dependency tree
2026-06-21 22:33:04 +02:00
forust fb43306571 Fix all lint issues: Dockerfiles (DL3015/DL3013/DL4006) + Ruff (173→0 errors)
lint / prettier (push) Successful in 8s
lint / ruff (push) Successful in 5s
lint / yamllint (push) Successful in 7s
lint / hadolint (push) Failing after 4s
validate / yaml (push) Successful in 5s
validate / k8s (push) Successful in 5s
Dockerfile fixes:
- edu_master/phpsessid-bot: add --no-install-recommends, pin pip versions
- edu_master/webinar-checker: pin pip versions with --no-cache-dir
- userbot: add SHELL with pipefail for pipe operations

Ruff fixes (173 → 0):
- W293/W291/W292: whitespace clean via ruff format
- N806: camelCase → snake_case (anilist, safone, hearts, flux, etc.)
- ARG001/ARG002: prefix unused params with _
- SIM115: use context managers for file I/O
- SIM117: combine nested with statements
- S608: noqa on SQL f-strings (module name is validated)
- E402/N812/N817: import fixes
- B023: pass loop variable as argument
- I001: auto-sorted imports
- syntax: fixed = vs == in dtek_notif/main.py
2026-06-21 22:01:51 +02:00
forust 9364392bc0 Merge commit '3eaef5dc90b716cc0fa391cbe2394be56d5f6041' as 'userbot'
Deploy to Server / deploy (push) Has been cancelled
2026-06-19 23:20:23 +02:00
forust 69ffd3682e refactor: userbot to subtree 2026-06-19 23:20:13 +02:00
forust 1930600c40 Revert "refactor: extract userbot to standalone repo, add as git submodule"
This reverts commit 3c383db9a7.
2026-06-19 23:11:27 +02:00
forust 3c383db9a7 refactor: extract userbot to standalone repo, add as git submodule
Deploy to Server / deploy (push) Has been cancelled
userbot now lives at ssh://git@gitssh.forust.xyz:2221/forust/userbot.git
and is included in homelab as a submodule at userbot/
2026-06-19 15:39:00 +02:00
forust 227e5fda27 chore: batch lint fixes across userbot and edu_master
- S113: Add timeout=10 to all requests calls (74 fixes)
- E722: Replace bare except: with except Exception:
- B904: Replace redundant re-raise with bare raise
- E402: Add noqa for intentional late imports after import_library()
- S102/S307/S310/S311/S603/S605/S606/S607/S108: Add noqa for intentional usage
- F601: Fix duplicate dict key in unsplash.py
- N802: Rename ReplyCheck -> reply_check with backward compat alias
- N813: Rename bs -> BS in icons.py
- B007/B020: Rename loop var _j in animations.py
- SIM102: Collapse nested if in autofwd.py
- SIM113: Use enumerate() in calculator.py
- A002: Add noqa for builtin shadowing in admlist.py
- F811: Add noqa for cohere redefinition
- edu_master: Fix ARG001, S108, S110, SIM117, apply --unsafe-fixes
- Add modules_list.txt with full module inventory
2026-06-19 15:36:25 +02:00
forust 70d7855f06 fix(userbot): add missing safone.py imports, apply ruff --unsafe-fixes
- Add missing aiohttp, PIL, BytesIO imports to safone.py (F821 runtime bugs)
- Apply ruff --unsafe-fixes (27 fixes): ternary operators, .get() patterns,
  contextlib.suppress, enumerate(), collapsible if/else, remove .keys()
2026-06-19 15:27:12 +02:00
forust fc83176522 chore(userbot): optimize Dockerfile with multi-stage build and static ffmpeg
Deploy to Server / deploy (push) Has been cancelled
- Multi-stage build: pip deps built in separate stage
- Static ffmpeg binary instead of apt package (avoid 200+ deps)
- Keep only git, mediainfo, wget via apt
2026-06-19 14:56:37 +02:00
forust 0506aaaac8 chore(userbot): apply ruff check --fix and ruff format
- ruff check --fix: 210 auto-fixed errors (import sorting, trailing
  whitespace, unused imports, f-string fixups, deprecated annotations)
- ruff format: 104 files reformatted to consistent style
- 268 non-auto-fixable issues remain (S113 requests timeout, etc.)
2026-06-19 12:19:01 +02:00
forust 1362ebc3c2 chore(userbot): apply prettier formatting across manifests 2026-06-19 12:03:13 +02:00
forust 5f88ecf02b chore(k8s): make dockmon statefulset
+ adjusted userbot sys reqs
2026-06-10 19:40:45 +02:00
forust 1ea669220b chore(k8): adjusted system resources requests and limits based on manual monitoring 2026-06-10 19:37:16 +02:00
forust 7a3708f70c lint: yaml spaces and tabs 2026-06-09 12:59:36 +02:00
forust 0c5cf29f83 feat: add userbot k8s deployment method
Deploy to Server / deploy (push) Has been cancelled
- Kustomize: base + overlays/dev + overlays/prod
2026-06-07 19:41:28 +02:00
forust 43c38767a1 fix: removed git checkout (was destructive)
- Remove git init/fetch/checkout from utils/misc.py
- Hardcode userbot_version to 2.5.0
2026-06-07 19:40:52 +02:00
forust a68c01a68f chore: add gitea container registry compose support for localy builded apps
Deploy to Server / deploy (push) Has been cancelled
2026-06-07 14:37:57 +02:00
forust 526a2b617a refactor: update .dockerignore
pull_policy never to use local images
2026-05-25 01:43:46 +02:00
forust 1e08391e0e refactor: improved error handling, timeouts and use temp files 2026-05-21 22:14:29 +02:00
forust 0a31601b77 refactor: imporved layer caching for dockerfile
using existing built image for account 2
2026-05-21 22:12:33 +02:00
forust 17cae71952 refactor: userbots' compose-files cleanup 2025-12-09 21:45:24 +01:00
forust 6cb49be951 chore: update gitignore, add translations 2025-11-27 18:58:17 +01:00
forust 681cb3c3a1 Renamed userbot's dockercompose for easy access 2025-11-13 04:00:23 +01:00
forust 1dacf1d67c Remove unnecessary network and development configurations from userbot Docker Compose file 2025-11-13 03:48:50 +01:00
forust 9688ea3e7d Add userbot Docker Compose configuration for userbot_forust and userbot_anna services 2025-11-13 00:17:26 +01:00
forust 90d2abdf1d Move userbot Docker Compose configuration for forust and anna services 2025-11-11 01:57:44 +01:00
forust 51ace86b8d deleting that install shit 2025-11-11 01:41:24 +01:00
forust 750076b5f4 userbot/install.sh, start 2025-11-11 01:39:53 +01:00
forust 32aac89fdf init, .gitignore 2025-11-11 00:02:49 +01:00