Massive nixfmt reformatting

This commit is contained in:
Natsu Kagami 2025-04-03 13:59:50 +02:00
parent fe4492f004
commit b29ddd5e65
Signed by: nki
GPG key ID: 55A032EB38B49ADB
109 changed files with 4323 additions and 2368 deletions

View file

@ -1,11 +1,15 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let
cfg = config.cloud.authentik;
mkImage =
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
mkImage = { imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage;
@ -62,7 +66,10 @@ in
image = images.postgresql;
restart = "unless-stopped";
healthcheck = {
test = [ "CMD-SHELL" "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}" ];
test = [
"CMD-SHELL"
"pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"
];
start_period = "20s";
interval = "30s";
retries = 5;
@ -73,14 +80,20 @@ in
POSTGRES_USER = "authentik";
POSTGRES_DB = "authentik";
};
env_file = [ cfg.envFile "${postgresEnv}" ];
env_file = [
cfg.envFile
"${postgresEnv}"
];
};
services.redis.service = {
image = images.redis;
command = "--save 60 1 --loglevel warning";
restart = "unless-stopped";
healthcheck = {
test = [ "CMD-SHELL" "redis-cli ping | grep PONG" ];
test = [
"CMD-SHELL"
"redis-cli ping | grep PONG"
];
start_period = "20s";
interval = "30s";
retries = 5;
@ -102,7 +115,10 @@ in
AUTHENTIK_POSTGRESQL__USER = "authentik";
AUTHENTIK_POSTGRESQL__NAME = "authentik";
};
env_file = [ cfg.envFile "${authentikEnv}" ];
env_file = [
cfg.envFile
"${authentikEnv}"
];
ports = [
"127.0.0.1:${toString cfg.port}:9000"
];
@ -124,7 +140,10 @@ in
AUTHENTIK_POSTGRESQL__USER = "authentik";
AUTHENTIK_POSTGRESQL__NAME = "authentik";
};
env_file = [ cfg.envFile "${authentikEnv}" ];
env_file = [
cfg.envFile
"${authentikEnv}"
];
user = "root";
};
docker-compose.volumes = {
@ -134,4 +153,3 @@ in
};
};
}

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
with lib;
let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
let
cfg = config.cloud.conduit;
@ -33,95 +38,105 @@ with lib;
};
instances = mkOption {
type = types.attrsOf (types.submodule {
options = {
host = mkOption {
type = types.str;
type = types.attrsOf (
types.submodule {
options = {
host = mkOption {
type = types.str;
};
server_name = mkOption {
type = types.str;
default = "";
};
port = mkOption {
type = types.int;
};
noCloudflare = mkOption {
type = types.bool;
default = false;
};
allow_registration = mkOption {
type = types.bool;
default = false;
};
well-known_port = mkOption {
type = types.int;
};
};
server_name = mkOption {
type = types.str;
default = "";
};
port = mkOption {
type = types.int;
};
noCloudflare = mkOption {
type = types.bool;
default = false;
};
allow_registration = mkOption {
type = types.bool;
default = false;
};
well-known_port = mkOption {
type = types.int;
};
};
});
}
);
};
};
config.systemd.services = mkIf cfg.enable
(lib.attrsets.mapAttrs'
(name: instance: lib.attrsets.nameValuePair "matrix-conduit-${name}"
(
let
srvName = "matrix-conduit-${name}";
format = pkgs.formats.toml { };
server_name = if instance.server_name == "" then instance.host else instance.server_name;
configFile = format.generate "conduit.toml" (lib.attrsets.recursiveUpdate defaultConfig {
config.systemd.services = mkIf cfg.enable (
lib.attrsets.mapAttrs' (
name: instance:
lib.attrsets.nameValuePair "matrix-conduit-${name}" (
let
srvName = "matrix-conduit-${name}";
format = pkgs.formats.toml { };
server_name = if instance.server_name == "" then instance.host else instance.server_name;
configFile = format.generate "conduit.toml" (
lib.attrsets.recursiveUpdate defaultConfig {
global.server_name = server_name;
global.port = instance.port;
global.allow_registration = instance.allow_registration;
global.database_path = "/mnt/data/${srvName}/";
global.well_known_client = "https://${instance.host}";
global.well_known_server = "${instance.host}:443";
});
in
{
description = "Conduit Matrix Server (for ${server_name})";
documentation = [ "https://gitlab.com/famedly/conduit/" ];
wantedBy = [ "multi-user.target" ];
environment = { CONDUIT_CONFIG = configFile; };
serviceConfig = {
DynamicUser = true;
User = "${srvName}";
LockPersonality = true;
MemoryDenyWriteExecute = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateUsers = true;
RestrictAddressFamilies = [ "AF_INET" "AF_INET6" ];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
# StateDirectory = "/mnt/data/${srvName}";
BindPaths = [ "/mnt/data/${srvName}" ];
ExecStart = "${cfg.package}/bin/conduit";
Restart = "on-failure";
RestartSec = 10;
StartLimitBurst = 5;
};
}
))
cfg.instances);
}
);
in
{
description = "Conduit Matrix Server (for ${server_name})";
documentation = [ "https://gitlab.com/famedly/conduit/" ];
wantedBy = [ "multi-user.target" ];
environment = {
CONDUIT_CONFIG = configFile;
};
serviceConfig = {
DynamicUser = true;
User = "${srvName}";
LockPersonality = true;
MemoryDenyWriteExecute = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateUsers = true;
RestrictAddressFamilies = [
"AF_INET"
"AF_INET6"
];
RestrictNamespaces = true;
RestrictRealtime = true;
SystemCallArchitectures = "native";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
# StateDirectory = "/mnt/data/${srvName}";
BindPaths = [ "/mnt/data/${srvName}" ];
ExecStart = "${cfg.package}/bin/conduit";
Restart = "on-failure";
RestartSec = 10;
StartLimitBurst = 5;
};
}
)
) cfg.instances
);
config.cloud.traefik.hosts = mkIf cfg.enable (
(lib.attrsets.mapAttrs'
(name: instance: lib.attrsets.nameValuePair "conduit-${name}" ({
(lib.attrsets.mapAttrs' (
name: instance:
lib.attrsets.nameValuePair "conduit-${name}" ({
inherit (instance) host port noCloudflare;
}))
cfg.instances)
})
) cfg.instances)
);
}

View file

@ -1,9 +1,15 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
let
cfg = config.cloud.conduit.heisenbridge;
cfgConduit = config.cloud.conduit;
in
with lib; {
with lib;
{
options.cloud.conduit.heisenbridge = {
enable = mkEnableOption "Enable heisenbridge for conduit";
package = mkPackageOption pkgs "heisenbridge" { };
@ -23,17 +29,26 @@ with lib; {
};
config = mkIf cfg.enable (
let
cfgFile = if cfg.port == null then cfg.appserviceFile else
pkgs.runCommand "heisenbridge-config" { } ''
cp ${cfg.appserviceFile} $out
${pkgs.sd}/bin/sd '^url: .*$' "url: http://127.0.0.1:${cfg.port}"
'';
listenArgs = lists.optionals (cfg.port != null) [ "--listen-port" (toString cfg.port) ];
cfgFile =
if cfg.port == null then
cfg.appserviceFile
else
pkgs.runCommand "heisenbridge-config" { } ''
cp ${cfg.appserviceFile} $out
${pkgs.sd}/bin/sd '^url: .*$' "url: http://127.0.0.1:${cfg.port}"
'';
listenArgs = lists.optionals (cfg.port != null) [
"--listen-port"
(toString cfg.port)
];
in
{
systemd.services.heisenbridge = {
description = "Matrix<->IRC bridge";
requires = [ "matrix-conduit-nkagami.service" "matrix-synapse.service" ]; # So the registration file can be used by Synapse
requires = [
"matrix-conduit-nkagami.service"
"matrix-synapse.service"
]; # So the registration file can be used by Synapse
wantedBy = [ "multi-user.target" ];
serviceConfig = rec {
@ -77,12 +92,18 @@ with lib; {
RemoveIPC = true;
UMask = "0077";
CapabilityBoundingSet = [ "CAP_CHOWN" ] ++ optional (cfg.port != null && cfg.port < 1024) "CAP_NET_BIND_SERVICE";
CapabilityBoundingSet = [
"CAP_CHOWN"
] ++ optional (cfg.port != null && cfg.port < 1024) "CAP_NET_BIND_SERVICE";
AmbientCapabilities = CapabilityBoundingSet;
NoNewPrivileges = true;
LockPersonality = true;
RestrictRealtime = true;
SystemCallFilter = [ "@system-service" "~@privileged" "@chown" ];
SystemCallFilter = [
"@system-service"
"~@privileged"
"@chown"
];
SystemCallArchitectures = "native";
RestrictAddressFamilies = "AF_INET AF_INET6";
};
@ -97,4 +118,3 @@ with lib; {
}
);
}

View file

@ -1,11 +1,15 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let
cfg = config.cloud.firezone;
mkImage =
{ imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
mkImage = { imageName, imageDigest, ... }: "${imageName}@${imageDigest}";
# If we can pullImage we can just do
# mkImage = pkgs.dockerTools.pullImage;
@ -48,7 +52,10 @@ in
image = images.postgresql;
restart = "unless-stopped";
healthcheck = {
test = [ "CMD-SHELL" "pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}" ];
test = [
"CMD-SHELL"
"pg_isready -d $\${POSTGRES_DB} -U $\${POSTGRES_USER}"
];
start_period = "20s";
interval = "30s";
retries = 5;
@ -89,7 +96,10 @@ in
driver = "bridge";
ipam.config = [
{ subnet = "172.25.0.0/16"; }
{ subnet = "2001:3990:3990::/64"; gateway = "2001:3990:3990::1"; }
{
subnet = "2001:3990:3990::/64";
gateway = "2001:3990:3990::1";
}
];
};
};

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let
cfg = config.cloud.gotosocial;
@ -41,13 +46,21 @@ in
# Postgres
cloud.postgresql.databases = [ dbUser ];
# Traefik
cloud.traefik.hosts = { gotosocial = { inherit (cfg) host port; }; } //
(if cfg.accountDomain != cfg.host && cfg.accountDomain != "" then {
gotosocial-wellknown = {
inherit (cfg) port;
filter = "Host(`${cfg.accountDomain}`) && (PathPrefix(`/.well-known/webfinger`) || PathPrefix(`/.well-known/nodeinfo`) || PathPrefix(`/.well-known/host-meta`))";
};
} else { });
cloud.traefik.hosts =
{
gotosocial = { inherit (cfg) host port; };
}
// (
if cfg.accountDomain != cfg.host && cfg.accountDomain != "" then
{
gotosocial-wellknown = {
inherit (cfg) port;
filter = "Host(`${cfg.accountDomain}`) && (PathPrefix(`/.well-known/webfinger`) || PathPrefix(`/.well-known/nodeinfo`) || PathPrefix(`/.well-known/host-meta`))";
};
}
else
{ }
);
# The service itself
services.gotosocial = {
enable = true;
@ -60,7 +73,10 @@ in
bind-address = "localhost";
port = cfg.port;
# Instance
instance-languages = [ "en-ca" "vi" ];
instance-languages = [
"en-ca"
"vi"
];
# Accounts
accounts-registration-open = false;
accounts-allow-custom-css = true;
@ -73,15 +89,23 @@ in
web-template-base-dir = "${cfg.package}/share/gotosocial/web/template";
web-asset-base-dir = "${cfg.package}/share/gotosocial/web/assets";
# Media
media-emoji-remote-max-size = 256 * 1024 /* bytes */;
media-emoji-local-max-size = 256 * 1024 /* bytes */;
media-emoji-remote-max-size =
256 * 1024 # bytes
;
media-emoji-local-max-size =
256 * 1024 # bytes
;
media-remote-cache-days = 7;
media-cleanup-from = "00:00";
media-cleanup-every = "24h";
# OIDC
oidc-enabled = true;
oidc-idp-name = "DTTH";
oidc-scopes = [ "openid" "email" "profile" ];
oidc-scopes = [
"openid"
"email"
"profile"
];
# HTTP Client
http-client.block-ips = [ "11.0.0.0/24" ];
# Advanced
@ -92,8 +116,14 @@ in
# instance-inject-mastodon-version = true;
};
};
systemd.services.gotosocial.requires = mkAfter [ "postgresql.service" "arion-authentik.service" ];
systemd.services.gotosocial.after = mkAfter [ "postgresql.service" "arion-authentik.service" ];
systemd.services.gotosocial.requires = mkAfter [
"postgresql.service"
"arion-authentik.service"
];
systemd.services.gotosocial.after = mkAfter [
"postgresql.service"
"arion-authentik.service"
];
systemd.services.gotosocial.unitConfig = {
RequiresMountsFor = [ storageLocation ];
ReadWritePaths = [ storageLocation ];

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
with lib;
let
@ -238,7 +243,12 @@ in
# MTA-STS server
services.nginx.enable = true;
services.nginx.virtualHosts.maddy-mta-sts = {
listen = [{ addr = "127.0.0.1"; port = mtaStsPort; }];
listen = [
{
addr = "127.0.0.1";
port = mtaStsPort;
}
];
root = mtaStsDir;
};
@ -273,7 +283,10 @@ in
# maddy itself
systemd.services."${name}" = {
after = [ "network.target" "traefik-certs-dumper.service" ];
after = [
"network.target"
"traefik-certs-dumper.service"
];
wantedBy = [ "multi-user.target" ];
requires = [ "postgresql.service" ];
@ -327,7 +340,6 @@ in
KillMode = "mixed";
KillSignal = "SIGTERM";
# Required to bind on ports lower than 1024.
AmbientCapabilities = "CAP_NET_BIND_SERVICE";
CapabilityBoundingSet = "CAP_NET_BIND_SERVICE";

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let

View file

@ -1,4 +1,9 @@
{ pkgs, lib, config, ... }:
{
pkgs,
lib,
config,
...
}:
with lib;
let
@ -9,126 +14,169 @@ let
};
# Copied from traefik.nix
jsonValue = with types;
jsonValue =
with types;
let
valueType = nullOr
(oneOf [
valueType =
nullOr (oneOf [
bool
int
float
str
(lazyAttrsOf valueType)
(listOf valueType)
]) // {
description = "JSON value";
emptyValue.value = { };
};
])
// {
description = "JSON value";
emptyValue.value = { };
};
in
valueType;
hostType = with types; submodule {
options = {
host = mkOption {
type = str;
description = "The host for the router filter";
};
path = mkOption {
type = nullOr str;
default = null;
description = "The path for the router filter (exact path is matched)";
};
filter = mkOption {
type = nullOr str;
default = null;
description = "The filter syntax for the router. Overrides `host` and `path` if provided";
};
localHost = mkOption {
type = types.nullOr types.str;
description = "The local host of the service. Must be an IP if protocol is TCP. Default to localhost/127.0.0.1";
default = null;
};
port = mkOption {
type = types.port;
description = "The port that the service is listening on";
};
entrypoints = mkOption {
type = listOf (enum [ "http" "https" "smtp-submission" "smtp-submission-ssl" "imap" "wireguard" ]);
default = [ "https" ];
description = "The entrypoints that will serve the host";
};
middlewares = mkOption {
type = listOf jsonValue;
default = [ ];
description = "The middlewares to be used with the host.";
};
protocol = mkOption {
type = enum [ "http" "tcp" "udp" ];
default = "http";
description = "The protocol of the router and service";
};
tlsPassthrough = mkOption {
type = types.bool;
default = true;
description = "Sets the TCP passthrough value. Defaults to `true` if the connection is tcp";
};
noCloudflare = mkOption {
type = types.bool;
default = false;
description = "Bypasses the client cert requirement, enable if you don't route things through cloudflare";
hostType =
with types;
submodule {
options = {
host = mkOption {
type = str;
description = "The host for the router filter";
};
path = mkOption {
type = nullOr str;
default = null;
description = "The path for the router filter (exact path is matched)";
};
filter = mkOption {
type = nullOr str;
default = null;
description = "The filter syntax for the router. Overrides `host` and `path` if provided";
};
localHost = mkOption {
type = types.nullOr types.str;
description = "The local host of the service. Must be an IP if protocol is TCP. Default to localhost/127.0.0.1";
default = null;
};
port = mkOption {
type = types.port;
description = "The port that the service is listening on";
};
entrypoints = mkOption {
type = listOf (enum [
"http"
"https"
"smtp-submission"
"smtp-submission-ssl"
"imap"
"wireguard"
]);
default = [ "https" ];
description = "The entrypoints that will serve the host";
};
middlewares = mkOption {
type = listOf jsonValue;
default = [ ];
description = "The middlewares to be used with the host.";
};
protocol = mkOption {
type = enum [
"http"
"tcp"
"udp"
];
default = "http";
description = "The protocol of the router and service";
};
tlsPassthrough = mkOption {
type = types.bool;
default = true;
description = "Sets the TCP passthrough value. Defaults to `true` if the connection is tcp";
};
noCloudflare = mkOption {
type = types.bool;
default = false;
description = "Bypasses the client cert requirement, enable if you don't route things through cloudflare";
};
};
};
};
# Returns the filter given a host configuration
filterOfHost = host:
filterOfHost =
host:
let
hostFilter = if host.protocol == "http" then "Host" else "HostSNI";
in
if host.filter != null then host.filter
else if host.path == null then "${hostFilter}(`${host.host}`)"
else "${hostFilter}(`${host.host}`) && Path(`${host.path}`)";
if host.filter != null then
host.filter
else if host.path == null then
"${hostFilter}(`${host.host}`)"
else
"${hostFilter}(`${host.host}`) && Path(`${host.path}`)";
# Turns a host configuration into dynamic traefik configuration
hostToConfig = name: host: {
"${host.protocol}" = {
routers."${name}-router" = (if (host.protocol != "udp") then {
rule = filterOfHost host;
tls = { certResolver = "le"; }
// (if host.protocol == "tcp" then { passthrough = if (host ? tlsPassthrough) then host.tlsPassthrough else true; } else { })
// (if host.noCloudflare then tlsNoCloudflare else { });
} else { }) // {
entryPoints = host.entrypoints;
service = "${name}-service";
} // (
if host.protocol == "http" then
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; }
else if host.middlewares == [ ] then
"${host.protocol}" =
{
routers."${name}-router" =
(
if (host.protocol != "udp") then
{
rule = filterOfHost host;
tls =
{
certResolver = "le";
}
// (
if host.protocol == "tcp" then
{ passthrough = if (host ? tlsPassthrough) then host.tlsPassthrough else true; }
else
{ }
)
// (if host.noCloudflare then tlsNoCloudflare else { });
}
else
{ }
)
// {
entryPoints = host.entrypoints;
service = "${name}-service";
}
// (
if host.protocol == "http" then
{ middlewares = lists.imap0 (id: m: "${name}-middleware-${toString id}") host.middlewares; }
else if host.middlewares == [ ] then
{ }
else
abort "Cannot have middlewares on non-http routers"
);
services."${name}-service".loadBalancer.servers = [
(
let
localhost =
if isNull host.localHost then
(if host.protocol == "http" then "localhost" else "127.0.0.1")
else
host.localHost;
in
if host.protocol == "http" then
{ url = "http://${localhost}:${toString host.port}"; }
else
{ address = "${localhost}:${toString host.port}"; }
)
];
}
// (
if (host.middlewares != [ ]) then
{
middlewares = builtins.listToAttrs (
lists.imap0 (id: v: {
name = "${name}-middleware-${toString id}";
value = v;
}) host.middlewares
);
}
else
{ }
else abort "Cannot have middlewares on non-http routers"
);
services."${name}-service".loadBalancer.servers = [
(
let
localhost =
if isNull host.localHost then
(
if host.protocol == "http" then "localhost"
else "127.0.0.1"
) else host.localHost;
in
if host.protocol == "http" then
{ url = "http://${localhost}:${toString host.port}"; }
else { address = "${localhost}:${toString host.port}"; }
)
];
} // (if (host.middlewares != [ ]) then {
middlewares = builtins.listToAttrs (lists.imap0
(id: v: {
name = "${name}-middleware-${toString id}";
value = v;
})
host.middlewares);
} else { });
};
tlsConfig = {

View file

@ -1,4 +1,9 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let
@ -28,7 +33,8 @@ in
# Dynamic configuration
# ---------------------
## Middleware
services.traefik.dynamicConfigOptions.http.middlewares.dashboard-auth.basicAuth.usersFile = cfg.usersFile;
services.traefik.dynamicConfigOptions.http.middlewares.dashboard-auth.basicAuth.usersFile =
cfg.usersFile;
## Router
services.traefik.dynamicConfigOptions.http.routers.dashboard = {
rule = "Host(`${cfg.host}`)";

View file

@ -1,22 +1,29 @@
{ pkgs, config, lib, ... }:
{
pkgs,
config,
lib,
...
}:
with lib;
let
# Copied from traefik.nix
jsonValue = with types;
jsonValue =
with types;
let
valueType = nullOr
(oneOf [
valueType =
nullOr (oneOf [
bool
int
float
str
(lazyAttrsOf valueType)
(listOf valueType)
]) // {
description = "JSON value";
emptyValue.value = { };
};
])
// {
description = "JSON value";
emptyValue.value = { };
};
in
valueType;
@ -41,7 +48,11 @@ let
cfg = config.cloud.traefik;
in
{
imports = [ ./config.nix ./dashboard.nix ./certs-dumper.nix ];
imports = [
./config.nix
./dashboard.nix
./certs-dumper.nix
];
options.cloud.traefik = {
cloudflareKeyFile = mkOption {
type = types.path;
@ -104,7 +115,12 @@ in
config.systemd.services.traefik.environment.CF_DNS_API_TOKEN_FILE = cfg.cloudflareKeyFile;
# Set up firewall to allow traefik traffic.
config.networking.firewall.allowedTCPPorts = [ 443 993 587 465 ];
config.networking.firewall.allowedTCPPorts = [
443
993
587
465
];
config.networking.firewall.allowedUDPPorts = [
443 # QUIC
51820 # Wireguard

View file

@ -1,4 +1,9 @@
{ config, pkgs, lib, ... }:
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.cloud.writefreely;
@ -62,4 +67,3 @@ in
}
);
}