{ flake, config, pkgs, lib, ... }: let psCfg = config.pub-solar; xdg = config.home-manager.users."${psCfg.user.name}".xdg; backupDir = "/var/lib/firefly/backup"; in { age.secrets."firefly-secrets.env" = { file = "${flake.self}/secrets/firefly-secrets.env.age"; mode = "400"; }; age.secrets."firefly-db-secrets.env" = { file = "${flake.self}/secrets/firefly-db-secrets.env.age"; mode = "400"; }; age.secrets."firefly-importer-secrets.env" = { file = "${flake.self}/secrets/firefly-importer-secrets.env.age"; mode = "400"; }; age.secrets."firefly-cron-secrets.env" = { file = "${flake.self}/secrets/firefly-cron-secrets.env.age"; mode = "400"; }; security.acme.certs = { "firefly.b12f.io" = {}; "firefly-importer.b12f.io" = {}; }; services.nginx.virtualHosts = { "firefly.b12f.io" = { forceSSL = true; useACMEHost = "firefly.b12f.io"; extraConfig = "include /etc/nginx/conf-available/authelia-location.conf;"; # Make api calls skip the nginx proxy auth locations."/api/v1".proxyPass = "http://127.0.0.1:8080"; locations."/".proxyPass = "http://127.0.0.1:8080"; locations."/".extraConfig = '' include /etc/nginx/conf-available/proxy.conf; include /etc/nginx/conf-available/authelia-authrequest.conf; ''; }; "firefly-importer.b12f.io" = { forceSSL = true; useACMEHost = "firefly-importer.b12f.io"; extraConfig = "include /etc/nginx/conf-available/authelia-location.conf;"; locations."/".proxyPass = "http://127.0.0.1:8081"; locations."/".extraConfig = '' include /etc/nginx/conf-available/proxy.conf; include /etc/nginx/conf-available/authelia-authrequest.conf; ''; }; }; systemd.services."docker-network-firefly" = let docker = config.virtualisation.oci-containers.backend; dockerBin = "${pkgs.${docker}}/bin/${docker}"; in { serviceConfig.Type = "oneshot"; before = ["docker-firefly.service"]; script = '' ${dockerBin} network inspect firefly >/dev/null 2>&1 || ${dockerBin} network create firefly --subnet 172.20.0.0/24 ''; }; virtualisation = { oci-containers = { backend = "docker"; containers."firefly" = { image = "fireflyiii/core:latest"; autoStart = true; volumes = [ "/var/lib/firefly/upload:/var/www/html/storage/upload" ]; extraOptions = [ "--network=firefly" ]; environmentFiles = [ ./.env.firefly config.age.secrets."firefly-secrets.env".path config.age.secrets."firefly-cron-secrets.env".path ]; ports = [ "127.0.0.1:8080:8080" ]; dependsOn = [ "firefly-db" ]; }; containers."firefly-db" = { image = "postgres:16"; autoStart = true; volumes = [ "/var/lib/firefly/db:/var/lib/postgresql/data" ]; extraOptions = [ "--network=firefly" ]; environmentFiles = [ config.age.secrets."firefly-db-secrets.env".path ]; }; containers."firefly-importer" = { image = "fireflyiii/data-importer:latest"; autoStart = true; extraOptions = [ "--network=firefly" ]; ports = [ "127.0.0.1:8081:8080" ]; environment = { FIREFLY_III_URL = "https://firefly.b12f.io"; }; environmentFiles = [ ./.env.firefly-importer config.age.secrets."firefly-importer-secrets.env".path ]; dependsOn = [ "firefly" ]; }; containers."firefly-cron" = { image = "alpine"; autoStart = true; cmd = [ "sh" "-c" "echo \"0 3 * * * wget -qO- http://firefly:8080/api/v1/cron/$STATIC_CRON_TOKEN\" | crontab - && crond -f -L /dev/stdout" ]; environmentFiles = [ config.age.secrets."firefly-cron-secrets.env".path ]; extraOptions = [ "--network=firefly" ]; }; }; }; systemd.tmpfiles.rules = [ "d '${backupDir}' 0700 root root - -" ]; services.restic.backups = { firefly = { paths = [ backupDir "/var/lib/firefly/upload" ]; initialize = true; passwordFile = config.age.secrets."restic-password".path; # See https://www.hosting.de/blog/verschluesselte-backups-mit-rclone-und-restic-in-nextcloud/ repository = "rclone:cloud.pub.solar:/backups/FireflyIII"; backupPrepareCommand = '' ${pkgs.docker-client}/bin/docker exec -t firefly-db pg_dumpall -c -U firefly > "${backupDir}/postgres.sql" ''; rcloneConfigFile = config.age.secrets."rclone-pie.conf".path; }; }; }