supabase-postgres.git / summary / log / commit / refs
commit dcbaa6dd72fdd4c305ebd82301d9ec9582cbfd12
Author: Crispy <12525875+Crispy1975@users.noreply.github.com>
Commit: GitHub <noreply@github.com>
Date: Thu Jul 03 09:24:14 2025 +0000
feat: add the supabase admin agent to the ami build (#1679)
* feat: add the supabase admin agent to the ami build
* chore: bump saa
* chore: underscore versus dashes
* chore: correc the uri
* chore: omg squash this later
* chore: xz to gz for saa
.github/workflows/nix-build.yml | 10 +--
.github/workflows/testinfra-ami-build.yml | 14 ++--
ansible/files/permission_check.py | 10 +++
.../supabase-admin-agent.sudoers.conf | 2 +
.../supabase-admin-agent_salt.service | 19 +++++
.../supabase-admin-agent_salt.timer | 13 ++++
ansible/tasks/internal/supabase-admin-agent.yml | 87 ++++++++++++++++++++++
ansible/tasks/setup-supabase-internal.yml | 17 +++--
ansible/vars.yml | 7 +-
9 files changed, 158 insertions(+), 21 deletions(-)
diff --git a/.github/workflows/nix-build.yml b/.github/workflows/nix-build.yml
index d562ab6c..36dc01d0 100644
--- a/.github/workflows/nix-build.yml
+++ b/.github/workflows/nix-build.yml
@@ -79,19 +79,19 @@ jobs:
trusted-public-keys = nix-postgres-artifacts:dGZlQOvKcNEjvT7QEAJbcV6b6uk7VF/hWMjhYleiaLI=% cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
- name: Build psql bundle
run: >
- nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48"
- -- --skip-cached --no-nom
- --flake ".#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem')"
+ nix run "github:Mic92/nix-fast-build?rev=b1dae483ab7d4139a6297e02b6de9e5d30e43d48"
+ -- --skip-cached --no-nom
+ --flake ".#checks.$(nix eval --raw --impure --expr 'builtins.currentSystem')"
env:
AWS_ACCESS_KEY_ID: ${{ env.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ env.AWS_SECRET_ACCESS_KEY }}
AWS_SESSION_TOKEN: ${{ env.AWS_SESSION_TOKEN }}
-
+
run-testinfra:
needs: build-run-image
if: ${{ success() }}
uses: ./.github/workflows/testinfra-ami-build.yml
-
+
run-tests:
needs: build-run-image
if: ${{ success() }}
diff --git a/.github/workflows/testinfra-ami-build.yml b/.github/workflows/testinfra-ami-build.yml
index 8544f1b8..321430c8 100644
--- a/.github/workflows/testinfra-ami-build.yml
+++ b/.github/workflows/testinfra-ami-build.yml
@@ -37,7 +37,7 @@ jobs:
ubuntu_release: focal
ubuntu_version: 20.04
mcpu: neoverse-n1
- runs-on: ${{ matrix.runner }}
+ runs-on: ${{ matrix.runner }}
timeout-minutes: 150
permissions:
contents: write
@@ -73,7 +73,7 @@ jobs:
echo 'postgres-version = "'$PG_VERSION'"' > common-nix.vars.pkr.hcl
# Ensure there's a newline at the end of the file
echo "" >> common-nix.vars.pkr.hcl
-
+
- name: Build AMI stage 1
run: |
packer init amazon-arm64-nix.pkr.hcl
@@ -84,7 +84,7 @@ jobs:
run: |
packer init stage2-nix-psql.pkr.hcl
GIT_SHA=${{github.sha}}
- packer build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${GITHUB_RUN_ID}" -var "postgres_major_version=${POSTGRES_MAJOR_VERSION}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "postgres-version=${{ steps.random.outputs.random_string }}" -var "region=ap-southeast-1" -var 'ami_regions=["ap-southeast-1"]' -var "force-deregister=true" -var "git_sha=${GITHUB_SHA}" stage2-nix-psql.pkr.hcl
+ packer build -var "git-head-version=${GIT_SHA}" -var "packer-execution-id=${GITHUB_RUN_ID}" -var "postgres_major_version=${POSTGRES_MAJOR_VERSION}" -var-file="development-arm.vars.pkr.hcl" -var-file="common-nix.vars.pkr.hcl" -var "postgres-version=${{ steps.random.outputs.random_string }}" -var "region=ap-southeast-1" -var 'ami_regions=["ap-southeast-1"]' -var "force-deregister=true" -var "git_sha=${GITHUB_SHA}" stage2-nix-psql.pkr.hcl
- name: Run tests
timeout-minutes: 10
@@ -93,8 +93,8 @@ jobs:
run: |
# TODO: use poetry for pkg mgmt
pip3 install boto3 boto3-stubs[essential] docker ec2instanceconnectcli pytest pytest-testinfra[paramiko,docker] requests
- pytest -vv -s testinfra/test_ami_nix.py
-
+ pytest -vv -s testinfra/test_ami_nix.py
+
- name: Cleanup resources on build cancellation
if: ${{ cancelled() }}
run: |
@@ -111,7 +111,7 @@ jobs:
# Define AMI name patterns
STAGE1_AMI_NAME="supabase-postgres-ci-ami-test-stage-1"
STAGE2_AMI_NAME="${{ steps.random.outputs.random_string }}"
-
+
# Function to deregister AMIs by name pattern
deregister_ami_by_name() {
local ami_name_pattern=$1
@@ -121,7 +121,7 @@ jobs:
aws ec2 deregister-image --region ap-southeast-1 --image-id $ami_id
done
}
-
+
# Deregister AMIs
deregister_ami_by_name "$STAGE1_AMI_NAME"
deregister_ami_by_name "$STAGE2_AMI_NAME"
diff --git a/ansible/files/permission_check.py b/ansible/files/permission_check.py
index a753f69e..46f458f9 100644
--- a/ansible/files/permission_check.py
+++ b/ansible/files/permission_check.py
@@ -94,11 +94,17 @@ expected_results = {
"systemd-coredump": [
{"groupname": "systemd-coredump", "username": "systemd-coredump"}
],
+ "supabase-admin-agent": [
+ {"groupname": "supabase-admin-agent", "username": "supabase-admin-agent"},
+ {"groupname": "admin", "username": "supabase-admin-agent"},
+ {"groupname": "salt", "username": "supabase-admin-agent"},
+ ],
}
# postgresql.service is expected to mount /etc as read-only
expected_mount = "/etc ro"
+
# This program depends on osquery being installed on the system
# Function to run osquery
def run_osquery(query):
@@ -154,6 +160,7 @@ def check_nixbld_users():
print("All nixbld users are in the 'nixbld' group.")
+
def check_postgresql_mount():
# processes table has the nix .postgres-wrapped path as the
# binary path, rather than /usr/lib/postgresql/bin/postgres which
@@ -182,6 +189,7 @@ def check_postgresql_mount():
print("postgresql.service mounts /etc as read-only.")
+
def main():
parser = argparse.ArgumentParser(
prog="Supabase Postgres Artifact Permissions Checker",
@@ -234,6 +242,7 @@ def main():
"postgrest",
"tcpdump",
"systemd-coredump",
+ "supabase-admin-agent",
]
if not qemu_artifact:
usernames.append("ec2-instance-connect")
@@ -251,5 +260,6 @@ def main():
# Check if postgresql.service is using a read-only mount for /etc
check_postgresql_mount()
+
if __name__ == "__main__":
main()
diff --git a/ansible/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf b/ansible/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf
new file mode 100644
index 00000000..6896e2f0
--- /dev/null
+++ b/ansible/files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf
@@ -0,0 +1,2 @@
+%supabase-admin-agent ALL= NOPASSWD: /usr/bin/salt-call
+%supabase-admin-agent ALL= NOPASSWD: /usr/bin/gpg --homedir {{ gpgdir }} --import, /usr/bin/gpg --homedir {{ gpgdir }} --list-secret-keys *
diff --git a/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service
new file mode 100644
index 00000000..92f1d2e3
--- /dev/null
+++ b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.service
@@ -0,0 +1,19 @@
+[Unit]
+Description=Configuration management via supabase-admin-agent salt
+After=network.target
+
+[Service]
+Type=oneshot
+ExecStart=/opt/supabase-admin-agent/supabase-admin-agent --config /opt/supabase-admin-agent/config.yaml salt --apply --store-result
+User=supabase-admin-agent
+Group=supabase-admin-agent
+StandardOutput=journal
+StandardError=journal
+StateDirectory=supabase-admin-agent
+CacheDirectory=supabase-admin-agent
+
+# Security hardening
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
diff --git a/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer
new file mode 100644
index 00000000..8044c2e1
--- /dev/null
+++ b/ansible/files/supabase_admin_agent_config/supabase-admin-agent_salt.timer
@@ -0,0 +1,13 @@
+[Unit]
+Description=Run Supabase supabase-admin-agent salt on a schedule
+Requires=supabase-admin-agent_salt.service
+
+[Timer]
+OnCalendar=*:0/10
+# Random delay up to {{ splay }} seconds splay
+RandomizedDelaySec={{ splay }}
+AccuracySec=1s
+Persistent=true
+
+[Install]
+WantedBy=timers.target
diff --git a/ansible/tasks/internal/supabase-admin-agent.yml b/ansible/tasks/internal/supabase-admin-agent.yml
new file mode 100644
index 00000000..4e5f87e5
--- /dev/null
+++ b/ansible/tasks/internal/supabase-admin-agent.yml
@@ -0,0 +1,87 @@
+- name: supabase-admin-agent - system group
+ group:
+ name: supabase-admin-agent
+ system: yes
+
+- name: supabase-admin-agent - system user
+ user:
+ name: supabase-admin-agent
+ group: supabase-admin-agent
+ groups: admin,salt
+ append: yes
+ system: yes
+ shell: /bin/sh
+
+- name: supabase-admin-agent - config dir
+ file:
+ path: /opt/supabase-admin-agent
+ owner: supabase-admin-agent
+ state: directory
+
+- name: supabase-admin-agent - gpg dir
+ file:
+ path: /etc/salt/gpgkeys
+ owner: root
+ group: salt
+ state: directory
+
+- name: give supabase-admin-agent user permissions
+ copy:
+ src: files/supabase_admin_agent_config/supabase-admin-agent.sudoers.conf
+ dest: /etc/sudoers.d/supabase-admin-agent
+ mode: "0644"
+
+- name: Setting arch (x86)
+ set_fact:
+ arch: "x86"
+ when: platform == "amd64"
+
+- name: Setting arch (arm)
+ set_fact:
+ arch: "arm64"
+ when: platform == "arm64"
+
+- name: Download supabase-admin-agent archive
+ get_url:
+ url: "https://supabase-public-artifacts-bucket.s3.amazonaws.com/supabase-admin-agent/v{{ supabase_admin_agent_release }}/supabase-admin-agent-{{ supabase_admin_agent_release }}-linux-{{ arch }}.tar.gz"
+ dest: "/tmp/supabase-admin-agent.tar.gz"
+ timeout: 90
+
+- name: supabase-admin-agent - unpack archive in /opt
+ unarchive:
+ remote_src: yes
+ src: /tmp/supabase-admin-agent.tar.gz
+ dest: /opt/supabase-admin-agent/
+ owner: supabase-admin-agent
+ extra_opts:
+ - --strip-components=1
+
+- name: supabase-admin-agent - create symlink
+ ansible.builtin.file:
+ path: /opt/supabase-admin-agent/supabase-admin-agent
+ src: "/opt/supabase-admin-agent/supabase-admin-agent-linux-{{ arch }}"
+ state: link
+ owner: supabase-admin-agent
+ mode: "0755"
+ force: yes
+
+- name: supabase-admin-agent - create salt systemd timer file
+ copy:
+ src: files/supabase_admin_agent_config/supabase-admin-agent_salt.timer
+ dest: /etc/systemd/system/supabase-admin-agent_salt.timer
+
+- name: supabase-admin-agent - create salt service file
+ copy:
+ src: files/supabase_admin_agent_config/supabase-admin-agent_salt.service
+ dest: /etc/systemd/system/supabase-admin-agent_salt.service
+
+- name: supabase-admin-agent - reload systemd
+ systemd:
+ daemon_reload: yes
+
+# Initially ensure supabase-admin-agent is installed but not started
+- name: supabase-admin-agent - DISABLE service
+ systemd:
+ name: supabase-admin-agent_salt
+ enabled: no
+ state: stopped
diff --git a/ansible/tasks/setup-supabase-internal.yml b/ansible/tasks/setup-supabase-internal.yml
index 7aa93176..d5583b59 100644
--- a/ansible/tasks/setup-supabase-internal.yml
+++ b/ansible/tasks/setup-supabase-internal.yml
@@ -34,19 +34,19 @@
aws configure set default.s3.use_dualstack_endpoint true
- name: install Vector for logging
- become: yes
+ become: true
apt:
deb: "{{ vector_x86_deb }}"
when: platform == "amd64"
- name: install Vector for logging
- become: yes
+ become: true
apt:
deb: "{{ vector_arm_deb }}"
when: platform == "arm64"
- name: add Vector to postgres group
- become: yes
+ become: true
shell:
cmd: |
usermod -a -G postgres vector
@@ -72,21 +72,21 @@
daemon_reload: yes
- name: Create checkpoints dir
- become: yes
+ become: true
file:
path: /var/lib/vector
state: directory
owner: vector
- name: Include file for generated optimizations in postgresql.conf
- become: yes
+ become: true
replace:
path: /etc/postgresql/postgresql.conf
regexp: "#include = '/etc/postgresql-custom/generated-optimizations.conf'"
replace: "include = '/etc/postgresql-custom/generated-optimizations.conf'"
- name: Include file for custom overrides in postgresql.conf
- become: yes
+ become: true
replace:
path: /etc/postgresql/postgresql.conf
regexp: "#include = '/etc/postgresql-custom/custom-overrides.conf'"
@@ -115,5 +115,10 @@
tags:
- aws-only
+- name: Install supabase-admin-agent
+ import_tasks: internal/supabase-admin-agent.yml
+ tags:
+ - aws-only
+
- name: Envoy - use lds.supabase.yaml for /etc/envoy/lds.yaml
command: mv /etc/envoy/lds.supabase.yaml /etc/envoy/lds.yaml
diff --git a/ansible/vars.yml b/ansible/vars.yml
index 7a714735..1d24249a 100644
--- a/ansible/vars.yml
+++ b/ansible/vars.yml
@@ -9,9 +9,9 @@ postgres_major:
# Full version strings for each major version
postgres_release:
- postgresorioledb-17: "17.0.1.098-orioledb"
- postgres17: "17.4.1.048"
- postgres15: "15.8.1.105"
+ postgresorioledb-17: "17.0.1.099-orioledb"
+ postgres17: "17.4.1.049"
+ postgres15: "15.8.1.106"
# Non Postgres Extensions
pgbouncer_release: "1.19.0"
@@ -54,6 +54,7 @@ postgres_exporter_release_checksum:
adminapi_release: 0.84.1
adminmgr_release: 0.25.1
+supabase_admin_agent_release: 1.4.36
vector_x86_deb: "https://packages.timber.io/vector/0.22.3/vector_0.22.3-1_amd64.deb"
vector_arm_deb: "https://packages.timber.io/vector/0.22.3/vector_0.22.3-1_arm64.deb"
[parent: c57842fd0832]