Big commit
This commit is contained in:
parent
44589ddc77
commit
0027566304
|
@ -6,7 +6,7 @@ let
|
||||||
localDomain = "fudo.org";
|
localDomain = "fudo.org";
|
||||||
serviceSecrets = config.fudo.secrets.files.service-secrets."${hostname}";
|
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}";
|
domain = config.fudo.domains."${localDomain}";
|
||||||
|
|
||||||
|
@ -18,6 +18,15 @@ let
|
||||||
|
|
||||||
mastodonHostname = "mastodon.fudo.org";
|
mastodonHostname = "mastodon.fudo.org";
|
||||||
|
|
||||||
|
servedDomains = [
|
||||||
|
"fudo.org"
|
||||||
|
"test.fudo.org"
|
||||||
|
"selby.ca"
|
||||||
|
"fudo.ca"
|
||||||
|
"fudo.im"
|
||||||
|
"stewartsoundservices.ca"
|
||||||
|
];
|
||||||
|
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
(import ./fudo.org/authentik.nix { inherit authentikHost; })
|
(import ./fudo.org/authentik.nix { inherit authentikHost; })
|
||||||
|
@ -50,12 +59,12 @@ in {
|
||||||
saslDomain = "FUDO.ORG";
|
saslDomain = "FUDO.ORG";
|
||||||
authentikOutpostToken =
|
authentikOutpostToken =
|
||||||
config.fudo.secrets.files.domain-secrets."${primaryDomain}"."authentik-ldap.token";
|
config.fudo.secrets.files.domain-secrets."${primaryDomain}"."authentik-ldap.token";
|
||||||
servedDomains =
|
inherit servedDomains;
|
||||||
[ "fudo.org" "fudo.ca" "fudo.im" "selby.ca" "selbyhomecentre.com" ];
|
|
||||||
# TODO: FIXME!
|
# TODO: FIXME!
|
||||||
dkimRecord = "";
|
dkimRecord = "";
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
|
||||||
config = {
|
config = {
|
||||||
# All Fudo hosts should redirect selby.ca to the selbyhomecentre website.
|
# All Fudo hosts should redirect selby.ca to the selbyhomecentre website.
|
||||||
services.nginx.virtualHosts = {
|
services.nginx.virtualHosts = {
|
||||||
|
@ -77,63 +86,67 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
fudo.services = {
|
fudo = {
|
||||||
jabber = {
|
services = {
|
||||||
domain = "jabber.fudo.org";
|
jabber = {
|
||||||
ldap.servers = map (host: "${host}.${localDomain}") domain.ldap-servers;
|
domain = "jabber.fudo.org";
|
||||||
};
|
ldap.servers =
|
||||||
|
map (host: "${host}.${localDomain}") domain.ldap-servers;
|
||||||
authoritative-dns = {
|
|
||||||
enable = hostname == primaryNameserver;
|
|
||||||
|
|
||||||
nameservers = {
|
|
||||||
primary = primaryNameserver;
|
|
||||||
external = map (hostname: {
|
|
||||||
inherit (config.fudo.zones."fudo.org".hosts."${hostname}")
|
|
||||||
ipv4-address ipv6-address description;
|
|
||||||
}) [ "ns2-fudo" "ns3-fudo" "ns4-fudo" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ip-host-map = let
|
authoritative-dns = {
|
||||||
networkHosts = getDomainHosts "fudo.org";
|
enable = hostname == primaryNameserver;
|
||||||
ipHostPairs =
|
|
||||||
map (host: nameValuePair (getHostIpv4 host) (getHostFqdn host))
|
|
||||||
networkHosts;
|
|
||||||
in listToAttrs ipHostPairs;
|
|
||||||
|
|
||||||
zones = let
|
container = {
|
||||||
defaultDeets = {
|
hostname = "nameserver";
|
||||||
inherit (config.fudo.zones."fudo.org".hosts."${defaultHost}")
|
interface = "enp5s0f0";
|
||||||
ipv4-address ipv6-address sshfp-records;
|
|
||||||
description = "fudo.org";
|
|
||||||
};
|
};
|
||||||
in {
|
|
||||||
"fudo.org" = {
|
nameservers = {
|
||||||
default-host = defaultDeets;
|
primary = primaryNameserver;
|
||||||
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.org";
|
external = map (hostname: {
|
||||||
reverse-zones = [ "208.81.1.128/28" "208.81.3.112/28" ];
|
inherit (config.fudo.zones."fudo.org".hosts."${hostname}")
|
||||||
|
ipv4-address ipv6-address description;
|
||||||
|
}) [ "ns2-fudo" "ns3-fudo" "ns4-fudo" ];
|
||||||
};
|
};
|
||||||
"test.fudo.org" = {
|
|
||||||
default-host = defaultDeets;
|
ip-host-map = let
|
||||||
ksk =
|
networkHosts = getDomainHosts "fudo.org";
|
||||||
config.fudo.secrets.files.dns.key-signing-keys."test.fudo.org";
|
ipHostPairs =
|
||||||
};
|
map (host: nameValuePair (getHostIpv4 host) (getHostFqdn host))
|
||||||
"selby.ca" = {
|
networkHosts;
|
||||||
default-host = defaultDeets;
|
in listToAttrs ipHostPairs;
|
||||||
ksk = config.fudo.secrets.files.dns.key-signing-keys."selby.ca";
|
|
||||||
};
|
zones = let
|
||||||
"fudo.ca" = {
|
defaultDeets = {
|
||||||
default-host = defaultDeets;
|
inherit (config.fudo.zones."fudo.org".hosts."${defaultHost}")
|
||||||
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.ca";
|
ipv4-address ipv6-address sshfp-records;
|
||||||
};
|
description = "fudo.org";
|
||||||
"fudo.im" = {
|
};
|
||||||
default-host = defaultDeets;
|
|
||||||
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.im";
|
fudoMailservers = {
|
||||||
};
|
smtp-servers = [ "smtp.fudo.org." ];
|
||||||
"stewartsoundservices.ca" = {
|
imap-servers = [ "imap.fudo.org." ];
|
||||||
default-host = defaultDeets;
|
};
|
||||||
ksk =
|
|
||||||
config.fudo.secrets.files.dns.key-signing-keys."stewartsoundservices.ca";
|
mkDomain = domain: extraConfig:
|
||||||
|
{
|
||||||
|
default-host = defaultDeets;
|
||||||
|
ksk =
|
||||||
|
config.fudo.secrets.files.dns.key-signing-keys."${domain}";
|
||||||
|
} // extraConfig;
|
||||||
|
in {
|
||||||
|
"fudo.org" = mkDomain "fudo.org" {
|
||||||
|
reverse-zones = [ "208.81.1.128/28" "208.81.3.112/28" ];
|
||||||
|
mail = fudoMailservers;
|
||||||
|
};
|
||||||
|
"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; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,13 @@ let
|
||||||
authentikHostname = "authentik.${domainName}";
|
authentikHostname = "authentik.${domainName}";
|
||||||
in {
|
in {
|
||||||
config = {
|
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 = {
|
services = {
|
||||||
authentikContainer = mkIf isAuthentik {
|
authentikContainer = mkIf isAuthentik {
|
||||||
|
@ -25,7 +31,7 @@ in {
|
||||||
smtp = {
|
smtp = {
|
||||||
host = "mail.fudo.org";
|
host = "mail.fudo.org";
|
||||||
password-file =
|
password-file =
|
||||||
config.fudo.secrets.files.service-passwords."${authentikHost}".authentik-smtp;
|
config.fudo.secrets.files.domain-secrets."${domainName}"."authentik-smtp.passwd";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,11 @@ let
|
||||||
|
|
||||||
in {
|
in {
|
||||||
config = {
|
config = {
|
||||||
|
systemd.services.arion-mail-server = {
|
||||||
|
requires = [ "podman.service" ];
|
||||||
|
after = [ "podman.service" ];
|
||||||
|
};
|
||||||
|
|
||||||
fudo = {
|
fudo = {
|
||||||
acme.host-domains = {
|
acme.host-domains = {
|
||||||
"imap.${primaryDomain}".extra-domain = [ "mail.${primaryDomain}" ];
|
"imap.${primaryDomain}".extra-domain = [ "mail.${primaryDomain}" ];
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,3 +1,52 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ 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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
|
@ -5,6 +5,8 @@ let fudo = config.fudo.domains."fudo.org";
|
||||||
in {
|
in {
|
||||||
config = {
|
config = {
|
||||||
fudo = {
|
fudo = {
|
||||||
|
zones."sea.fudo.org" = { aliases.frigate = "zbox"; };
|
||||||
|
|
||||||
domains."sea.fudo.org" = {
|
domains."sea.fudo.org" = {
|
||||||
local-networks = fudo.local-networks;
|
local-networks = fudo.local-networks;
|
||||||
|
|
||||||
|
|
|
@ -16,44 +16,49 @@
|
||||||
extraModulePackages = [ ];
|
extraModulePackages = [ ];
|
||||||
};
|
};
|
||||||
|
|
||||||
system.stateVersion = "21.05";
|
system.stateVersion = "23.05";
|
||||||
|
|
||||||
fileSystems = {
|
fileSystems = {
|
||||||
"/" = {
|
"/" = {
|
||||||
device = "zbox-root";
|
device = "zbox-root";
|
||||||
fsType = "tmpfs";
|
fsType = "tmpfs";
|
||||||
options = [ "mode=755" ];
|
options = [ "mode=755" "noexec" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
"/boot" = {
|
"/boot" = {
|
||||||
device = "/dev/disk/by-label/ZBOX-BOOT";
|
device = "/dev/disk/by-label/ZBOX-BOOT";
|
||||||
fsType = "vfat";
|
fsType = "vfat";
|
||||||
options = [ "noexec" "noatime" "nodiratime" ];
|
options = [ "noexec" "noatime" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
"/state" = {
|
"/state" = {
|
||||||
device = "/dev/disk/by-label/zbox-data";
|
device = "/dev/disk/by-label/zbox-data";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "noatime" "nodiratime" "compress=zstd" "subvol=@state" ];
|
options = [ "noatime" "compress=zstd" "noexec" "subvol=@state" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
"/nix" = {
|
"/nix" = {
|
||||||
device = "/dev/disk/by-label/zbox-data";
|
device = "/dev/disk/by-label/zbox-data";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options = [ "noatime" "nodiratime" "compress=zstd" "subvol=@nix" ];
|
options = [ "noatime" "compress=zstd" "subvol=@nix" ];
|
||||||
};
|
};
|
||||||
|
|
||||||
"/var/log" = {
|
"/var/log" = {
|
||||||
device = "/dev/disk/by-label/zbox-data";
|
device = "/dev/disk/by-label/zbox-data";
|
||||||
fsType = "btrfs";
|
fsType = "btrfs";
|
||||||
options =
|
options = [ "noatime" "compress=zstd" "noexec" "subvol=@log" ];
|
||||||
[ "noatime" "nodiratime" "compress=zstd" "noexec" "subvol=@logs" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
"/home" = {
|
"/var/lib/containers" = {
|
||||||
device = "/dev/disk/by-label/zbox-data";
|
device = "/dev/disk/by-label/zbox-data";
|
||||||
fsType = "btrfs";
|
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;
|
driSupport = true;
|
||||||
driSupport32Bit = true;
|
driSupport32Bit = true;
|
||||||
setLdLibraryPath = true;
|
setLdLibraryPath = true;
|
||||||
|
extraPackages = with pkgs; [ nvidia-vaapi-driver vaapiVdpau ];
|
||||||
};
|
};
|
||||||
|
|
||||||
pulseaudio = {
|
nvidia = {
|
||||||
support32Bit = true;
|
package = config.boot.kernelPackages.nvidiaPackages.stable;
|
||||||
package = pkgs.pulseaudioFull;
|
modesetting.enable = true;
|
||||||
|
powerManagement.enable = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
enableRedistributableFirmware = true;
|
|
||||||
|
|
||||||
enableAllFirmware = true;
|
enableAllFirmware = true;
|
||||||
|
|
||||||
# Required with Wayland?
|
|
||||||
nvidia.modesetting.enable = true;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
|
@ -101,10 +103,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.xserver.videoDrivers = [ "nvidia" ];
|
|
||||||
|
|
||||||
nix.settings.max-jobs = lib.mkDefault 8;
|
nix.settings.max-jobs = lib.mkDefault 8;
|
||||||
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
|
|
||||||
|
|
||||||
systemd.targets = {
|
systemd.targets = {
|
||||||
sleep.enable = false;
|
sleep.enable = false;
|
||||||
|
|
|
@ -1,7 +1,16 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
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 {
|
in {
|
||||||
config = {
|
config = {
|
||||||
networking = {
|
networking = {
|
||||||
|
@ -26,7 +35,7 @@ in {
|
||||||
|
|
||||||
firewall = {
|
firewall = {
|
||||||
# Until it becomes the gateway, this is necessary
|
# Until it becomes the gateway, this is necessary
|
||||||
enable = mkForce true;
|
# enable = mkForce true;
|
||||||
allowedTCPPorts = [ 80 443 25565 config.services.murmur.port ];
|
allowedTCPPorts = [ 80 443 25565 config.services.murmur.port ];
|
||||||
allowedUDPPorts = [ 25565 34197 ];
|
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 = {
|
fudo = {
|
||||||
hosts.fimbria.external-interfaces = [ "enp1s0" ];
|
hosts.fimbria.external-interfaces = [ "enp1s0" ];
|
||||||
client.dns.external-interface = "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 = {
|
services = {
|
||||||
local-network = {
|
local-network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -77,27 +139,92 @@ in {
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
## TODO: enable when ready
|
## TODO: enable when ready
|
||||||
# nginx = {
|
nginx = {
|
||||||
# enable = true;
|
enable = true;
|
||||||
# recommendedGzipSettings = true;
|
recommendedGzipSettings = true;
|
||||||
# recommendedOptimisation = true;
|
recommendedOptimisation = true;
|
||||||
# recommendedProxySettings = true;
|
recommendedProxySettings = true;
|
||||||
|
|
||||||
# virtualHosts = {
|
virtualHosts = let
|
||||||
# "sea-home.fudo.link" = {
|
authenticatedPassthrough = { target, authPort }: {
|
||||||
# enableACME = true;
|
enableACME = true;
|
||||||
# forceSSL = true;
|
forceSSL = true;
|
||||||
# locations."/" = {
|
locations = {
|
||||||
# proxyPass = "http://home-assist.sea.fudo.org/";
|
"/" = {
|
||||||
# extraConfig = ''
|
proxyPass = target;
|
||||||
# proxy_http_version 1.1;
|
proxyWebsockets = true;
|
||||||
# proxy_set_header Upgrade $http_upgrade;
|
extraConfig = ''
|
||||||
# proxy_set_header Connection "Upgrade";
|
##############################
|
||||||
# '';
|
# 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 = {
|
murmur = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with pkgs.lib;
|
||||||
let
|
let
|
||||||
primary-ip = "208.81.3.116";
|
primary-ip = "208.81.3.116";
|
||||||
dns-ip = "208.81.3.120";
|
|
||||||
hostname = config.instance.hostname;
|
hostname = config.instance.hostname;
|
||||||
host = config.fudo.hosts."${hostname}";
|
host = config.fudo.hosts."${hostname}";
|
||||||
domainName = host.domain;
|
domainName = host.domain;
|
||||||
|
domain = config.fudo.domains."${domainName}";
|
||||||
site = config.fudo.sites."${host.site}";
|
site = config.fudo.sites."${host.site}";
|
||||||
hostFqdn = "${hostname}.${domainName}";
|
hostFqdn = "${hostname}.${domainName}";
|
||||||
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
||||||
|
|
||||||
in {
|
in {
|
||||||
config = {
|
config = {
|
||||||
networking = {
|
networking = {
|
||||||
|
@ -25,16 +27,6 @@ in {
|
||||||
prefixLength = 28;
|
prefixLength = 28;
|
||||||
}];
|
}];
|
||||||
};
|
};
|
||||||
dnsif0 = {
|
|
||||||
ipv4.addresses = [{
|
|
||||||
address = dns-ip;
|
|
||||||
prefixLength = 32;
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
firewall = {
|
|
||||||
enable = false;
|
|
||||||
interfaces.podman0.allowedUDPPorts = [ 53 ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,16 +36,24 @@ in {
|
||||||
"d /state/services 0555 - - - -"
|
"d /state/services 0555 - - - -"
|
||||||
];
|
];
|
||||||
|
|
||||||
services.fudo-mail-sync = {
|
services = {
|
||||||
path = with pkgs; [ rsync openssh ];
|
# This has been failing because NS keys aren't available yet
|
||||||
serviceConfig = {
|
"container@nameserver" = {
|
||||||
Type = "oneshot";
|
after = [ "fudo-secrets.target" ];
|
||||||
ExecStart = pkgs.writeShellScript "fudo-mail-sync.sh" ''
|
requires = [ "fudo-secrets.target" ];
|
||||||
ssh-add ~/.ssh/id_ed25519
|
};
|
||||||
rsync -avz france.fudo.org:/srv/mail/mailboxes/ /state/services/mail/mail/
|
|
||||||
chown 5025:5025 -R /state/services/mail/mail
|
fudo-mail-sync = {
|
||||||
chmod go-rwx -R /state/services/mail/mail
|
path = with pkgs; [ rsync openssh ];
|
||||||
'';
|
serviceConfig = {
|
||||||
|
Type = "oneshot";
|
||||||
|
ExecStart = pkgs.writeShellScript "fudo-mail-sync.sh" ''
|
||||||
|
ssh-add ~/.ssh/id_ed25519
|
||||||
|
rsync -avz france.fudo.org:/srv/mail/mailboxes/ /state/services/mail/mail/
|
||||||
|
chown 5025:5025 -R /state/services/mail/mail
|
||||||
|
chmod go-rwx -R /state/services/mail/mail
|
||||||
|
'';
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,6 +92,12 @@ in {
|
||||||
|
|
||||||
nsd.zones."fudo.org".outgoingInterface = "extif0";
|
nsd.zones."fudo.org".outgoingInterface = "extif0";
|
||||||
|
|
||||||
|
# Necessary because germany isn't the default yet
|
||||||
|
postgresql = {
|
||||||
|
enable = true;
|
||||||
|
state-directory = "/state/services/postgresql";
|
||||||
|
};
|
||||||
|
|
||||||
services = {
|
services = {
|
||||||
auth = {
|
auth = {
|
||||||
kerberos.state-directory = "/state/services/kerberos";
|
kerberos.state-directory = "/state/services/kerberos";
|
||||||
|
@ -99,11 +105,18 @@ in {
|
||||||
};
|
};
|
||||||
authoritative-dns.state-directory = "/state/services/dns";
|
authoritative-dns.state-directory = "/state/services/dns";
|
||||||
jabber.state-directory = "/state/services/jabber";
|
jabber.state-directory = "/state/services/jabber";
|
||||||
|
logging.loki.state-directory = "/state/services/loki";
|
||||||
metrics = {
|
metrics = {
|
||||||
prometheus.state-directory = "/state/services/prometheus";
|
prometheus.state-directory = "/state/services/prometheus";
|
||||||
grafana.state-directory = "/state/services/grafana";
|
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}" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -38,6 +38,15 @@ in {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fonts.fontconfig = {
|
||||||
|
hinting = {
|
||||||
|
enable = true;
|
||||||
|
style = "hintfull";
|
||||||
|
};
|
||||||
|
subpixel.lcdfilter = "default";
|
||||||
|
antialias = true;
|
||||||
|
};
|
||||||
|
|
||||||
environment.etc = {
|
environment.etc = {
|
||||||
nixos.source = "/etc/nixos-live";
|
nixos.source = "/etc/nixos-live";
|
||||||
NIXOS.source = "${stateDir}/etc/NIXOS";
|
NIXOS.source = "${stateDir}/etc/NIXOS";
|
||||||
|
|
|
@ -89,6 +89,7 @@ in {
|
||||||
enable = true;
|
enable = true;
|
||||||
dockerSocket.enable = true;
|
dockerSocket.enable = true;
|
||||||
autoPrune.enable = true;
|
autoPrune.enable = true;
|
||||||
|
defaultNetwork.settings.dns_enabled = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,19 +155,6 @@ in {
|
||||||
external-interface = "extif0";
|
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 = {
|
secure-dns-proxy = {
|
||||||
enable = true;
|
enable = true;
|
||||||
upstream-dns =
|
upstream-dns =
|
||||||
|
|
|
@ -10,6 +10,13 @@ let
|
||||||
domain-name = host-config.domain;
|
domain-name = host-config.domain;
|
||||||
domain = config.fudo.domains.${domain-name};
|
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;
|
# dns-proxy-port = 5335;
|
||||||
|
|
||||||
in {
|
in {
|
||||||
|
@ -84,6 +91,31 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
fudo = {
|
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" ];
|
hosts.limina.external-interfaces = [ "enp1s0" ];
|
||||||
|
|
||||||
client.dns.external-interface = "enp1s0";
|
client.dns.external-interface = "enp1s0";
|
||||||
|
@ -139,6 +171,34 @@ in {
|
||||||
|
|
||||||
systemd.services.nginx.requires = [ "bind.service" ];
|
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 = {
|
services = {
|
||||||
nginx = {
|
nginx = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
@ -146,7 +206,62 @@ in {
|
||||||
recommendedOptimisation = true;
|
recommendedOptimisation = true;
|
||||||
recommendedProxySettings = 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" = {
|
"sea-home.fudo.link" = {
|
||||||
enableACME = true;
|
enableACME = true;
|
||||||
forceSSL = 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;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -91,16 +91,6 @@ in {
|
||||||
host-secrets = config.fudo.secrets.host-secrets.${hostname};
|
host-secrets = config.fudo.secrets.host-secrets.${hostname};
|
||||||
in {
|
in {
|
||||||
secrets.host-secrets.${hostname} = {
|
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 = {
|
pricebot-auth-token = {
|
||||||
source-file =
|
source-file =
|
||||||
config.fudo.secrets.files.service-secrets.nostromo."pricebot-auth.token";
|
config.fudo.secrets.files.service-secrets.nostromo."pricebot-auth.token";
|
||||||
|
@ -127,10 +117,6 @@ in {
|
||||||
metrics.grafana = {
|
metrics.grafana = {
|
||||||
state-directory = "/state/services/grafana";
|
state-directory = "/state/services/grafana";
|
||||||
smtp.hostname = "mail.fudo.org";
|
smtp.hostname = "mail.fudo.org";
|
||||||
# database = {
|
|
||||||
# user = "grafana";
|
|
||||||
# password-file = host-secrets.grafana-database-password.target-file;
|
|
||||||
# };
|
|
||||||
ldap.base-dn = "dc=fudo,dc=org";
|
ldap.base-dn = "dc=fudo,dc=org";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,16 +137,26 @@ in {
|
||||||
state-directory = "/state/services/postgresql";
|
state-directory = "/state/services/postgresql";
|
||||||
|
|
||||||
databases.grafana.users = config.instance.local-admins;
|
databases.grafana.users = config.instance.local-admins;
|
||||||
|
};
|
||||||
|
|
||||||
# users.grafana = {
|
services.gitea-container = {
|
||||||
# password-file = host-secrets.postgres-grafana-password.target-file;
|
enable = true;
|
||||||
# databases.grafana = {
|
site-name = "Seattle Fudo Git";
|
||||||
# entity-access = {
|
hostname = "git.fudo.org";
|
||||||
# "ALL TABLES IN SCHEMA public" = "ALL PRIVILEGES";
|
state-directory = "/state/services/gitea";
|
||||||
# "ALL SEQUENCES IN SCHEMA public" = "ALL PRIVILEGES";
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ let
|
||||||
primary-ip = "10.0.0.3";
|
primary-ip = "10.0.0.3";
|
||||||
state-dir = "/state";
|
state-dir = "/state";
|
||||||
zigbee2mqtt-statedir = "${state-dir}/services/zigbee2mqtt";
|
zigbee2mqtt-statedir = "${state-dir}/services/zigbee2mqtt";
|
||||||
home-assistant-port = 8123;
|
|
||||||
|
|
||||||
zigbee2mqtt-user = config.systemd.services.zigbee2mqtt.serviceConfig.User;
|
zigbee2mqtt-user = config.systemd.services.zigbee2mqtt.serviceConfig.User;
|
||||||
|
|
||||||
|
@ -26,20 +25,20 @@ let
|
||||||
pkgs.lib.passwd.stablerandom-passwd-file "node-red-mqtt-passwd"
|
pkgs.lib.passwd.stablerandom-passwd-file "node-red-mqtt-passwd"
|
||||||
config.instance.build-seed;
|
config.instance.build-seed;
|
||||||
|
|
||||||
|
homeAssistantPort = 8123;
|
||||||
teslaMatePort = 4400;
|
teslaMatePort = 4400;
|
||||||
teslaGraphPort = 4401;
|
teslaGraphPort = 4401;
|
||||||
|
|
||||||
nodeRedPort = 1880;
|
nodeRedPort = 1880;
|
||||||
|
|
||||||
host-secrets = config.fudo.secrets.host-secrets.${hostname};
|
host-secrets = config.fudo.secrets.host-secrets."${hostname}";
|
||||||
host-passwds = config.fudo.secrets.files.service-passwords.${hostname};
|
host-passwds = config.fudo.secrets.files.service-passwords."${hostname}";
|
||||||
|
|
||||||
in {
|
in {
|
||||||
imports = [
|
imports = [
|
||||||
(import ./wormhole0/home-assistant.nix {
|
(import ./wormhole0/home-assistant.nix {
|
||||||
homeAssistantImage = "ghcr.io/home-assistant/home-assistant:2023.9";
|
homeAssistantImage = "ghcr.io/home-assistant/home-assistant:2023.11.3";
|
||||||
nodeRedImage = "nodered/node-red:3.1.0-14";
|
nodeRedImage = "nodered/node-red:3.1.1";
|
||||||
inherit nodeRedPort;
|
inherit nodeRedPort homeAssistantPort;
|
||||||
stateDirectory = "/state/services/arion-home-assistant";
|
stateDirectory = "/state/services/arion-home-assistant";
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
@ -158,10 +157,9 @@ in {
|
||||||
recommendedGzipSettings = true;
|
recommendedGzipSettings = true;
|
||||||
|
|
||||||
virtualHosts = {
|
virtualHosts = {
|
||||||
|
|
||||||
"home-assist.sea.fudo.org" = {
|
"home-assist.sea.fudo.org" = {
|
||||||
locations."/" = {
|
locations."/" = {
|
||||||
proxyPass = "http://localhost:${toString home-assistant-port}";
|
proxyPass = "http://localhost:${toString homeAssistantPort}";
|
||||||
proxyWebsockets = true;
|
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 = {
|
zigbee2mqtt = {
|
||||||
enable = true;
|
enable = true;
|
||||||
dataDir = zigbee2mqtt-statedir;
|
dataDir = zigbee2mqtt-statedir;
|
||||||
|
@ -260,6 +224,7 @@ in {
|
||||||
user = "tesla-mate";
|
user = "tesla-mate";
|
||||||
password = readFile teslaMateMqttPasswdFile;
|
password = readFile teslaMateMqttPasswdFile;
|
||||||
};
|
};
|
||||||
|
images.tesla-mate = "teslamate/teslamate:1.28.2";
|
||||||
port = teslaMatePort;
|
port = teslaMatePort;
|
||||||
grafana-port = teslaGraphPort;
|
grafana-port = teslaGraphPort;
|
||||||
state-directory = "/state/services/tesla-mate";
|
state-directory = "/state/services/tesla-mate";
|
||||||
|
@ -280,20 +245,6 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
arion.backend = "podman-socket";
|
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 = ''
|
security.sudo.extraConfig = ''
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
{ homeAssistantImage, nodeRedImage, nodeRedPort ? 1880, stateDirectory, ... }:
|
{ homeAssistantImage, nodeRedImage, nodeRedPort, homeAssistantPort
|
||||||
|
, stateDirectory, ... }:
|
||||||
|
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@ in {
|
||||||
"${stateDirectory}/config:/config"
|
"${stateDirectory}/config:/config"
|
||||||
"/etc/localtime:/etc/localtime:ro"
|
"/etc/localtime:/etc/localtime:ro"
|
||||||
];
|
];
|
||||||
|
ports = [ "${toString homeAssistantPort}:8123" ];
|
||||||
user = "${toString homeAssistantUid}:${toString homeAssistantUid}";
|
user = "${toString homeAssistantUid}:${toString homeAssistantUid}";
|
||||||
network_mode = "host";
|
network_mode = "host";
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,51 +1,95 @@
|
||||||
{ config, lib, pkgs, ... }:
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
with lib;
|
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 {
|
in {
|
||||||
config = {
|
config = {
|
||||||
fudo = {
|
|
||||||
slynk.enable = true;
|
|
||||||
wallfly.location = "family_room";
|
|
||||||
};
|
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
interfaces.intif0.useDHCP = true;
|
useDHCP = false;
|
||||||
|
interfaces.intif0 = {
|
||||||
|
ipv4.addresses = [{
|
||||||
|
address = primaryIp;
|
||||||
|
prefixLength = 22;
|
||||||
|
}];
|
||||||
|
};
|
||||||
firewall.enable = false;
|
firewall.enable = false;
|
||||||
};
|
defaultGateway = {
|
||||||
|
address = "10.0.0.1";
|
||||||
i18n.inputMethod = {
|
interface = "intif0";
|
||||||
#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" ];
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
hardware = {
|
boot = let
|
||||||
bluetooth = {
|
gasket =
|
||||||
|
config.boot.kernelPackages.callPackage ./zbox/pkgs/gasket.nix { };
|
||||||
|
in {
|
||||||
|
extraModulePackages = [ gasket ];
|
||||||
|
kernelModules = [ "gasket" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
users.groups.plugdev = { };
|
||||||
|
|
||||||
|
virtualisation = {
|
||||||
|
podman = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.bluezFull;
|
dockerSocket.enable = true;
|
||||||
|
autoPrune.enable = true;
|
||||||
|
enableNvidia = true;
|
||||||
};
|
};
|
||||||
xpadneo.enable = true;
|
|
||||||
|
arion.backend = "podman-socket";
|
||||||
};
|
};
|
||||||
|
|
||||||
services.xserver = {
|
services = {
|
||||||
layout = "us";
|
frigateContainer = {
|
||||||
xkbVariant = mkForce "";
|
state-directory = "/state/services/frigate";
|
||||||
xkbOptions = mkForce "";
|
# 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
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
}
|
|
@ -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 {
|
|
@ -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
|
||||||
|
'';
|
||||||
|
}
|
|
@ -6,51 +6,133 @@ let
|
||||||
|
|
||||||
cfg = config.fudo.services.authoritative-dns;
|
cfg = config.fudo.services.authoritative-dns;
|
||||||
|
|
||||||
|
inherit (pkgs.lib)
|
||||||
|
getHostIps getSiteGatewayV4 getSiteV4PrefixLength getSiteV6PrefixLength;
|
||||||
|
|
||||||
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
hostSecrets = config.fudo.secrets.host-secrets."${hostname}";
|
||||||
|
|
||||||
domainName = config.instance.local-domain;
|
domainName = config.instance.local-domain;
|
||||||
|
|
||||||
|
primaryZone = config.fudo.domains."${domainName}".zone;
|
||||||
|
|
||||||
|
siteName = config.instance.local-site;
|
||||||
|
|
||||||
zoneKeySecret = zone: "${zone}-ksk";
|
zoneKeySecret = zone: "${zone}-ksk";
|
||||||
|
|
||||||
networkHostOpts = {
|
containerModule = { pkgs, config, ... }: {
|
||||||
options = with types; {
|
config = mkIf (cfg.enable && !isNull cfg.container) {
|
||||||
hostname = mkOption {
|
containers.nameserver = let
|
||||||
type = str;
|
securedZones =
|
||||||
description = "Hostname.";
|
filterAttrs (_: zoneOpts: !isNull zoneOpts.ksk) cfg.zones;
|
||||||
};
|
in {
|
||||||
ipv4-address = mkOption {
|
autoStart = true;
|
||||||
type = nullOr str;
|
additionalCapabilities = [ "CAP_NET_ADMIN" ];
|
||||||
description = "The V4 IP of a given host, if any.";
|
macvlans = [ cfg.container.interface ];
|
||||||
default = null;
|
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;
|
||||||
|
|
||||||
ipv6-address = mkOption {
|
identity = "${nameserverHost}.${primaryZone}";
|
||||||
type = nullOr str;
|
|
||||||
description = "The V6 IP of a given host, if any.";
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
mac-address = mkOption {
|
listen-ips = getHostIps nameserverHost;
|
||||||
type = nullOr str;
|
|
||||||
description =
|
|
||||||
"The MAC address of a given host, if desired for IP reservation.";
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
description = mkOption {
|
state-directory = "/var/lib/nsd";
|
||||||
type = nullOr str;
|
|
||||||
description = "Description of the host.";
|
|
||||||
default = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
sshfp-records = mkOption {
|
timestamp = toString config.instance.build-timestamp;
|
||||||
type = listOf str;
|
|
||||||
description = "List of SSHFP records for this host.";
|
ip-host-map = cfg.ip-host-map;
|
||||||
default = [ ];
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
hostModule = { config, ... }: {
|
||||||
|
config.services.authoritative-dns =
|
||||||
|
mkIf (cfg.enable && isNull cfg.container) {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
identity = "${hostname}.${primaryZone}";
|
||||||
|
|
||||||
|
listen-ips = getHostIps hostname;
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
zoneOpts = { name, ... }:
|
zoneOpts = { name, ... }:
|
||||||
let zoneName = name;
|
let zoneName = name;
|
||||||
in {
|
in {
|
||||||
|
@ -62,7 +144,7 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
default-host = mkOption {
|
default-host = mkOption {
|
||||||
type = nullOr (submodule networkHostOpts);
|
type = nullOr (submodule pkgs.lib.fudo-types.networkHost);
|
||||||
description =
|
description =
|
||||||
"Host which will respond to requests for the base domain.";
|
"Host which will respond to requests for the base domain.";
|
||||||
default = null;
|
default = null;
|
||||||
|
@ -123,6 +205,27 @@ in {
|
||||||
options.fudo.services.authoritative-dns = with types; {
|
options.fudo.services.authoritative-dns = with types; {
|
||||||
enable = mkEnableOption "Enable Authoritative DNS server.";
|
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 =
|
enable-notifications =
|
||||||
mkEnableOption "Enable notifications to secondary servers.";
|
mkEnableOption "Enable notifications to secondary servers.";
|
||||||
|
|
||||||
|
@ -152,7 +255,7 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
external = mkOption {
|
external = mkOption {
|
||||||
type = listOf (submodule networkHostOpts);
|
type = listOf (submodule pkgs.lib.fudo-types.networkHost);
|
||||||
description = "List of external secondary nameserver attributes.";
|
description = "List of external secondary nameserver attributes.";
|
||||||
default = [ ];
|
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 = {
|
fudo = {
|
||||||
secrets.host-secrets."${hostname}" = mkIf cfg.enable (mapAttrs'
|
secrets.host-secrets."${hostname}" = mapAttrs' (zone: zoneCfg:
|
||||||
(zone: zoneCfg:
|
nameValuePair (zoneKeySecret zone) {
|
||||||
nameValuePair (zoneKeySecret zone) {
|
source-file = zoneCfg.ksk.private-key;
|
||||||
source-file = zoneCfg.ksk.private-key;
|
target-file = "/run/nsd/${baseNameOf zoneCfg.ksk.private-key}";
|
||||||
target-file = "/run/nsd/${baseNameOf zoneCfg.ksk.private-key}";
|
user = config.fudo.nsd.user;
|
||||||
user = config.fudo.nsd.user;
|
}) (filterAttrs (_: zoneCfg: zoneCfg.ksk != null) cfg.zones);
|
||||||
}) (filterAttrs (_: zoneCfg: zoneCfg.ksk != null) cfg.zones));
|
|
||||||
|
|
||||||
zones = mapAttrs (zone-name: zoneCfg:
|
zones = mapAttrs (zone-name: zoneCfg:
|
||||||
let
|
let
|
||||||
|
@ -256,38 +367,5 @@ in {
|
||||||
];
|
];
|
||||||
}) cfg.zones;
|
}) 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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;" ]));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -134,11 +134,12 @@ in {
|
||||||
dns = {
|
dns = {
|
||||||
listen-ips = [ "127.0.0.1" ];
|
listen-ips = [ "127.0.0.1" ];
|
||||||
listen-port = agp.dns-listen-port;
|
listen-port = agp.dns-listen-port;
|
||||||
|
reverse-dns = [ (host-ipv4 gateway-host) ];
|
||||||
};
|
};
|
||||||
local-domain-name = domain-name;
|
local-domain-name = domain-name;
|
||||||
};
|
};
|
||||||
|
|
||||||
zones.${zone-name} = {
|
zones."${zone-name}" = {
|
||||||
aliases = {
|
aliases = {
|
||||||
"${agp.http-host-alias}" = mkIf (agp.enable) (fqdn gateway-host);
|
"${agp.http-host-alias}" = mkIf (agp.enable) (fqdn gateway-host);
|
||||||
ns = (fqdn nameserver-host);
|
ns = (fqdn nameserver-host);
|
||||||
|
|
|
@ -38,8 +38,8 @@ in {
|
||||||
|
|
||||||
config = mkIf postgresEnabled {
|
config = mkIf postgresEnabled {
|
||||||
fudo = {
|
fudo = {
|
||||||
acme.host-domains.${hostname} = mkIf (publicNetwork && isPostgresHost) {
|
acme.host-domains."${hostname}" = mkIf (publicNetwork && isPostgresHost) {
|
||||||
${postgresql-hostname}.local-copies = {
|
"${postgresql-hostname}".local-copies = {
|
||||||
postgresql = {
|
postgresql = {
|
||||||
user = postgresUser;
|
user = postgresUser;
|
||||||
dependent-services = [ "postgresql.service" ];
|
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) {
|
mkIf (cfg.keytab != null) {
|
||||||
source-file = cfg.keytab;
|
source-file = cfg.keytab;
|
||||||
target-file = "/run/postgresql/postgres.keytab";
|
target-file = "/run/postgresql/postgres.keytab";
|
||||||
user = postgresUser;
|
user = postgresUser;
|
||||||
};
|
};
|
||||||
|
|
||||||
zones.${zone-name}.aliases.postgresql =
|
zones."${zone-name}".aliases.postgresql =
|
||||||
"${domain.postgresql-server}.${domain-name}.";
|
pkgs.lib.getHostFqdn domain.postgresql-server;
|
||||||
|
|
||||||
postgresql = mkIf isPostgresHost (let
|
postgresql = mkIf isPostgresHost (let
|
||||||
ssl-config = optionalAttrs publicNetwork (let
|
ssl-config = optionalAttrs publicNetwork (let
|
||||||
|
|
|
@ -38,6 +38,8 @@ in {
|
||||||
};
|
};
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
|
systemd.services.snooper.after = mkIf isSnooper [ "fudo-secrets.target" ];
|
||||||
|
|
||||||
fudo = {
|
fudo = {
|
||||||
secrets.host-secrets."${hostname}" = {
|
secrets.host-secrets."${hostname}" = {
|
||||||
snooper-passwd = mkIf isSnooper {
|
snooper-passwd = mkIf isSnooper {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
./service/chute.nix
|
./service/chute.nix
|
||||||
./service/dns.nix
|
./service/dns.nix
|
||||||
./service/fudo-auth.nix
|
./service/fudo-auth.nix
|
||||||
|
./service/gitea-container.nix
|
||||||
./service/jabber.nix
|
./service/jabber.nix
|
||||||
./service/lemmy.nix
|
./service/lemmy.nix
|
||||||
./service/local-network.nix
|
./service/local-network.nix
|
||||||
|
|
|
@ -633,6 +633,12 @@ with lib; {
|
||||||
ldap-hashed-passwd = "{SSHA}mok5LrQtJ4pny2QTaN3sMmOZx6X0eg5R";
|
ldap-hashed-passwd = "{SSHA}mok5LrQtJ4pny2QTaN3sMmOZx6X0eg5R";
|
||||||
email = "jasper@selby.ca";
|
email = "jasper@selby.ca";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
authentik = {
|
||||||
|
uid = 10117;
|
||||||
|
primary-group = "fudo";
|
||||||
|
common-name = "Fudo Authentik";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
groupDomainMap = {
|
groupDomainMap = {
|
||||||
|
|
621
flake.lock
621
flake.lock
File diff suppressed because it is too large
Load Diff
13
flake.nix
13
flake.nix
|
@ -131,6 +131,11 @@
|
||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
frigate-container = {
|
||||||
|
url = "git+https://git.fudo.org/fudo-public/frigate-container.git";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
textfiles = {
|
textfiles = {
|
||||||
url = "git+https://git.informis.land/informis/textfiles.git";
|
url = "git+https://git.informis.land/informis/textfiles.git";
|
||||||
flake = false;
|
flake = false;
|
||||||
|
@ -142,7 +147,7 @@
|
||||||
, wallfly, objectifier, nexus, suanni, snooper, tattler, lemmy-docker
|
, wallfly, objectifier, nexus, suanni, snooper, tattler, lemmy-docker
|
||||||
, tesla-mate-container, mastodon-container, authentik-container
|
, tesla-mate-container, mastodon-container, authentik-container
|
||||||
, nextcloud-container, textfiles, matrix-module, mail-server
|
, nextcloud-container, textfiles, matrix-module, mail-server
|
||||||
, authoritative-dns, ... }@inputs:
|
, authoritative-dns, frigate-container, ... }@inputs:
|
||||||
with nixpkgs.lib;
|
with nixpkgs.lib;
|
||||||
let
|
let
|
||||||
fudo-nixos-hosts = filterAttrs (hostname: hostOpts: hostOpts.nixos-system)
|
fudo-nixos-hosts = filterAttrs (hostname: hostOpts: hostOpts.nixos-system)
|
||||||
|
@ -167,10 +172,11 @@
|
||||||
"openssl-1.1.1w"
|
"openssl-1.1.1w"
|
||||||
"python3.10-requests-2.28.2"
|
"python3.10-requests-2.28.2"
|
||||||
"python3.10-cryptography-40.0.1"
|
"python3.10-cryptography-40.0.1"
|
||||||
|
"gitea-1.19.4"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
overlays = [
|
overlays = [
|
||||||
fudo-lib.overlay
|
fudo-lib.overlays.default
|
||||||
fudo-pkgs.overlays.default
|
fudo-pkgs.overlays.default
|
||||||
fudo-secrets.overlays.default
|
fudo-secrets.overlays.default
|
||||||
fudo-entities.overlays.default
|
fudo-entities.overlays.default
|
||||||
|
@ -211,7 +217,7 @@
|
||||||
imports = [
|
imports = [
|
||||||
fudo-home.nixosModules.default
|
fudo-home.nixosModules.default
|
||||||
fudo-secrets.nixosModules.default
|
fudo-secrets.nixosModules.default
|
||||||
fudo-lib.nixosModule
|
fudo-lib.nixosModules.default
|
||||||
fudo-entities.nixosModule
|
fudo-entities.nixosModule
|
||||||
pricebot.nixosModules.default
|
pricebot.nixosModules.default
|
||||||
wallfly.nixosModule
|
wallfly.nixosModule
|
||||||
|
@ -227,6 +233,7 @@
|
||||||
matrix-module.nixosModules.default
|
matrix-module.nixosModules.default
|
||||||
mail-server.nixosModules.default
|
mail-server.nixosModules.default
|
||||||
authoritative-dns.nixosModules.default
|
authoritative-dns.nixosModules.default
|
||||||
|
frigate-container.nixosModules.default
|
||||||
|
|
||||||
nexus.nixosModules.nexus-client
|
nexus.nixosModules.nexus-client
|
||||||
nexus.nixosModules.nexus-server
|
nexus.nixosModules.nexus-server
|
||||||
|
|
|
@ -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; }
|
Loading…
Reference in New Issue