4 Commits

Author SHA1 Message Date
chexit 6775a88ca8 feat(yami): add dataDir option for storing stack state on separate disk
- Bind-mounts /var/lib/{gitea,postgresql} under configurable dataDir
- gitea-runner intentionally excluded: its DynamicUser + StateDirectory
  conflicts with pre-existing mount points ("File exists")
- Runner token moved to /var/lib/gitea-runner-secret/ to avoid the same
  symlink/StateDirectory conflict inside /var/lib/gitea-runner
- Enable the stack on this host with dataDir = /mnt/ssd_110/yami
2026-04-19 18:54:28 +03:00
chexit a83500e382 docs(yami): note that runner tokenFile must be env-file format (TOKEN=...) 2026-04-19 18:23:56 +03:00
chexit ecf8b5974a fix(yami): tmpfiles for runner token must use root (DynamicUser has no static user) 2026-04-19 18:17:24 +03:00
chexit 6a2fb0970c fix(yami): use services.gitea.lfs.enable instead of raw LFS_START_SERVER
Raw LFS_START_SERVER made gitea try to generate and persist LFS_JWT_SECRET
into app.ini, which NixOS intentionally keeps read-only. The lfs.enable
helper lets the module own the secret and wire it in correctly.
2026-04-19 18:00:03 +03:00
2 changed files with 62 additions and 7 deletions
+7 -1
View File
@@ -7,7 +7,7 @@
./desktop.nix ./desktop.nix
./nvidia.nix ./nvidia.nix
./shell.nix ./shell.nix
# ./yami-dev-stack.nix # uncomment to enable Yami dev stack, then set services.yami-dev-stack below ./yami-dev-stack.nix
]; ];
nix = { nix = {
@@ -98,5 +98,11 @@
# Docker is now managed by yami-dev-stack.nix when that module is enabled. # Docker is now managed by yami-dev-stack.nix when that module is enabled.
# services.yami-dev-stack = { enable = true; user = "chexit"; }; # services.yami-dev-stack = { enable = true; user = "chexit"; };
services.yami-dev-stack = {
enable = true;
user = "chexit";
dataDir = "/mnt/ssd_110/yami";
};
system.stateVersion = "25.11"; system.stateVersion = "25.11";
} }
+54 -5
View File
@@ -13,9 +13,20 @@ in
type = types.str; type = types.str;
description = "User that will own runner token and be added to docker group"; description = "User that will own runner token and be added to docker group";
}; };
dataDir = mkOption {
type = types.nullOr types.path;
default = null;
example = "/mnt/ssd_110/yami";
description = ''
If set, bind-mounts /var/lib/{gitea,postgresql,gitea-runner} under this
path so all stack data lives on a separate disk. Directories are created
automatically; existing data must be rsync'd manually before enabling.
'';
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable (mkMerge [ {
# ── Systemd target ───────────────────────────────────────────────────────── # ── Systemd target ─────────────────────────────────────────────────────────
# Manual-only: nothing in wantedBy, so it never starts on boot. # Manual-only: nothing in wantedBy, so it never starts on boot.
@@ -48,6 +59,10 @@ in
enable = true; enable = true;
appName = "Yami Git"; appName = "Yami Git";
# LFS enabled via the NixOS helper so the module manages LFS_JWT_SECRET
# (writing it to app.ini, which is read-only by design).
lfs.enable = true;
database = { database = {
type = "postgres"; type = "postgres";
socket = "/run/postgresql"; socket = "/run/postgresql";
@@ -63,7 +78,6 @@ in
HTTP_PORT = 3000; HTTP_PORT = 3000;
SSH_PORT = 2222; SSH_PORT = 2222;
START_SSH_SERVER = true; START_SSH_SERVER = true;
LFS_START_SERVER = true;
}; };
service = { service = {
@@ -125,7 +139,11 @@ in
enable = true; enable = true;
name = "home-runner"; name = "home-runner";
url = "http://localhost:3000"; url = "http://localhost:3000";
tokenFile = "/var/lib/gitea-runner/token"; # NOT under /var/lib/gitea-runner — that path is systemd-managed for the
# service (DynamicUser + StateDirectory means it becomes a symlink to
# /var/lib/private/gitea-runner). Pre-creating it ourselves breaks the
# service with "Failed to set up special execution directory: File exists".
tokenFile = "/var/lib/gitea-runner-secret/token";
labels = [ labels = [
"ubuntu-latest:docker://node:20" "ubuntu-latest:docker://node:20"
"native:host" "native:host"
@@ -139,9 +157,14 @@ in
requires = [ "gitea.service" "docker.service" ]; requires = [ "gitea.service" "docker.service" ];
}; };
# Directory for the runner token file; owner matches the runner service user. # Runner uses DynamicUser, so there's no static gitea-runner user/group.
# Token lives in a sibling dir (not /var/lib/gitea-runner — that's systemd's
# StateDirectory and pre-creating it breaks DynamicUser bind setup).
# The file MUST be in env-file format, not a raw token:
# TOKEN=<paste-registration-token-from-gitea-ui>
# Get the token from Site Administration → Actions → Runners → Create new Runner.
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [
"d /var/lib/gitea-runner 0700 gitea-runner gitea-runner -" "d /var/lib/gitea-runner-secret 0700 root root -"
]; ];
# ── Shell aliases ────────────────────────────────────────────────────────── # ── Shell aliases ──────────────────────────────────────────────────────────
@@ -155,5 +178,31 @@ in
# ── Firewall ─────────────────────────────────────────────────────────────── # ── Firewall ───────────────────────────────────────────────────────────────
# Merged with existing rules (Steam etc.); does not overwrite them. # Merged with existing rules (Steam etc.); does not overwrite them.
networking.firewall.allowedTCPPorts = [ 3000 2222 ]; networking.firewall.allowedTCPPorts = [ 3000 2222 ];
}
# ── Optional: move all stack data to a separate disk via bind-mounts ─────────
(mkIf (cfg.dataDir != null) (
let
# gitea-runner intentionally NOT bind-mounted: its service uses
# DynamicUser + StateDirectory, which refuses to adopt an existing
# mount point ("Failed to set up special execution directory: File exists").
# Its data is tiny (token + .runner state) so it stays on the system disk.
subs = [ "gitea" "postgresql" ];
mkBind = name: {
name = "/var/lib/${name}";
value = {
device = "${cfg.dataDir}/${name}";
fsType = "none";
options = [ "bind" ];
}; };
};
in {
# Ensure target dirs exist on the data disk before mounts happen.
systemd.tmpfiles.rules = map (n: "d ${cfg.dataDir}/${n} 0755 root root -") subs
++ [ "d ${cfg.dataDir} 0755 root root -" ];
fileSystems = listToAttrs (map mkBind subs);
}
))
]);
} }