Skip to content
Merged
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
5 changes: 5 additions & 0 deletions nixos/doc/manual/release-notes/rl-2411.section.md
Original file line number Diff line number Diff line change
Expand Up @@ -602,6 +602,11 @@

- `iproute2` now has libbpf support.

- `postgresql` is now [hardened by default](#module-services-postgres-hardening) using the common `systemd` settings for that.

If you use extensions that are not packaged in nixpkgs, please review whether it still works
with the current settings and adjust accordingly if needed.

- `nix.channel.enable = false` no longer implies `nix.settings.nix-path = []`.
Since Nix 2.13, a `nix-path` set in `nix.conf` cannot be overriden by the `NIX_PATH` configuration variable.

Expand Down
18 changes: 18 additions & 0 deletions nixos/modules/services/databases/postgresql.md
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,24 @@ postgresql.withJIT.pname

evaluates to `"foobar"`.

## Service hardening {#module-services-postgres-hardening}

The service created by the [`postgresql`-module](#opt-services.postgresql.enable) uses
several common hardening options from `systemd`, most notably:

* Memory pages must not be both writable and executable (this only applies to non-JIT setups).
* A system call filter (see {manpage}`systemd.exec(5)` for details on `@system-service`).
* A stricter default UMask (`0027`).
* Only sockets of type `AF_INET`/`AF_INET6`/`AF_NETLINK`/`AF_UNIX` allowed.
* Restricted filesystem access (private `/tmp`, most of the file-system hierachy is mounted read-only, only process directories in `/proc` that are owned by the same user).

The NixOS module also contains necessary adjustments for extensions from `nixpkgs`
if these are enabled. If an extension or a postgresql feature from `nixpkgs` breaks
with hardening, it's considered a bug.

When using extensions that are not packaged in `nixpkgs`, hardening adjustments may
become necessary.

## Notable differences to upstream {#module-services-postgres-upstream-deviation}

- To avoid circular dependencies between default and -dev outputs, the output of the `pg_config` system view has been removed.
39 changes: 39 additions & 0 deletions nixos/modules/services/databases/postgresql.nix
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,46 @@ in
TimeoutSec = 120;

ExecStart = "${postgresql}/bin/postgres";

# Hardening
CapabilityBoundingSet = [ "" ];
DevicePolicy = "closed";
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = "strict";
MemoryDenyWriteExecute = lib.mkDefault (cfg.settings.jit == "off");
NoNewPrivileges = true;
LockPersonality = true;
PrivateDevices = true;
PrivateMounts = true;
ProcSubset = "pid";
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectProc = "invisible";
RemoveIPC = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
"AF_NETLINK" # used for network interface enumeration
"AF_UNIX"
];
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use plv8 extension and the database server crashes every time a query using plv8 function is called:

postgres[2325667]: [2325667] LOG:  server process (PID 2327131) was terminated by signal 31: Bad system call

Is there a way to determine which system calls are needed?

I tried

SystemCallFilter = [ "" ];
SystemCallLog = [ "@privileged ~@resources ~@system-service" ];

but it only made it crash with

Nov 10 15:43:06 azazel postgres[2336657]: #
Nov 10 15:43:06 azazel postgres[2336657]: # Fatal error in , line 0
Nov 10 15:43:06 azazel postgres[2336657]: # Check failed: 12 == (*__errno_location ()).
Nov 10 15:43:06 azazel postgres[2336657]: #
Nov 10 15:43:06 azazel postgres[2336657]: #
Nov 10 15:43:06 azazel postgres[2336657]: #
Nov 10 15:43:06 azazel postgres[2336657]: #FailureMessage Object: 0x7ffff76dee30
Nov 10 15:43:06 azazel postgres[2336657]: ==== C stack trace ===============================
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::base::debug::StackTrace::StackTrace()+0x16) [0x7f056f00e386]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(+0xb12e4a) [0x7f056ead7e4a]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(V8_Fatal(char const*, ...)+0x17a) [0x7f056e8aacea]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(+0x8de83d) [0x7f056e8a383d]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::MemoryAllocator::SetPermissionsOnExecutableMemoryChunk(v8::internal::VirtualMemory*, unsigned long, unsigned long, unsigned long)+0xfa) [0x7f056ea4222a]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::MemoryAllocator::AllocateAlignedMemory(unsigned long, unsigned long, unsigned long, v8::internal::AllocationSpace, v8::internal::Executability, void*, v8::internal::VirtualMemory*)+0x1f5) [0x7f056ea42505]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::MemoryAllocator::AllocateUninitializedChunkAt(v8::internal::BaseSpace*, unsigned long, v8::internal::Executability, unsigned long, v8::internal::PageSize)+0x96) [0x7f056ea42606]
Nov 10 15:43:06 azazel kernel: traps: postgres[387266] trap int3 ip:7f056e8a3b2e sp:7ffff76dee08 error:0 in plv8-3.2.3.so[7f056e7e7000+1b90000]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::MemoryAllocator::AllocatePage(v8::internal::MemoryAllocator::AllocationMode, v8::internal::Space*, v8::internal::Executability)+0x7e) [0x7f056ea42d8e]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::PagedSpaceBase::TryExpandImpl()+0x2c) [0x7f056ea56d0c]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::PagedSpaceBase::TryExpand(int, v8::internal::AllocationOrigin)+0x1f) [0x7f056ea58a0f]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::PagedSpaceBase::RawRefillLabMain(int, v8::internal::AllocationOrigin)+0x416) [0x7f056ea593d6]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::PagedSpaceBase::RefillLabMain(int, v8::internal::AllocationOrigin)+0x28) [0x7f056ea596c8]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment)+0x5e1) [0x7f056e9c6201]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::Factory::CodeBuilder::AllocateInstructionStream(bool)+0x7d) [0x7f056e9ac52d]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::Factory::CodeBuilder::BuildInternal(bool)+0x21b) [0x7f056e9ac95b]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::compiler::CodeGenerator::FinalizeCode()+0x16c) [0x7f056fe8ba7c]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::compiler::PipelineImpl::FinalizeCode(bool)+0x4ef) [0x7f056f1753ef]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::compiler::PipelineCompilationJob::FinalizeJobImpl(v8::internal::Isolate*)+0x70) [0x7f056f1763e0]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::OptimizedCompilationJob::FinalizeJob(v8::internal::Isolate*)+0x44) [0x7f056e8b8234]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::Compiler::FinalizeTurbofanCompilationJob(v8::internal::TurbofanCompilationJob*, v8::internal::Isolate*)+0x40b) [0x7f056e8be13b]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::OptimizingCompileDispatcher::InstallOptimizedFunctions()+0xc9) [0x7f056e8f24a9]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::StackGuard::HandleInterrupts()+0x1e0) [0x7f056e981590]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(v8::internal::Runtime_StackGuard(int, unsigned long*, v8::internal::Isolate*)+0xb9) [0x7f056f3adef9]
Nov 10 15:43:06 azazel postgres[2336657]:     /nix/store/5nvfkms6x5nkaaq44w0xw7ph5dg051y6-postgresql-and-plugins-14.13/lib/plv8-3.2.3.so(+0xf1def6) [0x7f056eee2ef6]
Nov 10 15:43:06 azazel postgres[2336019]: [2336019] LOG:  server process (PID 2336657) was terminated by signal 5: Trace/breakpoint trap
Nov 10 15:43:06 azazel postgres[2336019]: [2336019] DETAIL:  Failed process was running: with recent_event as (select id from event where level = 'world' and "end" < current_date and "end" > '2022-01-01' order by "end" desc limit 2), past_team as (select *, 0.5 as coef, 6 as ceiling, position_in_class(age, 'ultraveteran') over (w order by score desc, time asc) as position_uv, count(nullif(is_in_class(age, 'ultraveteran'), false)) over w as limit_uv, position_in_class(age, 'superveteran') over (w order by score desc, time asc) as position_sv, count(nullif(is_in_class(age, 'superveteran'), false)) over w as limit_sv, position_in_class(age, 'veteran') over (w order by score desc, time asc) as position_v, count(nullif(is_in_class(age, 'veteran'), false)) over w as limit_v, position_in_class(age, 'open') over (w order by score desc, time asc) as position_o, count(nullif(is_in_class(age, 'open'), false)) over w as limit_o, position_in_class(age, 'junior') over (w order by score desc, time asc) as position_j, count(nullif(is_in_class(age, 'junior'), false)) over w as limit_j from team where event_id in
Nov 10 15:43:06 azazel postgres[2336019]: [2336019] LOG:  terminating any other active server processes
Nov 10 15:43:06 azazel node[2333506]: Error: Connection terminated unexpectedly
Nov 10 15:43:06 azazel node[2333506]:     at /nix/store/yq48bpc7clgjrybghnz5a57fnsw4scb4-wrcq-0-unstable-2024-10-22/node_modules/pg-pool/index.js:45:11
Nov 10 15:43:06 azazel node[2333506]:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Nov 10 15:43:06 azazel node[2333506]:     at async file:///nix/store/yq48bpc7clgjrybghnz5a57fnsw4scb4-wrcq-0-unstable-2024-10-22/index.js:309:32
Nov 10 15:43:06 azazel postgres[2336665]: [2336665] FATAL:  the database system is in recovery mode
Nov 10 15:43:06 azazel node[2333506]: ::1 - - [10/Nov/2024:14:43:06 +0000] "GET /qualified HTTP/1.0" 500 -
Nov 10 15:43:06 azazel node[2333506]: error: the database system is in recovery mode
Nov 10 15:43:06 azazel node[2333506]:     at /nix/store/yq48bpc7clgjrybghnz5a57fnsw4scb4-wrcq-0-unstable-2024-10-22/node_modules/pg-pool/index.js:45:11
Nov 10 15:43:06 azazel node[2333506]:     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
Nov 10 15:43:06 azazel node[2333506]:     at async PGStore._asyncQuery (/nix/store/yq48bpc7clgjrybghnz5a57fnsw4scb4-wrcq-0-unstable-2024-10-22/node_modules/connect-pg-simple/index.js:322:21)
Nov 10 15:43:06 azazel postgres[2336019]: [2336019] LOG:  all server processes terminated; reinitializing
Nov 10 15:43:06 azazel postgres[2336666]: [2336666] LOG:  database system was interrupted; last known up at 2024-11-10 14:42:55 GMT
Nov 10 15:43:06 azazel postgres[2336666]: [2336666] LOG:  database system was not properly shut down; automatic recovery in progress
Nov 10 15:43:06 azazel postgres[2336666]: [2336666] LOG:  redo starts at 2/9F5C7BE0
Nov 10 15:43:06 azazel postgres[2336666]: [2336666] LOG:  invalid record length at 2/9F5CEE68: wanted 24, got 0
Nov 10 15:43:06 azazel postgres[2336666]: [2336666] LOG:  redo done at 2/9F5CEE28 system usage: CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s
Nov 10 15:43:06 azazel postgres[2336019]: [2336019] LOG:  database system is ready to accept connections

Reverting this whole PR works as a workaround.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if the system call filter is the issue, you should see an error in the kernel log (or auditd, I'm not entirely sure).

But given that this is v8, there might be another problem: can you try setting MemoryDenyWriteExecute to false?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to set up a vm test for plv8 - then we could just bisect through the list of changes?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

then we could just bisect through the list of changes?

I guess I would've just turned off more and more flags until it works. But yeah.

@jtojnar never used this extension, but any chance you can share a reproducer?

Copy link
Member

@jtojnar jtojnar Nov 10, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even just calling ALTER EXTENSION plv8 UPDATE; was enough to trigger the crash for me. Maybe the example select from https://plv8.github.io/ would work too. Not sure if I will be able to create a test today, maybe sometime during the week.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, tried adding SystemCallFilter = [ "@pkey" ]; and got the errno fatal error above. Adding MemoryDenyWriteExecute = false; as well made it work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know what triggers the second error? Would be nice to be able to repro.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a pretty big SQL query including custom window functions:

Original query
WITH
  recent_event AS (
    SELECT
      id
    FROM
      event
    WHERE
      level = 'world'
      AND "end" < CURRENT_DATE
      AND "end" > '2022-01-01'
    ORDER BY
      "end" DESC
    LIMIT
      2
  ),
  past_team AS (
    SELECT
      *,
      0.5 AS coef,
      6 AS CEILING,
      position_in_class (age, 'ultraveteran') OVER (
        w
        ORDER BY
          score DESC,
          time ASC
      ) AS position_uv,
      count(nullif(is_in_class (age, 'ultraveteran'), FALSE)) OVER w AS limit_uv,
      position_in_class (age, 'superveteran') OVER (
        w
        ORDER BY
          score DESC,
          time ASC
      ) AS position_sv,
      count(nullif(is_in_class (age, 'superveteran'), FALSE)) OVER w AS limit_sv,
      position_in_class (age, 'veteran') OVER (
        w
        ORDER BY
          score DESC,
          time ASC
      ) AS position_v,
      count(nullif(is_in_class (age, 'veteran'), FALSE)) OVER w AS limit_v,
      position_in_class (age, 'open') OVER (
        w
        ORDER BY
          score DESC,
          time ASC
      ) AS position_o,
      count(nullif(is_in_class (age, 'open'), FALSE)) OVER w AS limit_o,
      position_in_class (age, 'junior') OVER (
        w
        ORDER BY
          score DESC,
          time ASC
      ) AS position_j,
      count(nullif(is_in_class (age, 'junior'), FALSE)) OVER w AS limit_j
    FROM
      team
    WHERE
      event_id IN (
        SELECT
          *
        FROM
          recent_event
      )
    WINDOW
      w AS (
        PARTITION BY
          event_id,
          gender
      )
  ),
  past_team_crit AS (
    SELECT
      *,
      (
        position_uv <= CEILING
        AND position_uv <= ceil(limit_uv * coef)
      ) AS prequalified_uv,
      (
        position_sv <= CEILING
        AND position_sv <= ceil(limit_sv * coef)
      ) AS prequalified_sv,
      (
        position_v <= CEILING
        AND position_v <= ceil(limit_v * coef)
      ) AS prequalified_v,
      (
        position_o <= CEILING
        AND position_o <= ceil(limit_o * coef)
      ) AS prequalified_o,
      (
        position_j <= CEILING
        AND position_j <= ceil(limit_j * coef)
      ) AS prequalified_j
    FROM
      past_team
  )
SELECT
  *
FROM
  member
  LEFT JOIN past_team_crit ON member.event_id = past_team_crit.event_id
  AND member.team_id = past_team_crit.id
WHERE
  prequalified_uv
  OR prequalified_sv
  OR prequalified_v
  OR prequalified_o
  OR prequalified_j;

I managed to pare it down slightly but it is not clear what is causing it:

Reduced query
WITH
  recent_event AS (
    SELECT
      id
    FROM
      event
    WHERE
      level = 'world'
      AND "end" < CURRENT_DATE
      AND "end" > '2022-01-01'
    ORDER BY
      "end" DESC
    LIMIT
      2
  ),
  past_team AS (
    SELECT
      *,
      0.5 AS coef,
      6 AS CEILING,
      position_in_class (age, 'ultraveteran') OVER (
        w
        ORDER BY
          score DESC,
          time ASC
      ) AS position_uv,
      count(nullif(is_in_class (age, 'ultraveteran'), FALSE)) OVER w AS limit_uv
    FROM
      team
    WHERE
      event_id IN (
        SELECT
          *
        FROM
          recent_event
      )
    WINDOW
      w AS (
        PARTITION BY
          event_id,
          gender
      )
  )
SELECT
  *,
  (
    position_uv <= CEILING
    AND position_uv <= ceil(limit_uv * coef)
  ) AS prequalified_uv
FROM
  past_team

Curiously, the crash triggers if I remove ultraveteran category or if I only keep ultraveteran category, but not when I keep any other category. I should really move the logic out of SQL.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that is probably too big for a reproducer in a nixos test. Either way #355010 should be ready to go. Feel free to pick that into your tree, if that fits your workflow.

Copy link
Member

@jtojnar jtojnar Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, so looking at nodejs/node#55509, it is probably indeed caused by V8 turning on JIT.

I managed to make PLV8 (presumably) enable JIT with the following:

DO $$
let xs = [];
for (let i = 0, n = 4000000000; i < n; i++) {
    xs.push(Math.round(Math.random() * n))
}
console.log(Math.sum(xs));
$$ LANGUAGE plv8;

"@system-service"
"~@privileged @resources"
];
UMask = if groupAccessAvailable then "0027" else "0077";
}
(mkIf (cfg.dataDir != "/var/lib/postgresql") {
ReadWritePaths = [ cfg.dataDir ];
})
(mkIf (cfg.dataDir == "/var/lib/postgresql/${cfg.package.psqlSchema}") {
StateDirectory = "postgresql postgresql/${cfg.package.psqlSchema}";
StateDirectoryMode = if groupAccessAvailable then "0750" else "0700";
Expand Down
9 changes: 7 additions & 2 deletions nixos/tests/postgresql-wal-receiver.nix
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ let
replicationUser = "wal_receiver_user";
replicationSlot = "wal_receiver_slot";
replicationConn = "postgresql://${replicationUser}@localhost";
baseBackupDir = "/tmp/pg_basebackup";
walBackupDir = "/tmp/pg_wal";
baseBackupDir = "/var/cache/wals/pg_basebackup";
walBackupDir = "/var/cache/wals/pg_wal";

recoveryFile = pkgs.writeTextDir "recovery.signal" "";

Expand All @@ -32,6 +32,10 @@ let
meta.maintainers = with lib.maintainers; [ pacien ];

nodes.machine = { ... }: {
systemd.tmpfiles.rules = [
"d /var/cache/wals 0750 postgres postgres - -"
];

services.postgresql = {
package = pkg;
enable = true;
Expand Down Expand Up @@ -60,6 +64,7 @@ let
# This is only to speedup test, it isn't time racing. Service is set to autorestart always,
# default 60sec is fine for real system, but is too much for a test
systemd.services.postgresql-wal-receiver-main.serviceConfig.RestartSec = lib.mkForce 5;
systemd.services.postgresql.serviceConfig.ReadWritePaths = [ "/var/cache/wals" ];
};

testScript = ''
Expand Down
2 changes: 2 additions & 0 deletions nixos/tests/postgresql.nix
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ let
with subtest("Initdb works"):
machine.succeed("sudo -u postgres initdb -D /tmp/testpostgres2")

machine.log(machine.execute("systemd-analyze security postgresql.service | grep -v ✓")[1])

machine.shutdown()
'';

Expand Down