Big commit
This commit is contained in:
parent
44589ddc77
commit
0027566304
|
@ -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,63 +86,67 @@ in {
|
|||
};
|
||||
};
|
||||
|
||||
fudo.services = {
|
||||
jabber = {
|
||||
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" ];
|
||||
fudo = {
|
||||
services = {
|
||||
jabber = {
|
||||
domain = "jabber.fudo.org";
|
||||
ldap.servers =
|
||||
map (host: "${host}.${localDomain}") domain.ldap-servers;
|
||||
};
|
||||
|
||||
ip-host-map = let
|
||||
networkHosts = getDomainHosts "fudo.org";
|
||||
ipHostPairs =
|
||||
map (host: nameValuePair (getHostIpv4 host) (getHostFqdn host))
|
||||
networkHosts;
|
||||
in listToAttrs ipHostPairs;
|
||||
authoritative-dns = {
|
||||
enable = hostname == primaryNameserver;
|
||||
|
||||
zones = let
|
||||
defaultDeets = {
|
||||
inherit (config.fudo.zones."fudo.org".hosts."${defaultHost}")
|
||||
ipv4-address ipv6-address sshfp-records;
|
||||
description = "fudo.org";
|
||||
container = {
|
||||
hostname = "nameserver";
|
||||
interface = "enp5s0f0";
|
||||
};
|
||||
in {
|
||||
"fudo.org" = {
|
||||
default-host = defaultDeets;
|
||||
ksk = config.fudo.secrets.files.dns.key-signing-keys."fudo.org";
|
||||
reverse-zones = [ "208.81.1.128/28" "208.81.3.112/28" ];
|
||||
|
||||
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" ];
|
||||
};
|
||||
"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";
|
||||
|
||||
ip-host-map = let
|
||||
networkHosts = getDomainHosts "fudo.org";
|
||||
ipHostPairs =
|
||||
map (host: nameValuePair (getHostIpv4 host) (getHostFqdn host))
|
||||
networkHosts;
|
||||
in listToAttrs ipHostPairs;
|
||||
|
||||
zones = let
|
||||
defaultDeets = {
|
||||
inherit (config.fudo.zones."fudo.org".hosts."${defaultHost}")
|
||||
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" = 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}";
|
||||
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";
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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}" ];
|
||||
|
|
|
@ -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, ... }:
|
||||
|
||||
{}
|
||||
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 {
|
||||
config = {
|
||||
fudo = {
|
||||
zones."sea.fudo.org" = { aliases.frigate = "zbox"; };
|
||||
|
||||
domains."sea.fudo.org" = {
|
||||
local-networks = fudo.local-networks;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,16 +36,24 @@ in {
|
|||
"d /state/services 0555 - - - -"
|
||||
];
|
||||
|
||||
services.fudo-mail-sync = {
|
||||
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
|
||||
'';
|
||||
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";
|
||||
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";
|
||||
|
||||
# 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}" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -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 = ''
|
||||
|
|
|
@ -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";
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
dockerSocket.enable = true;
|
||||
autoPrune.enable = true;
|
||||
enableNvidia = true;
|
||||
};
|
||||
xpadneo.enable = true;
|
||||
|
||||
arion.backend = "podman-socket";
|
||||
};
|
||||
|
||||
services.xserver = {
|
||||
layout = "us";
|
||||
xkbVariant = mkForce "";
|
||||
xkbOptions = mkForce "";
|
||||
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
|
||||
'';
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
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.";
|
||||
};
|
||||
ipv4-address = mkOption {
|
||||
type = nullOr str;
|
||||
description = "The V4 IP of a given host, if any.";
|
||||
default = null;
|
||||
};
|
||||
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;
|
||||
|
||||
ipv6-address = mkOption {
|
||||
type = nullOr str;
|
||||
description = "The V6 IP of a given host, if any.";
|
||||
default = null;
|
||||
};
|
||||
identity = "${nameserverHost}.${primaryZone}";
|
||||
|
||||
mac-address = mkOption {
|
||||
type = nullOr str;
|
||||
description =
|
||||
"The MAC address of a given host, if desired for IP reservation.";
|
||||
default = null;
|
||||
};
|
||||
listen-ips = getHostIps nameserverHost;
|
||||
|
||||
description = mkOption {
|
||||
type = nullOr str;
|
||||
description = "Description of the host.";
|
||||
default = null;
|
||||
};
|
||||
state-directory = "/var/lib/nsd";
|
||||
|
||||
sshfp-records = mkOption {
|
||||
type = listOf str;
|
||||
description = "List of SSHFP records for this host.";
|
||||
default = [ ];
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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, ... }:
|
||||
let zoneName = name;
|
||||
in {
|
||||
|
@ -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:
|
||||
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));
|
||||
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);
|
||||
|
||||
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;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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 = {
|
||||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 = {
|
||||
|
|
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";
|
||||
};
|
||||
|
||||
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
|
||||
|
|
|
@ -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