Big commit

This commit is contained in:
niten 2023-12-04 17:10:57 -08:00
parent 44589ddc77
commit 0027566304
29 changed files with 1582 additions and 521 deletions

View File

@ -6,7 +6,7 @@ let
localDomain = "fudo.org";
serviceSecrets = config.fudo.secrets.files.service-secrets."${hostname}";
inherit (pkgs.lib) getDomainHosts getHostIpv4 getHostFqdn;
inherit (pkgs.lib) getDomainHosts getHostIpv4 getHostIpv6 getHostFqdn;
domain = config.fudo.domains."${localDomain}";
@ -18,6 +18,15 @@ let
mastodonHostname = "mastodon.fudo.org";
servedDomains = [
"fudo.org"
"test.fudo.org"
"selby.ca"
"fudo.ca"
"fudo.im"
"stewartsoundservices.ca"
];
in {
imports = [
(import ./fudo.org/authentik.nix { inherit authentikHost; })
@ -50,12 +59,12 @@ in {
saslDomain = "FUDO.ORG";
authentikOutpostToken =
config.fudo.secrets.files.domain-secrets."${primaryDomain}"."authentik-ldap.token";
servedDomains =
[ "fudo.org" "fudo.ca" "fudo.im" "selby.ca" "selbyhomecentre.com" ];
inherit servedDomains;
# TODO: FIXME!
dkimRecord = "";
}))
];
config = {
# All Fudo hosts should redirect selby.ca to the selbyhomecentre website.
services.nginx.virtualHosts = {
@ -77,15 +86,22 @@ in {
};
};
fudo.services = {
fudo = {
services = {
jabber = {
domain = "jabber.fudo.org";
ldap.servers = map (host: "${host}.${localDomain}") domain.ldap-servers;
ldap.servers =
map (host: "${host}.${localDomain}") domain.ldap-servers;
};
authoritative-dns = {
enable = hostname == primaryNameserver;
container = {
hostname = "nameserver";
interface = "enp5s0f0";
};
nameservers = {
primary = primaryNameserver;
external = map (hostname: {
@ -107,33 +123,30 @@ in {
ipv4-address ipv6-address sshfp-records;
description = "fudo.org";
};
fudoMailservers = {
smtp-servers = [ "smtp.fudo.org." ];
imap-servers = [ "imap.fudo.org." ];
};
mkDomain = domain: extraConfig:
{
default-host = defaultDeets;
ksk =
config.fudo.secrets.files.dns.key-signing-keys."${domain}";
} // extraConfig;
in {
"fudo.org" = {
default-host = defaultDeets;
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.org";
"fudo.org" = mkDomain "fudo.org" {
reverse-zones = [ "208.81.1.128/28" "208.81.3.112/28" ];
mail = fudoMailservers;
};
"test.fudo.org" = {
default-host = defaultDeets;
ksk =
config.fudo.secrets.files.dns.key-signing-keys."test.fudo.org";
};
"selby.ca" = {
default-host = defaultDeets;
ksk = config.fudo.secrets.files.dns.key-signing-keys."selby.ca";
};
"fudo.ca" = {
default-host = defaultDeets;
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.ca";
};
"fudo.im" = {
default-host = defaultDeets;
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.im";
};
"stewartsoundservices.ca" = {
default-host = defaultDeets;
ksk =
config.fudo.secrets.files.dns.key-signing-keys."stewartsoundservices.ca";
"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; };
};
};
};

View File

@ -12,7 +12,13 @@ let
authentikHostname = "authentik.${domainName}";
in {
config = {
fudo.zones."${zoneName}".aliases.authentik = authentikHost;
fudo = {
users.authentik.ldap-hashed-passwd =
pkgs.lib.passwd.hash-ldap-passwd "authentik-smtp"
config.fudo.secrets.files.domain-secrets."${domainName}"."authentik-smtp.passwd";
zones."${zoneName}".aliases.authentik = authentikHost;
};
services = {
authentikContainer = mkIf isAuthentik {
@ -25,7 +31,7 @@ in {
smtp = {
host = "mail.fudo.org";
password-file =
config.fudo.secrets.files.service-passwords."${authentikHost}".authentik-smtp;
config.fudo.secrets.files.domain-secrets."${domainName}"."authentik-smtp.passwd";
};
};

View File

@ -11,6 +11,11 @@ let
in {
config = {
systemd.services.arion-mail-server = {
requires = [ "podman.service" ];
after = [ "podman.service" ];
};
fudo = {
acme.host-domains = {
"imap.${primaryDomain}".extra-domain = [ "mail.${primaryDomain}" ];

View File

@ -0,0 +1,59 @@
{ hostInterface, servedDomains, stateDirectory, ipHostMap, ... }:
{ config, lib, pkgs, ... }:
with lib;
let
inherit (pkgs.lib) getSiteGatewayV4;
zoneName = "fudo.org";
zone = config.fudo.zones."${zoneName}";
nameserverDeets = zone.hosts."nameserver";
siteName = config.instance.local-site;
in {
config = {
systemd.tmpfiles.rules = [ "d ${stateDirectory} 700 root root - -" ];
containers.nameserver = {
autoStart = true;
# Needs to be able to set it's own IP(s)
additionalCapabilities = [ "CAP_NET_ADMIN" ];
macvlans = [ hostInterface ];
bindMounts."/var/lib/nsd".hostPath = stateDirectory;
config = {
imports = [ pkgs.moduleRegistry.authoritativeDns ];
networking = {
defaultGateway = getSiteGatewayV4 siteName;
firewall = {
enable = true;
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
interfaces."mv-${hostInterface}" = {
ipv4.addresses = optional (nameserverDeets.ipv4-address != null) {
address = nameserverDeets.ipv4-address;
prefixLength = getSiteV4PrefixLength siteName;
};
ipv6.addresses = optional (nameserverDeets.ipv6-address != null) {
address = nameserverDeets.ipv6-address;
prefixLength = getSiteV6PrefixLength siteName;
};
};
};
services.authoritative-dns = {
enable = true;
identity = "nameserver.${zoneName}";
listen-ips = [ nameserverDeets.ipv4-address ];
state-directory = "/var/lib/nsd";
timestamp = toString config.instance.build-timestamp;
ip-host-map = ipHostMap;
domains = servedDomains;
};
};
};
};
}

View File

@ -1,3 +1,52 @@
{ config, lib, pkgs, ... }:
{}
with lib;
let
hostname = config.instance.hostname;
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
frigateExternalHost = "sea-cam.fudo.link";
frigateHost = "zbox";
frigateDirectory = frigateCfg.state-directory;
frigateMqttPassword =
pkgs.lib.passwd.stablerandom-passwd-file "frigate-mqtt-passwd"
config.instance.build-seed;
in {
config = {
fudo.zones."sea.fudo.org".aliases."frigate" = "zbox";
fudo = {
services.mqtt.private.users.frigate = {
password-file = frigateMqttPassword;
acl = [ "frigate/#" ];
};
};
services = {
frigateContainer = {
enable = config.instance.hostname == frigateHost;
log-level = "info";
images.frigate = "ghcr.io/blakeblackshear/frigate:0.13.0-beta5";
cameras =
genAttrs [ "cam-steps" "cam-patio" "cam-entrance" "cam-driveway" ]
(cam: {
default = cam == "cam-driveway";
streams = {
low =
"rtsp://frigate:{FRIGATE_RTSP_PASSWORD}@${cam}.sea.fudo.org:554/cam/realmonitor?channel=1&subtype=0";
high =
"rtsp://frigate:{FRIGATE_RTSP_PASSWORD}@${cam}.sea.fudo.org:554/cam/realmonitor?channel=1&subtype=0";
};
});
camera-password-file =
config.fudo.secrets.files.domain-secrets."sea.fudo.org".seattle-camera-password;
mqtt = {
host = config.fudo.services.mqtt.mqtt-hostname;
port = config.fudo.services.mqtt.private.port;
user = "frigate";
password-file = frigateMqttPassword;
};
};
};
};
}

View File

@ -5,6 +5,8 @@ let fudo = config.fudo.domains."fudo.org";
in {
config = {
fudo = {
zones."sea.fudo.org" = { aliases.frigate = "zbox"; };
domains."sea.fudo.org" = {
local-networks = fudo.local-networks;

View File

@ -16,44 +16,49 @@
extraModulePackages = [ ];
};
system.stateVersion = "21.05";
system.stateVersion = "23.05";
fileSystems = {
"/" = {
device = "zbox-root";
fsType = "tmpfs";
options = [ "mode=755" ];
options = [ "mode=755" "noexec" ];
};
"/boot" = {
device = "/dev/disk/by-label/ZBOX-BOOT";
fsType = "vfat";
options = [ "noexec" "noatime" "nodiratime" ];
options = [ "noexec" "noatime" ];
};
"/state" = {
device = "/dev/disk/by-label/zbox-data";
fsType = "btrfs";
options = [ "noatime" "nodiratime" "compress=zstd" "subvol=@state" ];
options = [ "noatime" "compress=zstd" "noexec" "subvol=@state" ];
};
"/nix" = {
device = "/dev/disk/by-label/zbox-data";
fsType = "btrfs";
options = [ "noatime" "nodiratime" "compress=zstd" "subvol=@nix" ];
options = [ "noatime" "compress=zstd" "subvol=@nix" ];
};
"/var/log" = {
device = "/dev/disk/by-label/zbox-data";
fsType = "btrfs";
options =
[ "noatime" "nodiratime" "compress=zstd" "noexec" "subvol=@logs" ];
options = [ "noatime" "compress=zstd" "noexec" "subvol=@log" ];
};
"/home" = {
"/var/lib/containers" = {
device = "/dev/disk/by-label/zbox-data";
fsType = "btrfs";
options = [ "noatime" "nodiratime" "compress=zstd" "subvol=@home" ];
options = [ "noatime" "compress=zstd" "noexec" "subvol=@containers" ];
};
"/state/services/frigate" = {
device = "/dev/disk/by-label/zbox-recordings";
fsType = "btrfs";
options = [ "noatime" "compress=zstd" "noexec" ];
};
};
@ -68,19 +73,16 @@
driSupport = true;
driSupport32Bit = true;
setLdLibraryPath = true;
extraPackages = with pkgs; [ nvidia-vaapi-driver vaapiVdpau ];
};
pulseaudio = {
support32Bit = true;
package = pkgs.pulseaudioFull;
nvidia = {
package = config.boot.kernelPackages.nvidiaPackages.stable;
modesetting.enable = true;
powerManagement.enable = false;
};
enableRedistributableFirmware = true;
enableAllFirmware = true;
# Required with Wayland?
nvidia.modesetting.enable = true;
};
networking = {
@ -101,10 +103,7 @@
};
};
services.xserver.videoDrivers = [ "nvidia" ];
nix.settings.max-jobs = lib.mkDefault 8;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
systemd.targets = {
sleep.enable = false;

View File

@ -1,7 +1,16 @@
{ config, lib, pkgs, ... }:
with lib;
let primaryIp = "10.0.0.2";
let
primaryIp = "10.0.0.1";
hostname = config.instance.hostname;
domSecrets =
config.fudo.secrets.files.domain-secrets."${config.instance.local-domain}";
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
authentikHost = "authentik.fudo.org";
in {
config = {
networking = {
@ -26,7 +35,7 @@ in {
firewall = {
# Until it becomes the gateway, this is necessary
enable = mkForce true;
# enable = mkForce true;
allowedTCPPorts = [ 80 443 25565 config.services.murmur.port ];
allowedUDPPorts = [ 25565 34197 ];
};
@ -52,9 +61,62 @@ in {
];
};
virtualisation = {
podman = {
enable = true;
dockerSocket.enable = true;
autoPrune.enable = true;
};
docker.enable = false;
oci-containers = {
backend = "podman";
containers = {
"sea-cam-auth-proxy" = {
image = "ghcr.io/goauthentik/proxy";
autoStart = true;
environmentFiles =
[ hostSecrets.sea-cam-auth-proxy-env.target-file ];
ports = [ "9000:9000" ];
};
"sea-red-auth-proxy" = {
image = "ghcr.io/goauthentik/proxy";
autoStart = true;
environmentFiles =
[ hostSecrets.sea-red-auth-proxy-env.target-file ];
ports = [ "9001:9000" ];
};
};
};
};
fudo = {
hosts.fimbria.external-interfaces = [ "enp1s0" ];
client.dns.external-interface = "enp1s0";
secrets.host-secrets."${hostname}" = {
sea-cam-auth-proxy-env = {
source-file = let
token = removeSuffix "\n"
(readFile domSecrets."seattle-camera-auth-proxy.token");
in pkgs.writeText "sea-cam-auth-proxy.env" ''
AUTHENTIK_HOST=https://${authentikHost}/;
AUTHENTIK_TOKEN=${token}
AUTHENTIK_INSECURE=0
'';
target-file = "/run/sea-cam-auth-proxy/env";
};
sea-red-auth-proxy-env = {
source-file = let
token = removeSuffix "\n"
(readFile domSecrets."seattle-red-auth-proxy.token");
in pkgs.writeText "sea-red-auth-proxy.env" ''
AUTHENTIK_HOST=https://${authentikHost}/;
AUTHENTIK_TOKEN=${token}
AUTHENTIK_INSECURE=0
'';
target-file = "/run/sea-red-auth-proxy/env";
};
};
services = {
local-network = {
enable = true;
@ -77,27 +139,92 @@ in {
services = {
## TODO: enable when ready
# nginx = {
# enable = true;
# recommendedGzipSettings = true;
# recommendedOptimisation = true;
# recommendedProxySettings = true;
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
# virtualHosts = {
# "sea-home.fudo.link" = {
# enableACME = true;
# forceSSL = true;
# locations."/" = {
# proxyPass = "http://home-assist.sea.fudo.org/";
# extraConfig = ''
# proxy_http_version 1.1;
# proxy_set_header Upgrade $http_upgrade;
# proxy_set_header Connection "Upgrade";
# '';
# };
# };
# };
# };
virtualHosts = let
authenticatedPassthrough = { target, authPort }: {
enableACME = true;
forceSSL = true;
locations = {
"/" = {
proxyPass = target;
proxyWebsockets = true;
extraConfig = ''
##############################
# authentik-specific config
##############################
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
'';
};
"/outpost.goauthentik.io" = {
proxyPass = "http://127.0.0.1:${
toString authPort
}/outpost.goauthentik.io";
extraConfig = ''
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie $upstream_http_set_cookie;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
'';
};
"@goauthentik_proxy_signin" = {
return = "302 /outpost.goauthentik.io/start?rd=$request_uri";
extraConfig = ''
add_header Set-Cookie $auth_cookie;
internal;
'';
};
};
};
in {
"sea-home.fudo.link" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://home-assist.sea.fudo.org/";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
'';
};
};
"sea-cam.fudo.link" = authenticatedPassthrough {
target = "http://frigate.sea.fudo.org/";
authPort = 9000;
};
"sea-red.fudo.link" = authenticatedPassthrough {
target = "http://node-red.sea.fudo.org/";
authPort = 9001;
};
};
};
murmur = {
enable = true;

View File

@ -1,14 +1,16 @@
{ config, lib, pkgs, ... }:
with pkgs.lib;
let
primary-ip = "208.81.3.116";
dns-ip = "208.81.3.120";
hostname = config.instance.hostname;
host = config.fudo.hosts."${hostname}";
domainName = host.domain;
domain = config.fudo.domains."${domainName}";
site = config.fudo.sites."${host.site}";
hostFqdn = "${hostname}.${domainName}";
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
in {
config = {
networking = {
@ -25,16 +27,6 @@ in {
prefixLength = 28;
}];
};
dnsif0 = {
ipv4.addresses = [{
address = dns-ip;
prefixLength = 32;
}];
};
};
firewall = {
enable = false;
interfaces.podman0.allowedUDPPorts = [ 53 ];
};
};
@ -44,7 +36,14 @@ in {
"d /state/services 0555 - - - -"
];
services.fudo-mail-sync = {
services = {
# This has been failing because NS keys aren't available yet
"container@nameserver" = {
after = [ "fudo-secrets.target" ];
requires = [ "fudo-secrets.target" ];
};
fudo-mail-sync = {
path = with pkgs; [ rsync openssh ];
serviceConfig = {
Type = "oneshot";
@ -56,6 +55,7 @@ in {
'';
};
};
};
timers.fudo-mail-sync = {
wantedBy = [ "timers.target" ];
@ -92,6 +92,12 @@ in {
nsd.zones."fudo.org".outgoingInterface = "extif0";
# Necessary because germany isn't the default yet
postgresql = {
enable = true;
state-directory = "/state/services/postgresql";
};
services = {
auth = {
kerberos.state-directory = "/state/services/kerberos";
@ -99,11 +105,18 @@ in {
};
authoritative-dns.state-directory = "/state/services/dns";
jabber.state-directory = "/state/services/jabber";
logging.loki.state-directory = "/state/services/loki";
metrics = {
prometheus.state-directory = "/state/services/prometheus";
grafana.state-directory = "/state/services/grafana";
};
logging.loki.state-directory = "/state/services/loki";
postgresql = {
state-directory = "/state/services/postgresql";
keytab = extractFudoKeytab {
realm = domain.gssapi-realm;
principals = [ "postgres/${hostFqdn}" ];
};
};
};
};
};

View File

@ -38,6 +38,15 @@ in {
};
};
fonts.fontconfig = {
hinting = {
enable = true;
style = "hintfull";
};
subpixel.lcdfilter = "default";
antialias = true;
};
environment.etc = {
nixos.source = "/etc/nixos-live";
NIXOS.source = "${stateDir}/etc/NIXOS";

View File

@ -89,6 +89,7 @@ in {
enable = true;
dockerSocket.enable = true;
autoPrune.enable = true;
defaultNetwork.settings.dns_enabled = true;
};
};
@ -154,19 +155,6 @@ in {
external-interface = "extif0";
};
# auth.kdc = {
# enable = true;
# realm = "FUDO.ORG";
# bind-addresses = [ host-ipv4 "127.0.0.1" ];
# master-key-file =
# secrets.heimdal-master-key.target-file;
# state-directory = "/state/kerberos";
# slave-config = {
# master-host = "france";
# ipropd-keytab = secrets.ipropd-keytab.target-file;
# };
# };
secure-dns-proxy = {
enable = true;
upstream-dns =

View File

@ -10,6 +10,13 @@ let
domain-name = host-config.domain;
domain = config.fudo.domains.${domain-name};
hostname = config.instance.hostname;
domSecrets =
config.fudo.secrets.files.domain-secrets."${config.instance.local-domain}";
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
authentikHost = "authentik.fudo.org";
# dns-proxy-port = 5335;
in {
@ -84,6 +91,31 @@ in {
};
fudo = {
secrets.host-secrets."${hostname}" = {
sea-cam-auth-proxy-env = {
source-file = let
token = removeSuffix "\n"
(readFile domSecrets."seattle-camera-auth-proxy.token");
in pkgs.writeText "sea-cam-auth-proxy.env" ''
AUTHENTIK_HOST=https://${authentikHost}/;
AUTHENTIK_TOKEN=${token}
AUTHENTIK_INSECURE=0
'';
target-file = "/run/sea-cam-auth-proxy/env";
};
sea-red-auth-proxy-env = {
source-file = let
token = removeSuffix "\n"
(readFile domSecrets."seattle-red-auth-proxy.token");
in pkgs.writeText "sea-red-auth-proxy.env" ''
AUTHENTIK_HOST=https://${authentikHost}/;
AUTHENTIK_TOKEN=${token}
AUTHENTIK_INSECURE=0
'';
target-file = "/run/sea-red-auth-proxy/env";
};
};
hosts.limina.external-interfaces = [ "enp1s0" ];
client.dns.external-interface = "enp1s0";
@ -139,6 +171,34 @@ in {
systemd.services.nginx.requires = [ "bind.service" ];
virtualisation = {
podman = {
enable = true;
dockerSocket.enable = true;
autoPrune.enable = true;
};
docker.enable = false;
oci-containers = {
backend = "podman";
containers = {
"sea-cam-auth-proxy" = {
image = "ghcr.io/goauthentik/proxy";
autoStart = true;
environmentFiles =
[ hostSecrets.sea-cam-auth-proxy-env.target-file ];
ports = [ "9000:9000" ];
};
"sea-red-auth-proxy" = {
image = "ghcr.io/goauthentik/proxy";
autoStart = true;
environmentFiles =
[ hostSecrets.sea-red-auth-proxy-env.target-file ];
ports = [ "9001:9000" ];
};
};
};
};
services = {
nginx = {
enable = true;
@ -146,7 +206,62 @@ in {
recommendedOptimisation = true;
recommendedProxySettings = true;
virtualHosts = {
virtualHosts = let
authenticatedPassthrough = { target, authPort }: {
enableACME = true;
forceSSL = true;
locations = {
"/" = {
proxyPass = target;
proxyWebsockets = true;
extraConfig = ''
##############################
# authentik-specific config
##############################
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
# translate headers from the outposts back to the actual upstream
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
auth_request_set $authentik_email $upstream_http_x_authentik_email;
auth_request_set $authentik_name $upstream_http_x_authentik_name;
auth_request_set $authentik_uid $upstream_http_x_authentik_uid;
proxy_set_header X-authentik-username $authentik_username;
proxy_set_header X-authentik-groups $authentik_groups;
proxy_set_header X-authentik-email $authentik_email;
proxy_set_header X-authentik-name $authentik_name;
proxy_set_header X-authentik-uid $authentik_uid;
'';
};
"/outpost.goauthentik.io" = {
proxyPass = "http://127.0.0.1:${
toString authPort
}/outpost.goauthentik.io";
extraConfig = ''
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
add_header Set-Cookie $auth_cookie;
auth_request_set $auth_cookie $upstream_http_set_cookie;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
'';
};
"@goauthentik_proxy_signin" = {
return = "302 /outpost.goauthentik.io/start?rd=$request_uri";
extraConfig = ''
add_header Set-Cookie $auth_cookie;
internal;
'';
};
};
};
in {
"sea-home.fudo.link" = {
enableACME = true;
forceSSL = true;
@ -159,6 +274,16 @@ in {
'';
};
};
"sea-cam.fudo.link" = authenticatedPassthrough {
target = "http://frigate.sea.fudo.org/";
authPort = 9000;
};
"sea-red.fudo.link" = authenticatedPassthrough {
target = "http://node-red.sea.fudo.org/";
authPort = 9001;
};
};
};

View File

@ -91,16 +91,6 @@ in {
host-secrets = config.fudo.secrets.host-secrets.${hostname};
in {
secrets.host-secrets.${hostname} = {
# grafana-database-password = {
# source-file = grafana-database-passwd-file;
# target-file = "/run/services/grafana/db.passwd";
# user = config.systemd.services.grafana.serviceConfig.User;
# };
# postgres-grafana-password = {
# source-file = grafana-database-passwd-file;
# target-file = "/run/services/postgres/db.passwd";
# user = config.services.postgresql.superUser;
# };
pricebot-auth-token = {
source-file =
config.fudo.secrets.files.service-secrets.nostromo."pricebot-auth.token";
@ -127,10 +117,6 @@ in {
metrics.grafana = {
state-directory = "/state/services/grafana";
smtp.hostname = "mail.fudo.org";
# database = {
# user = "grafana";
# password-file = host-secrets.grafana-database-password.target-file;
# };
ldap.base-dn = "dc=fudo,dc=org";
};
@ -151,16 +137,26 @@ in {
state-directory = "/state/services/postgresql";
databases.grafana.users = config.instance.local-admins;
};
# users.grafana = {
# password-file = host-secrets.postgres-grafana-password.target-file;
# databases.grafana = {
# entity-access = {
# "ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES";
# "ALL SEQUENCES IN SCHEMA public" = "ALL PRIVILEGES";
# };
# };
# };
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/" ];
secret-key-file =
pkgs.lib.passwd.stablerandom-passwd-file "gitea-seattle-secret-key"
config.instance.build-seed;
networking = {
interface = "eno2";
ipv4 = {
address = "10.0.0.15";
prefixLength = 24;
};
};
};
};

View File

@ -6,7 +6,6 @@ let
primary-ip = "10.0.0.3";
state-dir = "/state";
zigbee2mqtt-statedir = "${state-dir}/services/zigbee2mqtt";
home-assistant-port = 8123;
zigbee2mqtt-user = config.systemd.services.zigbee2mqtt.serviceConfig.User;
@ -26,20 +25,20 @@ let
pkgs.lib.passwd.stablerandom-passwd-file "node-red-mqtt-passwd"
config.instance.build-seed;
homeAssistantPort = 8123;
teslaMatePort = 4400;
teslaGraphPort = 4401;
nodeRedPort = 1880;
host-secrets = config.fudo.secrets.host-secrets.${hostname};
host-passwds = config.fudo.secrets.files.service-passwords.${hostname};
host-secrets = config.fudo.secrets.host-secrets."${hostname}";
host-passwds = config.fudo.secrets.files.service-passwords."${hostname}";
in {
imports = [
(import ./wormhole0/home-assistant.nix {
homeAssistantImage = "ghcr.io/home-assistant/home-assistant:2023.9";
nodeRedImage = "nodered/node-red:3.1.0-14";
inherit nodeRedPort;
homeAssistantImage = "ghcr.io/home-assistant/home-assistant:2023.11.3";
nodeRedImage = "nodered/node-red:3.1.1";
inherit nodeRedPort homeAssistantPort;
stateDirectory = "/state/services/arion-home-assistant";
})
];
@ -158,10 +157,9 @@ in {
recommendedGzipSettings = true;
virtualHosts = {
"home-assist.sea.fudo.org" = {
locations."/" = {
proxyPass = "http://localhost:${toString home-assistant-port}";
proxyPass = "http://localhost:${toString homeAssistantPort}";
proxyWebsockets = true;
};
};
@ -189,40 +187,6 @@ in {
};
};
# mosquitto = {
# enable = true;
# dataDir = mosquitto-statedir;
# listeners = [{
# settings.allow_anonymous = false;
# port = 1883;
# address = "0.0.0.0";
# users = {
# zigbee2mqtt = {
# passwordFile =
# host-secrets.mosquitto-zigbee2mqtt-passwd.target-file;
# acl = [ "readwrite #" ];
# };
# home-assistant = {
# passwordFile =
# host-secrets.mosquitto-home-assistant-passwd.target-file;
# acl = [ "readwrite #" ];
# };
# niten = {
# passwordFile = host-secrets.mosquitto-niten-passwd.target-file;
# acl = [ "readwrite #" ];
# };
# # xiaoxuan = {
# # passwordFile = host-secrets.mosquitto-xiaoxuan-passwd.target-file;
# # acl = [ "readwrite #" ];
# # };
# # wallfly = {
# # passwordFile = host-secrets.mosquitto-wallfly-passwd.target-file;
# # acl = [ "readwrite homeassistant/binary_sensor/#" ];
# # };
# };
# }];
# };
zigbee2mqtt = {
enable = true;
dataDir = zigbee2mqtt-statedir;
@ -260,6 +224,7 @@ in {
user = "tesla-mate";
password = readFile teslaMateMqttPasswdFile;
};
images.tesla-mate = "teslamate/teslamate:1.28.2";
port = teslaMatePort;
grafana-port = teslaGraphPort;
state-directory = "/state/services/tesla-mate";
@ -280,20 +245,6 @@ in {
};
arion.backend = "podman-socket";
# oci-containers = {
# backend = "podman";
# containers = {
# home-assistant = {
# image = "homeassistant/home-assistant:stable";
# autoStart = true;
# environment.TZ = config.time.timeZone;
# #ports = [ "${toString home-assistant-port}:8123" ];
# volumes = [ "/state/services/home-assistant:/config" ];
# extraOptions = [ "--network=host" ];
# };
# };
# };
};
security.sudo.extraConfig = ''

View File

@ -1,4 +1,5 @@
{ homeAssistantImage, nodeRedImage, nodeRedPort ? 1880, stateDirectory, ... }:
{ homeAssistantImage, nodeRedImage, nodeRedPort, homeAssistantPort
, stateDirectory, ... }:
{ config, lib, pkgs, ... }:
@ -56,6 +57,7 @@ in {
"${stateDirectory}/config:/config"
"/etc/localtime:/etc/localtime:ro"
];
ports = [ "${toString homeAssistantPort}:8123" ];
user = "${toString homeAssistantUid}:${toString homeAssistantUid}";
network_mode = "host";
};

View File

@ -1,51 +1,95 @@
{ config, lib, pkgs, ... }:
with lib;
let state-dir = "/state";
let
primaryIp = pkgs.lib.getHostIpv4 "zbox";
openVinoModel = "ssdlite_mobilenet_v2";
libedgetpu =
config.boot.kernelPackages.callPackage ./zbox/pkgs/libedgetpu.nix { };
in {
config = {
fudo = {
slynk.enable = true;
wallfly.location = "family_room";
};
networking = {
interfaces.intif0.useDHCP = true;
useDHCP = false;
interfaces.intif0 = {
ipv4.addresses = [{
address = primaryIp;
prefixLength = 22;
}];
};
firewall.enable = false;
};
i18n.inputMethod = {
#enabled = "fcitx5";
# fcitx5.addons = with pkgs; [ fcitx5-chinese-addons fcitx5-rime ];
};
systemd.tmpfiles.rules = [
"d ${state-dir}/lib/cups 755 root root - -"
"d ${state-dir}/lib/flatpak 0755 root root - -"
"d ${state-dir}/etc 0755 root root - -"
"L /var/lib/flatpak - - - - ${state-dir}/lib/flatpak"
"L /etc/adjtime - - - - ${state-dir}/etc/adjtime"
];
fileSystems = {
"/var/lib/cups" = {
device = "${state-dir}/lib/cups";
options = [ "bind" ];
defaultGateway = {
address = "10.0.0.1";
interface = "intif0";
};
};
hardware = {
bluetooth = {
boot = let
gasket =
config.boot.kernelPackages.callPackage ./zbox/pkgs/gasket.nix { };
in {
extraModulePackages = [ gasket ];
kernelModules = [ "gasket" ];
};
users.groups.plugdev = { };
virtualisation = {
podman = {
enable = true;
package = pkgs.bluezFull;
};
xpadneo.enable = true;
dockerSocket.enable = true;
autoPrune.enable = true;
enableNvidia = true;
};
services.xserver = {
layout = "us";
xkbVariant = mkForce "";
xkbOptions = mkForce "";
arion.backend = "podman-socket";
};
services = {
frigateContainer = {
state-directory = "/state/services/frigate";
# hwaccel = "preset-vaapi";
devices = [ "/dev/apex_0" "/dev/dri/renderD128" ];
detectors = {
coral = {
type = "edgetpu";
device = "";
};
};
};
udev = {
packages = [ "${libedgetpu}" ];
extraRules = ''
SUBSYSTEM=="pci",ATTRS{device}=="089a",GROUP="plugdev"
SUBSYSTEM=="apex",ATTRS{device_type}=="apex",GROUP="plugdev"
'';
};
xserver = {
enable = mkForce true;
videoDrivers = [ "nvidia" ];
};
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
virtualHosts."frigate.sea.fudo.org" = {
locations."/" = {
proxyPass = "http://localhost:5000";
proxyWebsockets = true;
};
};
};
};
security.sudo.extraConfig = ''
# Due to rollback, sudo will lecture after every reboot
Defaults lecture = never
'';
};
}

View File

@ -0,0 +1,36 @@
{ stdenv, lib, fetchFromGitHub, kernel }:
stdenv.mkDerivation rec {
pname = "gasket";
version = "1.0-18";
src = fetchFromGitHub {
owner = "google";
repo = "gasket-driver";
rev = "97aeba584efd18983850c36dcf7384b0185284b3";
sha256 = "pJwrrI7jVKFts4+bl2xmPIAD01VKFta2SRuElerQnTo=";
};
makeFlags = [
"-C"
"${kernel.dev}/lib/modules/${kernel.modDirVersion}/build"
"M=$(PWD)"
];
buildFlags = [ "modules" ];
installFlags = [ "INSTALL_MOD_PATH=${placeholder "out"}" ];
installTargets = [ "modules_install" ];
sourceRoot = "source/src";
hardeningDisable = [ "pic" "format" ];
nativeBuildInputs = kernel.moduleBuildDependencies;
meta = with lib; {
description =
"The Coral Gasket Driver allows usage of the Coral EdgeTPU on Linux systems.";
homepage = "https://github.com/google/gasket-driver";
license = licenses.gpl2;
maintainers = [ lib.maintainers.kylehendricks ];
platforms = platforms.linux;
};
}

View File

@ -0,0 +1,12 @@
diff --git a/api/allocated_buffer.h b/api/allocated_buffer.h
index 97740f0..7bc0547 100644
--- a/api/allocated_buffer.h
+++ b/api/allocated_buffer.h
@@ -16,6 +16,7 @@
#define DARWINN_API_ALLOCATED_BUFFER_H_
#include <functional>
+#include <cstddef>
namespace platforms {
namespace darwinn {

View File

@ -0,0 +1,57 @@
{ stdenv, lib, fetchFromGitHub, libusb1, abseil-cpp, flatbuffers, xxd }:
let
flatbuffers_1_12 = flatbuffers.overrideAttrs (oldAttrs: rec {
version = "1.12.0";
NIX_CFLAGS_COMPILE =
"-Wno-error=class-memaccess -Wno-error=maybe-uninitialized";
cmakeFlags = (oldAttrs.cmakeFlags or [ ])
++ [ "-DFLATBUFFERS_BUILD_SHAREDLIB=ON" ];
NIX_CXXSTDLIB_COMPILE = "-std=c++17";
configureFlags = (oldAttrs.configureFlags or [ ]) ++ [ "--enable-shared" ];
src = fetchFromGitHub {
owner = "google";
repo = "flatbuffers";
rev = "v${version}";
sha256 = "sha256-L1B5Y/c897Jg9fGwT2J3+vaXsZ+lfXnskp8Gto1p/Tg=";
};
});
in stdenv.mkDerivation rec {
pname = "libedgetpu";
version = "grouper";
src = fetchFromGitHub {
owner = "google-coral";
repo = pname;
rev = "release-${version}";
sha256 = "sha256-73hwItimf88Iqnb40lk4ul/PzmCNIfdt6Afi+xjNiBE=";
};
patches = [ ./libedgetpu-stddef.diff ];
makeFlags = [ "-f" "makefile_build/Makefile" "libedgetpu" ];
buildInputs = [ libusb1 abseil-cpp flatbuffers_1_12 ];
nativeBuildInputs = [ xxd ];
NIX_CXXSTDLIB_COMPILE = "-std=c++17";
TFROOT = "${fetchFromGitHub {
owner = "tensorflow";
repo = "tensorflow";
rev = "v2.7.4";
sha256 = "sha256-liDbUAdaVllB0b74aBeqNxkYNu/zPy7k3CevzRF5dk0=";
}}";
enableParallelBuilding = false;
installPhase = ''
mkdir -p $out/lib
cp out/direct/k8/libedgetpu.so.1.0 $out/lib
ln -s $out/lib/libedgetpu.so.1.0 $out/lib/libedgetpu.so.1
mkdir -p $out/lib/udev/rules.d
cp debian/edgetpu-accelerator.rules $out/lib/udev/rules.d/99-edgetpu-accelerator.rules
'';
}

View File

@ -6,48 +6,130 @@ let
cfg = config.fudo.services.authoritative-dns;
inherit (pkgs.lib)
getHostIps getSiteGatewayV4 getSiteV4PrefixLength getSiteV6PrefixLength;
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
domainName = config.instance.local-domain;
primaryZone = config.fudo.domains."${domainName}".zone;
siteName = config.instance.local-site;
zoneKeySecret = zone: "${zone}-ksk";
networkHostOpts = {
options = with types; {
hostname = mkOption {
type = str;
description = "Hostname.";
containerModule = { pkgs, config, ... }: {
config = mkIf (cfg.enable && !isNull cfg.container) {
containers.nameserver = let
securedZones =
filterAttrs (_: zoneOpts: !isNull zoneOpts.ksk) cfg.zones;
in {
autoStart = true;
additionalCapabilities = [ "CAP_NET_ADMIN" ];
macvlans = [ cfg.container.interface ];
bindMounts = {
"/var/lib/nsd" = {
hostPath = cfg.state-directory;
isReadOnly = false;
};
} // (mapAttrs' (zoneName: _:
let zoneKeyName = zoneKeySecret zoneName;
in nameValuePair "/run/nsd/keys/${zoneKeyName}" {
hostPath = hostSecrets."${zoneKeyName}".target-file;
}) securedZones);
config = let
nameserverHost = cfg.container.hostname;
nameserverDeets =
config.fudo.zones."${primaryZone}".hosts."${nameserverHost}";
in {
imports = [ pkgs.moduleRegistry.authoritativeDns ];
nixpkgs.pkgs = pkgs;
networking = {
defaultGateway = {
address = getSiteGatewayV4 siteName;
interface = "mv-${cfg.container.interface}";
};
firewall = {
enable = true;
allowedTCPPorts = [ 53 ];
allowedUDPPorts = [ 53 ];
};
interfaces."mv-${cfg.container.interface}" = {
ipv4.addresses = optional (nameserverDeets.ipv4-address != null) {
address = trace "IP ADDRESS: ${nameserverDeets.ipv4-address}"
nameserverDeets.ipv4-address;
prefixLength = getSiteV4PrefixLength siteName;
};
ipv6.addresses = optional (nameserverDeets.ipv6-address != null) {
address = nameserverDeets.ipv6-address;
prefixLength = getSiteV6PrefixLength siteName;
};
};
};
services.authoritative-dns = {
enable = true;
identity = "${nameserverHost}.${primaryZone}";
listen-ips = getHostIps nameserverHost;
state-directory = "/var/lib/nsd";
timestamp = toString config.instance.build-timestamp;
ip-host-map = cfg.ip-host-map;
domains = mapAttrs' (zoneName: zoneCfg:
nameValuePair zoneCfg.domain {
ksk.key-file = "/run/nsd/keys/${zoneKeySecret zoneName}";
reverse-zones = zoneCfg.reverse-zones;
notify = mkIf cfg.enable-notifications {
ipv4 = concatMap
(ns: optional (ns.ipv4-address != null) ns.ipv4-address)
cfg.nameservers.external;
ipv6 = concatMap
(ns: optional (ns.ipv6-address != null) ns.ipv6-address)
cfg.nameservers.external;
};
zone = config.fudo.zones."${zoneName}";
}) cfg.zones;
};
};
};
};
ipv4-address = mkOption {
type = nullOr str;
description = "The V4 IP of a given host, if any.";
default = null;
};
ipv6-address = mkOption {
type = nullOr str;
description = "The V6 IP of a given host, if any.";
default = null;
};
hostModule = { config, ... }: {
config.services.authoritative-dns =
mkIf (cfg.enable && isNull cfg.container) {
enable = true;
mac-address = mkOption {
type = nullOr str;
description =
"The MAC address of a given host, if desired for IP reservation.";
default = null;
};
identity = "${hostname}.${primaryZone}";
description = mkOption {
type = nullOr str;
description = "Description of the host.";
default = null;
};
listen-ips = getHostIps hostname;
sshfp-records = mkOption {
type = listOf str;
description = "List of SSHFP records for this host.";
default = [ ];
state-directory = "/var/lib/nsd";
timestamp = toString config.instance.build-timestamp;
ip-host-map = cfg.ip-host-map;
domains = mapAttrs' (zoneName: zoneCfg:
nameValuePair zoneCfg.domain {
ksk.key-file = mkIf (hasAttr (zoneKeySecret zoneName) hostSecrets)
hostSecrets."${zoneKeySecret zoneName}".target-file;
reverse-zones = zoneCfg.reverse-zones;
notify = mkIf cfg.enable-notifications {
ipv4 = concatMap
(ns: optional (ns.ipv4-address != null) ns.ipv4-address)
cfg.nameservers.external;
ipv6 = concatMap
(ns: optional (ns.ipv6-address != null) ns.ipv6-address)
cfg.nameservers.external;
};
zone = config.fudo.zones."${zoneName}";
}) cfg.zones;
};
};
@ -62,7 +144,7 @@ let
};
default-host = mkOption {
type = nullOr (submodule networkHostOpts);
type = nullOr (submodule pkgs.lib.fudo-types.networkHost);
description =
"Host which will respond to requests for the base domain.";
default = null;
@ -123,6 +205,27 @@ in {
options.fudo.services.authoritative-dns = with types; {
enable = mkEnableOption "Enable Authoritative DNS server.";
container = mkOption {
type = nullOr (submodule {
options = {
interface = mkOption {
type = str;
description = "Interface on which to listen for DNS traffic.";
};
hostname = mkOption {
type = str;
description = ''
Hostname (in the zone) of the container nameserver.
The associated IP(s) will be assigned to the container,
and must be accessible.
'';
};
};
});
};
enable-notifications =
mkEnableOption "Enable notifications to secondary servers.";
@ -152,7 +255,7 @@ in {
};
external = mkOption {
type = listOf (submodule networkHostOpts);
type = listOf (submodule pkgs.lib.fudo-types.networkHost);
description = "List of external secondary nameserver attributes.";
default = [ ];
};
@ -165,15 +268,23 @@ in {
};
};
config = {
imports = [ hostModule containerModule ];
config = mkIf cfg.enable {
systemd.tmpfiles.rules = [ "d ${cfg.state-directory} 700 root root - -" ];
fileSystems."/var/lib/nsd" = mkIf (isNull cfg.container) {
device = cfg.state-directory;
options = [ "bind" ];
};
fudo = {
secrets.host-secrets."${hostname}" = mkIf cfg.enable (mapAttrs'
(zone: zoneCfg:
secrets.host-secrets."${hostname}" = mapAttrs' (zone: zoneCfg:
nameValuePair (zoneKeySecret zone) {
source-file = zoneCfg.ksk.private-key;
target-file = "/run/nsd/${baseNameOf zoneCfg.ksk.private-key}";
user = config.fudo.nsd.user;
}) (filterAttrs (_: zoneCfg: zoneCfg.ksk != null) cfg.zones));
}) (filterAttrs (_: zoneCfg: zoneCfg.ksk != null) cfg.zones);
zones = mapAttrs (zone-name: zoneCfg:
let
@ -256,38 +367,5 @@ in {
];
}) cfg.zones;
};
services = {
authoritative-dns = {
enable = cfg.enable;
identity = "${hostname}.${domainName}";
listen-ips =
optionals cfg.enable (pkgs.lib.network.host-ips config hostname);
state-directory = cfg.state-directory;
timestamp = toString config.instance.build-timestamp;
ip-host-map = cfg.ip-host-map;
domains = mapAttrs' (zoneName: zoneCfg:
nameValuePair zoneCfg.domain {
ksk.key-file = mkIf (hasAttr (zoneKeySecret zoneName) hostSecrets)
hostSecrets."${zoneKeySecret zoneName}".target-file;
reverse-zones = zoneCfg.reverse-zones;
notify = mkIf cfg.enable-notifications {
ipv4 = concatMap
(ns: optional (ns.ipv4-address != null) ns.ipv4-address)
cfg.nameservers.external;
ipv6 = concatMap
(ns: optional (ns.ipv6-address != null) ns.ipv6-address)
cfg.nameservers.external;
};
zone = config.fudo.zones."${zoneName}";
}) cfg.zones;
};
};
};
}

View File

@ -0,0 +1,208 @@
{ config, lib, pkgs, ... }:
with lib;
let cfg = config.fudo.services.gitea-container;
in {
options.fudo.services.gitea-container = with types; {
enable = mkEnableOption "Enable Gitea running in a container.";
site-name = mkOption {
type = str;
description = "Name of this Gitea instance.";
};
hostname = mkOption {
type = str;
description = "Hostname at which the server is reachable.";
};
state-directory = mkOption {
type = str;
description = "Path at which to store Gitea state.";
};
secret-key-file = mkOption {
type = str;
description =
"Path to file containing Gitea secret key, for encrypting secrets.";
};
trusted-networks = mkOption {
type = listOf str;
description =
"List of networks to be considered trusted (for metrics access).";
default = [ ];
};
openid-urls = mkOption {
type = listOf str;
description = "List of authorized OpenID providers.";
};
networking = {
interface = mkOption {
type = str;
description = "Parent host interface on which to listen.";
};
ipv4 = mkOption {
type = nullOr (submodule {
options = {
address = mkOption {
type = str;
description = "IP address.";
};
prefixLength = mkOption {
type = int;
description = "Significant bits in the address.";
};
};
});
default = null;
};
ipv6 = mkOption {
type = nullOr (submodule {
options = {
address = mkOption {
type = str;
description = "IP address.";
};
prefixLength = mkOption {
type = int;
description = "Significant bits in the address.";
};
};
});
default = null;
};
};
};
config = mkIf cfg.enable {
systemd.tmpfiles.rules = [ "d ${cfg.state-directory} 700 root root - -" ];
containers.gitea = {
autoStart = true;
additionalCapabilities = [ "CAP_NET_ADMIN" ];
macvlans = [ cfg.networking.interface ];
bindMounts = {
"/state" = {
hostPath = cfg.state-directory;
isReadOnly = false;
};
};
config = {
nixpkgs.pkgs = pkgs;
systemd = { tmpfiles.rules = [ "d /state 0755 root root - -" ]; };
networking = {
defaultGateway = config.networking.defaultGateway;
enableIPv6 = !isNull cfg.networking.ipv6;
firewall = {
enable = true;
allowedTCPPorts = [ 22 80 443 ];
};
interfaces."mv-${cfg.networking.interface}" = {
ipv4.addresses = optional (!isNull cfg.networking.ipv4) {
address = cfg.networking.ipv4.address;
prefixLength = cfg.networking.ipv4.prefixLength;
};
ipv6.addresses = optional (!isNull cfg.networking.ipv6) {
address = cfg.networking.ipv6.address;
prefixLength = cfg.networking.ipv6.prefixLength;
};
};
};
services = {
gitea = {
enable = true;
appName = cfg.site-name;
database = {
createDatabase = true;
type = "sqlite3";
};
repositoryRoot = "/state/repositories";
stateDir = "/state/gitea";
settings = {
service.DISABLE_REGISTRATION = true;
security = {
INSTALL_LOCK = true;
SECRET_KEY = "file:${cfg.secret-key-file}";
LOGIN_REMEMBER_DAYS = 30;
};
metrics.ENABLED = cfg.trusted-networks != [ ];
server = {
START_SSH_SERVER = true;
# Host & port to display in the clone URL
SSH_DOMAIN = cfg.hostname;
SSH_PORT = 22;
SSH_LISTEN_PORT = 2222;
SSH_LISTEN_HOST = "0.0.0.0";
DOMAIN = cfg.hostname;
ROOT_URL = "https://${cfg.hostname}";
HTTP_ADDR = "127.0.0.1";
HTTP_PORT = 8080;
};
openid = {
ENABLE_OPENID_SIGNIN = true;
WHITELISTED_URIS = cfg.openid-urls;
};
oauth2_client = {
REGISTER_EMAIL_CONFIRM = false;
OPENID_CONNECT_SCOPES = [ "email" "profile" ];
ENABLE_AUTO_REGISTRATION = true;
USERNAME = "email";
UPDATE_AVATAR = true;
ACCOUNT_LINKING = "login";
};
};
};
xinetd = {
enable = true;
services = [{
name = "ssh";
# port = 22;
# protocol = "tcp";
extraConfig = ''
redirect = localhost 2222
wait = no
socket_type = stream
'';
user = "nobody";
# Must be defined, but not used
server = "/usr/bin/env";
# unlisted = true;
}];
};
nginx = {
enable = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedGzipSettings = true;
virtualHosts."${cfg.hostname}" = {
# enableACME = true;
# forceSSL = true;
locations."/".proxyPass = "http://127.0.0.1:8080";
locations."/metrics" = mkIf (cfg.trusted-networks != [ ]) (let
networkAllowClauses =
map (net: "allow ${net};") cfg.trusted-networks;
in concatStringsSep "\n"
(networkAllowClauses ++ [ "deny all;" ]));
};
};
};
};
};
};
}

View File

@ -134,11 +134,12 @@ in {
dns = {
listen-ips = [ "127.0.0.1" ];
listen-port = agp.dns-listen-port;
reverse-dns = [ (host-ipv4 gateway-host) ];
};
local-domain-name = domain-name;
};
zones.${zone-name} = {
zones."${zone-name}" = {
aliases = {
"${agp.http-host-alias}" = mkIf (agp.enable) (fqdn gateway-host);
ns = (fqdn nameserver-host);

View File

@ -38,8 +38,8 @@ in {
config = mkIf postgresEnabled {
fudo = {
acme.host-domains.${hostname} = mkIf (publicNetwork && isPostgresHost) {
${postgresql-hostname}.local-copies = {
acme.host-domains."${hostname}" = mkIf (publicNetwork && isPostgresHost) {
"${postgresql-hostname}".local-copies = {
postgresql = {
user = postgresUser;
dependent-services = [ "postgresql.service" ];
@ -48,15 +48,15 @@ in {
};
};
secrets.host-secrets.${hostname}.postgres-keytab =
secrets.host-secrets."${hostname}".postgres-keytab =
mkIf (cfg.keytab != null) {
source-file = cfg.keytab;
target-file = "/run/postgresql/postgres.keytab";
user = postgresUser;
};
zones.${zone-name}.aliases.postgresql =
"${domain.postgresql-server}.${domain-name}.";
zones."${zone-name}".aliases.postgresql =
pkgs.lib.getHostFqdn domain.postgresql-server;
postgresql = mkIf isPostgresHost (let
ssl-config = optionalAttrs publicNetwork (let

View File

@ -38,6 +38,8 @@ in {
};
config = mkIf cfg.enable {
systemd.services.snooper.after = mkIf isSnooper [ "fudo-secrets.target" ];
fudo = {
secrets.host-secrets."${hostname}" = {
snooper-passwd = mkIf isSnooper {

View File

@ -8,6 +8,7 @@
./service/chute.nix
./service/dns.nix
./service/fudo-auth.nix
./service/gitea-container.nix
./service/jabber.nix
./service/lemmy.nix
./service/local-network.nix

View File

@ -633,6 +633,12 @@ with lib; {
ldap-hashed-passwd = "{SSHA}mok5LrQtJ4pny2QTaN3sMmOZx6X0eg5R";
email = "jasper@selby.ca";
};
authentik = {
uid = 10117;
primary-group = "fudo";
common-name = "Fudo Authentik";
};
};
groupDomainMap = {

File diff suppressed because it is too large Load Diff

View File

@ -131,6 +131,11 @@
inputs.nixpkgs.follows = "nixpkgs";
};
frigate-container = {
url = "git+https://git.fudo.org/fudo-public/frigate-container.git";
inputs.nixpkgs.follows = "nixpkgs";
};
textfiles = {
url = "git+https://git.informis.land/informis/textfiles.git";
flake = false;
@ -142,7 +147,7 @@
, wallfly, objectifier, nexus, suanni, snooper, tattler, lemmy-docker
, tesla-mate-container, mastodon-container, authentik-container
, nextcloud-container, textfiles, matrix-module, mail-server
, authoritative-dns, ... }@inputs:
, authoritative-dns, frigate-container, ... }@inputs:
with nixpkgs.lib;
let
fudo-nixos-hosts = filterAttrs (hostname: hostOpts: hostOpts.nixos-system)
@ -167,10 +172,11 @@
"openssl-1.1.1w"
"python3.10-requests-2.28.2"
"python3.10-cryptography-40.0.1"
"gitea-1.19.4"
];
};
overlays = [
fudo-lib.overlay
fudo-lib.overlays.default
fudo-pkgs.overlays.default
fudo-secrets.overlays.default
fudo-entities.overlays.default
@ -211,7 +217,7 @@
imports = [
fudo-home.nixosModules.default
fudo-secrets.nixosModules.default
fudo-lib.nixosModule
fudo-lib.nixosModules.default
fudo-entities.nixosModule
pricebot.nixosModules.default
wallfly.nixosModule
@ -227,6 +233,7 @@
matrix-module.nixosModules.default
mail-server.nixosModules.default
authoritative-dns.nixosModules.default
frigate-container.nixosModules.default
nexus.nixosModules.nexus-client
nexus.nixosModules.nexus-server

18
lib/instantiate-zone.nix Normal file
View File

@ -0,0 +1,18 @@
{ config, lib, pkgs, ... }:
with lib;
let
mkSrvRecord = host: port: { inherit host port; };
instantiateZone = zoneName:
{ primaryNameserver, secondaryNameservers ? [ ], externalNameservers ? [ ]
, smtpServers, imapServers, ... }: {
gssapi-realm = gssapiRealm;
mx = smtpServers;
dmarc-report-address = "dmarc-report@${zoneName}";
default-host = defaultHost;
verbatim-dns-records =
mkIf (ksk != null) [ ksk.public-key-record ksk.ds ];
};
in { inherit instantiateZone; }