diff --git a/.gitignore b/.gitignore index acab1be45..5f19b5380 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ www/.DS_Store www/node_modules npm-debug.log .data +result diff --git a/flake.lock b/flake.lock new file mode 100644 index 000000000..123b37c33 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1746576598, + "narHash": "sha256-FshoQvr6Aor5SnORVvh/ZdJ1Sa2U4ZrIMwKBX5k2wu0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "b3582c75c7f21ce0b429898980eddbbf05c68e55", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 000000000..ea5b08139 --- /dev/null +++ b/flake.nix @@ -0,0 +1,272 @@ +{ + description = "Supabase Auth Service with Nix modules and steps"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + let + systems = [ + "x86_64-linux" + "aarch64-linux" + "x86_64-darwin" + "aarch64-darwin" + ]; + + forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system); + + mkAuthConfig = system: + let + pkgs = nixpkgs.legacyPackages.${system}; + lib = pkgs.lib; + + # Go package + auth-service = pkgs.buildGoModule { + pname = "supabase-auth"; + version = "0.1.0"; + src = ./.; + + vendorHash = "sha256-QBQUUFWT3H3L7ajFV8cgi0QREXnm0ReIisD+4ACfLZQ="; + + buildFlags = [ "-tags" "netgo" ]; + doCheck = false; + + # Specify the main package + subPackages = [ "." ]; + + # Specify the output binary name + postInstall = '' + mv $out/bin/auth $out/bin/supabase-auth + ''; + }; + + # Evaluate both the auth and steps modules + config = lib.evalModules { + modules = [ + ./nix/auth-module.nix + ./nix/steps-module.nix + { + _module.args.pkgs = pkgs; + auth = { + enable = true; + package = auth-service; + port = 9999; + settings = { + GOTRUE_DB_DRIVER = "postgres"; + GOTRUE_SITE_URL = "http://localhost:3000"; + SITE_URL = "http://localhost:3000"; + GOTRUE_API_EXTERNAL_URL = "http://localhost:9999"; + API_EXTERNAL_URL = "http://localhost:9999"; + GOTRUE_DB_HOST = "localhost"; + GOTRUE_DB_PORT = "5432"; + GOTRUE_DB_NAME = "postgres"; + GOTRUE_DB_USER = "postgres"; + GOTRUE_DB_PASSWORD = "postgres"; + DATABASE_URL = "postgres://postgres:postgres@localhost:5432/postgres"; + GOTRUE_JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + GOTRUE_JWT_EXP = "3600"; + GOTRUE_JWT_DEFAULT_GROUP_NAME = "authenticated"; + GOTRUE_DISABLE_SIGNUP = "false"; + GOTRUE_MAILER_AUTOCONFIRM = "true"; + GOTRUE_SMTP_ADMIN_EMAIL = "admin@example.com"; + GOTRUE_SMTP_HOST = "localhost"; + GOTRUE_SMTP_PORT = "2500"; + GOTRUE_SMTP_USER = ""; + GOTRUE_SMTP_PASS = ""; + GOTRUE_SMTP_SENDER_NAME = "Supabase"; + }; + }; + steps = { + enable = true; + }; + } + ]; + }; + + authConfigOutput = pkgs.stdenv.mkDerivation { + name = "auth-config"; + src = ./.; + buildInputs = [ pkgs.bash auth-service ]; + + buildPhase = '' + mkdir -p $out/etc $out/bin $out/lib/systemd/system + + # Write the auth configuration + cat > $out/etc/auth.env < $out/lib/systemd/system/gotrue.service < $out/bin/manage-auth < /dev/null; then + echo "Auth service is running" + else + echo "Auth service is not running" + fi + ;; + *) + echo "Usage: \$0 {start|stop|restart|status}" + exit 1 + ;; + esac + EOF + chmod +x $out/bin/manage-auth + + # Write the activation script + cat > $out/bin/activate </dev/null 2>&1; then + ufw allow 9122/tcp comment "GoTrue metrics exporter" + echo "Added UFW rule for GoTrue metrics exporter" + fi + + # Reload systemd + systemctl daemon-reload + + # Enable and start the service + systemctl enable gotrue.service + systemctl restart gotrue.service + + echo "Gotrue service has been activated and started" + echo "You can manage the service using: gotrue-manage {start|stop|restart|status}" + echo "The following commands are available:" + echo " gotrue-manage - Manage the Gotrue service" + echo " auth-activate - Run this activation script again" + echo " gotrue - The auth service binary" + EOF + chmod +x $out/bin/activate + + # Create symlinks to the systemd unit files for easy access + mkdir -p $out/share/gotrue + ln -s $out/lib/systemd/system/gotrue.service $out/share/gotrue/gotrue.service + + # Copy the auth binary to the package's bin directory + cp ${auth-service}/bin/supabase-auth $out/bin/gotrue + chmod +x $out/bin/gotrue + ''; + + installPhase = "true"; + }; + + in + { + packages = { + default = authConfigOutput; + }; + devShells.default = pkgs.mkShell { + buildInputs = [ + pkgs.bash + auth-service + pkgs.go + pkgs.gopls + pkgs.gotools + pkgs.go-outline + pkgs.gocode + pkgs.gopkgs + pkgs.godef + pkgs.golint + pkgs.delve + ]; + shellHook = '' + echo "Build with: nix build ." + echo "Result will be in ./result" + echo "Auth service version: ${auth-service.version}" + ''; + }; + }; + in + { + packages = forAllSystems (system: (mkAuthConfig system).packages); + devShells = forAllSystems (system: (mkAuthConfig system).devShells); + }; +} \ No newline at end of file diff --git a/nix/README.md b/nix/README.md new file mode 100644 index 000000000..8d9e38e02 --- /dev/null +++ b/nix/README.md @@ -0,0 +1,97 @@ +# Nix Configuration for Auth Service + +This directory contains Nix modules and configurations for the Auth service. The setup allows for building and installing the Auth service using Nix, with proper systemd integration and configuration management. + +## Files + +- `auth-module.nix`: Defines the Nix module for the Auth service configuration +- `steps-module.nix`: Defines the Nix module for service startup steps and commands + +## Building and Installation + +### Prerequisites + +- Nix package manager installed +- System with systemd (for service management) + +### Installation + +1. Install the package: +```bash +nix profile install . +``` + +2. Activate the service: +```bash +sudo auth-activate +``` + +### Available Commands + +After installation, the following commands are available: + +- `gotrue`: The auth service binary +- `gotrue-manage`: Manage the service (start/stop/restart/status) +- `auth-activate`: Run the activation script again + +## Configuration + +The service configuration is managed through environment variables, which are set in the Nix configuration. The main configuration file is generated at `/etc/auth.d/20_generated.env` during activation. + +### Service Structure + +- Binary: `/opt/gotrue/gotrue` +- Config directory: `/etc/auth.d` +- Systemd service: `gotrue.service` +- Metrics port: 9122 (automatically configured in UFW if available) + +## Development + +### Updating the Service + +1. Modify the relevant Nix files: + - `flake.nix` for package definition and build process + - `auth-module.nix` for service configuration + - `steps-module.nix` for startup steps + +2. Rebuild and reinstall: +```bash +nix profile install . +sudo auth-activate +``` + +### Testing Changes + +1. Build the package: +```bash +nix build . +``` + +2. The result will be in `./result/` with the following structure: + - `bin/`: Contains the binary and management scripts + - `share/gotrue/`: Contains the systemd service file + - `etc/`: Contains the environment configuration + +## System Requirements + +- Linux system with systemd +- UFW (optional, for metrics port configuration) +- Proper permissions for the `gotrue` user (created by system image) + +## Troubleshooting + +1. If the service fails to start: + - Check logs: `journalctl -u gotrue.service` + - Verify permissions: `ls -l /opt/gotrue /etc/auth.d` + - Check config: `cat /etc/auth.d/20_generated.env` + +2. If commands are not found: + - Verify installation: `nix profile list` + - Check symlinks: `ls -l /usr/local/bin/gotrue*` + +## Notes + +- The activation script assumes the `gotrue` user exists (created by system image) +- The service runs as the `gotrue` user +- Configuration is managed through environment variables +- The service is automatically started and enabled on activation \ No newline at end of file diff --git a/nix/auth-module.nix b/nix/auth-module.nix new file mode 100644 index 000000000..ddf3382d7 --- /dev/null +++ b/nix/auth-module.nix @@ -0,0 +1,51 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.auth; +in { + options.auth = { + enable = mkEnableOption "Supabase Auth Service"; + + package = mkOption { + type = types.package; + description = "The Supabase Auth package to use."; + }; + + port = mkOption { + type = types.port; + default = 9999; + description = "Port to run the auth service on."; + }; + + settings = mkOption { + type = types.attrs; + default = { + SITE_URL = "http://localhost:3000"; + API_EXTERNAL_URL = "http://localhost:9999"; + DB_HOST = "localhost"; + DB_PORT = "5432"; + DB_NAME = "postgres"; + DB_USER = "postgres"; + DB_PASSWORD = "postgres"; + JWT_SECRET = "your-super-secret-jwt-token-with-at-least-32-characters-long"; + JWT_EXP = "3600"; + JWT_DEFAULT_GROUP_NAME = "authenticated"; + DISABLE_SIGNUP = "false"; + MAILER_AUTOCONFIRM = "true"; + SMTP_ADMIN_EMAIL = "admin@example.com"; + SMTP_HOST = "localhost"; + SMTP_PORT = "2500"; + SMTP_USER = ""; + SMTP_PASS = ""; + SMTP_SENDER_NAME = "Supabase"; + }; + description = "Configuration settings for the auth service."; + }; + }; + + config = mkIf cfg.enable { + # No NixOS-specific options here + }; +} \ No newline at end of file diff --git a/nix/steps-module.nix b/nix/steps-module.nix new file mode 100644 index 000000000..d31ee2778 --- /dev/null +++ b/nix/steps-module.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.steps; +in { + options.steps = { + enable = mkEnableOption "Auth service initialization steps"; + + commands = mkOption { + type = types.listOf types.str; + default = []; + description = "Commands to run during service initialization."; + }; + }; + + config = mkIf cfg.enable { + steps.commands = [ + # 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" + ]; + }; +} \ No newline at end of file