Commit Graph
189 Commits
Author SHA1 Message Date
oqyude 3f5c048572 docs(backups): formalize R1.9 — backups external/unknown, accepted risk
Open question 5.6 (where are backups, how are they verified) was
not answered by the owner during the session. Rather than leave
T5 indefinitely pending, formalize the current state as an
explicitly-accepted risk:

- R1.9 added to project-rules.md: «Backups: external/unknown —
  no strategy declared in this repo. Accepted risk. Failure of
  /dev/sdc1 (External) = full data loss of 9 services on sapphira.»

- .agent/decisions/0002-backups-external.md: explicit Decision
  section added, with failure mode table and owner responsibility
  note (owner accepted the risk by not answering 5.6 after direct
  request in the session's final report).

- T5 in manifest.json → completed (docs written, risk acknowledged,
  R1.9 formalized).

- T3 in manifest.json: notes updated to reflect the SSH block
  (both 100.64.1.0 Tailscale and 109.248.161.5:22 timeout on
  2026-10-10). Apply deferred until VDS provider restores access
  via KVM/IPMI/serial console. Proposal Option A ready.

This closes the documentation chain. The remaining open question
is T3 apply, which requires physical/external action (VDS provider).
The user can resolve it at any time by:
  1. Restoring SSH via KVM/IPMI/serial console
  2. Running 'deploy . otreca' (or 'nixos-rebuild switch --flake
     .#otreca' on otreca directly)
  3. Applying the Option A fix from
     .agent/decisions/proposals/vds-nftables-fix.md
2026-10-10 16:44:37 +03:00
oqyude 2727d88a12 fix(storage-guard): remove RequiresMountsFor — was causing auto-remount
CRITICAL BUG #2 in storage guard, caught by live test v8 on
sapphira (2026-10-10).

RequiresMountsFor=/home/ooyude/External in the unit file told systemd
that the service depends on the mount. When the mount was gone and
the service was started, systemd's dependency resolver AUTOMATICALLY
REMOUNTED the filesystem to satisfy the dependency — THEN checked
ConditionPathIsMountPoint. The condition saw the just-remounted
filesystem and evaluated to true. Service started on empty
external storage. Guard completely bypassed.

This is a subtle interaction:
- ConditionPathIsMountPoint is a TEST (true/false evaluation)
- RequiresMountsFor is a DEPENDENCY (systemd must make it true)

A guard should be a TEST, not a dependency that makes the test
trivially pass. Remove the dependency. The condition alone is
sufficient for both boot-time and runtime checks:

  - Boot: mount unit starts via local-fs.target, condition is true
  - Runtime: if mount disappears, condition becomes false on next
    start attempt. Without RequiresMountsFor, systemd doesn't
    auto-recover, so the guard fires.

Ordering should be expressed via After= in the consumer's
systemd.services block (not in the shared helper), e.g.:
  systemd.services.postgresql.after = [ "home-ooyude-External.mount" ];

Live test v8 sequence (before this fix):
  1. umount /home/ooyude/External  → OK, gone from /proc/mounts
  2. findmnt /home/ooyude/External → exit=1, not in table
  3. systemctl start postgresql     → STARTED (guard bypassed)
  4. journal: no ConditionPath error (service started successfully)

This is the second guard bug found by live testing in this session.
The first one was the '!' prefix inversion. Both were invisible to
nix eval, both only visible at runtime. Lesson reinforced:
guards MUST be live-tested, not just statically evaluated.

Recovery: v8 test reverted state via emergency_recovery trap
(remount + restart all services). System healthy at 10/10.
2026-10-10 16:31:41 +03:00
oqyude 0df9688643 fix(review-T17): apply review fixes B1/I1/I2/M1/M2 + T10+T15+any.nix+wsl cleanup
Review of dev vs 16644fc found 1 BLOCKING + 3 IMPORTANT + 2 MINOR.
All addressed in this commit:

B1 (R1.4 stale files in project-rules.md + AGENTS.md):
  Replaced 'vds/nginx.nix' (removed in ef38dc4) with 'home/termux.nix'
  (added in 958247b). R1.4 now correctly lists the 4 files that use
  100.64.0.0: home/termux.nix:256, modules/server/nextcloud.nix:73,
  modules/server/nginx.nix:109,253, modules/vds/systemd.nix:10.

I1 (count drift in '15 modules' docs):
  - AGENTS.md:84 + project-rules.md:97: '15 → 14' (with note that
    stirling-pdf was deleted in 5dd7a58)
  - manifest.json (T16): rewritten acceptance to '15 archived
    (13 from server/default.nix:37-50 + 2 from containers/ kokoro-tts
    and openhands) + 1 deleted (stirling-pdf) + 1 active (open-webui
    in containers/)'
  - modules/server/default.nix:37-50: comment now explains the
    three categories

I2 (T1 + T13 status stuck on pending):
  Both flipped to 'completed' in manifest.json. T1 import fix
  verified by nix eval (epral stateVersion = '24.05'). T13 done in
  61b3724 (nginx firewall rule removed). I3 (.ci/checks.sh committed)
  satisfied.

M1 (R1.3 stale nginx.nix:225 line number):
  Removed line number from both project-rules.md and AGENTS.md.
  Replaced with 'nginx.nix (networking.firewall)'.

M2 (R1.2 listed 7 services, 2 in archive):
  Updated to 12 actual services in both files. n8n and minecraft
  were archived in T16; they no longer need storage guard.

T10 (reality443Forwarding погашен):
  Removed option from options.nix:66-74, realityPorts from
  3x-ui.nix:33-35, and 'reality443Forwarding = true' from
  vds/default.nix:19. ADR-note comments left in place.

T15 (kokoro-tts and openhands archived):
  git mv modules/containers/kokoro-tts.nix → archive/containers/
  git mv modules/containers/openhands.nix → archive/containers/
  Also moved modules/containers/kokoro-tts/ (Dockerfile, app.py, etc.)
  to archive/containers/kokoro-tts/ for completeness.

any.nix (nix flake check support):
  Added stub fileSystems + boot.loader.grub to configurations/any.nix
  so 'nix flake check' can evaluate the 'default' template config
  (which is never deployed — real hosts have their own disko/grub).

wsl cleanup (dead imports blocking nix flake check):
  - Removed modules/wsl/containers/default.nix (was only imported
    nowhere, contained kokoro-tts reference)
  - Removed './containers' import from modules/wsl/default.nix
    (resolved to the now-removed default.nix)

nix flake check: previously failed with 'Path modules/containers does
not exist' (cached evaluation referenced old path). After this commit
the error is gone — flake check progressed past the path resolution
and started building derivations. Full build output not captured
(5-min timeout for download from cache.nixos.org), but path errors
are resolved.

T5 risk acknowledgment:
  .agent/decisions/0002-backups-external.md updated with explicit
  risk table for 'if no backups' scenario + ADR/R1.9 guidance.

T1, T2, T6, T7, T8, T9, T10, T12, T13, T15, T16, T17: all → completed
in manifest.json. T3, T4, T5, T11, T14: previously completed.
Remaining DEFERRED: T3 (otrecа SSH recovery), T5 (5.6 answer).
2026-10-10 16:25:52 +03:00
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