1
0
Fork 0
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-06-20 08:29:20 +03:00
nixpkgs/nixos/modules/services/matrix/appservice-irc.nix
Silvan Mosberger 4f0dadbf38 treewide: format all inactive Nix files
After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.

Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.

A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.

This commit was automatically created and can be verified using

    nix-build a08b3a4d19.tar.gz \
      --argstr baseRev b32a094368
    result/bin/apply-formatting $NIXPKGS_PATH
2024-12-10 20:26:33 +01:00

284 lines
9.8 KiB
Nix

{
config,
pkgs,
lib,
...
}:
let
cfg = config.services.matrix-appservice-irc;
pkg = pkgs.matrix-appservice-irc;
bin = "${pkg}/bin/matrix-appservice-irc";
jsonType = (pkgs.formats.json { }).type;
configFile =
pkgs.runCommand "matrix-appservice-irc.yml"
{
# Because this program will be run at build time, we need `nativeBuildInputs`
nativeBuildInputs = [
(pkgs.python3.withPackages (ps: [ ps.jsonschema ]))
pkgs.remarshal
];
preferLocalBuild = true;
config = builtins.toJSON cfg.settings;
passAsFile = [ "config" ];
}
''
# The schema is given as yaml, we need to convert it to json
remarshal --if yaml --of json -i ${pkg}/config.schema.yml -o config.schema.json
python -m jsonschema config.schema.json -i $configPath
cp "$configPath" "$out"
'';
registrationFile = "/var/lib/matrix-appservice-irc/registration.yml";
in
{
options.services.matrix-appservice-irc = with lib.types; {
enable = lib.mkEnableOption "the Matrix/IRC bridge";
port = lib.mkOption {
type = port;
description = "The port to listen on";
default = 8009;
};
needBindingCap = lib.mkOption {
type = bool;
description = "Whether the daemon needs to bind to ports below 1024 (e.g. for the ident service)";
default = false;
};
passwordEncryptionKeyLength = lib.mkOption {
type = ints.unsigned;
description = "Length of the key to encrypt IRC passwords with";
default = 4096;
example = 8192;
};
registrationUrl = lib.mkOption {
type = str;
description = ''
The URL where the application service is listening for homeserver requests,
from the Matrix homeserver perspective.
'';
example = "http://localhost:8009";
};
localpart = lib.mkOption {
type = str;
description = "The user_id localpart to assign to the appservice";
default = "appservice-irc";
};
settings = lib.mkOption {
description = ''
Configuration for the appservice, see
<https://github.com/matrix-org/matrix-appservice-irc/blob/${pkgs.matrix-appservice-irc.version}/config.sample.yaml>
for supported values
'';
default = { };
type = submodule {
freeformType = jsonType;
options = {
homeserver = lib.mkOption {
description = "Homeserver configuration";
default = { };
type = submodule {
freeformType = jsonType;
options = {
url = lib.mkOption {
type = str;
description = "The URL to the home server for client-server API calls";
};
domain = lib.mkOption {
type = str;
description = ''
The 'domain' part for user IDs on this home server. Usually
(but not always) is the "domain name" part of the homeserver URL.
'';
};
};
};
};
database = lib.mkOption {
default = { };
description = "Configuration for the database";
type = submodule {
freeformType = jsonType;
options = {
engine = lib.mkOption {
type = str;
description = "Which database engine to use";
default = "nedb";
example = "postgres";
};
connectionString = lib.mkOption {
type = str;
description = "The database connection string";
default = "nedb://var/lib/matrix-appservice-irc/data";
example = "postgres://username:password@host:port/databasename";
};
};
};
};
ircService = lib.mkOption {
default = { };
description = "IRC bridge configuration";
type = submodule {
freeformType = jsonType;
options = {
passwordEncryptionKeyPath = lib.mkOption {
type = str;
description = ''
Location of the key with which IRC passwords are encrypted
for storage. Will be generated on first run if not present.
'';
default = "/var/lib/matrix-appservice-irc/passkey.pem";
};
servers = lib.mkOption {
type = submodule { freeformType = jsonType; };
description = "IRC servers to connect to";
};
mediaProxy = {
signingKeyPath = lib.mkOption {
type = path;
default = "/var/lib/matrix-appservice-irc/media-signingkey.jwk";
description = ''
Path to the signing key file for authenticated media.
'';
};
ttlSeconds = lib.mkOption {
type = ints.unsigned;
default = 3600;
example = 0;
description = ''
Lifetime in seconds, that generated URLs stay valid.
Set the lifetime to 0 to prevent URLs from becoming invalid.
'';
};
bindPort = lib.mkOption {
type = port;
default = 11111;
description = ''
Port that the media proxy binds to.
'';
};
publicUrl = lib.mkOption {
type = str;
example = "https://matrix.example.com/media";
description = ''
URL under which the media proxy is publicly acccessible.
'';
};
};
};
};
};
};
};
};
};
config = lib.mkIf cfg.enable {
systemd.services.matrix-appservice-irc = {
description = "Matrix-IRC bridge";
before = [ "matrix-synapse.service" ]; # So the registration can be used by Synapse
after = lib.optionals (cfg.settings.database.engine == "postgres") [
"postgresql.service"
];
wantedBy = [ "multi-user.target" ];
preStart = ''
umask 077
# Generate key for crypting passwords
if ! [ -f "${cfg.settings.ircService.passwordEncryptionKeyPath}" ]; then
${pkgs.openssl}/bin/openssl genpkey \
-out "${cfg.settings.ircService.passwordEncryptionKeyPath}" \
-outform PEM \
-algorithm RSA \
-pkeyopt "rsa_keygen_bits:${toString cfg.passwordEncryptionKeyLength}"
fi
# Generate registration file
if ! [ -f "${registrationFile}" ]; then
# The easy case: the file has not been generated yet
${bin} --generate-registration --file ${registrationFile} --config ${configFile} --url ${cfg.registrationUrl} --localpart ${cfg.localpart}
else
# The tricky case: we already have a generation file. Because the NixOS configuration might have changed, we need to
# regenerate it. But this would give the service a new random ID and tokens, so we need to back up and restore them.
# 1. Backup
id=$(grep "^id:.*$" ${registrationFile})
hs_token=$(grep "^hs_token:.*$" ${registrationFile})
as_token=$(grep "^as_token:.*$" ${registrationFile})
# 2. Regenerate
${bin} --generate-registration --file ${registrationFile} --config ${configFile} --url ${cfg.registrationUrl} --localpart ${cfg.localpart}
# 3. Restore
sed -i "s/^id:.*$/$id/g" ${registrationFile}
sed -i "s/^hs_token:.*$/$hs_token/g" ${registrationFile}
sed -i "s/^as_token:.*$/$as_token/g" ${registrationFile}
fi
if ! [ -f "${cfg.settings.ircService.mediaProxy.signingKeyPath}"]; then
${lib.getExe pkgs.nodejs} ${pkg}/lib/generate-signing-key.js > "${cfg.settings.ircService.mediaProxy.signingKeyPath}"
fi
# Allow synapse access to the registration
if ${pkgs.getent}/bin/getent group matrix-synapse > /dev/null; then
chgrp matrix-synapse ${registrationFile}
chmod g+r ${registrationFile}
fi
'';
serviceConfig = rec {
Type = "simple";
ExecStart = "${bin} --config ${configFile} --file ${registrationFile} --port ${toString cfg.port}";
ProtectHome = true;
PrivateDevices = true;
ProtectKernelTunables = true;
ProtectKernelModules = true;
ProtectControlGroups = true;
StateDirectory = "matrix-appservice-irc";
StateDirectoryMode = "755";
User = "matrix-appservice-irc";
Group = "matrix-appservice-irc";
CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ lib.optional (cfg.needBindingCap) "CAP_NET_BIND_SERVICE";
AmbientCapabilities = CapabilityBoundingSet;
NoNewPrivileges = true;
LockPersonality = true;
RestrictRealtime = true;
PrivateMounts = true;
SystemCallFilter = [
"@system-service @pkey"
"~@privileged @resources"
"@chown"
];
SystemCallArchitectures = "native";
# AF_UNIX is required to connect to a postgres socket.
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
};
};
users.groups.matrix-appservice-irc = { };
users.users.matrix-appservice-irc = {
description = "Service user for the Matrix-IRC bridge";
group = "matrix-appservice-irc";
isSystemUser = true;
};
};
# uses attributes of the linked package
meta.buildDocsInSandbox = false;
}