bikeshedding
This commit is contained in:
parent
f77271b249
commit
5bc6d6a996
|
@ -36,7 +36,7 @@
|
||||||
inherit nixpkgs;
|
inherit nixpkgs;
|
||||||
};
|
};
|
||||||
lib = nixpkgs.lib // {
|
lib = nixpkgs.lib // {
|
||||||
quotePotentialIpV6 = addr:
|
quoteListenAddr = addr:
|
||||||
if nixpkgs.lib.hasInfix ":" addr then "[${addr}]" else addr;
|
if nixpkgs.lib.hasInfix ":" addr then "[${addr}]" else addr;
|
||||||
};
|
};
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
|
|
|
@ -34,6 +34,7 @@ in {
|
||||||
./matrix.nix
|
./matrix.nix
|
||||||
./fdroid.nix
|
./fdroid.nix
|
||||||
./mumble.nix
|
./mumble.nix
|
||||||
|
./mailserver.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
system.stateVersion = "22.11";
|
system.stateVersion = "22.11";
|
||||||
|
@ -75,11 +76,7 @@ in {
|
||||||
path = /persist;
|
path = /persist;
|
||||||
directories = [
|
directories = [
|
||||||
{ directory = /var/www/${cfg.domainName}; }
|
{ directory = /var/www/${cfg.domainName}; }
|
||||||
{ directory = /var/lib/maubot; }
|
{ directory = /home/${config.common.mainUsername}; }
|
||||||
{ directory = /var/lib/fdroid; }
|
|
||||||
{ directory = config.mailserver.dkimKeyDirectory; }
|
|
||||||
{ directory = config.mailserver.mailDirectory; }
|
|
||||||
{ directory = /home/user; }
|
|
||||||
{ directory = /root; }
|
{ directory = /root; }
|
||||||
{ directory = /nix; }
|
{ directory = /nix; }
|
||||||
];
|
];
|
||||||
|
@ -109,12 +106,12 @@ in {
|
||||||
allowedUDPPorts = [
|
allowedUDPPorts = [
|
||||||
# dns
|
# dns
|
||||||
53 853
|
53 853
|
||||||
# wireguard
|
|
||||||
# 5553
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
# UNBOUND
|
# UNBOUND
|
||||||
|
users.users.${config.common.mainUsername}.extraGroups = [ config.services.unbound.group ];
|
||||||
|
|
||||||
services.unbound = {
|
services.unbound = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.unbound-with-systemd.override {
|
package = pkgs.unbound-with-systemd.override {
|
||||||
|
@ -166,8 +163,6 @@ in {
|
||||||
startWhenNeeded = false;
|
startWhenNeeded = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users.user.extraGroups = [ config.services.unbound.group ];
|
|
||||||
|
|
||||||
services.postgresql.enable = true;
|
services.postgresql.enable = true;
|
||||||
services.postgresql.package = pkgs.postgresql_13;
|
services.postgresql.package = pkgs.postgresql_13;
|
||||||
|
|
||||||
|
@ -203,7 +198,7 @@ in {
|
||||||
});
|
});
|
||||||
services.searx.runInUwsgi = true;
|
services.searx.runInUwsgi = true;
|
||||||
services.searx.uwsgiConfig = let inherit (config.services.searx) settings; in {
|
services.searx.uwsgiConfig = let inherit (config.services.searx) settings; in {
|
||||||
socket = "${lib.quotePotentialIpV6 settings.server.bind_address}:${toString settings.server.port}";
|
socket = "${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
||||||
};
|
};
|
||||||
services.searx.environmentFile = /var/lib/searx/searx.env;
|
services.searx.environmentFile = /var/lib/searx/searx.env;
|
||||||
services.searx.settings = {
|
services.searx.settings = {
|
||||||
|
@ -239,9 +234,9 @@ in {
|
||||||
services.nginx.virtualHosts."search.${cfg.domainName}" = let inherit (config.services.searx) settings; in {
|
services.nginx.virtualHosts."search.${cfg.domainName}" = let inherit (config.services.searx) settings; in {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
# locations."/".proxyPass = "http://${lib.quotePotentialIpV6 settings.server.bind_address}:${toString settings.server.port}";
|
# locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
||||||
locations."/".extraConfig = ''
|
locations."/".extraConfig = ''
|
||||||
uwsgi_pass "${lib.quotePotentialIpV6 settings.server.bind_address}:${toString settings.server.port}";
|
uwsgi_pass "${lib.quoteListenAddr settings.server.bind_address}:${toString settings.server.port}";
|
||||||
include ${config.services.nginx.package}/conf/uwsgi_params;
|
include ${config.services.nginx.package}/conf/uwsgi_params;
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
|
@ -295,55 +290,11 @@ in {
|
||||||
globalRedirect = cfg.domainName;
|
globalRedirect = cfg.domainName;
|
||||||
};
|
};
|
||||||
|
|
||||||
# MAILSERVER
|
|
||||||
# roundcube
|
|
||||||
services.nginx.virtualHosts."mail.${cfg.domainName}" = {
|
|
||||||
enableACME = true;
|
|
||||||
};
|
|
||||||
services.roundcube = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.roundcube.withPlugins (plugins: [ plugins.persistent_login ]);
|
|
||||||
dicts = with pkgs.aspellDicts; [ en ru ];
|
|
||||||
hostName = "mail.${cfg.domainName}";
|
|
||||||
maxAttachmentSize = 100;
|
|
||||||
plugins = [ "persistent_login" ];
|
|
||||||
};
|
|
||||||
mailserver = {
|
|
||||||
enable = true;
|
|
||||||
fqdn = "mail.${cfg.domainName}";
|
|
||||||
domains = [ cfg.domainName ];
|
|
||||||
certificateScheme = 1;
|
|
||||||
certificateFile = config.security.acme.certs."mail.${cfg.domainName}".directory + "/fullchain.pem";
|
|
||||||
keyFile = config.security.acme.certs."mail.${cfg.domainName}".directory + "/key.pem";
|
|
||||||
localDnsResolver = false;
|
|
||||||
recipientDelimiter = "-";
|
|
||||||
lmtpSaveToDetailMailbox = "no";
|
|
||||||
hierarchySeparator = "/";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Only allow local connections to noreply account
|
|
||||||
mailserver.loginAccounts."noreply@${cfg.domainName}" = {
|
|
||||||
# password is set in private.nix
|
|
||||||
hashedPassword = cfg.hashedNoreplyPassword;
|
|
||||||
sendOnly = true;
|
|
||||||
};
|
|
||||||
services.dovecot2.extraConfig =
|
|
||||||
let
|
|
||||||
passwd = builtins.toFile "dovecot2-local-passwd" ''
|
|
||||||
noreply@${cfg.domainName}:{plain}${cfg.unhashedNoreplyPassword}::::::allow_nets=local,127.0.0.0/8,::1
|
|
||||||
'';
|
|
||||||
in ''
|
|
||||||
passdb {
|
|
||||||
driver = passwd-file
|
|
||||||
args = ${passwd}
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# GITEA
|
# GITEA
|
||||||
services.nginx.virtualHosts."git.${cfg.domainName}" = let inherit (config.services.gitea) settings; in {
|
services.nginx.virtualHosts."git.${cfg.domainName}" = let inherit (config.services.gitea) settings; in {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
locations."/".proxyPass = "http://${lib.quotePotentialIpV6 settings.server.HTTP_ADDR}:${toString settings.server.HTTP_PORT}";
|
locations."/".proxyPass = "http://${lib.quoteListenAddr settings.server.HTTP_ADDR}:${toString settings.server.HTTP_PORT}";
|
||||||
};
|
};
|
||||||
services.gitea = {
|
services.gitea = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -5,6 +5,9 @@
|
||||||
let
|
let
|
||||||
cfg = config.server;
|
cfg = config.server;
|
||||||
in {
|
in {
|
||||||
|
impermanence.directories = [
|
||||||
|
{ directory = /var/lib/fdroid; user = "fdroid"; group = "fdroid"; mode = "0755"; }
|
||||||
|
];
|
||||||
services.nginx.virtualHosts."${cfg.domainName}" = {
|
services.nginx.virtualHosts."${cfg.domainName}" = {
|
||||||
locations."/fdroid/".alias = "/var/lib/fdroid/repo/";
|
locations."/fdroid/".alias = "/var/lib/fdroid/repo/";
|
||||||
};
|
};
|
||||||
|
|
56
system/hosts/nixserver/mailserver.nix
Normal file
56
system/hosts/nixserver/mailserver.nix
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{ config
|
||||||
|
, pkgs
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
impermanence.directories = [
|
||||||
|
{ directory = config.mailserver.dkimKeyDirectory; user = "opendkim"; group = "opendkim"; mode = "0755"; }
|
||||||
|
{ directory = config.mailserver.mailDirectory; user = "virtualMail"; group = "virtualMail"; mode = "0700"; }
|
||||||
|
];
|
||||||
|
|
||||||
|
# roundcube
|
||||||
|
# TODO: fix sending mail via roundcube
|
||||||
|
services.nginx.virtualHosts."mail.${cfg.domainName}" = {
|
||||||
|
enableACME = true;
|
||||||
|
};
|
||||||
|
services.roundcube = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.roundcube.withPlugins (plugins: [ plugins.persistent_login ]);
|
||||||
|
dicts = with pkgs.aspellDicts; [ en ru ];
|
||||||
|
hostName = "mail.${cfg.domainName}";
|
||||||
|
maxAttachmentSize = 100;
|
||||||
|
plugins = [ "persistent_login" ];
|
||||||
|
};
|
||||||
|
mailserver = {
|
||||||
|
enable = true;
|
||||||
|
fqdn = "mail.${cfg.domainName}";
|
||||||
|
domains = [ cfg.domainName ];
|
||||||
|
certificateScheme = 1;
|
||||||
|
certificateFile = config.security.acme.certs."mail.${cfg.domainName}".directory + "/fullchain.pem";
|
||||||
|
keyFile = config.security.acme.certs."mail.${cfg.domainName}".directory + "/key.pem";
|
||||||
|
localDnsResolver = false;
|
||||||
|
recipientDelimiter = "-";
|
||||||
|
lmtpSaveToDetailMailbox = "no";
|
||||||
|
hierarchySeparator = "/";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Only allow local connections to noreply account
|
||||||
|
mailserver.loginAccounts."noreply@${cfg.domainName}" = {
|
||||||
|
# password is set in private.nix
|
||||||
|
hashedPassword = cfg.hashedNoreplyPassword;
|
||||||
|
sendOnly = true;
|
||||||
|
};
|
||||||
|
services.dovecot2.extraConfig =
|
||||||
|
let
|
||||||
|
passwd = builtins.toFile "dovecot2-local-passwd" ''
|
||||||
|
noreply@${cfg.domainName}:{plain}${cfg.unhashedNoreplyPassword}::::::allow_nets=local,127.0.0.0/8,::1
|
||||||
|
'';
|
||||||
|
in ''
|
||||||
|
passdb {
|
||||||
|
driver = passwd-file
|
||||||
|
args = ${passwd}
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
}
|
|
@ -39,7 +39,7 @@ in {
|
||||||
locations = {
|
locations = {
|
||||||
"= /.well-known/matrix/server".extraConfig = matrixServerConfigResponse;
|
"= /.well-known/matrix/server".extraConfig = matrixServerConfigResponse;
|
||||||
"= /.well-known/matrix/client".extraConfig = matrixClientConfigResponse;
|
"= /.well-known/matrix/client".extraConfig = matrixClientConfigResponse;
|
||||||
"/".proxyPass = "http://${lib.quotePotentialIpV6 matrixAddr}:${toString matrixPort}";
|
"/".proxyPass = "http://${lib.quoteListenAddr matrixAddr}:${toString matrixPort}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ in {
|
||||||
systemd.services.heisenbridge.after = [ "matrix-synapse.service" ];
|
systemd.services.heisenbridge.after = [ "matrix-synapse.service" ];
|
||||||
services.heisenbridge = {
|
services.heisenbridge = {
|
||||||
enable = true;
|
enable = true;
|
||||||
homeserver = "http://${lib.quotePotentialIpV6 matrixAddr}:${toString matrixPort}/";
|
homeserver = "http://${lib.quoteListenAddr matrixAddr}:${toString matrixPort}/";
|
||||||
};
|
};
|
||||||
# so synapse can read the registration
|
# so synapse can read the registration
|
||||||
users.groups.heisenbridge.members = [ "matrix-synapse" ];
|
users.groups.heisenbridge.members = [ "matrix-synapse" ];
|
||||||
|
|
|
@ -9,9 +9,12 @@ let
|
||||||
maubotAddr = "127.0.0.1";
|
maubotAddr = "127.0.0.1";
|
||||||
maubotPort = 29316;
|
maubotPort = 29316;
|
||||||
in {
|
in {
|
||||||
|
impermanence.directories = [
|
||||||
|
{ directory = /var/lib/maubot; user = "maubot"; group = "maubot"; mode = "0755"; }
|
||||||
|
];
|
||||||
services.nginx.virtualHosts."matrix.${cfg.domainName}".locations = {
|
services.nginx.virtualHosts."matrix.${cfg.domainName}".locations = {
|
||||||
"/_matrix/maubot/" = {
|
"/_matrix/maubot/" = {
|
||||||
proxyPass = "http://${lib.quotePotentialIpV6 maubotAddr}:${toString maubotPort}";
|
proxyPass = "http://${lib.quoteListenAddr maubotAddr}:${toString maubotPort}";
|
||||||
proxyWebsockets = true;
|
proxyWebsockets = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,7 +33,7 @@ in {
|
||||||
forceSSL = true;
|
forceSSL = true;
|
||||||
globalRedirect = cfg.domainName;
|
globalRedirect = cfg.domainName;
|
||||||
locations."/music".extraConfig = "return 301 https://mumble.${cfg.domainName}/music/;";
|
locations."/music".extraConfig = "return 301 https://mumble.${cfg.domainName}/music/;";
|
||||||
locations."/music/".proxyPass = "http://${lib.quotePotentialIpV6 settings.webinterface.listening_addr}:${toString settings.webinterface.listening_port}/";
|
locations."/music/".proxyPass = "http://${lib.quoteListenAddr settings.webinterface.listening_addr}:${toString settings.webinterface.listening_port}/";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.botamusique = {
|
services.botamusique = {
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
lanCidrV4 = mkOption {
|
lanCidrV4 = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "LAN mask (IPv4)";
|
description = "LAN mask (IPv4)";
|
||||||
example = "192.168.1.0/96";
|
example = "192.168.1.0/24";
|
||||||
default = "0.0.0.0/0";
|
default = "0.0.0.0/0";
|
||||||
};
|
};
|
||||||
lanCidrV6 = mkOption {
|
lanCidrV6 = mkOption {
|
||||||
|
@ -33,19 +33,14 @@
|
||||||
example = "fd01:abcd::2";
|
example = "fd01:abcd::2";
|
||||||
default = null;
|
default = null;
|
||||||
};
|
};
|
||||||
noreplyPassword = mkOption {
|
|
||||||
type = types.str;
|
|
||||||
description = "noreply (only available via localhost) account password";
|
|
||||||
default = "totallysafe";
|
|
||||||
};
|
|
||||||
hashedNoreplyPassword = mkOption {
|
hashedNoreplyPassword = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "hashed noreply password via mkpasswd -sm bcrypt";
|
description = "hashed noreply password via mkpasswd -sm bcrypt for external access";
|
||||||
};
|
};
|
||||||
unhashedNoreplyPassword = mkOption {
|
unhashedNoreplyPassword = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
description = "unhashed noreply password. \
|
description = "unhashed noreply password for internal access only. \
|
||||||
This should preferably be different from the password that is hashed for better security (yes, really)";
|
This should be different from the password that is hashed for better security";
|
||||||
};
|
};
|
||||||
pizzabotMagic = mkOption {
|
pizzabotMagic = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
workstation = mkOption {
|
workstation = mkOption {
|
||||||
type = types.bool;
|
type = types.bool;
|
||||||
default = false;
|
default = false;
|
||||||
description = "whether this device is a workstation (meaning a device for personal use rather than a server)";
|
description = "whether this device is a workstation (meaning a device for personal use rather than a server/embedded device)";
|
||||||
};
|
};
|
||||||
mainUsername = mkOption {
|
mainUsername = mkOption {
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
|
Loading…
Reference in a new issue