diff --git a/docs/lamassu-future-peer-auth.md b/docs/lamassu-future-peer-auth.md deleted file mode 100644 index 88cc9fc..0000000 --- a/docs/lamassu-future-peer-auth.md +++ /dev/null @@ -1,167 +0,0 @@ -# Lamassu Server: Future Peer Authentication Implementation - -This document describes how to implement PostgreSQL peer authentication (Unix socket) for the lamassu-server module in the future. - -## Current Limitation - -The lamassu-server's `constants.js` builds the database URL from individual environment variables: - -```javascript -const POSTGRES_USER = process.env.POSTGRES_USER -const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD -const POSTGRES_HOST = process.env.POSTGRES_HOST -const POSTGRES_PORT = process.env.POSTGRES_PORT -const POSTGRES_DB = process.env.POSTGRES_DB - -const PSQL_URL = `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}` -``` - -This means: -- `DATABASE_URL` environment variable is **not supported** -- Unix socket connections are **not possible** (setting `POSTGRES_HOST=/run/postgresql` produces invalid URL syntax) -- Password authentication via TCP is **required** - -## Required Upstream Changes - -### 1. Modify `packages/server/lib/constants.js` - -Add support for `DATABASE_URL` environment variable: - -```javascript -const POSTGRES_USER = process.env.POSTGRES_USER -const POSTGRES_PASSWORD = process.env.POSTGRES_PASSWORD -const POSTGRES_HOST = process.env.POSTGRES_HOST -const POSTGRES_PORT = process.env.POSTGRES_PORT -const POSTGRES_DB = process.env.POSTGRES_DB - -// Support DATABASE_URL for Unix socket connections (peer auth) -const PSQL_URL = process.env.DATABASE_URL || - `postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}` -``` - -### 2. Update nix-bitcoin module - -Once upstream supports `DATABASE_URL`, update `modules/lamassu-lnbits.nix`: - -#### Remove password secret - -```nix -nix-bitcoin.secrets = { - lamassu-key.user = cfg.user; - lamassu-cert = { - user = cfg.user; - permissions = "444"; - }; - # Remove: lamassu-db-password -}; - -nix-bitcoin.generateSecretsCmds.lamassu = '' - makeCert lamassu '${nbLib.mkCertExtraAltNames cfg.certificate}' - # Remove: makePasswordSecret lamassu-db-password -''; -``` - -#### Remove lamassu-postgres-setup service - -Delete the entire `systemd.services.lamassu-postgres-setup` block. - -#### Simplify PostgreSQL config - -```nix -services.postgresql = { - enable = true; - package = pkgs.postgresql_15; - ensureDatabases = [ cfg.database.name ]; - ensureUsers = [ - { - name = cfg.database.user; - ensureDBOwnership = true; - } - ]; - # No custom authentication needed - default peer auth works -}; -``` - -#### Update service wrapper scripts - -```nix -lamassuEnv = pkgs.writeShellScript "lamassu-env" '' - #!/bin/bash - set -euo pipefail - export PATH=${pkgs.nodejs_22}/bin:$PATH - # Use Unix socket for peer authentication (no password needed) - export DATABASE_URL="postgresql://${cfg.database.user}@/${cfg.database.name}?host=/run/postgresql" - export NODE_PATH=${cfg.package}/node_modules:${cfg.package}/packages/server/node_modules - cd ${cfg.package} - exec "$@" -''; -``` - -#### Remove password-related env vars - -Remove from service `environment` blocks: -- `POSTGRES_HOST` -- `POSTGRES_PORT` -- `POSTGRES_PASSWORD` - -## Benefits of Peer Authentication - -1. **No password to manage** - No secrets generation, storage, or rotation -2. **More secure** - Authentication handled by OS kernel, not application -3. **Simpler module** - ~55 fewer lines of code -4. **Consistent with btcpayserver** - Same pattern used by other nix-bitcoin modules - -## Architecture Comparison - -### Current (password auth via TCP) - -``` -┌─────────────────────────────────────────────────────────────┐ -│ lamassu-server │ -│ └── connects to 127.0.0.1:5432 with password │ -│ │ │ -│ ▼ │ -│ PostgreSQL (TCP) │ -│ └── validates password via md5 auth │ -└─────────────────────────────────────────────────────────────┘ - -Requires: - - lamassu-db-password secret - - lamassu-postgres-setup service - - POSTGRES_HOST, POSTGRES_PORT, POSTGRES_PASSWORD env vars -``` - -### Future (peer auth via Unix socket) - -``` -┌─────────────────────────────────────────────────────────────┐ -│ lamassu-server (runs as user: lamassu-server) │ -│ └── connects to /run/postgresql socket │ -│ │ │ -│ ▼ │ -│ PostgreSQL (Unix socket) │ -│ └── validates OS user matches DB user (peer auth) │ -└─────────────────────────────────────────────────────────────┘ - -Requires: - - Nothing extra! Default NixOS PostgreSQL config works. -``` - -## DATABASE_URL Format for Unix Socket - -The node-postgres library supports Unix sockets via the `host` query parameter: - -``` -postgresql://username@/database?host=/run/postgresql -``` - -Components: -- `username` - PostgreSQL user (must match OS user for peer auth) -- `database` - Database name -- `host=/run/postgresql` - Path to Unix socket directory - -## Reference - -- btcpayserver module uses peer auth: `postgres=User ID=btcpayserver;Host=/run/postgresql;Database=btcpaydb` -- node-postgres Unix socket docs: https://node-postgres.com/features/connecting -- pg-promise (used by lamassu): https://github.com/vitaly-t/pg-promise diff --git a/examples/configuration.nix b/examples/configuration.nix index b242392..125beaa 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -80,15 +80,6 @@ # Set this to enable lnd, a lightning implementation written in Go. # services.lnd.enable = true; # - # By default, lnd uses bitcoind as its backend. You can use neutrino instead - # to run lnd without a full Bitcoin node. This is useful for resource-constrained - # systems, but provides less privacy and security than a local bitcoind. - # services.lnd = { - # enable = true; - # backend = "neutrino"; - # neutrino.peers = [ "btcd.example.com:8333" ]; - # }; - # # NOTE: In order to avoid collisions with clightning you must disable clightning or # change the services.clightning.port or services.lnd.port to a port other than # 9735. diff --git a/modules/lamassu-lnbits.nix b/modules/lamassu-lnbits.nix index 7bb6b4e..82fbbd5 100644 --- a/modules/lamassu-lnbits.nix +++ b/modules/lamassu-lnbits.nix @@ -104,8 +104,11 @@ in description = "PostgreSQL username"; }; - # Password is managed by nix-bitcoin secrets system. - # See: ${secretsDir}/lamassu-db-password + password = mkOption { + type = types.str; + default = "lamassu123"; + description = "PostgreSQL password for lamassu-server user"; + }; }; hostname = mkOption { @@ -184,15 +187,10 @@ in user = cfg.user; permissions = "444"; # World readable (it's a public cert) }; - lamassu-db-password = { - user = cfg.user; - group = "postgres"; # PostgreSQL needs to read this too - }; }; nix-bitcoin.generateSecretsCmds.lamassu = '' makeCert lamassu '${nbLib.mkCertExtraAltNames cfg.certificate}' - makePasswordSecret lamassu-db-password ''; # ═══════════════════════════════════════════════════════════════════════════ @@ -218,6 +216,10 @@ in host all all 127.0.0.1/32 md5 host all all ::1/128 md5 ''; + # Set initial password for lamassu-server user + initialScript = pkgs.writeText "postgres-init.sql" '' + ALTER USER "${cfg.database.user}" WITH PASSWORD '${cfg.database.password}'; + ''; }; # Create system users and groups @@ -247,11 +249,11 @@ in "Z '${cfg.package}' 0755 ${cfg.user} ${cfg.group} - -" ]; - # Service to set PostgreSQL password from nix-bitcoin secrets + # Service to set PostgreSQL password systemd.services.lamassu-postgres-setup = { description = "Setup PostgreSQL password for lamassu-server"; wantedBy = [ "multi-user.target" ]; - after = [ "postgresql.service" "nix-bitcoin-secrets.target" ]; + after = [ "postgresql.service" ]; wants = [ "postgresql.service" ]; serviceConfig = { Type = "oneshot"; @@ -259,12 +261,11 @@ in User = "postgres"; }; script = '' - # Wait for user to exist, then set password from secrets + # Wait for user to exist, then set password for i in {1..30}; do if ${pkgs.postgresql}/bin/psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='${cfg.database.user}'" | grep -q 1; then echo "Setting password for ${cfg.database.user}..." - password=$(cat ${secretsDir}/lamassu-db-password) - ${pkgs.postgresql}/bin/psql -c "ALTER USER \"${cfg.database.user}\" WITH PASSWORD '$password';" + ${pkgs.postgresql}/bin/psql -c "ALTER USER \"${cfg.database.user}\" WITH PASSWORD '${cfg.database.password}';" exit 0 fi echo "Waiting for user ${cfg.database.user} to be created (attempt $i/30)..." @@ -285,11 +286,12 @@ in environment = { NODE_ENV = "production"; - # Database configuration (password read at runtime from secrets) + # Database configuration (using TCP with password auth) POSTGRES_HOST = "127.0.0.1"; POSTGRES_PORT = "5432"; POSTGRES_DB = cfg.database.name; POSTGRES_USER = cfg.database.user; + POSTGRES_PASSWORD = cfg.database.password; # Server configuration SERVER_PORT = toString cfg.serverPort; @@ -327,10 +329,8 @@ in #!/bin/bash set -euo pipefail export PATH=${pkgs.nodejs_22}/bin:$PATH - # Read database password from nix-bitcoin secrets - DB_PASSWORD=$(cat ${secretsDir}/lamassu-db-password) - export DATABASE_URL="postgresql://${cfg.database.user}:$DB_PASSWORD@127.0.0.1:5432/${cfg.database.name}" - export POSTGRES_PASSWORD="$DB_PASSWORD" + # Use TCP connection to localhost with password + export DATABASE_URL="postgresql://${cfg.database.user}:${cfg.database.password}@127.0.0.1:5432/${cfg.database.name}" export NODE_PATH=${cfg.package}/node_modules:${cfg.package}/packages/server/node_modules cd ${cfg.package} exec "$@" @@ -391,11 +391,12 @@ in CA_PATH = cfg.certPath; CERT_PATH = cfg.certPath; KEY_PATH = cfg.keyPath; - # Database configuration (password read at runtime from secrets) + # Database configuration (using TCP with password auth) POSTGRES_HOST = "127.0.0.1"; POSTGRES_PORT = "5432"; POSTGRES_DB = cfg.database.name; POSTGRES_USER = cfg.database.user; + POSTGRES_PASSWORD = cfg.database.password; MNEMONIC_PATH = "${cfg.dataDir}/lamassu-mnemonic"; SKIP_2FA = if cfg.skip2FA then "true" else "false"; # Data directories @@ -410,10 +411,8 @@ in #!/bin/bash set -euo pipefail export PATH=${pkgs.nodejs_22}/bin:$PATH - # Read database password from nix-bitcoin secrets - DB_PASSWORD=$(cat ${secretsDir}/lamassu-db-password) - export DATABASE_URL="postgresql://${cfg.database.user}:$DB_PASSWORD@127.0.0.1:5432/${cfg.database.name}" - export POSTGRES_PASSWORD="$DB_PASSWORD" + # Use TCP connection to localhost with password + export DATABASE_URL="postgresql://${cfg.database.user}:${cfg.database.password}@127.0.0.1:5432/${cfg.database.name}" export NODE_PATH=${cfg.package}/node_modules:${cfg.package}/packages/admin-server/node_modules cd ${cfg.package} exec "$@" @@ -445,16 +444,14 @@ in nodePackages.pnpm postgresql (writeShellScriptBin "lamassu-register-user" '' - # Read database password from nix-bitcoin secrets - DB_PASSWORD=$(cat ${secretsDir}/lamassu-db-password) export NODE_PATH="${cfg.package}/node_modules:${cfg.package}/packages/server/node_modules" - export DATABASE_URL="postgresql://${cfg.database.user}:$DB_PASSWORD@127.0.0.1:5432/${cfg.database.name}" + export DATABASE_URL="postgresql://${cfg.database.user}:${cfg.database.password}@127.0.0.1:5432/${cfg.database.name}" export HOSTNAME="${cfg.hostname}" export POSTGRES_HOST="127.0.0.1" export POSTGRES_PORT="5432" export POSTGRES_DB="${cfg.database.name}" export POSTGRES_USER="${cfg.database.user}" - export POSTGRES_PASSWORD="$DB_PASSWORD" + export POSTGRES_PASSWORD="${cfg.database.password}" export SKIP_2FA="${if cfg.skip2FA then "true" else "false"}" sudo -E -u ${cfg.user} bash -c "cd ${cfg.package}/packages/server && ${pkgs.nodejs_22}/bin/node bin/lamassu-register \"\$@\"" -- "$@" diff --git a/modules/lnd.nix b/modules/lnd.nix index 38f00bc..3482cce 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -150,12 +150,12 @@ let description = "The backend to use for fetching blockchain data."; }; neutrino = { - peers = mkOption { + addpeers = mkOption { type = types.listOf types.str; default = []; example = [ "192.168.1.1:8333" "btcd.example.com:8333" ]; description = '' - List of Bitcoin full node peers to connect to for neutrino. + List of Bitcoin full node peers to connect to via neutrino.addpeer. Multiple peers provide redundancy for maximum uptime. ''; }; @@ -167,13 +167,6 @@ let Required because neutrino doesn't have access to mempool data. ''; }; - maxPeers = mkOption { - type = types.int; - default = 8; - description = '' - Maximum number of inbound and outbound peers for neutrino. - ''; - }; }; }; @@ -213,8 +206,7 @@ let bitcoind.zmqpubrawtx=${zmqHandleSpecialAddress bitcoind.zmqpubrawtx} '' else '' bitcoin.node=neutrino - ${lib.concatMapStringsSep "\n" (peer: "neutrino.addpeer=${peer}") cfg.neutrino.peers} - neutrino.maxpeers=${toString cfg.neutrino.maxPeers} + ${lib.concatMapStringsSep "\n" (peer: "neutrino.addpeer=${peer}") cfg.neutrino.addpeers} fee.url=${cfg.neutrino.feeUrl} ''} @@ -240,10 +232,10 @@ in { services.lnd.port to a port other than 9735. ''; } - { assertion = cfg.backend != "neutrino" || cfg.neutrino.peers != []; + { assertion = cfg.backend != "neutrino" || cfg.neutrino.addpeers != []; message = '' When using neutrino backend, you must configure at least one peer - in services.lnd.neutrino.peers. + in services.lnd.neutrino.addpeers. ''; } ]; @@ -269,8 +261,8 @@ in { systemd.services.lnd = { wantedBy = [ "multi-user.target" ]; - requires = optionals (cfg.backend == "bitcoind") [ "bitcoind.service" ]; - after = optionals (cfg.backend == "bitcoind") [ "bitcoind.service" ] ++ [ "nix-bitcoin-secrets.target" ]; + requires = optional (cfg.backend == "bitcoind") "bitcoind.service"; + after = optional (cfg.backend == "bitcoind") "bitcoind.service" ++ [ "nix-bitcoin-secrets.target" ]; preStart = '' install -m600 ${configFile} '${cfg.dataDir}/lnd.conf' ${optionalString (cfg.backend == "bitcoind") '' @@ -332,7 +324,7 @@ in { users.users.${cfg.user} = { isSystemUser = true; group = cfg.group; - extraGroups = optionals (cfg.backend == "bitcoind") [ "bitcoinrpc-public" ]; + extraGroups = optional (cfg.backend == "bitcoind") "bitcoinrpc-public"; home = cfg.dataDir; # lnd creates .lnd dir in HOME }; users.groups.${cfg.group} = {}; diff --git a/modules/modules.nix b/modules/modules.nix index 1759a1b..1b3c204 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -28,7 +28,6 @@ ./joinmarket.nix ./joinmarket-ob-watcher.nix ./hardware-wallets.nix - ./lamassu-lnbits.nix # Support features ./versioning.nix diff --git a/modules/rtl.nix b/modules/rtl.nix index 9d7df66..60a3bca 100644 --- a/modules/rtl.nix +++ b/modules/rtl.nix @@ -11,7 +11,7 @@ let }; port = mkOption { type = types.port; - default = 3001; + default = 3000; description = "HTTP server port."; }; dataDir = mkOption {