{ lib, config, pkgs, ... }: let cfg = config.my.services.firefly-iii; dbName = "firefly-iii"; appPort = 9080; dataImpPort = 9081; in { options.my.services.firefly-iii = { enable = lib.mkEnableOption "Enable Firefly-III budgeting app"; accessToken = lib.mkOption { type = lib.types.path; default = ""; description = '' Access token for Firefly-III ''; }; # age.secrets.firefly-iii-mailgun-key.file = ../../secrets/firefly-iii-mailgun-key.age; mailgun_key = lib.mkOption { type = lib.types.path; default = ""; description = '' Mailgun API key for sending emails ''; }; proxy = { enable = lib.mkEnableOption "Set the proxy entry for this service"; domain = lib.mkOption { default = "example.com"; type = lib.types.str; description = '' The domain where Caddy is reachable ''; }; subdomain = lib.mkOption { default = "money"; type = lib.types.str; description = '' The subdomain where Immich is reachable ''; }; host = lib.mkOption { default = "localhost"; type = lib.types.str; description = '' host name where the service is running ''; }; }; }; config = lib.mkMerge [ (lib.mkIf cfg.enable { my.services.postgresql = { enable = true; ensures = [ { username = config.services.firefly-iii.user; database = dbName; } ]; }; services.firefly-iii = { enable = true; enableNginx = true; settings = { APP_ENV = "production"; APP_URL = "https://${cfg.proxy.subdomain}.${cfg.proxy.domain}"; SITE_OWNER = "davide@pasetto.me"; DEFAULT_LANGUAGE = "en_US"; TZ = "Europe/Rome"; TRUSTED_PROXIES = "**"; SEND_ERROR_MESSAGE = "true"; SEND_REPORT_JOURNALS = "false"; # AUTHENTICATION_GUARD = "web"; AUTHENTICATION_GUARD = "remote_user_guard"; AUTHENTICATION_GUARD_HEADER = "X-Authentik-Username"; AUTHENTICATION_GUARD_EMAIL = "X-Authentik-Email"; PGSQL_SCHEMA = "public"; DB_CONNECTION = "pgsql"; DB_DATABASE = dbName; DB_USERNAME = config.services.firefly-iii.user; MAILGUN_ENDPOINT = "api.eu.mailgun.net"; MAILGUN_DOMAIN = "pazpi.top"; MAILGUN_SECRET_FILE = cfg.mailgun_key; # Exactly 32 chars APP_KEY_FILE = cfg.accessToken; }; }; services.firefly-iii-data-importer = { enable = true; enableNginx = true; virtualHost = "firefly-iii-data-importer"; settings = { FIREFLY_III_ACCESS_TOKEN = cfg.accessToken; }; }; networking.firewall.allowedTCPPorts = [ appPort dataImpPort ]; services.nginx.virtualHosts = { ${config.services.firefly-iii.virtualHost} = { listen = [ { addr = "0.0.0.0"; port = appPort; } ]; }; ${config.services.firefly-iii-data-importer.virtualHost} = { listen = [ { addr = "0.0.0.0"; port = dataImpPort; } ]; }; }; }) (lib.mkIf cfg.proxy.enable { services.caddy = with cfg.proxy; { virtualHosts."${subdomain}.${domain}".extraConfig = '' # directive execution order is only as stated if enclosed with route. route { # always forward outpost path to actual outpost reverse_proxy /outpost.goauthentik.io/* https://auth.pasetto.me { header_up Host {http.reverse_proxy.upstream.hostport} } # forward authentication to outpost forward_auth https://auth.pasetto.me { uri /outpost.goauthentik.io/auth/caddy # capitalization of the headers is important, otherwise they will be empty copy_headers X-Authentik-Username X-Authentik-Email # optional, in this config trust all private ranges, should probably be set to the outposts IP trusted_proxies private_ranges } # Firefly-III reverse_proxy http://${host}:${toString appPort} } reverse_proxy http://${host}:${toString appPort} import cloudflare_${domain} ''; }; }) ]; }