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
12 changes: 12 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# EditorConfig is awesome: https://EditorConfig.org

# top-most EditorConfig file
root = true

[*.nix]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ www/.DS_Store
www/node_modules
npm-debug.log
.data

result
.nixos-test-history
77 changes: 77 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
inputs = {
nixpkgs.url = "https://channels.nixos.org/nixos-unstable/nixexprs.tar.xz";
blueprint.url = "github:numtide/blueprint";
blueprint.inputs.nixpkgs.follows = "nixpkgs";
nix-filter.url = "github:numtide/nix-filter";
};

outputs =
inputs:
inputs.blueprint {
inherit inputs;
prefix = "nix/";
};
}
63 changes: 63 additions & 0 deletions nix/checks/nixos.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
{
pkgs,
flake,
perSystem,
...
}:
flake.inputs.nixpkgs.lib.nixos.runTest {
name = "auth";
hostPkgs = pkgs;
node.specialArgs = { inherit flake perSystem; };
nodes.server =
{ config, ... }:
{
imports = [
(import flake.nixosModules.auth)
];

virtualisation = {
forwardPorts = [
{
from = "host";
host.port = 13022;
guest.port = 22;
}
];
};
services.openssh = {
enable = true;
};

services.auth = {
enable = true;
package = perSystem.self.default;
};

services.postgresql = {
enable = true;
enableTCPIP = true;
initialScript = pkgs.writeText "init-postgres-with-password" ''
CREATE USER supabase_admin LOGIN CREATEROLE CREATEDB REPLICATION BYPASSRLS;

-- Supabase super admin
CREATE USER supabase_auth_admin NOINHERIT CREATEROLE LOGIN NOREPLICATION PASSWORD 'secret';
CREATE SCHEMA IF NOT EXISTS auth AUTHORIZATION supabase_auth_admin;
GRANT CREATE ON DATABASE postgres TO supabase_auth_admin;
ALTER USER supabase_auth_admin SET search_path = 'auth';
'';
authentication = ''
host supabase_auth_admin postgres samenet scram-sha-256
'';
};
};
testScript =
{ nodes, ... }:
''
start_all()

server.wait_for_unit("multi-user.target")
server.wait_for_unit("postgresql.service")

server.wait_for_unit("gotrue.service")
'';
}
7 changes: 7 additions & 0 deletions nix/devshell.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{ pkgs, ... }:
with pkgs;
mkShell {
packages = [
go
];
}
146 changes: 146 additions & 0 deletions nix/modules/nixos/auth.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.services.auth;
default_settings = rec {
API_EXTERNAL_URL = "http://localhost:9999";
DB_HOST = "localhost";
DB_NAME = "postgres";
DB_PASSWORD = "secret";
DB_PORT = "5432";
DB_USER = "supabase_auth_admin";
DISABLE_SIGNUP = "false";
DATABASE_URL = "postgres://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}";
GOTRUE_API_EXTERNAL_URL = "http://localhost:9999";
GOTRUE_DB_DRIVER = "postgres";
GOTRUE_DB_HOST = DB_HOST;
GOTRUE_DB_NAME = DB_NAME;
GOTRUE_DB_PASSWORD = DB_PASSWORD;
GOTRUE_DB_PORT = DB_PORT;
GOTRUE_DB_USER = DB_USER;
GOTRUE_DISABLE_SIGNUP = "false";
GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated";
GOTRUE_JWT_EXP = "3600";
GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long";
GOTRUE_MAILER_AUTOCONFIRM = "true";

# Both v2 & v3 support reloading via signals, on linux this is SIGUSR1.
GOTRUE_RELOADING_SIGNAL_ENABLED = "true";
GOTRUE_RELOADING_SIGNAL_NUMBER = "10";

# Both v2 & v3 disable the poller. While gotrue sets it to off by default we
# defensively set it to false here.
GOTRUE_RELOADING_POLLER_ENABLED = "false";

# Determines how much idle time must pass before triggering a reload. This
# ensures only 1 reload operation occurs during a burst of config updates.
GOTRUE_RELOADING_GRACE_PERIOD_INTERVAL = "2s";

# v3 does not use filesystem notifications for config reloads.
GOTRUE_RELOADING_NOTIFY_ENABLED = "false";

# TODO: remove duplicates?
GOTRUE_SITE_URL = "http://localhost:3000";
GOTRUE_SMTP_ADMIN_EMAIL = "[email protected]";
GOTRUE_SMTP_HOST = "localhost";
GOTRUE_SMTP_PASS = "";
GOTRUE_SMTP_PORT = "2500";
GOTRUE_SMTP_SENDER_NAME = "Supabase";
GOTRUE_SMTP_USER = "";
JWT_DEFAULT_GROUP_NAME = "authenticated";
JWT_EXP = "3600";
JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long";
MAILER_AUTOCONFIRM = "true";
SITE_URL = "http://localhost:3000";
SMTP_ADMIN_EMAIL = "[email protected]";
SMTP_HOST = "localhost";
SMTP_PASS = "";
SMTP_PORT = "2500";
SMTP_SENDER_NAME = "Supabase";
SMTP_USER = "";
};
auth_env = pkgs.writeText "auth.env" (
lib.concatStringsSep "\n" (
(lib.mapAttrsToList (name: value: "${name}=${value}") (default_settings // cfg.settings))
)
);
in
{
options.services.auth = {
enable = lib.mkEnableOption "Supabase Auth Service";

package = lib.mkOption {
type = lib.types.package;
description = "The Supabase Auth package to use.";
};

port = lib.mkOption {
type = lib.types.port;
default = 9999;
description = "Port to run the auth service on.";
};

settings = lib.mkOption {
type = lib.types.attrs;
default = { };
description = "Configuration settings for the auth service.";
};
};

config = lib.mkIf cfg.enable {
networking.firewall.allowedTCPPorts = [ 9122 ];

users.users.gotrue = {
isSystemUser = true;
description = "gotrue service user";
group = "gotrue";
};
users.groups.gotrue = { };

systemd.services.gotrue = {
description = "gotrue (auth)";
wantedBy = [ "multi-user.target" ];
after = [ "postgresql.service" ];
serviceConfig = {
Type = "exec";
WorkingDirectory = "/opt/gotrue";
ExecStart = "${cfg.package}/bin/gotrue --config-dir /etc/auth.d";
ExecReload = "${pkgs.coreutils}/bin/kill -10 $MAINPID";
User = "gotrue";
Restart = "always";
RestartSec = 3;
MemoryAccounting = true;
MemoryMax = "50%";
Slice = "services.slice";
EnvironmentFile = [
"/etc/gotrue/auth.env"
"-/etc/gotrue.generated.env"
"-/etc/gotrue.overrides.env"
];
# preStart = ''
# pg_isready -h ${config.auth.settings.DB_HOST} -p ${config.auth.settings.DB_PORT} -U ${config.auth.settings.DB_USER}; do sleep 1; done
# '';
};
unitConfig = {
StartLimitIntervalSec = 10;
StartLimitBurst = 5;
};
};

systemd.tmpfiles.rules = [
"d /etc/auth.d 0755 gotrue gotrue -"
"d /opt/gotrue 0755 gotrue gotrue -"
"C /etc/gotrue/auth.env 0440 gotrue gotrue - ${auth_env}"
];
};
}

# TODO: initialization steps as activation script?
# - Wait for database to be ready:
# until pg_isready -h ${config.auth.settings.DB_HOST} -p ${config.auth.settings.DB_PORT} -U ${config.auth.settings.DB_USER}; do sleep 1; done
# - Run migrations if they exist:
# if [ -d migrations ]; then go run main.go migrate up; fi
42 changes: 42 additions & 0 deletions nix/package.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
flake,
inputs,
pkgs,
...
}:
let
filter = inputs.nix-filter.lib;
in
pkgs.buildGoModule {
pname = "supabase-auth";
version = "2.180.0";
src = filter {
root = flake;
include = [
(filter.matchExt "go")
"go.mod"
"go.sum"
"client"
"cmd"
"internal"
"migrations"
"tools"
];
};

vendorHash = "sha256-knYvNkEVffWisvb4Dhm5qqtqQ4co9MGoNt6yH6dUll8=";

buildFlags = [
"-tags"
"netgo"
];

# we cannot run test in the sandbox as tests rely on postgresql tcp connection
doCheck = false;

subPackages = [ "." ];

postInstall = ''
mv $out/bin/auth $out/bin/gotrue
'';
}