bucur/modules/services/oberon.nix

89 lines
3.7 KiB
Nix
Raw Normal View History

2026-07-04 17:39:55 +03:00
{ 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})
export ADAPTY_SECRET_KEY=$(cat ${config.sops.secrets.oberon_adapty_secret_key.path})
2026-07-04 17:39:55 +03:00
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"; };
sops.secrets.oberon_adapty_secret_key = { owner = "oberon"; };
2026-07-04 17:39:55 +03:00
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"
2026-07-11 11:35:48 +03:00
# Feature flags. Credits stay off (defaults false); PDF fax is entitlement-gated.
"FAX_PDF_ENABLED=true"
2026-07-04 17:39:55 +03:00
# 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}
}
'';
}