{ pkgs, inputs, config, ... }: let # Public domain for the fax backend — numbers REST + Sinch inbound webhook only. # The outbound consumer is relay-driven and has no public route. domain = "fax.xfay.app"; # Non-secret runtime configuration. port = 8391; relayUrl = "wss://relay.xfay.app/"; cdnUrl = "https://upload.xfay.app"; pkg = inputs.oberon.packages.${pkgs.system}.default; # Wrapper that exports sops-managed secrets, then execs oberon (same pattern as # jirorian.nix — EnvironmentFile loads too early for sops-nix). startScript = pkgs.writeShellScript "oberon-start" '' set -euo pipefail export SINCH_PROJECT_ID=$(cat ${config.sops.secrets.oberon_sinch_project_id.path}) export SINCH_KEY_ID=$(cat ${config.sops.secrets.oberon_sinch_key_id.path}) export SINCH_KEY_SECRET=$(cat ${config.sops.secrets.oberon_sinch_key_secret.path}) export SINCH_FAX_SERVICE_ID=$(cat ${config.sops.secrets.oberon_sinch_service_id.path}) export SINCH_WEBHOOK_USER=$(cat ${config.sops.secrets.oberon_sinch_webhook_user.path}) export SINCH_WEBHOOK_PASS=$(cat ${config.sops.secrets.oberon_sinch_webhook_pass.path}) export FAX_INBOUND_NOSTR_PRIVKEY=$(cat ${config.sops.secrets.oberon_inbound_privkey.path}) export FAX_OUTBOUND_NOSTR_PRIVKEY=$(cat ${config.sops.secrets.oberon_outbound_privkey.path}) export OFFICIAL_FAX_NUMBER=$(cat ${config.sops.secrets.oberon_official_number.path}) export CDN_APP_SECRET=$(cat ${config.sops.secrets.oberon_cdn_app_secret.path}) exec ${pkg}/bin/oberon ''; in { # Secrets — add corresponding keys to secrets/bucur.yaml via sops. sops.secrets.oberon_sinch_project_id = { owner = "oberon"; }; sops.secrets.oberon_sinch_key_id = { owner = "oberon"; }; sops.secrets.oberon_sinch_key_secret = { owner = "oberon"; }; sops.secrets.oberon_sinch_service_id = { owner = "oberon"; }; sops.secrets.oberon_sinch_webhook_user = { owner = "oberon"; }; sops.secrets.oberon_sinch_webhook_pass = { owner = "oberon"; }; sops.secrets.oberon_inbound_privkey = { owner = "oberon"; }; sops.secrets.oberon_outbound_privkey = { owner = "oberon"; }; sops.secrets.oberon_official_number = { owner = "oberon"; }; sops.secrets.oberon_cdn_app_secret = { owner = "oberon"; }; users.users.oberon = { isSystemUser = true; group = "oberon"; home = "/var/lib/oberon"; }; users.groups.oberon = {}; systemd.services.oberon = { description = "Oberon — xfay fax backend (Sinch ⇄ Nostr bridge)"; after = [ "network.target" "sops-nix.service" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "simple"; User = "oberon"; Group = "oberon"; StateDirectory = "oberon"; RuntimeDirectory = "oberon"; ExecStart = startScript; Environment = [ "PORT=${toString port}" "DB_PATH=/var/lib/oberon/oberon.db" "RELAY_URLS=${relayUrl}" "CDN_URL=${cdnUrl}" "CDN_APP_NAME=xfay" # Feature flags. Credits stay off (defaults false); PDF fax is entitlement-gated. "FAX_PDF_ENABLED=true" # Abuse controls (M4) — start conservative; empty prefix list = allow all. "ALLOWED_DESTINATION_PREFIXES=+1" "MAX_FAXES_PER_PUBKEY_PER_DAY=20" "MAX_FAXES_PER_DESTINATION_PER_DAY=5" ]; Restart = "on-failure"; RestartSec = 5; }; }; # Caddy reverse proxy fragment — picked up via the glob import in caddy.nix. environment.etc."caddy/Caddyfile.d/oberon.caddyfile".text = '' ${domain} { reverse_proxy localhost:${toString port} } ''; }