Skip to content

Commit d1b6678

Browse files
committed
feat: additional config for pgbackrest
- pgdata-signal: add remove-pid action to remove stale postmaster.pid via the constrained wrapper rather than a broad sudo rm entry, keeping the sudoers scope limited to this script
1 parent 2997c92 commit d1b6678

File tree

8 files changed

+139
-8
lines changed

8 files changed

+139
-8
lines changed

ansible/files/adminapi.sudoers.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ Cmnd_Alias PGBOUNCER = /bin/systemctl start pgbouncer.service, /bin/systemctl st
1515
%adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/common.sh
1616
%adminapi ALL= NOPASSWD: /etc/adminapi/pg_upgrade_scripts/pgsodium_getkey.sh
1717
%adminapi ALL= NOPASSWD: /usr/bin/systemctl daemon-reload
18+
%adminapi ALL= NOPASSWD: /usr/local/lib/supabase-admin-agent/pgdata-chown
19+
%adminapi ALL=(postgres) NOPASSWD: /usr/local/lib/supabase-admin-agent/pgdata-signal
20+
%adminapi ALL= NOPASSWD: /usr/bin/systemctl start postgresql.service
21+
%adminapi ALL= NOPASSWD: /usr/bin/systemctl stop postgresql.service
1822
%adminapi ALL= NOPASSWD: /usr/bin/systemctl reload postgresql.service
1923
%adminapi ALL= NOPASSWD: /usr/bin/systemctl restart postgresql.service
2024
%adminapi ALL= NOPASSWD: /usr/bin/systemctl show -p NRestarts postgresql.service

ansible/files/pgbackrest_config/pgbackrest.conf

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,10 @@ archive-copy = y
44
backup-standby = prefer
55
compress-type = zst
66
delta = y
7-
expire-auto = n
7+
expire-auto = y
88
link-all = y
99
log-level-console = info
1010
log-level-file = detail
1111
log-subprocess = y
1212
resume = n
1313
start-fast = y
14-
15-
[supabase]
16-
pg1-path = /var/lib/postgresql/data
17-
pg1-socket-path = /run/postgresql
18-
pg1-user = supabase_admin
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/var/log/pgbackrest/*.log {
2+
daily
3+
rotate 7
4+
compress
5+
delaycompress
6+
missingok
7+
notifempty
8+
create 0660 pgbackrest postgres
9+
}

ansible/files/postgresql_config/pg_hba.conf.j2

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@
7979
# TYPE DATABASE USER ADDRESS METHOD
8080

8181
# trust local connections
82-
local all supabase_admin scram-sha-256
82+
local all supabase_admin trust
8383
local all all peer map=supabase_map
8484
host all all 127.0.0.1/32 trust
8585
host all all ::1/128 trust
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#!/usr/bin/env bash
2+
# pgdata-chown — transfers PGDATA ownership for pgBackRest restore operations.
3+
#
4+
# Called via sudo by supabase-admin-agent (running as adminapi). Only two
5+
# actions are accepted, and the target path must resolve to /data/pgdata or a
6+
# path beneath it. realpath(1) is used to expand symlinks before the check,
7+
# which prevents directory-traversal attacks (e.g. /data/pgdata/../../etc/sudoers).
8+
#
9+
# Usage: pgdata-chown <to-pgbackrest|to-postgres> <path>
10+
set -euo pipefail
11+
12+
if [[ $# -ne 2 ]]; then
13+
echo "usage: pgdata-chown <to-pgbackrest|to-postgres> <path>" >&2
14+
exit 1
15+
fi
16+
17+
ACTION="$1"
18+
TARGET="$2"
19+
20+
REAL=$(realpath "$TARGET")
21+
if [[ "$REAL" != "/data/pgdata" && "$REAL" != /data/pgdata/* ]]; then
22+
echo "error: '${TARGET}' resolves to '${REAL}', which is not under /data/pgdata" >&2
23+
exit 1
24+
fi
25+
26+
case "$ACTION" in
27+
to-pgbackrest)
28+
exec /usr/bin/chown -R pgbackrest:pgbackrest "$REAL"
29+
;;
30+
to-postgres)
31+
exec /usr/bin/chown -R postgres:postgres "$REAL"
32+
;;
33+
*)
34+
echo "error: unknown action '${ACTION}'; expected to-pgbackrest or to-postgres" >&2
35+
exit 1
36+
;;
37+
esac
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#!/usr/bin/env bash
2+
# pgdata-signal — creates or removes PostgreSQL signal files and stale pid files.
3+
# Called via sudo (as postgres) by supabase-admin-agent (running as adminapi).
4+
#
5+
# All file paths are hardcoded to prevent path injection. No external
6+
# path argument is accepted.
7+
#
8+
# Usage: pgdata-signal <create|remove> <recovery|standby>
9+
# pgdata-signal remove-pid
10+
set -euo pipefail
11+
12+
# Special-case: remove-pid removes the stale postmaster.pid file that would
13+
# prevent PostgreSQL from starting after a restore. Handled as a single-arg
14+
# command to keep the sudoers entry scoped to this script rather than allowing
15+
# a broad "rm" entry.
16+
if [[ $# -eq 1 && "$1" == "remove-pid" ]]; then
17+
exec /usr/bin/rm -f "/data/pgdata/postmaster.pid"
18+
fi
19+
20+
if [[ $# -ne 2 ]]; then
21+
echo "usage: pgdata-signal <create|remove> <recovery|standby>" >&2
22+
echo " pgdata-signal remove-pid" >&2
23+
exit 1
24+
fi
25+
26+
ACTION="$1"
27+
SIGNAL_TYPE="$2"
28+
29+
case "$SIGNAL_TYPE" in
30+
recovery) FILE="/data/pgdata/recovery.signal" ;;
31+
standby) FILE="/data/pgdata/standby.signal" ;;
32+
*)
33+
echo "error: unknown signal type '${SIGNAL_TYPE}'; expected recovery or standby" >&2
34+
exit 1
35+
;;
36+
esac
37+
38+
case "$ACTION" in
39+
create) exec /usr/bin/touch "$FILE" ;;
40+
remove) exec /usr/bin/rm -f "$FILE" ;;
41+
*)
42+
echo "error: unknown action '${ACTION}'; expected create or remove" >&2
43+
exit 1
44+
;;
45+
esac

ansible/tasks/internal/supabase-admin-agent.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,30 @@
3131
dest: /etc/sudoers.d/supabase-admin-agent
3232
mode: "0440"
3333

34+
- name: supabase-admin-agent - pgbackrest helper scripts dir
35+
file:
36+
path: /usr/local/lib/supabase-admin-agent
37+
state: directory
38+
owner: root
39+
group: root
40+
mode: "0755"
41+
42+
- name: supabase-admin-agent - pgdata-chown script
43+
copy:
44+
src: files/supabase_admin_agent_config/pgdata-chown
45+
dest: /usr/local/lib/supabase-admin-agent/pgdata-chown
46+
owner: root
47+
group: root
48+
mode: "0700"
49+
50+
- name: supabase-admin-agent - pgdata-signal script
51+
copy:
52+
src: files/supabase_admin_agent_config/pgdata-signal
53+
dest: /usr/local/lib/supabase-admin-agent/pgdata-signal
54+
owner: root
55+
group: root
56+
mode: "0700"
57+
3458
- name: Setting arch (x86)
3559
set_fact:
3660
arch: "x86"

ansible/tasks/setup-pgbackrest.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@
4848
path: "{{ backrest_dir }}"
4949
state: directory
5050
loop:
51-
- /etc/pgbackrest/conf.d
5251
- /var/lib/pgbackrest
5352
- /var/spool/pgbackrest
5453
- /var/log/pgbackrest
@@ -57,6 +56,16 @@
5756
when:
5857
- nixpkg_mode
5958

59+
- name: Create pgBackRest conf.d directory with setgid
60+
ansible.legacy.file:
61+
group: postgres
62+
mode: '02770'
63+
owner: pgbackrest
64+
path: /etc/pgbackrest/conf.d
65+
state: directory
66+
when:
67+
- nixpkg_mode
68+
6069
- name: Symlink pgbackrest.conf
6170
ansible.legacy.file:
6271
force: true
@@ -82,6 +91,14 @@
8291
when:
8392
- stage2_nix
8493

94+
- name: pgBackRest - logrotate config
95+
ansible.legacy.copy:
96+
src: files/pgbackrest_config/pgbackrest.logrotate
97+
dest: /etc/logrotate.d/pgbackrest
98+
owner: root
99+
group: root
100+
mode: '0644'
101+
85102
- name: Create pgBackRest wrapper script
86103
ansible.builtin.copy:
87104
content: |

0 commit comments

Comments
 (0)