Lemmy broken on Germany
This commit is contained in:
parent
7a73028ad2
commit
cf10f910bd
|
@ -6,22 +6,41 @@ let
|
|||
localDomain = "fudo.org";
|
||||
|
||||
domainSecrets = config.fudo.secrets.files.domain-secrets."${localDomain}";
|
||||
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
||||
|
||||
inherit (pkgs.lib) getDomainHosts getHostIpv4 getHostIpv6 getHostFqdn;
|
||||
inherit (pkgs.lib)
|
||||
getDomainHosts getHostIpv4 getHostIpv6 getHostFqdn getSiteV4PrefixLength;
|
||||
|
||||
domain = config.fudo.domains."${localDomain}";
|
||||
|
||||
authentikHost = "legatus";
|
||||
authentikImage = "ghcr.io/goauthentik/server:2023.10.7";
|
||||
|
||||
primaryNameserver = "germany";
|
||||
|
||||
webmailHost = "germany";
|
||||
|
||||
defaultHost = "germany";
|
||||
|
||||
mastodonHost = "germany";
|
||||
mastodonHostname = "fudo.live";
|
||||
|
||||
giteaHost = "germany";
|
||||
giteaHostname = "fudo.dev";
|
||||
giteaIpv4Address = "208.81.3.118";
|
||||
|
||||
cloudHost = "germany";
|
||||
cloudHostname = "fudo.cloud";
|
||||
|
||||
lemmyHost = "germany";
|
||||
lemmyHostname = "fudo.social";
|
||||
|
||||
matrixHost = "germany";
|
||||
matrixHostname = "fudo.im";
|
||||
|
||||
immichHost = "germany";
|
||||
immichHostname = "pics.fudo.org";
|
||||
|
||||
servedDomains = [
|
||||
"fudo.org"
|
||||
"test.fudo.org"
|
||||
|
@ -30,35 +49,36 @@ let
|
|||
"fudo.im"
|
||||
"fudo.live"
|
||||
"fudo.social"
|
||||
"fudo.dev"
|
||||
"fudo.cloud"
|
||||
"stewartsoundservices.ca"
|
||||
];
|
||||
|
||||
static = ../../static;
|
||||
|
||||
in {
|
||||
imports = [
|
||||
(import ./fudo.org/authentik.nix {
|
||||
inherit authentikHost;
|
||||
authentikImage = "ghcr.io/goauthentik/server:2023.10.6";
|
||||
})
|
||||
(import ./fudo.org/authentik.nix { inherit authentikHost authentikImage; })
|
||||
(import ./fudo.org/mastodon.nix {
|
||||
mastodonHost = "germany";
|
||||
mastodonHost = mastodonHost;
|
||||
mastodonHostname = mastodonHostname;
|
||||
mastodonWebDomain = mastodonHostname;
|
||||
mastodonOidcClientId = domainSecrets."mastodon-oidc.clientid";
|
||||
mastodonOidcClientSecret = domainSecrets."mastodon-oidc.secret";
|
||||
})
|
||||
(import ./fudo.org/nextcloud.nix {
|
||||
nextcloudHost = "legatus";
|
||||
nextcloudHostname = "cloud.fudo.org";
|
||||
nextcloudHost = cloudHost;
|
||||
nextcloudHostname = cloudHostname;
|
||||
nextcloudPackage = pkgs.nextcloud28;
|
||||
})
|
||||
(import ./fudo.org/matrix.nix {
|
||||
matrixHost = "germany";
|
||||
matrixServerName = "fudo.im";
|
||||
matrixHost = matrixHost;
|
||||
matrixServerName = matrixHostname;
|
||||
openIdClientId = readFile domainSecrets."matrix-oidc.clientid";
|
||||
openIdClientSecret = readFile domainSecrets."matrix-oidc.secret";
|
||||
})
|
||||
(import ./fudo.org/mail-server.nix (rec {
|
||||
primaryMailserver = "france";
|
||||
primaryMailserver = "germany";
|
||||
primaryDomain = "fudo.org";
|
||||
authentikServer = "authentik.fudo.org";
|
||||
ldapBase = "dc=fudo,dc=org";
|
||||
|
@ -73,8 +93,21 @@ in {
|
|||
];
|
||||
|
||||
config = {
|
||||
# All Fudo hosts should redirect selby.ca to the selbyhomecentre website.
|
||||
systemd.services = { lemmy.after = [ "postgresql.service" ]; };
|
||||
|
||||
services = {
|
||||
immichContainer = mkIf (hostname == immichHost) {
|
||||
enable = true;
|
||||
images = let immichVersion = "v1.94.1";
|
||||
in {
|
||||
immich = "ghcr.io/immich-app/immich-server:${immichVersion}";
|
||||
immich-ml =
|
||||
"ghcr.io/immich-app/immich-machine-learning:${immichVersion}";
|
||||
redis = "redis:6.2-alpine";
|
||||
postgresql = "tensorchord/pgvecto-rs:pg14-v0.1.11";
|
||||
};
|
||||
};
|
||||
|
||||
nginx.virtualHosts = {
|
||||
# Pass requests to selby on to selbyhomecentre
|
||||
"selby.ca".locations."/".return =
|
||||
|
@ -82,34 +115,110 @@ in {
|
|||
"www.selby.ca".locations."/".return =
|
||||
"301 https://selbyhomecentre.com$request_uri";
|
||||
|
||||
# For Mastodon
|
||||
"fudo.org".locations = {
|
||||
"/.well-known/webfinger" = {
|
||||
return = "301 http://${mastodonHostname}";
|
||||
extraConfig = "add_header Access-Control-Allow-Origin '*';";
|
||||
"pics.fudo.org" = mkIf (hostname == immichHost) {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${
|
||||
toString config.services.immichContainer.port
|
||||
}/";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
"/.well-known/host-meta" = {
|
||||
return = "301 https://${mastodonHostname}$request_uri";
|
||||
};
|
||||
|
||||
"fudo.org" = mkIf (hostname == defaultHost) {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations = let
|
||||
mkWellKnown = data: ''
|
||||
add_header Content-Type application/json;
|
||||
add_header Access-Control-Allow-Origin *;
|
||||
return 200 '${builtins.toJSON data}';
|
||||
'';
|
||||
in {
|
||||
# Mastodon
|
||||
"/.well-known/webfinger" = {
|
||||
return = "301 https://${mastodonHostname}";
|
||||
extraConfig = "add_header Access-Control-Allow-Origin '*';";
|
||||
};
|
||||
"/.well-known/host-meta" = {
|
||||
return = "301 https://${mastodonHostname}$request_uri";
|
||||
};
|
||||
# Matrix
|
||||
"/.well-known/matrix/server".extraConfig =
|
||||
mkWellKnown { "m.server" = "matrix.${matrixHostname}:443"; };
|
||||
"/.well-known/matrix/client".extraConfig = mkWellKnown {
|
||||
"m.homeserver".base_url = "https://web.${matrixHostname}:443";
|
||||
};
|
||||
"/.well-known/acme-challenge" = {
|
||||
root = "/var/lib/acme/acme-challenge/";
|
||||
extraConfig = "auth_basic off;";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
lemmyDocker = {
|
||||
enable = config.instance.hostname == lemmyHost;
|
||||
hostname = lemmyHostname;
|
||||
site-name = "Fudo Lemmy";
|
||||
version = "0.19.2";
|
||||
smtp-server = "mail.fudo.org:587";
|
||||
docker-images = {
|
||||
pictrs = "asonix/pictrs:0.5.1";
|
||||
postgres = "postgres:15-alpine";
|
||||
};
|
||||
};
|
||||
# lemmyContainer = {
|
||||
# enable = config.instance.hostname == lemmyHost;
|
||||
# hostname = lemmyHostname;
|
||||
# site-name = "Fudo Lemmy";
|
||||
# smtp.host = "mail.fudo.org:587";
|
||||
# # admin-password-file = hostSecrets.lemmyAdminPasswd.target-file;
|
||||
# server-package = pkgs.pkgsUnstable.lemmy-server;
|
||||
# };
|
||||
};
|
||||
|
||||
fudo = {
|
||||
secrets.host-secrets."${hostname}" = {
|
||||
lemmyAdminPasswd = {
|
||||
source-file =
|
||||
pkgs.lib.passwd.stablerandom-passwd-file "lemmy-admin.passwd"
|
||||
config.instance.build-seed;
|
||||
target-file = "/run/lemmy/admin.passwd";
|
||||
};
|
||||
};
|
||||
|
||||
zones = {
|
||||
"fudo.org".aliases = {
|
||||
cloud = "germany.fudo.org.";
|
||||
pics = "germany.fudo.org.";
|
||||
webmail = "germany.fudo.org.";
|
||||
};
|
||||
"selby.ca".aliases.webmail = "germany.fudo.org.";
|
||||
};
|
||||
|
||||
webmail = {
|
||||
enable = hostname == webmailHost;
|
||||
|
||||
sites = {
|
||||
"webmail.fudo.org" = {
|
||||
title = "Fudo Webmail";
|
||||
favicon = "${static}/fudo.org/favicon.ico";
|
||||
mail-server = "mail.fudo.org";
|
||||
domain = "fudo.org";
|
||||
edit-mode = "Plain";
|
||||
};
|
||||
|
||||
"webmail.fudo.link" = {
|
||||
title = "Fudo Link Webmail";
|
||||
favicon = "${static}/fudo.link/favicon.ico";
|
||||
mail-server = "mail.fudo.org";
|
||||
domain = "fudo.link";
|
||||
edit-mode = "Plain";
|
||||
layout-mode = "bottom";
|
||||
};
|
||||
|
||||
"webmail.selby.ca" = {
|
||||
title = "Selby Webmail";
|
||||
favicon = "${static}/selby.ca/favicon.ico";
|
||||
mail-server = "mail.fudo.org";
|
||||
domain = "selby.ca";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
# TEMPORARY
|
||||
# DON'T enable, we're using mail-container instead
|
||||
mail-server.enable = false;
|
||||
|
||||
jabber = {
|
||||
|
@ -127,6 +236,25 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
lemmy = {
|
||||
enable = hostname == lemmyHost;
|
||||
hostname = "fudo.social";
|
||||
site-name = "Fudo Lemmy";
|
||||
smtp.host = "mail.fudo.org";
|
||||
};
|
||||
|
||||
gitea-container = let siteName = config.fudo.hosts."${giteaHost}".site;
|
||||
in {
|
||||
enable = hostname == giteaHost;
|
||||
site-name = "Fudo Git";
|
||||
hostname = giteaHostname;
|
||||
trusted-networks = config.instance.local-networks;
|
||||
networking.ipv4 = {
|
||||
address = giteaIpv4Address;
|
||||
prefixLength = getSiteV4PrefixLength siteName;
|
||||
};
|
||||
};
|
||||
|
||||
authoritative-dns = {
|
||||
enable = hostname == primaryNameserver;
|
||||
|
||||
|
@ -167,23 +295,56 @@ in {
|
|||
|
||||
mkDomain = domain: extraConfig:
|
||||
{
|
||||
default-host = defaultDeets;
|
||||
ksk =
|
||||
config.fudo.secrets.files.dns.key-signing-keys."${domain}";
|
||||
} // extraConfig;
|
||||
|
||||
getDeets = hostname: description: {
|
||||
inherit (config.fudo.zones."fudo.org".hosts."${hostname}")
|
||||
ipv4-address ipv6-address sshfp-records;
|
||||
};
|
||||
in {
|
||||
"fudo.org" = mkDomain "fudo.org" {
|
||||
reverse-zones = [ "208.81.1.128/28" "208.81.3.112/28" ];
|
||||
mail = fudoMailservers;
|
||||
default-host = defaultDeets;
|
||||
};
|
||||
"test.fudo.org" = mkDomain "test.fudo.org" { };
|
||||
"selby.ca" = mkDomain "selby.ca" { mail = fudoMailservers; };
|
||||
"fudo.ca" = mkDomain "fudo.ca" { mail = fudoMailservers; };
|
||||
"fudo.im" = mkDomain "fudo.im" { mail = fudoMailservers; };
|
||||
"stewartsoundservices.ca" =
|
||||
mkDomain "stewartsoundservices.ca" { mail = fudoMailservers; };
|
||||
"fudo.live" = mkDomain "fudo.live" { mail = fudoMailservers; };
|
||||
"fudo.social" = mkDomain "fudo.social" { mail = fudoMailservers; };
|
||||
"selby.ca" = mkDomain "selby.ca" {
|
||||
mail = fudoMailservers;
|
||||
default-host = defaultDeets;
|
||||
};
|
||||
"fudo.ca" = mkDomain "fudo.ca" {
|
||||
mail = fudoMailservers;
|
||||
default-host = defaultDeets;
|
||||
};
|
||||
"fudo.im" = mkDomain "fudo.im" {
|
||||
mail = fudoMailservers;
|
||||
default-host = getDeets matrixHost "fudo.im primary server";
|
||||
};
|
||||
"stewartsoundservices.ca" = mkDomain "stewartsoundservices.ca" {
|
||||
mail = fudoMailservers;
|
||||
default-host = defaultDeets;
|
||||
};
|
||||
"fudo.live" = mkDomain "fudo.live" {
|
||||
mail = fudoMailservers;
|
||||
default-host = getDeets mastodonHost "fudo.live primary server";
|
||||
};
|
||||
"fudo.social" = mkDomain "fudo.social" {
|
||||
mail = fudoMailservers;
|
||||
default-host = getDeets lemmyHost "fudo.social primary server";
|
||||
};
|
||||
"fudo.dev" = mkDomain "fudo.dev" {
|
||||
mail = fudoMailservers;
|
||||
default-host = {
|
||||
ipv4-address = giteaIpv4Address;
|
||||
description = "fudo.dev";
|
||||
};
|
||||
};
|
||||
"fudo.cloud" = mkDomain "fudo.cloud" {
|
||||
mail = fudoMailservers;
|
||||
default-host = getDeets cloudHost "fudo.dev primary server";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -22,39 +22,48 @@ in {
|
|||
# };
|
||||
|
||||
fudo = {
|
||||
zones."${primaryDomain}" = let
|
||||
mailserverDomain = config.fudo.hosts."${primaryMailserver}".domain;
|
||||
mailserverIps = {
|
||||
ipv4-address = getHostIpv4 primaryMailserver;
|
||||
ipv6-address = getHostIpv6 primaryMailserver;
|
||||
};
|
||||
srvRecord = host: port: [{ inherit host port; }];
|
||||
zones = let
|
||||
mailserverIp = getHostIpv4 primaryMailserver;
|
||||
spfRecords = [
|
||||
''@ IN TXT "v=spf1 mx ip4:${mailserverIp}/32 -all"''
|
||||
''@ IN SPF "v=spf1 mx ip4:${mailserverIp}/32 -all"''
|
||||
];
|
||||
in {
|
||||
srv-records = {
|
||||
tcp = {
|
||||
imap = srvRecord "imap.${primaryDomain}" 143;
|
||||
imaps = srvRecord "imap.${primaryDomain}" 993;
|
||||
smtp = srvRecord "smtp.${primaryDomain}" 25;
|
||||
submission = srvRecord "smtp.${primaryDomain}" 587;
|
||||
submissions = srvRecord "smtp.${primaryDomain}" 465;
|
||||
"${primaryDomain}" = let
|
||||
mailserverDomain = config.fudo.hosts."${primaryMailserver}".domain;
|
||||
mailserverIps = {
|
||||
ipv4-address = getHostIpv4 primaryMailserver;
|
||||
ipv6-address = getHostIpv6 primaryMailserver;
|
||||
};
|
||||
udp = {
|
||||
smtp = srvRecord "smtp.${primaryDomain}" 25;
|
||||
submission = srvRecord "smtp.${primaryDomain}" 587;
|
||||
srvRecord = host: port: [{ inherit host port; }];
|
||||
in {
|
||||
srv-records = {
|
||||
tcp = {
|
||||
imap = srvRecord "mail.${primaryDomain}" 143;
|
||||
imaps = srvRecord "mail.${primaryDomain}" 993;
|
||||
smtp = srvRecord "mail.${primaryDomain}" 25;
|
||||
submission = srvRecord "mail.${primaryDomain}" 587;
|
||||
submissions = srvRecord "mail.${primaryDomain}" 465;
|
||||
};
|
||||
udp = {
|
||||
smtp = srvRecord "mail.${primaryDomain}" 25;
|
||||
submission = srvRecord "mail.${primaryDomain}" 587;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
metric-records = genAttrs [ "dovecot" "postfix" "rspamd" ]
|
||||
(_: srvRecord "mail-stats.${primaryDomain}" 443);
|
||||
metric-records = genAttrs [ "dovecot" "postfix" "rspamd" ]
|
||||
(_: srvRecord "mail-stats.${primaryDomain}" 443);
|
||||
|
||||
hosts = {
|
||||
imap = mailserverIps;
|
||||
smtp = mailserverIps;
|
||||
mail = mailserverIps;
|
||||
mail-stats = mailserverIps;
|
||||
hosts = {
|
||||
imap = mailserverIps;
|
||||
smtp = mailserverIps;
|
||||
mail = mailserverIps;
|
||||
mail-stats = mailserverIps;
|
||||
};
|
||||
verbatim-dns-records = [ dkimRecord ] ++ spfRecords;
|
||||
};
|
||||
verbatim-dns-records = [ dkimRecord ];
|
||||
};
|
||||
} // (genAttrs (filter (dom: dom != primaryDomain) servedDomains)
|
||||
(domain: { verbatim-dns-records = [ dkimRecord ] ++ spfRecords; }));
|
||||
|
||||
metrics.prometheus.service-discovery-dns =
|
||||
(genAttrs [ "dovecot" "postfix" "rspamd" ]
|
||||
|
@ -68,14 +77,14 @@ in {
|
|||
sasl-domain = saslDomain;
|
||||
trusted-networks = config.instance.local-networks;
|
||||
smtp = {
|
||||
hostname = "smtp.${primaryDomain}";
|
||||
hostname = "mail.${primaryDomain}";
|
||||
ssl-directory =
|
||||
config.security.acme.certs."smtp.${primaryDomain}".directory;
|
||||
config.security.acme.certs."mail.${primaryDomain}".directory;
|
||||
};
|
||||
imap = {
|
||||
hostname = "imap.${primaryDomain}";
|
||||
hostname = "mail.${primaryDomain}";
|
||||
ssl-directory =
|
||||
config.security.acme.certs."imap.${primaryDomain}".directory;
|
||||
config.security.acme.certs."mail.${primaryDomain}".directory;
|
||||
};
|
||||
ldap = {
|
||||
authentik-host = "https://${authentikServer}";
|
||||
|
@ -112,7 +121,7 @@ in {
|
|||
"imap.${primaryDomain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".return = "301 https://webmail.${primaryDomain}";
|
||||
locations."/".return = "403 Forbidden";
|
||||
};
|
||||
"mail.${primaryDomain}" = {
|
||||
enableACME = true;
|
||||
|
@ -122,7 +131,7 @@ in {
|
|||
"smtp.${primaryDomain}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/".return = "301 https://webmail.${primaryDomain}";
|
||||
locations."/".return = "403 Forbidden";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -7,50 +7,46 @@ with lib;
|
|||
let
|
||||
hostname = config.instance.hostname;
|
||||
isMastodon = hostname == mastodonHost;
|
||||
mkEnvFile = vars:
|
||||
pkgs.writeText "mastodon.env"
|
||||
(concatStringsSep "\n" (mapAttrsToList (k: v: ''${k}="${v}"'') vars));
|
||||
|
||||
in {
|
||||
config = {
|
||||
fudo.secrets.host-secrets."${hostname}".mastodonEnv = {
|
||||
source-file = mkEnvFile {
|
||||
OIDC_ENABLED = "true";
|
||||
OIDC_DISPLAY_NAME = "fudo auth";
|
||||
OIDC_DISCOVERY = "true";
|
||||
OIDC_ISSUER = "https://authentik.fudo.org/application/o/mastodon/";
|
||||
OIDC_AUTH_ENDPOINT =
|
||||
"https://authentik.fudo.org/application/o/authorize/";
|
||||
OIDC_SCOPE = "openid,profile,email";
|
||||
OIDC_UID_FIELD = "sub";
|
||||
OIDC_CLIENT_ID = readFile mastodonOidcClientId;
|
||||
OIDC_CLIENT_SECRET = readFile mastodonOidcClientSecret;
|
||||
OIDC_REDIRECT_URI =
|
||||
"https://fudo.live/auth/auth/openid_connect/callback";
|
||||
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED = "true";
|
||||
OMNIAUTH_ONLY = "true";
|
||||
ONE_CLICK_SSO_LOGIN = "true";
|
||||
};
|
||||
target-file = "/run/mastodon/env";
|
||||
};
|
||||
|
||||
services = {
|
||||
mastodonContainer = mkIf isMastodon {
|
||||
enable = true;
|
||||
hostname = mastodonWebDomain;
|
||||
web-domain = mastodonHostname;
|
||||
version = "v4.1.6";
|
||||
state-directory = "/state/services/mastodon";
|
||||
smtp.server = "mail.fudo.org";
|
||||
environment = {
|
||||
OIDC_ENABLED = "true";
|
||||
OIDC_DISPLAY_NAME = "fudo auth";
|
||||
OIDC_DISCOVERY = "true";
|
||||
OIDC_ISSUER = "https://authentik.fudo.org/application/o/mastodon/";
|
||||
OIDC_AUTH_ENDPOINT =
|
||||
"https://authentik.fudo.org/application/o/authorize/";
|
||||
OIDC_SCOPE = "openid,profile,email";
|
||||
OIDC_UID_FIELD = "sub";
|
||||
OIDC_CLIENT_ID = readFile mastodonOidcClientId;
|
||||
OIDC_CLIENT_SECRET = readFile mastodonOidcClientSecret;
|
||||
OIDC_REDIRECT_URI =
|
||||
"https://mastodon.fudo.org/auth/auth/openid_connect/callback";
|
||||
OIDC_SECURITY_ASSUME_EMAIL_IS_VERIFIED = "true";
|
||||
};
|
||||
};
|
||||
nginx = mkIf isMastodon {
|
||||
enable = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts = {
|
||||
"${mastodonHostname}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${
|
||||
toString config.services.mastodonContainer.port
|
||||
}";
|
||||
proxyWebsockets = true;
|
||||
};
|
||||
};
|
||||
hostname = mastodonHostname;
|
||||
domain = mastodonWebDomain;
|
||||
environment-files = [
|
||||
config.fudo.secrets.host-secrets."${hostname}".mastodonEnv.target-file
|
||||
];
|
||||
smtp = {
|
||||
host = "mail.fudo.org";
|
||||
port = 25;
|
||||
};
|
||||
allow-registrations = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -40,6 +40,10 @@ in {
|
|||
};
|
||||
extraConfig = ''
|
||||
client_body_buffer_size 1024m;
|
||||
client_max_body_size 4096m;
|
||||
fastcgi_read_timeout 120s;
|
||||
proxy_max_temp_file_size 4096m;
|
||||
proxy_buffering off;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
|
|
@ -5,6 +5,8 @@ let
|
|||
hostname = config.instance.hostname;
|
||||
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
||||
|
||||
domainName = "sea.fudo.org";
|
||||
|
||||
frigateExternalHost = "sea-cam.fudo.link";
|
||||
frigateHost = "zbox";
|
||||
frigateDirectory = frigateCfg.state-directory;
|
||||
|
@ -12,9 +14,15 @@ let
|
|||
pkgs.lib.passwd.stablerandom-passwd-file "frigate-mqtt-passwd"
|
||||
config.instance.build-seed;
|
||||
|
||||
immichHost = "toothless";
|
||||
|
||||
in {
|
||||
config = {
|
||||
fudo.zones."sea.fudo.org".aliases = { "frigate" = "zbox"; };
|
||||
fudo.zones."sea.fudo.org".aliases = {
|
||||
chat = "nostromo";
|
||||
frigate = "zbox";
|
||||
immich = immichHost;
|
||||
};
|
||||
fudo = {
|
||||
services = {
|
||||
metrics = {
|
||||
|
@ -37,8 +45,33 @@ in {
|
|||
};
|
||||
|
||||
services = {
|
||||
frigateContainer = {
|
||||
enable = config.instance.hostname == frigateHost;
|
||||
immichContainer = mkIf (hostname == immichHost) {
|
||||
enable = true;
|
||||
images = let immichVersion = "v1.94.1";
|
||||
in {
|
||||
immich = "ghcr.io/immich-app/immich-server:${immichVersion}";
|
||||
immich-ml =
|
||||
"ghcr.io/immich-app/immich-machine-learning:${immichVersion}";
|
||||
redis = "redis:6.2-alpine";
|
||||
postgresql = "tensorchord/pgvecto-rs:pg14-v0.1.11";
|
||||
};
|
||||
};
|
||||
|
||||
nginx = mkIf (hostname == immichHost) {
|
||||
enable = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedProxySettings = true;
|
||||
virtualHosts."immich.${domainName}".locations."/" = {
|
||||
proxyPass = "http://${immichHost}.${domainName}:${
|
||||
toString config.services.immichContainer.port
|
||||
}/";
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
|
||||
frigateContainer = mkIf (config.instance.hostname == frigateHost) {
|
||||
enable = true;
|
||||
log-level = "info";
|
||||
images.frigate = "ghcr.io/blakeblackshear/frigate:0.13.0-beta5";
|
||||
cameras =
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let generateMac = pkgs.lib.network.generate-mac-address;
|
||||
|
||||
in {
|
||||
|
@ -22,6 +23,8 @@ in {
|
|||
extraModulePackages = [ ];
|
||||
kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
supportedFilesystems = [ "bcachefs" ];
|
||||
|
||||
loader.grub = {
|
||||
enable = true;
|
||||
devices = [
|
||||
|
@ -85,11 +88,45 @@ in {
|
|||
fsType = "btrfs";
|
||||
options = [ "subvol=@container-data" "noatime" "compress=zstd" "noexec" ];
|
||||
};
|
||||
|
||||
## BROKEN!
|
||||
# "/store" = {
|
||||
# device = lib.concatStringsSep ":" [
|
||||
# "/dev/disk/by-id/ata-Crucial_CT525MX300SSD1_171516B3CB40"
|
||||
# "/dev/disk/by-id/ata-ST8000DM004-2U9188_ZR153N5H"
|
||||
# "/dev/disk/by-id/ata-ST8000DM004-2U9188_ZR153CDK"
|
||||
# ];
|
||||
# fsType = "bcachefs";
|
||||
# options = [ "noexec" "compression=zstd" ];
|
||||
# };
|
||||
};
|
||||
|
||||
systemd.services.mount-bcachefs-store = let
|
||||
mountpoint = "/store";
|
||||
deviceString = concatStringsSep ":" [
|
||||
"/dev/disk/by-id/ata-Crucial_CT525MX300SSD1_171516B3CB40"
|
||||
"/dev/disk/by-id/ata-ST8000DM004-2U9188_ZR153N5H"
|
||||
"/dev/disk/by-id/ata-ST8000DM004-2U9188_ZR153CDK"
|
||||
];
|
||||
options = concatStringsSep "," [ "noexec" "compression=zstd" ];
|
||||
in {
|
||||
description =
|
||||
"Mount ${mountpoint} filesystem (can't use fileSystems with multiple devices).";
|
||||
wantedBy = [ "local-fs.target" ];
|
||||
script = ''
|
||||
[ -d ${mountpoint} ] || mkdir ${mountpoint}
|
||||
if ${pkgs.util-linux}/bin/findmnt ${mountpoint}; then
|
||||
echo "already mounted: ${mountpoint}"
|
||||
else
|
||||
echo "mounting filesystem: ${mountpoint}"
|
||||
${pkgs.bcachefs-tools}/bin/mount.bcachefs ${deviceString} -o ${options} ${mountpoint}
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
swapDevices = [{ device = "/dev/disk/by-label/germany-swap"; }];
|
||||
|
||||
nix.settings.max-jobs = lib.mkDefault 24;
|
||||
nix.settings.max-jobs = mkDefault 24;
|
||||
|
||||
hardware.bluetooth.enable = false;
|
||||
|
||||
|
|
|
@ -248,6 +248,16 @@ in {
|
|||
(trustedNetworkClauses ++ [ "deny all;" ]);
|
||||
};
|
||||
};
|
||||
|
||||
"pics.fudo.link" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://immich.sea.fudo.org/";
|
||||
proxyWebsockets = true;
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ in {
|
|||
};
|
||||
firewall = {
|
||||
enable = false;
|
||||
interfaces."podman+".allowedUDPPorts = [ 53 ];
|
||||
interfaces."podman[0-9]+".allowedUDPPorts = [ 53 ];
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -60,6 +60,11 @@ in {
|
|||
'';
|
||||
};
|
||||
};
|
||||
|
||||
webmail-init = {
|
||||
after = [ "fudo-secrets.target" ];
|
||||
requires = [ "fudo-secrets.target" ];
|
||||
};
|
||||
};
|
||||
|
||||
timers.fudo-mail-sync = {
|
||||
|
@ -79,13 +84,42 @@ in {
|
|||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
dockerSocket.enable = true;
|
||||
defaultNetwork.settings.dns_enabled = true;
|
||||
dockerCompat = true;
|
||||
defaultNetwork.settings = {
|
||||
dns_enabled = true;
|
||||
network_dns_servers = [ "1.1.1.1" "8.8.4.4" ];
|
||||
};
|
||||
};
|
||||
oci-containers.backend = "podman";
|
||||
arion.backend = "podman-socket";
|
||||
};
|
||||
|
||||
services.lemmyDocker.state-directory = "/state/services/lemmy";
|
||||
services = {
|
||||
lemmyContainer.state-directory = "/state/services/lemmy-container";
|
||||
mastodonContainer.streaming-processes = 6;
|
||||
nextcloudContainer = {
|
||||
state-directory = "/state/services/nextcloud";
|
||||
store-directory = "/store/nextcloud";
|
||||
};
|
||||
immichContainer = {
|
||||
state-directory = "/state/services/immich";
|
||||
store-directory = "/store/immich";
|
||||
};
|
||||
nginx = {
|
||||
enable = true;
|
||||
commonHttpConfig = ''
|
||||
log_format with_response_time '$remote_addr - $remote_user [$time_local] '
|
||||
'"$request" $status $body_bytes_sent '
|
||||
'"$http_referer" "$http_user_agent" '
|
||||
'"$request_time" "$upstream_response_time"';
|
||||
access_log /var/log/nginx/access.log with_response_time;
|
||||
'';
|
||||
recommendedTlsSettings = true;
|
||||
recommendedGzipSettings = true;
|
||||
recommendedOptimisation = true;
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
};
|
||||
|
||||
fudo = {
|
||||
client.dns = {
|
||||
|
@ -105,12 +139,18 @@ in {
|
|||
state-directory = "/state/services/postgresql";
|
||||
};
|
||||
|
||||
webmail.state-directory = "/state/services/webmail";
|
||||
|
||||
services = {
|
||||
auth = {
|
||||
kerberos.state-directory = "/state/services/kerberos";
|
||||
ldap.state-directory = "/state/services/ldap";
|
||||
};
|
||||
authoritative-dns.state-directory = "/state/services/dns";
|
||||
gitea-container = {
|
||||
networking.interface = "enp5s0f0";
|
||||
state-directory = "/state/services/gitea-container";
|
||||
};
|
||||
jabber.state-directory = "/state/services/jabber";
|
||||
logging.loki.state-directory = "/state/services/loki";
|
||||
mail-server.state-directory = "/state/services/mail";
|
||||
|
@ -118,6 +158,7 @@ in {
|
|||
prometheus.state-directory = "/state/services/prometheus";
|
||||
grafana.state-directory = "/state/services/grafana";
|
||||
};
|
||||
nexus.dns-server.listen-addresses = [ primary-ip ];
|
||||
postgresql = {
|
||||
state-directory = "/state/services/postgresql";
|
||||
keytab = extractFudoKeytab {
|
||||
|
|
|
@ -125,22 +125,6 @@ in {
|
|||
local-networks = config.instance.local-networks;
|
||||
state-directory = "/state/services/postgresql";
|
||||
};
|
||||
|
||||
services.gitea-container = {
|
||||
enable = true;
|
||||
site-name = "Seattle Fudo Git";
|
||||
hostname = "git.fudo.org";
|
||||
state-directory = "/state/services/gitea";
|
||||
trusted-networks = config.instance.local-networks;
|
||||
openid-urls = [ "https://authentik.fudo.org/" ];
|
||||
networking = {
|
||||
interface = "eno2";
|
||||
ipv4 = {
|
||||
address = "10.0.0.15";
|
||||
prefixLength = 24;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
|
|
|
@ -14,7 +14,7 @@ let
|
|||
|
||||
host-secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||
|
||||
postgresql-user = config.systemd.services.postgresql.serviceConfig.User;
|
||||
# postgresql-user = config.systemd.services.postgresql.serviceConfig.User;
|
||||
|
||||
files = config.fudo.secrets.files;
|
||||
|
||||
|
@ -48,10 +48,10 @@ in {
|
|||
"L /etc/adjtime - - - - /state/etc/adjtime"
|
||||
"d /state/services 0555 - - - -"
|
||||
];
|
||||
services.grafana = {
|
||||
bindsTo = [ "postgresql.service" ];
|
||||
requires = [ "postgresql.service" ];
|
||||
};
|
||||
# services.grafana = {
|
||||
# bindsTo = [ "postgresql.service" ];
|
||||
# requires = [ "postgresql.service" ];
|
||||
# };
|
||||
};
|
||||
|
||||
environment = { systemPackages = local-packages; };
|
||||
|
@ -69,11 +69,11 @@ in {
|
|||
# part-of = [ config.fudo.auth.ldap-server.systemd-target ];
|
||||
# };
|
||||
|
||||
postgresql = {
|
||||
user = postgresql-user;
|
||||
dependent-services = [ "postgresql.service" ];
|
||||
part-of = [ config.fudo.postgresql.systemd-target ];
|
||||
};
|
||||
# postgresql = {
|
||||
# user = postgresql-user;
|
||||
# dependent-services = [ "postgresql.service" ];
|
||||
# part-of = [ config.fudo.postgresql.systemd-target ];
|
||||
# };
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -99,13 +99,13 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
postgresql = {
|
||||
state-directory = "/state/services/postgresql";
|
||||
keytab = extractFudoKeytab {
|
||||
realm = domain.gssapi-realm;
|
||||
principals = [ "postgres/${host-fqdn}" ];
|
||||
};
|
||||
};
|
||||
# postgresql = {
|
||||
# state-directory = "/state/services/postgresql";
|
||||
# keytab = extractFudoKeytab {
|
||||
# realm = domain.gssapi-realm;
|
||||
# principals = [ "postgres/${host-fqdn}" ];
|
||||
# };
|
||||
# };
|
||||
|
||||
metrics = {
|
||||
prometheus.state-directory = "/state/services/prometheus";
|
||||
|
|
|
@ -28,21 +28,14 @@ in {
|
|||
Defaults lecture = never
|
||||
'';
|
||||
|
||||
services = {
|
||||
immichContainer = {
|
||||
state-directory = "/state/immich/state";
|
||||
store-directory = "/state/immich/store";
|
||||
};
|
||||
};
|
||||
|
||||
fudo = {
|
||||
# minecraft-server = {
|
||||
# enable = true;
|
||||
# data-dir = "/state/services/minecraft";
|
||||
# world-name = "TLS";
|
||||
# motd = "Welcome to Jasper's TLS minecraft server.";
|
||||
# game-mode = "survival";
|
||||
# difficulty = 1;
|
||||
# allow-cheats = true;
|
||||
# allocated-memory = 16;
|
||||
# port = 25555;
|
||||
# query-port = 25556;
|
||||
# rcon-port = 25557;
|
||||
# world-seed = 2090763904884813452;
|
||||
# };
|
||||
minecraft-clj = {
|
||||
enable = true;
|
||||
state-directory = "/state/services/minecraft-clj";
|
||||
|
@ -86,6 +79,21 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
virtualisation = {
|
||||
podman = {
|
||||
enable = true;
|
||||
autoPrune.enable = true;
|
||||
dockerSocket.enable = true;
|
||||
dockerCompat = true;
|
||||
defaultNetwork.settings = {
|
||||
dns_enabled = true;
|
||||
network_dns_servers = [ "1.1.1.1" "8.8.4.4" ];
|
||||
};
|
||||
};
|
||||
oci-containers.backend = "podman";
|
||||
arion.backend = "podman-socket";
|
||||
};
|
||||
|
||||
systemd.targets = {
|
||||
sleep.enable = false;
|
||||
suspend.enable = false;
|
||||
|
|
|
@ -34,9 +34,9 @@ let
|
|||
isReadOnly = false;
|
||||
};
|
||||
} // (mapAttrs' (zoneName: _:
|
||||
let zoneKeyName = zoneKeySecret zoneName;
|
||||
in nameValuePair "/run/nsd/keys/${zoneKeyName}" {
|
||||
hostPath = hostSecrets."${zoneKeyName}".target-file;
|
||||
nameValuePair "/run/nsd/keys/${zoneName}" {
|
||||
hostPath =
|
||||
dirOf hostSecrets."${zoneKeySecret zoneName}".target-file;
|
||||
}) securedZones);
|
||||
config = let
|
||||
nameserverHost = cfg.container.hostname;
|
||||
|
@ -82,7 +82,10 @@ let
|
|||
|
||||
domains = mapAttrs' (zoneName: zoneCfg:
|
||||
nameValuePair zoneCfg.domain {
|
||||
ksk.key-file = "/run/nsd/keys/${zoneKeySecret zoneName}";
|
||||
ksk.key-file = "/run/nsd/keys/${zoneName}/${
|
||||
baseNameOf
|
||||
hostSecrets."${zoneKeySecret zoneName}".target-file
|
||||
}";
|
||||
reverse-zones = zoneCfg.reverse-zones;
|
||||
notify = mkIf cfg.enable-notifications {
|
||||
ipv4 = concatMap
|
||||
|
@ -280,11 +283,21 @@ in {
|
|||
};
|
||||
|
||||
fudo = {
|
||||
secrets.host-secrets."${hostname}" = mapAttrs' (zone: zoneCfg:
|
||||
nameValuePair (zoneKeySecret zone) {
|
||||
secrets.host-secrets."${hostname}" = concatMapAttrs (zone: zoneCfg: {
|
||||
"${zoneKeySecret zone}" = {
|
||||
source-file = zoneCfg.ksk.private-key;
|
||||
target-file = "/run/nsd/${baseNameOf zoneCfg.ksk.private-key}";
|
||||
}) (filterAttrs (_: zoneCfg: zoneCfg.ksk != null) cfg.zones);
|
||||
target-file =
|
||||
"/run/nsd/${zone}/${baseNameOf zoneCfg.ksk.private-key}";
|
||||
};
|
||||
"${zone}-ds" = {
|
||||
source-file = zoneCfg.ksk.ds;
|
||||
target-file = "/run/nsd/${zone}/${baseNameOf zoneCfg.ksk.ds}";
|
||||
};
|
||||
"${zone}-pubkey" = {
|
||||
source-file = zoneCfg.ksk.public-key;
|
||||
target-file = "/run/nsd/${zone}/${baseNameOf zoneCfg.ksk.public-key}";
|
||||
};
|
||||
}) (filterAttrs (_: zoneCfg: zoneCfg.ksk != null) cfg.zones);
|
||||
|
||||
zones = mapAttrs (zone-name: zoneCfg:
|
||||
let
|
||||
|
|
|
@ -1,7 +1,20 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
let cfg = config.fudo.services.gitea-container;
|
||||
let
|
||||
cfg = config.fudo.services.gitea-container;
|
||||
|
||||
hostname = config.instance.hostname;
|
||||
domainName = config.fudo.hosts."${hostname}".domain;
|
||||
zoneName = config.fudo.domains."${domainName}".zone;
|
||||
siteName = config.fudo.hosts."${hostname}".site;
|
||||
|
||||
getSiteGatewayV4 = pkgs.lib.getSiteGatewayV4;
|
||||
|
||||
keyPaths = {
|
||||
ed25519 = "/state/ssh/ed25519.key";
|
||||
ecdsa = "/state/ssh/ecdsa.key";
|
||||
};
|
||||
|
||||
in {
|
||||
options.fudo.services.gitea-container = with types; {
|
||||
|
@ -29,11 +42,6 @@ in {
|
|||
default = [ ];
|
||||
};
|
||||
|
||||
openid-urls = mkOption {
|
||||
type = listOf str;
|
||||
description = "List of authorized OpenID providers.";
|
||||
};
|
||||
|
||||
networking = {
|
||||
interface = mkOption {
|
||||
type = str;
|
||||
|
@ -75,7 +83,10 @@ in {
|
|||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.tmpfiles.rules = [ "d ${cfg.state-directory} 700 root root - -" ];
|
||||
systemd.tmpfiles.rules = [
|
||||
"d ${cfg.state-directory}/gitea 755 root root - -"
|
||||
"d ${cfg.state-directory}/acme 755 root root - -"
|
||||
];
|
||||
|
||||
containers.gitea = {
|
||||
autoStart = true;
|
||||
|
@ -83,18 +94,63 @@ in {
|
|||
macvlans = [ cfg.networking.interface ];
|
||||
bindMounts = {
|
||||
"/state" = {
|
||||
hostPath = cfg.state-directory;
|
||||
hostPath = "${cfg.state-directory}/gitea";
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/var/lib/acme" = {
|
||||
hostPath = "${cfg.state-directory}/acme";
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
config = {
|
||||
nixpkgs.pkgs = pkgs;
|
||||
|
||||
systemd = { tmpfiles.rules = [ "d /state 0755 root root - -" ]; };
|
||||
systemd = {
|
||||
tmpfiles.rules = [ "d /state 0755 root root - -" ];
|
||||
services = {
|
||||
gitea-chown = {
|
||||
requiredBy = [ "gitea.service" ];
|
||||
before = [ "gitea.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = "chown -R gitea:gitea /state";
|
||||
};
|
||||
|
||||
gitea-keygen = {
|
||||
requiredBy = [ "gitea.service" ];
|
||||
before = [ "gitea.service" ];
|
||||
serviceConfig.Type = "oneshot";
|
||||
script = let
|
||||
keygenScripts = mapAttrsToList (type: path:
|
||||
let dir = dirOf path;
|
||||
in ''
|
||||
if [ ! -f ${path} ]; then
|
||||
mkdir -p ${dir}
|
||||
${pkgs.openssh}/bin/ssh-keygen -q -N "" -t ${type} -f ${path}
|
||||
chown -R gitea:gitea ${dir}
|
||||
chmod 0750 ${dir}
|
||||
chmod 0440 ${path}
|
||||
fi
|
||||
'') keyPaths;
|
||||
in concatStringsSep "\n" keygenScripts;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = let
|
||||
giteaCli = pkgs.writeShellApplication {
|
||||
name = "gitea-cli";
|
||||
runtimeInputs = with pkgs; [ gitea ];
|
||||
text = ''gitea --config /state/gitea/custom/conf/app.ini "$@"'';
|
||||
};
|
||||
in [ giteaCli ];
|
||||
|
||||
networking = {
|
||||
defaultGateway = config.networking.defaultGateway;
|
||||
defaultGateway = {
|
||||
address = getSiteGatewayV4 siteName;
|
||||
interface = "mv-${cfg.networking.interface}";
|
||||
};
|
||||
enableIPv6 = !isNull cfg.networking.ipv6;
|
||||
nameservers = config.networking.nameservers;
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ 22 80 443 ];
|
||||
|
@ -111,6 +167,11 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults.email = "admin@${cfg.hostname}";
|
||||
};
|
||||
|
||||
services = {
|
||||
gitea = {
|
||||
enable = true;
|
||||
|
@ -122,7 +183,10 @@ in {
|
|||
repositoryRoot = "/state/repositories";
|
||||
stateDir = "/state/gitea";
|
||||
settings = {
|
||||
service.DISABLE_REGISTRATION = true;
|
||||
service = {
|
||||
#DISABLE_REGISTRATION = true;
|
||||
ALLOW_ONLY_EXTERNAL_REGISTRATION = true;
|
||||
};
|
||||
security = {
|
||||
INSTALL_LOCK = true;
|
||||
LOGIN_REMEMBER_DAYS = 30;
|
||||
|
@ -133,26 +197,23 @@ in {
|
|||
|
||||
# Host & port to display in the clone URL
|
||||
SSH_DOMAIN = cfg.hostname;
|
||||
# SSH_LISTEN_HOST = "0.0.0.0";
|
||||
SSH_PORT = 22;
|
||||
|
||||
SSH_LISTEN_PORT = 2222;
|
||||
SSH_LISTEN_HOST = "0.0.0.0";
|
||||
|
||||
DOMAIN = cfg.hostname;
|
||||
ROOT_URL = "https://${cfg.hostname}";
|
||||
|
||||
SSH_SERVER_HOST_KEYS =
|
||||
concatStringsSep "," (attrValues keyPaths);
|
||||
|
||||
HTTP_ADDR = "127.0.0.1";
|
||||
HTTP_PORT = 8080;
|
||||
};
|
||||
openid = {
|
||||
ENABLE_OPENID_SIGNIN = true;
|
||||
WHITELISTED_URIS = concatStringsSep "," cfg.openid-urls;
|
||||
};
|
||||
oauth2_client = {
|
||||
REGISTER_EMAIL_CONFIRM = false;
|
||||
OPENID_CONNECT_SCOPES =
|
||||
concatStringsSep "," [ "email" "profile" ];
|
||||
ENABLE_AUTO_REGISTRATION = true;
|
||||
#ENABLE_AUTO_REGISTRATION = true;
|
||||
USERNAME = "email";
|
||||
UPDATE_AVATAR = true;
|
||||
ACCOUNT_LINKING = "login";
|
||||
|
@ -164,8 +225,8 @@ in {
|
|||
enable = true;
|
||||
services = [{
|
||||
name = "ssh";
|
||||
# port = 22;
|
||||
# protocol = "tcp";
|
||||
port = 22;
|
||||
protocol = "tcp";
|
||||
extraConfig = ''
|
||||
redirect = localhost 2222
|
||||
wait = no
|
||||
|
@ -185,9 +246,13 @@ in {
|
|||
recommendedTlsSettings = true;
|
||||
recommendedGzipSettings = true;
|
||||
virtualHosts."${cfg.hostname}" = {
|
||||
# enableACME = true;
|
||||
# forceSSL = true;
|
||||
locations."/".proxyPass = "http://127.0.0.1:8080";
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:8080";
|
||||
proxyWebsockets = true;
|
||||
recommendedProxySettings = true;
|
||||
};
|
||||
locations."/metrics" = mkIf (cfg.trusted-networks != [ ]) {
|
||||
proxyPass = "http://127.0.0.1:8080/metrics";
|
||||
extraConfig = let
|
||||
|
|
|
@ -2,20 +2,12 @@
|
|||
|
||||
with lib;
|
||||
let
|
||||
lemmyDbPasswd = pkgs.lib.passwd.stablerandom-passwd-file "lemmy-server-passwd"
|
||||
"lemmy-server-${config.instance.build-seed}";
|
||||
|
||||
cfg = config.fudo.services.lemmy;
|
||||
|
||||
hostname = config.instance.hostname;
|
||||
|
||||
domainName = config.fudo.hosts."${hostname}".domain;
|
||||
|
||||
postgresqlServer = config.fudo.domains."${domainName}".postgresql-server;
|
||||
postgresqlFqdn = pkgs.lib.getHostFqdn postgresqlServer;
|
||||
|
||||
isPostgresServer = hostname == postgresqlServer;
|
||||
|
||||
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
||||
|
||||
in {
|
||||
|
@ -27,38 +19,55 @@ in {
|
|||
description = "Hostname at which this server will be reachable.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = port;
|
||||
description = "Port on which to listen for requests";
|
||||
default = 8536;
|
||||
site-name = mkOption {
|
||||
type = str;
|
||||
description = "Site Name";
|
||||
};
|
||||
|
||||
listen-ip = mkOption {
|
||||
type = str;
|
||||
description = "IP on which to listen for incoming requests.";
|
||||
default = "0.0.0.0";
|
||||
smtp = {
|
||||
host = mkOption {
|
||||
type = str;
|
||||
description = "SMTP server to relay Lemmy emails.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = port;
|
||||
description = "Port to which to send outgoing messages.";
|
||||
default = 25;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
fudo = {
|
||||
secrets.host-secrets."${hostname}" = {
|
||||
dbLemmyPasswd = mkIf isPostgresServer {
|
||||
source-file = lemmyDbPasswd;
|
||||
secrets.host-secrets."${hostname}" = let
|
||||
lemmyDbPasswdFile =
|
||||
pkgs.lib.passwd.stablerandom-passwd-file "lemmy-server-passwd"
|
||||
"lemmy-server-${config.instance.build-seed}";
|
||||
lemmyDbPasswd = readFile lemmyDbPasswdFile;
|
||||
in {
|
||||
lemmyDbUrl = {
|
||||
source-file = let
|
||||
url =
|
||||
"postgres:///lemmy?user=lemmy&password=${lemmyDbPasswd}&host=/var/run/postgresql";
|
||||
in pkgs.writeText "lemmy-db.url" url;
|
||||
target-file = "/run/lemmy/db.url";
|
||||
};
|
||||
dbLemmyPasswd = {
|
||||
source-file = lemmyDbPasswdFile;
|
||||
target-file = "/run/postgres/lemmy.passwd";
|
||||
user = config.systemd.services.postgresql.serviceConfig.User;
|
||||
};
|
||||
lemmyEnv = mkIf cfg.enable {
|
||||
source-file = pkgs.writeText "lemmy.env" ''
|
||||
LEMMY_DATABASE_URL=postgres:///lemmy:${
|
||||
readFile lemmyDbPasswd
|
||||
}@${postgresqlFqdn}:5432/lemmy
|
||||
'';
|
||||
target-file = "/run/lemmy/env";
|
||||
lemmyAdminPasswdFile = {
|
||||
source-file =
|
||||
pkgs.lib.passwd.stablerandom-passwd-file "lemmy-admin.passwd"
|
||||
config.instance.build-seed;
|
||||
target-file = "/run/lemmy/admin.passwd";
|
||||
};
|
||||
};
|
||||
|
||||
postgresql = mkIf isPostgresServer {
|
||||
postgresql = {
|
||||
enable = true;
|
||||
databases.lemmy.users = config.instance.local-admins;
|
||||
users.lemmy = {
|
||||
password-file = hostSecrets.dbLemmyPasswd.target-file;
|
||||
|
@ -74,35 +83,36 @@ in {
|
|||
};
|
||||
|
||||
systemd.services.lemmy = {
|
||||
requires = [ "fudo-secret-lemmyEnv.service" ];
|
||||
after = [ "fudo-secret-lemmyEnv.service" ];
|
||||
environment.LEMMY_DATABASE_URL = mkForce null;
|
||||
serviceConfig = mkIf cfg.enable {
|
||||
LoadCredential = [ "env:${hostSecrets.lemmyEnv.target-file}" ];
|
||||
EnvironmentFile = "$$CREDENTIALS_DIRECTORY/env";
|
||||
};
|
||||
requires = [ "fudo-secret-lemmyDbUrl.service" "postgresql.service" ];
|
||||
after = [ "fudo-secret-lemmyDbUrl.service" "postgresql.service" ];
|
||||
};
|
||||
|
||||
services.lemmy = mkIf cfg.enable {
|
||||
services.nginx.virtualHosts."${cfg.hostname}" = {
|
||||
enableACME = true;
|
||||
forceSSL = true;
|
||||
};
|
||||
|
||||
services.lemmy = {
|
||||
enable = true;
|
||||
nginx.enable = true;
|
||||
adminPasswordFile = hostSecrets.lemmyAdminPasswdFile.target-file;
|
||||
database.uriFile = hostSecrets.lemmyDbUrl.target-file;
|
||||
ui.port = 50395;
|
||||
settings = {
|
||||
hostname = cfg.hostname;
|
||||
federation.enabled = true;
|
||||
host = cfg.hostname;
|
||||
captcha.enabled = true;
|
||||
database = {
|
||||
user = "lemmy";
|
||||
host = pkgs.lib.getHostFqdn postgresqlServer;
|
||||
database = "lemmy";
|
||||
password = readFile lemmyDbPasswd;
|
||||
email = {
|
||||
smtp_server = "${cfg.smtp.host}:${toString cfg.smtp.port}";
|
||||
smtp_from_address = "noreply@${cfg.hostname}";
|
||||
tls_type = "starttls";
|
||||
};
|
||||
admin_username = "admin";
|
||||
setup = {
|
||||
site_name = cfg.site-name;
|
||||
admin_username = "admin";
|
||||
};
|
||||
bind = cfg.listen-ip;
|
||||
port = cfg.port;
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -103,22 +103,6 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
zones = {
|
||||
${mailserver-domain.zone} = let
|
||||
server-ipv4 = pkgs.lib.network.host-ipv4 config mailserver-host;
|
||||
server-ipv6 = pkgs.lib.network.host-ipv6 config mailserver-host;
|
||||
|
||||
srv-record = host: port: [{ inherit host port; }];
|
||||
|
||||
in {
|
||||
aliases = mkIf metricsEnabled { mail-stats = "${mailserver-fqdn}."; };
|
||||
|
||||
metric-records = mkIf metricsEnabled
|
||||
(genAttrs [ "dovecot" "postfix" "rspamd" ]
|
||||
(_: srv-record "mail-stats" 443));
|
||||
};
|
||||
};
|
||||
|
||||
metrics.prometheus.service-discovery-dns = mkIf metricsEnabled
|
||||
(genAttrs [ "dovecot" "postfix" "rspamd" ]
|
||||
(mtype: [ "${mtype}._metrics._tcp.${mailserver-domain-name}" ]));
|
||||
|
|
|
@ -56,7 +56,7 @@ in {
|
|||
};
|
||||
|
||||
zones."${zone-name}".aliases.postgresql =
|
||||
pkgs.lib.getHostFqdn domain.postgresql-server;
|
||||
"${pkgs.lib.getHostFqdn domain.postgresql-server}.";
|
||||
|
||||
postgresql = mkIf isPostgresHost (let
|
||||
ssl-config = optionalAttrs publicNetwork (let
|
||||
|
|
1520
flake.lock
1520
flake.lock
File diff suppressed because it is too large
Load Diff
26
flake.nix
26
flake.nix
|
@ -98,6 +98,14 @@
|
|||
};
|
||||
};
|
||||
|
||||
lemmy-container = {
|
||||
url = "git+https://git.fudo.org/fudo-public/lemmy-container.git";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
arion.follows = "arion";
|
||||
};
|
||||
};
|
||||
|
||||
authentik-container = {
|
||||
url = "git+https://git.fudo.org/fudo-nix/authentik-container.git";
|
||||
inputs = {
|
||||
|
@ -121,7 +129,18 @@
|
|||
|
||||
mail-server = {
|
||||
url = "git+https://git.fudo.org/fudo-public/mail-server.git";
|
||||
inputs.nixpkgs.follows = "nixpkgs";
|
||||
inputs = {
|
||||
arion.follows = "arion";
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
immich-container = {
|
||||
url = "git+https://git.fudo.org/fudo-public/immich-container.git";
|
||||
inputs = {
|
||||
arion.follows = "arion";
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
|
||||
authoritative-dns = {
|
||||
|
@ -150,7 +169,8 @@
|
|||
, objectifier, nexus, suanni, snooper, tattler, lemmy-docker
|
||||
, tesla-mate-container, mastodon-container, authentik-container
|
||||
, nextcloud-container, textfiles, matrix-module, mail-server
|
||||
, authoritative-dns, frigate-container, grafana-module, ... }@inputs:
|
||||
, authoritative-dns, frigate-container, grafana-module, lemmy-container
|
||||
, immich-container, ... }@inputs:
|
||||
with nixpkgs.lib;
|
||||
let
|
||||
fudo-nixos-hosts = filterAttrs (hostname: hostOpts: hostOpts.nixos-system)
|
||||
|
@ -232,6 +252,8 @@
|
|||
authoritative-dns.nixosModules.default
|
||||
frigate-container.nixosModules.default
|
||||
grafana-module.nixosModules.default
|
||||
lemmy-container.nixosModules.default
|
||||
immich-container.nixosModules.default
|
||||
|
||||
nexus.nixosModules.nexus-client
|
||||
nexus.nixosModules.nexus-server
|
||||
|
|
Loading…
Reference in New Issue