Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions nix/docs/site-profile.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Site profile

The `site-env-15`, `site-env-17`, and `site-env-orioledb-17` package sets are deployed to `/nix/var/nix/profiles/site`. They hold supautils, and `activate`.
The `site-env-15`, `site-env-17`, and `site-env-orioledb-17` package sets are deployed to `/nix/var/nix/profiles/site`. They hold supautils, `activate`, and `site-nix-gc`.

`dynamic_library_path` in `postgresql.conf` includes `/nix/var/nix/profiles/site/lib/postgresql` first, then `$libdir`. supautils also remains in `$libdir`, pending cleanup.

Expand All @@ -19,6 +19,8 @@ nix-env --profile /nix/var/nix/profiles/site --set <store path>

`activate` runs after the switch. It sets up supautils, and gatekeeper where present, idempotently. If it fails, the new generation stays active. Run `activate` again, or roll back.

`site-nix-gc` keeps the current generation and one older one for the site, postgres, and default profiles. It then runs `nix-store --gc` to completion. With systemd it runs in a throttled transient unit. Without systemd it runs under `nice` and `ionice`.

## Roll back

```sh
Expand All @@ -28,7 +30,7 @@ nix-env --profile /nix/var/nix/profiles/site --rollback

Rollback switches to the previous generation. `activate` then runs from that generation and makes the machine match it. There is no separate rollback script.

To go further back than the previous generation, install an older version by path.
`site-nix-gc` keeps the current generation and one older one. To go further back, install an older version by path.

New sessions load supautils from the rolled-back profile. Open sessions keep the copy they loaded until they reconnect. Postgres does not restart. A restart applies the change to every session at once.

Expand Down
35 changes: 34 additions & 1 deletion nix/packages/site-env.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,38 @@
'';
};

# Prunes old generations, then runs nix-store --gc. Throttled by a transient systemd unit, or by nice and ionice without systemd.
site-nix-gc = writeHostBash "site-nix-gc" ''
prune() { nix-env --profile "$1" --delete-generations +2; }
prune /nix/var/nix/profiles/site
prune /nix/var/nix/profiles/default
if [[ -L /var/lib/postgresql/.nix-profile ]]; then
prune "$(readlink /var/lib/postgresql/.nix-profile)"
fi

export NIX_REMOTE=local
gc=("$(command -v nix-store)" --gc --quiet)

if [[ -d /run/systemd/system ]]; then
if systemctl is-active --quiet site-nix-gc; then
echo "Garbage collection already running."
exit 0
fi
systemd-run \
--unit=site-nix-gc --collect --no-block --setenv=NIX_REMOTE=local \
-p Nice=19 -p CPUSchedulingPolicy=idle -p CPUQuota=20% \
-p IOSchedulingClass=idle -p IOWeight=1 -p IOWriteBandwidthMax="/nix 20M" \
-p MemoryHigh=10% -p MemoryMax=15% -p OOMScoreAdjust=1000 \
-p RuntimeMaxSec=2h \
"''${gc[@]}" && exit 0
echo "systemd-run failed. Running in the foreground."
fi

throttle=(nice -n 19)
command -v ionice >/dev/null && throttle+=(ionice -c 3)
exec "''${throttle[@]}" "''${gc[@]}"
'';

makeSiteEnv =
version: extraPaths:
let
Expand All @@ -42,9 +74,10 @@
paths = [
supautils
activate
site-nix-gc
]
++ extraPaths;
passthru = { inherit activate; };
passthru = { inherit activate site-nix-gc; };
};

siteEnvs = {
Expand Down
11 changes: 11 additions & 0 deletions nix/tests/site.nix
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,17 @@ pkgs.testers.runNixOSTest {
machine.succeed("su postgres -c '${psql_17}/bin/psql -h /tmp -d postgres -c \"select 1\"'")
machine.succeed("su postgres -c '${psql_17}/bin/pg_ctl -D /tmp/pgdata stop'")

# site-nix-gc runs to the end and reports what it freed
machine.succeed("nix-store --gc")
machine.succeed("echo garbage > /tmp/garbage && nix-store --add /tmp/garbage")
machine.succeed("nix-env --profile /nix/var/nix/profiles/default --set $(dirname $(dirname $(readlink -f $(command -v nix-env))))")
machine.succeed("${site-env-17}/bin/activate")
machine.succeed("${site-env-17}/bin/site-nix-gc")
machine.wait_until_fails("systemctl is-active site-nix-gc", timeout=1800)
print(machine.succeed("journalctl -u site-nix-gc --no-pager | grep freed"))

# without systemd the gc runs in the foreground
machine.succeed("mount -t tmpfs none /run/systemd")
machine.succeed("${site-env-17}/bin/site-nix-gc 2>&1 | grep freed")
'';
}
Loading