sneeuwvlok/modules/nixos/temp/services/arrtrix/default.nix
Chris Kruining 81f34676c4
Add OpenTelemetry observability to Arrtrix
- Add OTLP/gRPC observability config and resource attributes
- Instrument webhook and onboarding handlers with tracing and metrics
- Add OpenTelemetry dependencies to go.mod/go.sum
- Update NixOS modules to configure observability settings
2026-04-16 10:13:51 +02:00

181 lines
5.5 KiB
Nix

{
config,
lib,
pkgs,
namespace,
...
}: let
inherit (lib) mkEnableOption mkPackageOption mkIf mkOption optionalAttrs recursiveUpdate types baseNameOf;
cfg = config.services.arrtrix;
dataDir = "/var/lib/arrtrix";
registrationFile = "${dataDir}/arrtrix-registration.yaml";
settingsFile = "${dataDir}/config.yaml";
settingsFileUnsubstituted = settingsFormat.generate "arrtrix-config-unsubstituted.json" cfg.settings;
settingsFormat = pkgs.formats.json {};
defaultConfig = {
bridge = {
command_prefix = "!arr";
relay.enabled = true;
permissions."*" = "relay";
};
database = {
type = "sqlite3-fk-wal";
uri = "file:${dataDir}/arrtrix.db?_txlock=immediate";
};
homeserver = {
address = "http://localhost:8448";
domain = config.services.matrix-synapse.settings.server_name or "example.com";
};
appservice = {
hostname = "[::]";
port = 29329;
id = "arrtrix";
bot = {
username = "arrtrixbot";
displayname = "arrtrix Bot";
};
as_token = "";
hs_token = "";
username_template = "arrtrix_{{.}}";
};
logging = {
min_level = "info";
writers = lib.singleton {
type = "stdout";
format = "pretty-colored";
time_format = " ";
};
};
observability = {
otlp_grpc_endpoint = "";
service_name = "arrtrix";
resource_attributes = {};
};
};
in {
options.services.arrtrix = {
enable = mkEnableOption "Arr-focused Matrix appservice foundation";
package = mkPackageOption pkgs.${namespace} "arrtrix" {};
registerToSynapse = mkOption {
type = types.bool;
default = config.services.matrix-synapse.enable;
defaultText = lib.literalExpression ''
config.services.matrix-synapse.enable
'';
description = ''
Whether to add the bridge's app service registration file to
`services.matrix-synapse.settings.app_service_config_files`.
'';
};
settings = mkOption {
apply = lib.recursiveUpdate defaultConfig;
type = settingsFormat.type;
default = defaultConfig;
description = ''
{file}`config.yaml` configuration as a Nix attribute set.
Configuration options should match those described in the example configuration.
Get an example configuration by executing `arrtrix -c example.yaml --generate-example-config`
Secret tokens should be specified using {option}`environmentFile`
instead of this world-readable attribute set.
'';
example = {};
};
serviceDependencies = lib.mkOption {
type = with lib.types; listOf str;
default =
(lib.optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit)
++ (lib.optional config.services.matrix-conduit.enable "conduit.service");
defaultText = lib.literalExpression ''
(optional config.services.matrix-synapse.enable config.services.matrix-synapse.serviceUnit)
++ (optional config.services.matrix-conduit.enable "conduit.service")
'';
description = ''
List of systemd units to require and wait for when starting the application service.
'';
};
};
config = mkIf cfg.enable {
users = {
users."arrtrix" = {
isSystemUser = true;
group = "arrtrix";
};
groups."arrtrix" = {};
};
services.matrix-synapse = lib.mkIf cfg.registerToSynapse {
settings.app_service_config_files = [registrationFile];
};
systemd.services.matrix-synapse = lib.mkIf cfg.registerToSynapse {
serviceConfig.SupplementaryGroups = ["arrtrix"];
};
systemd.services.arrtrix = {
description = "arrtrix, A *arr stack to matrix bridge for *arr-notifications";
wantedBy = ["multi-user.target"];
after = ["network-online.target"];
wants = ["network-online.target"];
restartTriggers = [settingsFileUnsubstituted];
preStart = ''
# substitute the settings file by environment variables
# in this case read from EnvironmentFile
test -f '${settingsFile}' && rm -f '${settingsFile}'
old_umask=$(umask)
umask 0177
${lib.getExe pkgs.envsubst} -o '${settingsFile}' -i '${settingsFileUnsubstituted}'
umask $old_umask
if [ ! -f '${registrationFile}' ]; then
${lib.getExe cfg.package} --generate-registration --config='${settingsFile}' --registration='${registrationFile}'
fi
chmod 640 ${registrationFile}
'';
serviceConfig = {
Type = "simple";
User = "arrtrix";
Group = "arrtrix";
StateDirectory = baseNameOf dataDir;
WorkingDirectory = dataDir;
ExecStart = ''
${lib.getExe cfg.package} --config='${settingsFile}' --registration='${registrationFile}'
'';
Restart = "on-failure";
RestartSec = "30s";
NoNewPrivileges = true;
PrivateTmp = true;
ProtectHome = true;
ProtectSystem = "strict";
ProtectClock = true;
ProtectControlGroups = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
RestrictNamespaces = true;
RestrictRealtime = true;
RestrictSUIDSGID = true;
LockPersonality = true;
MemoryDenyWriteExecute = true;
SystemCallArchitectures = "native";
SystemCallErrorNumber = "EPERM";
SystemCallFilter = ["@system-service"];
UMask = "0027";
};
};
};
}