129 lines
4.8 KiB
Nix
129 lines
4.8 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
service_configs,
|
|
...
|
|
}:
|
|
let
|
|
fidi = service_configs.firefly_iii_data_importer;
|
|
in
|
|
{
|
|
imports = [
|
|
# Same chicanery as services/firefly-iii.nix: the upstream module's
|
|
# actual systemd units are firefly-iii-data-importer-setup.service and
|
|
# phpfpm-firefly-iii-data-importer.service. Hook the zfs mount into the
|
|
# `-setup` unit; the upstream `requiredBy` chain pulls phpfpm forward.
|
|
(lib.serviceMountWithZpool "firefly-iii-data-importer-setup" service_configs.zpool_ssds [
|
|
fidi.dataDir
|
|
])
|
|
];
|
|
|
|
services.firefly-iii-data-importer = {
|
|
enable = true;
|
|
dataDir = fidi.dataDir;
|
|
# Same trick as firefly-iii: run as group caddy so caddy can read the
|
|
# php-fpm unix socket without us having to override `listen.group`.
|
|
group = "caddy";
|
|
virtualHost = fidi.domain;
|
|
settings = {
|
|
APP_ENV = "production";
|
|
APP_KEY_FILE = config.age.secrets.firefly-iii-data-importer-app-key.path;
|
|
LOG_CHANNEL = "syslog";
|
|
LOG_LEVEL = "info";
|
|
|
|
# Importer → Firefly III. The /etc/hosts override below pins this hostname
|
|
# to 127.0.0.1 on muffin so the importer's outbound HTTPS lands on the
|
|
# local Caddy without hairpinning through the WAN gateway. The TLS cert
|
|
# is the same wildcard Caddy serves externally, so verification works.
|
|
FIREFLY_III_URL = "https://${service_configs.firefly_iii.domain}";
|
|
FIREFLY_III_ACCESS_TOKEN_FILE = config.age.secrets.firefly-iii-fidi-token.path;
|
|
|
|
TRUSTED_PROXIES = "127.0.0.1,::1";
|
|
|
|
# SimpleFIN polls the last 90d every run; without this, every daily run
|
|
# logs hundreds of "duplicate transaction" warnings as Firefly's server-
|
|
# side dedup catches them. Firefly still rejects the duplicates; we just
|
|
# don't see the noise.
|
|
IGNORE_DUPLICATE_ERRORS = true;
|
|
|
|
# CLI-driven imports only. Leave the /autoimport HTTP endpoint disabled
|
|
# (default) — the systemd timer below uses `artisan importer:import`
|
|
# against a static config file, which avoids exposing another web-
|
|
# reachable surface that needs its own shared secret.
|
|
CAN_POST_AUTOIMPORT = false;
|
|
CAN_POST_FILES = false;
|
|
};
|
|
};
|
|
|
|
# Pin the firefly-iii hostname to loopback on muffin so the importer's
|
|
# outbound API calls hit local Caddy directly. No effect on any other host.
|
|
networking.extraHosts = "127.0.0.1 ${service_configs.firefly_iii.domain}";
|
|
|
|
services.caddy.virtualHosts.${fidi.domain}.extraConfig = ''
|
|
encode zstd gzip
|
|
import ${config.age.secrets.caddy_auth.path}
|
|
|
|
root * ${config.services.firefly-iii-data-importer.package}/public
|
|
php_fastcgi unix/${config.services.phpfpm.pools.firefly-iii-data-importer.socket}
|
|
file_server
|
|
'';
|
|
|
|
# Daily SimpleFIN import via the importer's CLI. The unit is gated by
|
|
# ConditionPathExists so it silently no-ops until the user has uploaded
|
|
# `simplefin.json` (per the post-deploy operational steps).
|
|
systemd.services.firefly-iii-data-importer-import = {
|
|
description = "Run scheduled Firefly III data importer config (SimpleFIN)";
|
|
after = [
|
|
"phpfpm-firefly-iii-data-importer.service"
|
|
"network-online.target"
|
|
];
|
|
wants = [ "network-online.target" ];
|
|
unitConfig.ConditionPathExists = fidi.simplefinConfigPath;
|
|
serviceConfig = {
|
|
Type = "oneshot";
|
|
User = config.services.firefly-iii-data-importer.user;
|
|
Group = config.services.firefly-iii-data-importer.group;
|
|
WorkingDirectory = config.services.firefly-iii-data-importer.package;
|
|
ExecStart = "${config.services.firefly-iii-data-importer.package}/artisan importer:import ${fidi.simplefinConfigPath}";
|
|
# Same hardening posture as the upstream commonServiceConfig.
|
|
ReadWritePaths = [ fidi.dataDir ];
|
|
PrivateTmp = true;
|
|
PrivateDevices = true;
|
|
ProtectSystem = "strict";
|
|
ProtectHome = "tmpfs";
|
|
ProtectKernelTunables = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectControlGroups = true;
|
|
ProtectClock = true;
|
|
ProtectHostname = true;
|
|
ProtectProc = "invisible";
|
|
ProcSubset = "pid";
|
|
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
|
|
RestrictNamespaces = true;
|
|
RestrictRealtime = true;
|
|
RestrictSUIDSGID = true;
|
|
LockPersonality = true;
|
|
NoNewPrivileges = true;
|
|
RemoveIPC = true;
|
|
CapabilityBoundingSet = "";
|
|
AmbientCapabilities = "";
|
|
SystemCallArchitectures = "native";
|
|
SystemCallFilter = [
|
|
"@system-service @resources"
|
|
"~@obsolete @privileged"
|
|
];
|
|
};
|
|
};
|
|
|
|
systemd.timers.firefly-iii-data-importer-import = {
|
|
description = "Daily Firefly III SimpleFIN import";
|
|
wantedBy = [ "timers.target" ];
|
|
timerConfig = {
|
|
OnCalendar = "daily";
|
|
RandomizedDelaySec = "1h";
|
|
Persistent = true;
|
|
};
|
|
};
|
|
}
|