nix-home/modules/cloud/gotosocial/default.nix

120 lines
4 KiB
Nix

{ pkgs, config, lib, ... }:
with lib;
let
cfg = config.cloud.gotosocial;
dbUser = "gotosocial";
configFile = pkgs.writeText "config.yml" (generators.toYAML { } {
# General
host = cfg.host;
account-domain = cfg.accountDomain;
bind-address = "localhost";
port = cfg.port;
# Database
db-port = 0; # Use socket
db-user = dbUser;
db-database = dbUser;
# Web
web-template-base-dir = "${cfg.package}/share/web/template";
web-asset-base-dir = "${cfg.package}/share/web/assets";
# OIDC
oidc-enabled = true;
oidc-idp-name = "DTTH";
oidc-scopes = [ "openid" "email" "profile" ];
# HTTP Client
http-client.block-ips = [ "11.0.0.0/24" ];
# Advanced
advanced-rate-limit-requests = 0;
});
in
{
options.cloud.gotosocial = {
enable = mkEnableOption "Enable our local GtS server";
package = mkPackageOption pkgs "gotosocial-bin" { };
host = mkOption {
type = types.str;
description = "The GtS host";
default = "gts.dtth.ch";
};
accountDomain = mkOption {
type = types.str;
description = "The GtS account domain";
default = "dtth.ch";
};
port = mkOption {
type = types.int;
description = "The port to listen to";
default = 10010;
};
envFile = mkOption {
type = types.str;
description = "Additional environment variables to pass, as a file";
};
};
config = mkIf cfg.enable {
# System user
users.users."${dbUser}" = {
group = "${dbUser}";
isSystemUser = true;
};
users.groups."${dbUser}" = { };
# 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 { });
# The service itself
systemd.services.gotosocial = {
after = [ "network.target" ];
serviceConfig = {
User = dbUser;
Group = dbUser;
ExecStart = "${cfg.package}/bin/gotosocial --config-path ${configFile} server start";
EnvironmentFile = cfg.envFile;
# Sandboxing options to harden security
# Details for these options: https://www.freedesktop.org/software/systemd/man/systemd.exec.html
NoNewPrivileges = "yes";
PrivateTmp = "yes";
PrivateDevices = "yes";
RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6";
RestrictNamespaces = "yes";
RestrictRealtime = "yes";
DevicePolicy = "closed";
ProtectSystem = "full";
ProtectControlGroups = "yes";
ProtectKernelModules = "yes";
ProtectKernelTunables = "yes";
LockPersonality = "yes";
SystemCallFilter = "~@clock @debug @module @mount @obsolete @reboot @setuid @swap";
# Denying access to capabilities that should not be relevant
# Doc: https://man7.org/linux/man-pages/man7/capabilities.7.html
CapabilityBoundingSet = strings.concatStringsSep " " [
"CAP_RAWIO CAP_MKNOD"
"CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_AUDIT_WRITE"
"CAP_SYS_BOOT CAP_SYS_TIME CAP_SYS_MODULE CAP_SYS_PACCT"
"CAP_LEASE CAP_LINUX_IMMUTABLE CAP_IPC_LOCK"
"CAP_BLOCK_SUSPEND CAP_WAKE_ALARM"
"CAP_SYS_TTY_CONFIG"
"CAP_MAC_ADMIN CAP_MAC_OVERRIDE"
"CAP_NET_ADMIN CAP_NET_BROADCAST CAP_NET_RAW"
"CAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYSLOG "
];
# You might need this if you are running as non-root on a privileged port (below 1024)
#AmbientCapabilities=CAP_NET_BIND_SERVICE
StateDirectory = "gotosocial";
WorkingDirectory = "/var/lib/gotosocial";
};
wantedBy = [ "multi-user.target" ];
requires = [ "minio.service" ];
};
};
}