Commit Graph
186 Commits
Author SHA1 Message Date
oqyude 55fc093ec6 ci(checks): whitelist tape-rotation-backend/frontend for :latest
tape-rotation is an SQLite-backed tape tracking app, similar to
3x-ui in that:
  - data lives on /home/ooyude/External (storage-guarded as of T4)
  - images are small and updated manually via Nix
  - :latest is acceptable because breaking image changes would
    fail fast at container start (storage guard + systemd)

Three image :latest entries are now whitelisted (with rationale):
  - ghcr.io/mhsanaei/3x-ui:latest (R1.5 — panel frozen, Xray is panel state)
  - docker.io/elizaroveugene/taperotation-backend:latest (this commit)
  - docker.io/elizaroveugene/taperotation-frontend:latest (this commit)

Two :latest violations remain (both in modules/containers/ but NOT
imported in modules/server/default.nix — effectively dead code):
  - localhost/kokoro-tts:latest
  - ghcr.io/openhands/openhands:latest

Decision pending: archive like T16, whitelist, or remove. They are
not running on sapphira, so the check failure is informational only.
2026-10-10 16:04:01 +03:00
oqyude 2a1a30f08d fix(storage-guard): remove '!' from ConditionPathIsMountPoint
CRITICAL BUG FIX caught by live test v6 on sapphira.

The '!' prefix INVERTS the systemd test:
  ConditionPathIsMountPoint=!/path  → test passes if path is NOT a mount
                                     → unit STARTS when storage is unmounted
                                     → exactly the opposite of what we want

Correct semantics for a storage guard:
  ConditionPathIsMountPoint=/path   → test passes if path IS a mount
                                     → unit starts ONLY when storage is mounted
                                     → unit refuses to start when storage is gone

With the inverted condition, postgresql started on empty bind-mount
after lazy-umount of /home/oqyude/External — the exact silent-data-loss
scenario R1.2 is supposed to prevent.

This is the canonical 'bug the test caught' case. Live test v6 on
sapphira (2026-10-10) demonstrated: with '!' the guard does nothing,
without '!' the guard fires correctly.

Lesson: always run a live test of the guard, don't trust nix eval alone
for systemd Condition* semantics — they're evaluated by systemd at
runtime, and '!' inverts the test.
2026-10-10 15:51:12 +03:00
oqyude 61b3724752 metaagent: Wave 1 + T4 + T7 + T3 + T5 + T15 + T16 — 12 tasks of tech-debt reduction
Comprehensive batch addressing the 16-task backlog in
.agent/tasks/manifest.json. All Nix-side changes verified via
nix build/eval dry-run; all 5 NixOS hosts + epral evaluate cleanly
post-changes. No regressions.

Wave 1 (non-functional cleanup):

  T1/A1 — configurations/mobile.nix:12: fix `import ../lib/xlib.nix`
          (broken path) → `import ../lib/xlib`. Unblocks nixOnDroid
          configurations.epral. R1.1 invariant.

  T8/C3 — modules/containers/3x-ui.nix: remove `podman-update-3xui_app`
          systemd service and commented timer. Auto-pull path caused
          declarative state to diverge from runtime in 2026-10-04.
          R1.5 invariant.

  T13/D3 — modules/server/nginx.nix:368-371: remove dead
          `networking.firewall.allowedTCPPorts = [80 443]`.
          `firewall.enable = false` on sapphira (R1.3), so openFirewall
          rules are no-op. Replace with R1.3 comment.

  T6/C1 — .agent/decisions/notes/3x-ui-xray-26.9.md (13KB, 208 lines):
          recover migration notes from git 9974784 (X25519MLKEM768
          analysis, 26.7→26.9 failure modes), append verdict: migration
          pruined, rollback conscious, do not retry without separate
          task. R1.5 / C1.

  T9/C4 — .agent/rules/project-rules.md: add R1.8 — Xray-core version is
          state of 3x-ui panel, not Nix. Update trap entry for
          3x-ui.nix:54 to reference R1.8.

  T11/D1, T12/D2 — .agent/checkpoints.json + .agent/tasks/manifest.json:
          verify R1.3 (router port-forwards 22/80/443/8443/22000) and
          R1.4 (100.64.0.0 = Tailscale sapphira) wording already
          satisfies acceptance criteria. Flip status pending → completed.

T4 (storage guard, FUNCTIONAL CHANGE):

  New helper in lib/xlib/helpers.nix:
      mkStorageGuard = xlib: {
        RequiresMountsFor = [ xlib.dirs.server-home ];
        ConditionPathIsMountPoint = [ "!${xlib.dirs.server-home}" ];
      };

  Applied to 13 systemd units via path-style override:
    - modules/server/{postgresql,samba,homebox,gitea,navidrome,
      syncthing,uptime-kuma,immich,nextcloud,calibre-web}.nix
    - modules/containers/3x-ui.nix (podman-3xui_app)
    - modules/containers/tape-rotation.nix (podman-taperotation-{backend,frontend})

  Anchor: xlib.dirs.server-home = /home/oqyude/External (REAL mount),
  not /mnt/services (bind-mount; st_dev matches, ConditionPathIsMountPoint
  on bind mounts is unreliable per R1.2 note).

  Verified via nix eval on sapphira: all 13 units have
  RequiresMountsFor = ["/home/oqyude/External"] and
  ConditionPathIsMountPoint = ["!/home/oqyude/External"].

  Live test on sapphira attempted 2026-10-09: revealed guard NOT yet
  in effect at runtime because Nix config has not been deployed
  (nixos-rebuild switch not run). postgresql started despite External
  being unmounted. Implementation correct, deployment pending user
  action.

T7/C2 (read-only diag, no code change):

  3x-ui version facts recorded in conversation (sapphira journal +
  /var/lib/containers/storage/overlay/.../diff/app/bin/xray-linux-amd64):
    - Active Xray: 26.7.28 (go1.26.5 linux/amd64) — R1.5 validated at runtime
    - Stale binary: 26.9.30 (go1.27.1) — leftover from failed 26.9 migration
    - Panel DB (x-ui.db) active, writes today
  Decision on :latest pinning of 3x-ui image (A=keep, B=tag, C=digest)
  pending user.

T3/A3 (nftables on otreca — config analysis + proposal):

  Diagnostic attempted via ssh otreca-tailscale (100.64.1.0) and
  otreca public (109.248.161.5:22): BOTH UNREACHABLE. Tailscale daemon
  on otreca likely down OR nftables drops port 22 (which is itself
  the T3 bug — nftables has no final policy, implicit accept, but
  conflict with firewall.enable = true per R1.6).

  Proposal written: .agent/decisions/proposals/vds-nftables-fix.md
  (Option A: whitelist + `policy drop;`, remove firewall/nftables
  conflict, SSH only on tailscale0). Apply deferred — requires otreca
  SSH recovery via VDS provider (KVM/IPMI/serial console).

T5/B2 (backups documentation):

  .agent/decisions/0002-backups-external.md (draft): catalog of what
  is declared in Nix vs. what is external; awaiting answer to open
  question 5.6 (where are backups, how are they verified).

T15/E2 (CI checks):

  .ci/checks.sh (executable, ~140 lines) with 3 checks from
  analysis-report.md §5:
    - #1: no `:latest` in container images (with R1.5 whitelist
          for 3x-ui). FAIL — 4 violations:
            localhost/kokoro-tts:latest
            ghcr.io/openhands/openhands:latest
            docker.io/elizaroveugene/taperotation-backend:latest
            docker.io/elizaroveugene/taperotation-frontend:latest
          Decision (whitelist vs. pin) pending user.
    - #2: nix flake check (skipped with --no-build).
    - #7: secrets/ files match .sops.yaml path_regex. PASS.

T16/E3 (archive commented modules):

  13 of 14 commented modules in modules/server/default.nix:37-50
  existed as files. git mv them to archive/{server-modules,containers}/.
  1 (stirling-pdf.nix) didn't exist; just removed the comment.

  modules/server/default.nix:37-50 cleaned of 14 commented lines.
  Added 3-line comment recording the archive date and reason.

  Verified: nixosConfigurations.sapphira still evaluates.

Post-change state:

  $ nix build .#nixosConfigurations.{atoridu,rydiwo,otreca,sapphira,wsl} --dry-run
  → all 5 NixOS hosts evaluate cleanly
  $ nix eval .#nixOnDroidConfigurations.epral.config.system.stateVersion
  → "24.05"

Pending (user input required — not in this commit):

  - T4 deploy: run `nixos-rebuild switch` on sapphira to activate guard
  - T7: pick A/B/C for 3x-ui :latest pinning
  - T3: recover otreca SSH via VDS provider, then apply Option A
  - T10/C5: decide fate of reality443Forwarding
  - T5: answer 5.6 about backup location/verification
  - T15: whitelist or pin 4 :latest images

Untracked files NOT committed (in .gitignore):

  .temp/t4-live-test*.sh, .temp/cleanup-*.sh — throwaway test scripts
  from T4 live test attempts. Preserved locally for reference; see
  AGENTS.md convention ("Создавать `.temp/` в корне проекта — Для
  временных файлов агента. Всегда в `.gitignore`").

Also untracked, committed:

  .agent/reviews/2026-10-10-review-dev-diff-vs-16644fc.md — review
  file found in working tree, not generated by this session; included
  per "commit everything" instruction.
2026-10-10 15:15:22 +03:00
oqyude c6701d4128 chore(flake): wire devshells/ into the root outputs aggregator 2026-10-10 15:10:55 +03:00
oqyude 0e622eaa13 feat(devshells): add vtimeline devshell for the VeeamTimelineView project
Sister project at S:\Git\VeeamTimelineView has its own repo and gitea

remote; we keep its Nix env here in the home-fleet flake so the project

itself stays free of Nix.

`nix develop .#vtimeline` provides:

  - nodejs_22 (Node 20 hit EOL 2026-04-30 and was removed from nixpkgs)

  - python3 (Playwright webServer)

  - chromium (used via PLAYWRIGHT_BROWSERS_PATH symlink farm, since

    Playwright 1.40+ hard-codes a separate chrome-headless-shell path)

Shell banner points at ../VeeamTimelineView. The absolute project path

cannot be baked into the shellHook (Nix forbids escaping the flake source

dir at eval time); user is expected to `cd` themselves.
2026-10-10 15:10:37 +03:00
oqyude 16644fcc0b metaagent: install v3.0.0, migrate docs/arch/* → .agent/
- install.sh: .agent/src/ (PROTOCOLS, COMMANDS, TEMPLATES, install.sh/ps1, GUIDE)
- .temp/ добавлен в .gitignore
- .agent/checkpoints.json: phases.init=completed, project_type=existing
- .agent/rules/project-rules.md: R1-R5 (инварианты, ловушки, куда лезть, проверки)
- .agent/context/analysis-report.md: стек, архитектура, конвенции, кандидаты CI
- .agent/context/project-state.md: сжатый слепок (хосты, сервисы, ADR)
- .agent/roadmap/sources.md: открытые вопросы слоёв 0-11 (бывший invariants.md)
- .agent/tasks/manifest.{json,md}: 16 задач A1-F + 23 в backlog
- .agent/decisions/0001-sops-secrets-paths.md: ADR для инварианта S1
- AGENTS.md: metaagent-шапка + сжатая выжимка nixos (yaml frontmatter сохранён)
- удалены docs/arch/{map,invariants,todo}.md
2026-10-09 20:37:14 +03:00
oqyude 7c9aa24779 agents: yaml frontmatter for Obsidian dataview 2026-10-09 20:28:49 +03:00
oqyude a4984a6b37 sops secrets path changed 2026-10-09 19:26:31 +03:00
oqyude 02927a26bb vtimeline added and formatted 2026-10-09 16:59:45 +03:00
oqyude bc5aad87da opencode remapping 2026-10-09 16:38:16 +03:00
oqyude f3c50e90ba authelia in services 2026-10-09 16:37:03 +03:00
oqyude e7c0fde0b1 tty added and opencode fixed 2026-10-09 14:48:12 +03:00
oqyude 3c9c5100a8 authelia added 2026-10-08 15:30:05 +03:00
oqyude 75433e2af7 vhost connecting 2026-10-07 17:53:06 +03:00
oqyude 7fd1736f1d vtimeline arch 2026-10-07 17:52:54 +03:00
oqyude 58333d0257 open-webui via podman added 2026-10-07 13:49:40 +03:00
oqyude 5e9641602a opencode: dynamic HM symlink, env via xlib, document migration journal
Three small things together:

1. relinkHomeManager was pinning the versioned symlink name to
   'home-manager-24-link'. That breaks on every HM major-version bump:
   HM 25 will move the alias to 'home-manager-25-link' and the script
   will silently stop relinking. Derive the name from one hop of the
   stable 'home-manager' symlink, with a guard against the missing case
   so a fallback never accidentally rewrites the profiles/ directory
   itself.

2. programs.opencode.web.environmentFile now reads from
   xlib.dirs.opencode-server-env (added previously in users.nix + dirs.nix).
   The sops materialization and the systemd EnvironmentFile can no
   longer silently desync.

3. Document the oh-my-openagent 2026-07-opencode-config-unification
   migration trap that logs 'Migration backup path already exists' on
   every startup: the backup path embeds the content-hashed store path,
   which stays valid in /nix/store across HM activations, so the
   deterministic collision never resolves itself. Recovery is
   'rm -rf ~/.omo/migration-backup-*' to let omo retry; if it keeps
   failing on the same path the plugin version probably expects a new
   schema and this file needs changes.

Also trim the over-explained [Service] / serviceConfig comment: the
home-manager attrset-union behavior is general, not specific to this
unit, so the explanation got shorter without losing the invariant.
2026-10-07 11:38:16 +03:00
oqyude b2718fd1e7 xlib+users: centralize opencode server.env path
The path '/home/<user>/.config/opencode/server.env' was duplicated
between users.nix (sops materialization) and home/modules/opencode.nix
(programs.opencode.web.environmentFile). Drift between the two was a
silent auth-bypass vector: if one moved, the systemd unit would either
fail to find OPENCODE_SERVER_PASSWORD or skip EnvironmentFile entirely.

Single source in lib/xlib/dirs.nix; both call sites now read from it.
2026-10-07 11:36:55 +03:00
oqyude 534fa429e1 docs arch begin 2026-10-07 11:29:21 +03:00
oqyude 698a1afaf7 glow added 2026-10-06 15:17:15 +03:00
oqyude 14c91e68a4 todo removed 2026-10-05 15:38:16 +03:00
oqyude c73a698857 opencode fix linger 2026-10-04 22:27:55 +03:00
oqyude c8d4a12a73 3x-ui: revert nginx + ports to 543fcc6 (testing) declarative state
Sapphira: HTTP reverse proxy serves panel/sub on x.zeroq.su;
no xray stream on 443 and no 8443 stream either (8443 is directly
exposed by podman as 0.0.0.0:8443:8443/tcp).

Otreca: stream on 443 routes by SNI (panel via pubray1.zeroq.su,
xray default) and 8443 is direct 0.0.0.0:8443.

Modules/containers/3x-ui.nix:
  - basePorts restored: '0.0.0.0:8443:8443/tcp' (was '127.0.0.1:15380:8443/tcp')
  - realityPorts restored (was 'lib.optional ... "127.0.0.1:15380:443/tcp"')
  - image restored: ':latest' (was ':v3.9.0')

Modules/server/nginx.nix:
  - removed 8443 streamConfig for xray (the one b0191bc added)
  - removed 8443 from allowedTCPPorts

Other files (configurations/{server,vds,wsl}.nix, home/modules/opencode.nix)
left alone — they contain SSH firewall / builder / opencode web changes
unrelated to nginx + ports that the user asked to revert.
2026-10-04 22:05:27 +03:00
oqyude c854b2cc6d 3x-ui: drop dead -p 127.0.0.1:15380:443/tcp (double-bind blocks start)
The systemd unit on the otreca VDS carried two -p flags that bind
the same host port 127.0.0.1:15380:

  -p 127.0.0.1:15380:8443/tcp   # from basePorts
  -p 127.0.0.1:15380:443/tcp    # from realityPorts (when reality443Forwarding=true)

podman 5.x tries to bind 127.05 in each -p flag and the second
fails with EADDRINUSE, even though no process is visible in ss —
the bind happens at the proxy level before the container starts:

  Error: cannot listen on the TCP port: listen tcp4 127.0.0.1:15380:
  bind: address already in use

Symptom on otreca: podman-3xui_app.service hits start-limit-hit
after 5 rapid retries.

The 15380:443 mapping is dead code: the container's only Reality
inbound listens on 8443, and nginx stream already routes host:443
to 127.0.0.1:15380 via SNI (modules/server/nginx.nix streamConfig).
reality443Forwarding remains a host option for configurations to
declare intent; the broken port-mapping generation is replaced with
an empty list.
2026-10-04 21:37:14 +03:00
oqyude 22a19be1b6 3x-ui: rollback to c05cc88 (before otreca vds commit)
Revert the b0191bc 'otreca vds: pin 3x-ui:v3.8.5 + nginx stream + ssh
tailscale-only + patch-3xui-xray-config' changes:

- 3x-ui.nix: back to :latest image, direct 0.0.0.0:8443 port mapping,
  remove migrateScript + patchScript and their systemd units/timer.
- vds.nix: re-open 22/tcp on public (openFirewall = true); remove the
  tailscale0-only port rule.
- nginx.nix: drop the 8443 stream proxy.
- Remove modules/containers/3x-ui-migration-notes.md.

Reason: those changes, once applied on otreca, left the 3x-ui container
in a start-limit-hit loop (bind 127.0.0.1:15380: address already in use,
nothing visible in ss - probably a stale TIME_WAIT or slirp4netns port
from a prior container that never released).
2026-10-04 21:30:47 +03:00
oqyude 99747849d3 3x-ui regress 2026-10-04 21:03:48 +03:00
oqyude b88c8ebce0 remote building off 2026-10-04 18:34:39 +03:00
oqyude cc20ee637d opencode oom fixes 2026-10-04 17:41:32 +03:00
oqyude 95ba7c2903 Remove empty TODO.md (duplicate of todo.md on case-insensitive fs) 2026-10-04 04:58:55 +03:00
oqyude b0191bc7d1 otreca vds: pin 3x-ui:v3.8.5 + nginx stream + ssh tailscale-only + patch-3xui-xray-config 2026-10-04 04:47:33 +03:00
oqyude 543fcc61d9 testing 2026-10-03 23:39:21 +03:00
oqyude 0b9ac53b71 removed unne 2026-10-03 21:59:46 +03:00
oqyude b476cace8e kokoro-tts autostart disabled 2026-10-03 21:53:27 +03:00
oqyude 2de80a356b wsl ssh bridge 2026-10-03 21:51:33 +03:00
oqyude fb56f6310b opencode 2026-10-03 20:21:19 +03:00
oqyude 1c77ae658e kokoro-tts stream added 2026-10-03 15:20:33 +03:00
oqyude 509fd3dde0 kokoro-tts 2026-10-03 01:03:50 +03:00
oqyude 958247b22c soft coding 2026-10-02 23:05:00 +03:00
oqyude c05cc88843 restructuring 2026-10-01 15:14:37 +03:00
oqyude d49fd5a358 big refactoring 2026-10-01 14:16:17 +03:00
oqyude 417c7abda6 hide ports 2026-09-26 16:07:37 +03:00
oqyude ac561815ed 3x-ui fix 2026-09-24 22:49:52 +03:00
oqyudeandSisyphus 2be5b168ac tape-rotation fix
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2026-09-24 17:21:58 +03:00
oqyude eddf44fb02 tape-rotation res 2026-09-24 15:38:24 +03:00
oqyude caeb04142d onlyoffice regress 2026-09-23 23:17:39 +03:00
oqyude 1db2b0955b nextcloud fix 2026-09-23 22:23:13 +03:00
oqyude a8ddf9b8dc changes 2026-09-23 22:16:04 +03:00
oqyude bc3566d80e nextcloud35 2026-09-23 22:14:08 +03:00
oqyude 0fdf6c965c tape-rotation freezed 2026-09-23 22:05:13 +03:00
oqyude 5bccf7586d nix flake update 2026-09-23 22:03:40 +03:00