firefly-iii-data-importer: init
This commit is contained in:
128
services/firefly-iii-data-importer.nix
Normal file
128
services/firefly-iii-data-importer.nix
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
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;
|
||||
};
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user