feat(supabase): add Google/Apple OAuth and fueltide.io-branded email flows
Enables the auth providers and transactional email flows the self-hosted Supabase was missing compared to the cloud instance: - GoTrue now accepts Google and Apple OAuth (web flow); Apple client-secret JWT is signed fresh on every activation from the SOPS-stored .p8 so there's no 6-month rotation ritual. - SMTP points at mail.cloonar.com:587 with SASL auth via a new `supabase` LDAP account; a `noreply@fueltide.io` mailAlias lets that account send as the fueltide.io address. - rspamd on mail.cloonar.com gets a per-domain DKIM key for fueltide.io (selector `default`) so outbound mail is signed. - MAILER_AUTOCONFIRM is off so signup confirmation + password reset actually go through email. - SITE_URL + URI_ALLOW_LIST point at app.fueltide.io / stage so links in emails and OAuth redirects land in the right app. FUELTIDE_AUTH_SETUP.md documents the manual steps (LDAP entries, SOPS additions, DNS records, Google/Apple console setup) that must be completed before merging.
This commit is contained in:
parent
1f5e5b9a37
commit
67e81d39f3
5 changed files with 366 additions and 12 deletions
|
|
@ -19,11 +19,14 @@ in
|
|||
sops.secrets.supabase-env = { };
|
||||
|
||||
# --- Persistent data directories ---
|
||||
# Postgres data lives in a named podman volume (supabase-db-data) so podman
|
||||
# owns the permissions on the container's postgres UID; logical dumps go to
|
||||
# /var/backups/supabase where borg picks them up from /var.
|
||||
systemd.tmpfiles.rules = [
|
||||
"d /var/lib/supabase/db/data 0700 root root -"
|
||||
"d /var/lib/supabase/storage 0755 root root -"
|
||||
"d /var/lib/supabase/functions 0755 root root -"
|
||||
"d /var/lib/supabase/snippets 0755 root root -"
|
||||
"d /var/backups/supabase 0700 root root -"
|
||||
];
|
||||
|
||||
|
||||
|
|
@ -67,7 +70,12 @@ in
|
|||
supabase-env-generate = {
|
||||
description = "Generate Supabase per-container env files from SOPS secrets";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = [ pkgs.jq ];
|
||||
# python+cryptography is used to sign the Apple OAuth client-secret JWT
|
||||
# (ES256) inside env-generate.sh.
|
||||
path = [
|
||||
pkgs.jq
|
||||
(pkgs.python3.withPackages (ps: [ ps.cryptography ]))
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
|
|
@ -95,9 +103,38 @@ in
|
|||
after = [ "supabase-functions-seed.service" ];
|
||||
requires = [ "supabase-functions-seed.service" ];
|
||||
};
|
||||
# Logical daily dump of the containerised Postgres cluster. Writes to
|
||||
# /var/backups/supabase which is covered by the borg path /var;
|
||||
# /var/lib/containers (the named-volume storage) is excluded from borg,
|
||||
# so the dump is the only copy borg ships off-host.
|
||||
supabase-db-backup = {
|
||||
description = "pg_dumpall of the Supabase Postgres cluster";
|
||||
after = [ "podman-supabase-db.service" ];
|
||||
requires = [ "podman-supabase-db.service" ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
};
|
||||
script = ''
|
||||
set -euo pipefail
|
||||
tmp=/var/backups/supabase/supabase-all.sql.tmp
|
||||
out=/var/backups/supabase/supabase-all.sql
|
||||
${pkgs.podman}/bin/podman exec -u postgres supabase-db \
|
||||
pg_dumpall -U postgres --clean --if-exists > "$tmp"
|
||||
mv "$tmp" "$out"
|
||||
'';
|
||||
};
|
||||
}
|
||||
]);
|
||||
|
||||
systemd.timers.supabase-db-backup = {
|
||||
description = "Daily Supabase Postgres dump";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "*-*-* 02:30:00";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
# --- Containers ---
|
||||
virtualisation.oci-containers.containers = {
|
||||
|
||||
|
|
@ -114,7 +151,7 @@ in
|
|||
};
|
||||
environmentFiles = [ "/run/supabase/db.env" ];
|
||||
volumes = [
|
||||
"/var/lib/supabase/db/data:/var/lib/postgresql/data"
|
||||
"supabase-db-data:/var/lib/postgresql/data"
|
||||
"${./sql/_supabase.sql}:/docker-entrypoint-initdb.d/migrations/97-_supabase.sql:ro"
|
||||
"${./sql/realtime.sql}:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:ro"
|
||||
"${./sql/logs.sql}:/docker-entrypoint-initdb.d/migrations/99-logs.sql:ro"
|
||||
|
|
@ -166,8 +203,8 @@ in
|
|||
GOTRUE_API_PORT = "9999";
|
||||
API_EXTERNAL_URL = "https://supabase.cloonar.com";
|
||||
GOTRUE_DB_DRIVER = "postgres";
|
||||
GOTRUE_SITE_URL = "https://supabase.cloonar.com";
|
||||
GOTRUE_URI_ALLOW_LIST = "";
|
||||
GOTRUE_SITE_URL = "https://app.fueltide.io";
|
||||
GOTRUE_URI_ALLOW_LIST = "https://app.fueltide.io,https://app.fueltide.io/**,https://app.stage.fueltide.io,https://app.stage.fueltide.io/**,io.fueltide.workout://";
|
||||
GOTRUE_DISABLE_SIGNUP = "false";
|
||||
GOTRUE_JWT_ADMIN_ROLES = "service_role";
|
||||
GOTRUE_JWT_AUD = "authenticated";
|
||||
|
|
@ -175,19 +212,21 @@ in
|
|||
GOTRUE_JWT_EXP = "3600";
|
||||
GOTRUE_EXTERNAL_EMAIL_ENABLED = "true";
|
||||
GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED = "false";
|
||||
GOTRUE_MAILER_AUTOCONFIRM = "true";
|
||||
GOTRUE_SMTP_ADMIN_EMAIL = "admin@cloonar.com";
|
||||
GOTRUE_SMTP_HOST = "supabase-mail";
|
||||
GOTRUE_SMTP_PORT = "2500";
|
||||
GOTRUE_SMTP_USER = "";
|
||||
GOTRUE_SMTP_PASS = "";
|
||||
GOTRUE_SMTP_SENDER_NAME = "Supabase";
|
||||
GOTRUE_MAILER_AUTOCONFIRM = "false";
|
||||
GOTRUE_SMTP_ADMIN_EMAIL = "noreply@fueltide.io";
|
||||
GOTRUE_SMTP_HOST = "mail.cloonar.com";
|
||||
GOTRUE_SMTP_PORT = "587";
|
||||
GOTRUE_SMTP_SENDER_NAME = "Fueltide";
|
||||
GOTRUE_MAILER_URLPATHS_INVITE = "/auth/v1/verify";
|
||||
GOTRUE_MAILER_URLPATHS_CONFIRMATION = "/auth/v1/verify";
|
||||
GOTRUE_MAILER_URLPATHS_RECOVERY = "/auth/v1/verify";
|
||||
GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE = "/auth/v1/verify";
|
||||
GOTRUE_EXTERNAL_PHONE_ENABLED = "false";
|
||||
GOTRUE_SMS_AUTOCONFIRM = "false";
|
||||
GOTRUE_EXTERNAL_GOOGLE_ENABLED = "true";
|
||||
GOTRUE_EXTERNAL_GOOGLE_REDIRECT_URI = "https://supabase.cloonar.com/auth/v1/callback";
|
||||
GOTRUE_EXTERNAL_APPLE_ENABLED = "true";
|
||||
GOTRUE_EXTERNAL_APPLE_REDIRECT_URI = "https://supabase.cloonar.com/auth/v1/callback";
|
||||
};
|
||||
environmentFiles = [ "/run/supabase/auth.env" ];
|
||||
extraOptions = supabaseNet ++ [
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue