Still very broken...moving to start testing

This commit is contained in:
nostoromo root 2021-02-23 12:58:29 -08:00
parent d34fc495b4
commit 372cf5fc6a
91 changed files with 3535 additions and 488 deletions

View File

@ -2,12 +2,12 @@
let
helpers = pkgs.writeText "bash.helpers"
(builtins.readFile ./static/bash/bash.helpers);
(builtins.readFile ../static/bash/bash.helpers);
colors =
pkgs.writeText "bash.colors" (builtins.readFile ./static/bash/bash.colors);
pkgs.writeText "bash.colors" (builtins.readFile ../static/bash/bash.colors);
env = pkgs.writeText "bash.env" (builtins.readFile ./static/bash/bash.env);
env = pkgs.writeText "bash.env" (builtins.readFile ../static/bash/bash.env);
in {
config.programs.bash = {

View File

@ -1,38 +1,15 @@
{ lib, config, pkgs, ... }:
{ config, lib, pkgs, ... }:
with lib; {
imports = [
./fudo/acme-for-hostname.nix
./fudo/authentication.nix
./fudo/backplane
./fudo/chat.nix
./fudo/client/dns.nix
./fudo/common.nix
./fudo/dns.nix
./fudo/garbage-collector.nix
./fudo/git.nix
./fudo/grafana.nix
./fudo/ipfs.nix
./fudo/kdc.nix
./fudo/ldap.nix
./fudo/local-network.nix
./fudo/mail.nix
./fudo/mail-container.nix
./fudo/minecraft-server.nix
./fudo/netinfo-email.nix
./fudo/node-exporter.nix
./fudo/password.nix
./fudo/postgres.nix
./fudo/prometheus.nix
./fudo/secure-dns-proxy.nix
./fudo/slynk.nix
./fudo/system.nix
./fudo/vpn.nix
./fudo/webmail.nix
./informis/cl-gemini.nix
../fudo/profiles
../fudo/sites
];
{
config = {
imports = [
./bash.nix
./domains.nix
./groups.nix
./hosts.nix
./sites.nix
./users.nix
./wireless-networks.nix
];
};
}

56
config/domains.nix Normal file
View File

@ -0,0 +1,56 @@
{ config, lib, pkgs, ... }:
{
config.fudo.domains = {
fudo.org = {
local-networks = [ "208.81.1.128/28" "208.81.3.112/28" ];
local-users = [ "niten" "reaper" ];
admin-users = [ "niten" "reaper" ];
admin-email = "admin@fudo.org";
gssapi-realm = "FUDO.ORG";
};
sea.fudo.org = {
local-networks = [ "10.0.0.0/24" ];
local-users = [ "niten" "reaper" "xiaoxuan" "ken" ];
admin-users = [ "niten" ];
admin-email = "niten@fudo.org";
gssapi-realm = "FUDO.ORG";
local-dns = import ./networks/sea.fudo.org.nix { };
};
rus.selby.ca = {
local-networks = [ "10.0.0.0/24" ];
local-users = [
"niten"
"ken"
"helen"
"xiaoxuan"
"laura"
"vee"
"kris"
"jeramy"
"jess"
"andrew"
];
local-admins = [ "niten" ];
admin-email = "niten@fudo.org";
gssapi-realm = "FUDO.ORG";
local-dns = import ./networks/rus.selby.ca.nix { };
};
informis.land = {
local-networks = [ ];
local-users = [ "niten" "viator" ];
admin-users = [ "niten" ];
admin-email = "viator@informis.land";
gssapi-realm = "INFORMIS.LAND";
};
};
}

View File

@ -1,58 +0,0 @@
# General Fudo config, shared across packages
{ config, lib, pkgs, ... }:
with lib;
{
options.fudo.common = {
local-networks = mkOption {
type = with types; listOf str;
description = ''
A list of networks to consider 'local'. Used by various services to
limit access to the external world.
'';
default = [];
};
domain = mkOption {
type = types.str;
description = ''
Domain of the local network.
'';
};
profile = mkOption {
type = with types; nullOr str;
example = "desktop";
description = ''
The profile to use for this host. This will do some profile-dependent
configuration, for example removing X-libs from servers and adding UI
packages to desktops.
'';
default = null;
};
site = mkOption {
type = with types; nullOr str;
example = "seattle";
description = ''
The site at which this host is located. This will do some site-dependent
configuration.
'';
default = null;
};
www-root = mkOption {
type = types.path;
description = "Path at which to store www files for serving.";
example = /var/www;
};
admin-email = mkOption {
type = types.str;
description = "Email for administrator of this system.";
default = "admin@fudo.org";
};
enable-gui = mkEnableOption "Install desktop GUI software.";
};
}

70
config/hardware/clunk.nix Normal file
View File

@ -0,0 +1,70 @@
{ config, lib, pkgs, ... }:
{
imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];
boot = {
initrd = {
availableKernelModules =
[ "ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod" ];
kernelModules = [ ];
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
kernelPackages = pkgs.linuxPackages_latest;
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
# Limit tmpfs size of /run
runSize = "50%";
};
fileSystems = {
"/boot" = {
device = "/dev/disk/by-label/boot";
fsType = "vfat";
};
"/" = {
device = "/dev/disk/by-label/root";
fsType = "ext4";
};
};
swapDevices = [{ device = "/dev/disk/by-label/swap"; }];
nix.maxJobs = lib.mkDefault 4;
powerManagement.cpuFreqGovernor = lib.mkDefault "powersave";
hardware.bluetooth.enable = false;
network = {
macvlans = {
intif0 = {
interface = "enp2s0";
mode = "bridge";
};
extif0 = {
interface = "enp1s0";
mode = "bridge";
};
};
interfaces = {
intif0 = {
# output of: echo clunk-intif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:44:d1:eb:c3:6b";
};
extif0 = {
# output of: echo clunk-extif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:5e:ff:e4:83:e4";
};
};
};
}

View File

@ -0,0 +1,85 @@
{ config, lib, pkgs, ... }:
{
imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];
boot = {
initrd = {
availableKernelModules =
[ "uhci_hcd" "ehci_pci" "ata_piix" "ahci" "floppy" "sd_mod" "sr_mod" ];
kernelModules = [ "dm-snapshot" ];
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
kernelPackages = pkgs.linuxPackages_latest;
loader.grub = {
enable = true;
version = 2;
device = "/dev/sda";
};
};
boot.initrd.availableKernelModules =
[ "uhci_hcd" "ehci_pci" "ata_piix" "ahci" "floppy" "sd_mod" "sr_mod" ];
boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
fileSystems = {
"/boot" = {
device = "/dev/disk/by-label/france-boot";
fsType = "ext4";
};
"/" = {
device = "/dev/disk/by-label/france-root";
fsType = "ext4";
};
"/var/lib/lxd/storage-pools/pool0" = {
device = "/dev/disk/by-label/pool0";
fsType = "btrfs";
label = "pool0";
};
"/var/lib/lxd/storage-pools/pool1" = {
device = "/dev/france-user/fudo-user";
fsType = "btrfs";
label = "pool1";
};
};
swapDevices = [{ device = "/dev/disk/by-label/france-swap"; }];
nix.maxJobs = lib.mkDefault 24;
hardware.bluetooth.enable = false;
network = {
macvlans = {
intif0 = {
interface = "enp4s0f1";
mode = "bridge";
};
extif0 = {
interface = "enp4s0f0";
mode = "bridge";
};
};
interfaces = {
intif0 = {
# output of: echo france-intif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:44:d1:eb:c3:6b";
};
extif0 = {
# output of: echo france-extif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:5e:ff:e4:83:e4";
};
};
};
}

View File

@ -0,0 +1,65 @@
{ config, lib, pkgs, ... }:
{
imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];
boot = {
initrd = {
availableKernelModules = [
"uhci_hcd"
"ehci_pci"
"ata_piix"
"hpsa"
"usb_storage"
"usbhid"
"sd_mod"
"sr_mod"
];
kernelModules = [ ];
};
kernelModules = [ "kvm-amd" ];
externalModulePackages = [ ];
kernelPackages = pkgs.linuxPackages_latest;
loader.grub = {
enable = true;
version = 2;
device = "/dev/disk/by-label/nixos-root";
};
};
fileSystems = {
"/" = {
device = "/dev/disk/by-label/nixos-root";
fsType = "btrfs";
};
"/boot" = {
device = "/dev/disk/by-label/nixos-boot";
fsType = "ext4";
};
};
swapDevices = [{ device = "/dev/disk/by-label/nixos-swap"; }];
nix.maxJobs = lib.mkDefault 12;
hardware.bluetooth.enable = false;
networking = {
macvlans = {
intif0 = {
interface = "enp3s0f1";
mode = "bridge";
};
};
interfaces = {
intif0 = {
# output of: echo lambda-intif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:f5:fe:8c:22:fe";
};
};
};
}

View File

@ -0,0 +1,68 @@
{ config, lib, pkgs, ... }:
{
imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];
boot = {
initrd = {
availableKernelModules = [
"ahci"
"ohci_pci"
"ehci_pci"
"megaraid_sas"
"usbhid"
"sd_mod"
"sr_mod"
];
kernelModules = [ "dm-snapshot" ];
};
kernelModules = [ "kvm-amd" ];
externalModulePackages = [ ];
kernelPackages = pkgs.linuxPackages_latest;
loader.grub = {
enable = true;
version = 2;
device = "/dev/sda";
};
};
fileSystems = {
"/" = {
device = "/dev/disk/by-label/nixos";
fsType = "ext4";
};
};
nix.maxJobs = lib.mkDefault 24;
hardware.bluetooth.enable = false;
networking = {
macvlans = {
intif0 = {
interface = "eno1";
mode = "bridge";
};
extif0 = {
interface = "eno2";
mode = "bridge";
};
};
interfaces = {
intif0 = {
# output of: echo nostromo-intif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:14:25:55:ee:5a";
};
extif0 = {
# echo nostromo-extif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:cf:d7:de:f9:ad";
};
};
};
}

79
config/hardware/plato.nix Normal file
View File

@ -0,0 +1,79 @@
{ config, lib, pkgs, ... }:
{
imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ];
boot = {
initrd = {
availableKernelModules =
[ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" ];
kernelModules = [ ];
};
kernelModules = [ "kvm-intel" ];
extraModulePackages = [ ];
loader = {
systemd-boot.enable = true;
efi.canTouchEfiVariables = true;
};
supportedFilesystems = [ "zfs" ];
kernelPackages = pkgs.linuxPackages_latest;
};
fileSystems = {
"/boot" = {
device = "/dev/disk/by-label/PLATO-BOOT";
fsType = "vfat";
};
"/" = {
device = "zroot/transient/root";
fsType = "zfs";
};
"/nix" = {
device = "zroot/transient/nix";
fsType = "zfs";
};
"/var/log" = {
device = "zroot/transient/logs";
fsType = "zfs";
neededForBoot = true;
};
"/home" = {
device = "zroot/persistent/home";
fsType = "zfs";
};
"/state" = {
device = "zroot/persistent/state";
fsType = "zfs";
};
};
services.autoScrub.enable = true;
swapDevices = [{ device = "/dev/disk/by-label/plato-swap"; }];
nix.maxJobs = lib.mkDefault 4;
hardware.bluetooth.enable = false;
network = {
macvlans = {
intif0 = {
interface = "enp1s0";
mode = "bridge";
};
};
interfaces = {
intif0 = {
# output of: echo plato-intif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:25:b7:67:c4:c2";
};
};
};
}

90
config/hosts.nix Normal file
View File

@ -0,0 +1,90 @@
{ config, lib, pkgs, ... }:
{
config.fudo.hosts = {
atom = {
description = "Niten's toy laptop.";
domain = "sea.fudo.org";
site = "seattle";
profile = "laptop";
enable-gui = false;
hardware-config = ./hardware/atom.nix;
};
clunk = let
primary-ip = "10.0.0.1";
internal-interfaces = [ "intif0" ];
external-interface = "extif0";
dns-over-https-port = 5353;
in {
description = "rus.selby.ca gateway box.";
domain = "rus.selby.ca";
site = "russell";
profile = "gateway-server";
docker-server = true;
hardware-config = ./hardware/clunk.nix;
extra-config = import ./hosts/clunk.nix { };
};
france = {
description = "Primary fudo.org server.";
domain = "fudo.org";
site = "portage";
profile = "server";
docker-server = true;
hardware-config = ./hardware/france.nix;
};
lambda = {
description = "Niten's experiment server.";
domain = "sea.fudo.org";
site = "seattle";
profile = "server";
docker-server = true;
hardware-config = ./hardware/lambda.nix;
};
nostromo = {
description = "sea.fudo.org gateway box and primary server.";
domain = "sea.fudo.org";
site = "seattle";
profile = "gateway-server";
docker-server = true;
hardware-config = ./hardware/nostromo.nix;
};
plato = {
description = "Niten's toy server.";
domain = "rus.selby.ca";
site = "russell";
profile = "server";
hardware-config = ./hardware/plato.nix;
};
procul = {
description = "informis.land server.";
domain = "informis.land";
site = "joes-datacenter-0";
profile = "server";
docker-server = true;
hardware-config = ./hardware/procul.nix;
};
spark = {
description = "Niten's backup desktop.";
domain = "sea.fudo.org";
site = "seattle";
profile = "desktop";
hardware-config = ./hardware/spark.nix;
};
zbox = {
description = "Niten's primary desktop.";
domain = "sea.fudo.org";
site = "seattle";
profile = "desktop";
hardware-config = ./hardware/zbox.nix;
};
};
}

9
config/hosts/atom.nix Normal file
View File

@ -0,0 +1,9 @@
{ config, lib, pkgs, ... }:
{
fudo.laptop.use-network-manager = false;
fudo.slynk.enable = true;
services.xserver = { videoDrivers = [ "nvidia" ]; };
}

135
config/hosts/clunk.nix Normal file
View File

@ -0,0 +1,135 @@
{ config, lib, pkgs, ... }:
let
primary-ip = "10.0.0.1";
dns-proxy-ip = "10.0.0.2";
in {
fudo.local-network = {
# FIXME: think about this -- actual network config?
enable = true;
# NOTE: requests go:
# - local bind instance
# - pi-hole
# - DoH resolver
dns-servers = [ primary-ip ];
gateway = primary-ip;
dhcp-interfaces = [ "intif0" ];
dns-serve-ips = [ primary-ip "127.0.0.1" "127.0.1.1" "::1" ];
recursive-resolver = "${primary-ip} port 5353";
server-ip = primary-ip;
domain = "rus.selby.ca";
};
networking = {
firewall = {
enable = true;
trustedInterfaces = [ "intif0" "docker0" ];
allowedTCPPorts = [ 22 ];
};
interfaces = {
enp2s0.useDHCP = false;
enp3s0.useDHCP = false;
enp4s0.useDHCP = false;
enp1s0.useDHCP = true;
intif0 = {
useDHCP = false;
ipv4.addresses = [
{
address = primary-ip;
prefixLength = 22;
}
{
address = dns-proxy-ip;
prefixLength = 32;
}
];
};
extif0 = { useDHCP = true; };
};
nat = {
enable = true;
externalInterface = "extif0";
internalInterfaces = [ "intif0" ];
};
};
fudo = {
garbage-collector = {
enable = true;
timing = "weekly";
};
secure-dns-proxy = {
enable = true;
listen-port = 53;
upstream-dns =
[ "https://1.1.1.1/dns-query" "https://1.0.0.1/dns-query" ];
bootstrap-dns = "1.1.1.1";
listen-ips = [ dns-proxy-ip ];
};
};
# environment.systemPackages = with pkgs; [ dnsproxy ];
virtualization = {
docker = {
enable = true;
autoPrune.enable = true;
enableOnBoot = true;
};
};
docker-containers = {
pihole = {
image = "pihole/pihole:v5.1.2";
ports = [ "5353:53/tcp" "5353:53/udp" "3080:80/tcp" ];
environment = {
ServerIP = primary-ip;
VIRTUAL_HOST = "dns-hole.rus.selby.ca";
DNS1 = dns-proxy-ip;
};
volumes = [
"/srv/pihole/etc-pihole/:/etc/pihole/"
"/srv/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/"
];
};
};
services.nginx = {
enable = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
recommendedProxySettings = true;
virtualHosts = {
"dns-hole.rus.selby.ca" = {
serverAliases = [
"pihole.rus.selby.ca"
"hole.rus.selby.ca"
"pihole"
"dns-hole"
"hole"
];
locations."/" = {
proxyPass = "http://127.0.0.1:3080";
# extraConfig = ''
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $remote_addr;
# proxy_set_header X-Forwarded-By $server_addr:$server_port;
# proxy_set_header X-Forwarded-For $remote_addr;
# proxy_set_header X-Forwarded-Proto $scheme;
# '';
};
};
};
};
}

179
config/hosts/france.nix Normal file
View File

@ -0,0 +1,179 @@
{ config, lib, pkgs, ... }:
let
primary-ip = "208.81.3.117";
hostname = config.instance.hostname;
domain-name = config.fudo.hosts.${hostname}.domain;
domain = config.fudo.domains.${domain-name};
host-fqdn = "${hostname}.${domain-name}";
mail-hostname = "mail.fudo.org";
in {
imports = [ ./france/postgresql.nix ];
config = {
fudo = {
auth = {
ldap = {
enable = true;
base = "dc=fudo,dc=org";
organization = "Fudo";
rootpw-file = "FIXME";
kerberos-host = host-fqdn;
kerberos-keytab = "FIXME";
sslCert = "FIXME";
sslKey = "FIXME";
sslCaCert = "FIXME";
listen-uris = [ "ldap:///" "ldaps:///" "ldapi:///" ];
users = config.fudo.users;
groups = config.fudo.groups;
system-users = config.fudo.system-users;
};
kdc = let realm = "FUDO.ORG";
in {
enable = true;
database-path = "FIXME";
realm = realm;
mkey-file = "FIXME";
acl = [
{
principal = "pam_migrate/*.fudo.org@${realm}";
access = "add";
}
{
principal = "host/*.fudo.org@${realm}";
access = "add";
}
] ++ (concatMap (user: [
{
principal = "${user}@${realm}";
access = "add,list,modify";
}
{
principal = "${user}/root@${realm}";
access = "all";
}
]) domain.admin-users);
bind-addresses = [ primary-ip "127.0.0.1" "127.0.1.1" "::1" ];
};
};
prometheus = {
enable = true;
hostname = "metrics.fudo.org";
service-discovery-dns = let dns-root = "_metrics._tcp.fudo.org";
in {
node = [ "node.${dns-root}" ];
postfix = [ "postfix.${dns-root}" ];
dovecot = [ "dovecot.${dns-root}" ];
rspamd = [ "rspamd.${dns-root}" ];
};
};
postgresql = {
enable = true;
# FIXME: ssl-private-key && ssl certificate
keytab = "/srv/postgres/secure/postgres.keytab";
local-networks = getHostLocalNetworks hostname;
admin-users = domain.admin-users;
};
client.dns = {
enable = true;
ipv4 = true;
ipv6 = true;
user = "FIXME";
external-interface = "extif0";
password-file = "FIXME";
};
mail-server = domain.mail-config // {
enableContainer = true;
monitoring = true;
hostname = mail-hostname;
state-directory = "FIXME";
mail-directory = "FIXME";
dovecot.ldap = {
reader-dn = "FIXME";
reader-password = "FIXME";
server-urls = [ "FIXME" ];
};
clamav.enable = true;
dkim.signing = true;
};
git = {
enable = true;
hostname = "git.fudo.org";
site-name = "Fudo Git";
user = "FIXME";
database = {
user = "FIXME";
password-file = "FIXME";
hostname = "127.0.0.1";
name = "FIXME";
};
repository-dir = "FIXME";
state-dir = "FIXME";
ssh = {
listen-ip = git-server-ip;
listen-port = 22;
};
};
minecraft-server = {
enable = true;
package = pkgs.minecraft-current;
data-dir = "FIXME";
world-name = "selbyland";
motd = "Welcome to the Selby Minecraft server.";
};
};
networking = {
intif0 = {
ipv4.addresses = [{
address = "192.168.11.1";
prefixLength = 24;
}];
};
extif0 = {
ipv4.addresses = [
{
address = primary-ip;
prefixLength = 28;
}
{
address = git-server-ip;
prefixLength = 32;
}
];
};
};
services = {
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisations = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
virtualHosts = {
"mail.fudo.org" = {
enableACME = true;
locations."/".return = "301 https://webmail.fudo.org$request_uri";
};
};
};
};
};
}

32
config/hosts/lambda.nix Normal file
View File

@ -0,0 +1,32 @@
{ config, lib, pkgs, ... }:
let primary-ip = "10.0.0.3";
in {
fudo.slynk.enable = true;
networking = {
interfaces = {
enp3s0f0.useDHCP = false;
enp3s0f1.useDHCP = false;
enp4s0f0.useDHCP = false;
enp4s0f1.useDHCP = false;
extif0 = {
useDHCP = false;
ipv4.addresses = [{
address = primary-ip;
prefixLength = 22;
}];
};
};
};
fudo.ipfs = {
enable = true;
users = [ "niten" ];
api-address = "/ip4/${primary-ip}/tcp/5001";
};
# TODO: add camera
}

169
config/hosts/nostromo.nix Normal file
View File

@ -0,0 +1,169 @@
{ config, lib, pkgs, ... }:
let
primary-ip = "10.0.0.1";
dns-proxy-ip = "10.0.0.5";
in {
fudo.local-network = let
hostname = config.instance.hostname;
site-name = config.fudo.hosts.${hostname}.site;
site = config.fudo.site.${site-name};
in {
enable = true;
dns-servers = site.dns-servers;
gateway = site.gateway;
dhcp-interfaces = [ "intif0" ];
dns-serve-ips = [ primary-ip "127.0.0.1" "127.0.1.1" "::1" ];
recursive-resolver = "${primary-ip} port 5353";
server-ip = primary-ip;
};
fudo.slynk.enable = true;
# systemd.network.networks.eno2 = {
# extraConfig = {
# IPv6AcceptRA = true;
# IPv6PrefixDelegation = "dhcpv6";
# };
# };
networking = {
# dhcpd.extraConfig = ''
# interface eno2
# ia_na 1
# ia_pd 2 eno2/0
# '';
eno1.useDHCP = false;
eno2.useDHCP = false;
eno3.useDHCP = false;
eno4.useDHCP = false;
enp33s0f0.useDHCP = false;
enp33s0f1.useDHCP = false;
enp9s0f0.useDHCP = false;
enp9s0f1.useDHCP = false;
intif0 = {
useDHCP = false;
ipv4.addresses = [
{
address = primary-ip;
prefixLength = 22;
}
{
address = dns-proxy-ip;
prefixLength = 32;
}
];
};
extif0 = { useDHCP = true; };
nat = {
enable = true;
externalInterface = "extif0";
internalInterfaces = [ "intif0" ];
};
};
fudo = {
client.dns = {
enable = true;
ipv4 = true;
ipv6 = true;
user = "fudo-client";
external-interface = "extif0";
password-file = "/srv/client/secure/client.passwd";
};
secure-dns-proxy = {
enable = true;
port = 3535;
upstream-dns =
[ "https://1.1.1.1/dns-query" "https://1.0.0.1/dns-query" ];
bootstrap-dns = "1.1.1.1";
listen-ips = [ dns-proxy-ip ];
};
};
virtualization = {
docker = {
enable = true;
autoPrune.enable = true;
enableOnBoot = true;
};
libvirtd = {
enable = true;
qemuPackage = pkgs.qemu_kvm;
onShutdown = "shutdown";
};
};
docker-containers = {
pihole = {
image = "pihole/pihole:4.3.2-1";
ports = [ "5353:53/tcp" "5353:53/udp" "3080:80/tcp" ];
environment = {
ServerIP = primary-ip;
VIRTUAL_HOST = "dns-hole.sea.fudo.org";
DNS1 = dns-proxy-ip;
};
volumes = [
"/srv/pihole/etc-pihole/:/etc/pihole/"
"/srv/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/"
];
};
};
security.acme.certs = {
"sea-camera.fudo.link".email = "niten@fudo.org";
"sea-camera-od.fudo.link".email = "niten@fudo.org";
};
services = {
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
virtualHosts = {
"sea-camera.fudo.link" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://panopticon.sea.fudo.org/";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
'';
};
};
# Supposed to be for object detection...
"sea-camera-od.fudo.link" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://panopticon-od.sea.fudo.org/";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
'';
};
};
"pihole.sea.fudo.org" = {
serverAliases = [ "dns-hole.sea.fudo.org" "hole.sea.fudo.org" ];
locations."/" = { proxyPass = "http://127.0.0.1:3000"; };
};
};
};
};
}

34
config/hosts/plato.nix Normal file
View File

@ -0,0 +1,34 @@
{ config, lib, pkgs, ... }:
with lib; {
config = {
environment.etc = {
nixos.source = "/state/nixos";
adjtime.source = "/state/etc/adjtime";
NIXOS.source = "/state/etc/NIXOS";
machine-id.source = "/state/etc/machine-id";
};
system.stateVersion = "20.09";
boot.initrd.postDeviceCommands = lib.mkAfter ''
${pkgs.zfs}/bin/zfs rollback -r zroot/transient/root@blank
'';
services = {
openssh = {
hostKeys = [
{
path = "/state/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
{
path = "/state/ssh/ssh_host_rsa_key";
type = "rsa";
bits = 4096;
}
];
};
};
};
}

10
config/hosts/zbox.nix Normal file
View File

@ -0,0 +1,10 @@
{ config, lib, pkgs, ... }:
{
fudo.slynk.enable = true;
networking = {
eno1.useDHCP = false;
intif0 = { useDHCP = true; };
};
}

View File

@ -0,0 +1,84 @@
let local-domain = "rus.selby.ca";
in {
domain = "${local-domain}";
network = "10.0.0.0/16";
dhcp-dynamic-network = "10.0.1.0/24";
enable-reverse-mappings = true;
srv-records = {
tcp = {
domain = [{
port = 53;
host = "clunk.${local-domain}";
}];
kerberos = [{
port = 88;
host = "france.fudo.org";
}];
kerberos-adm = [{
port = 88;
host = "france.fudo.org";
}];
ssh = [{
port = 22;
host = "clunk.${local-domain}";
}];
};
udp = {
domain = [{
port = 53;
host = "clunk.${local-domain}";
}];
kerberos = [{
port = 88;
host = "france.fudo.org";
}];
kerboros-master = [{
port = 88;
host = "france.fudo.org";
}];
kpasswd = [{
port = 464;
host = "france.fudo.org";
}];
};
};
aliases = { dns-hole = "clunk"; };
hosts = {
clunk = {
ip-address = "10.0.0.1";
mac-address = "02:44:d1:eb:c3:6b";
};
dns-proxy = {
ip-address = "10.0.0.2";
# This is just an alias for clunk's primary interface
};
google-wifi = {
ip-address = "10.0.0.11";
mac-address = "70:3a:cb:c0:3b:09";
};
pselby-work = {
ip-address = "10.0.0.151";
mac-address = "00:50:b6:aa:bd:b3";
};
downstairs-desktop = {
ip-address = "10.0.0.100";
mac-address = "90:b1:1c:8e:29:cf";
};
upstairs-desktop = {
ip-address = "10.0.0.101";
mac-address = "80:e8:2c:22:65:c2";
};
};
}

View File

@ -0,0 +1,217 @@
let local-domain = "sea.fudo.org";
in {
domain = "${local-domain}";
aliases = {
kadmin = "nostromo";
kdc = "nostromo";
photo = "doraemon";
music = "doraemon";
panopticon = "lambda";
panopticon-od = "lambda";
ipfs = "nostromo";
hole = "nostromo";
pihole = "nostromo";
dns-hole = "nostromo";
mon-1 = "srv-1";
};
network = "10.0.0.0/16";
dhcp-dynamic-network = "10.0.1.0/24";
enable-reverse-mappings = true;
srv-records = {
tcp = {
domain = [{
port = 53;
host = "nostromo.sea.fudo.org";
}];
kerberos = [{
port = 88;
host = "france.fudo.org";
}];
kerberos-adm = [{
port = 88;
host = "france.fudo.org";
}];
ssh = [{
port = 22;
host = "nostromo.sea.fudo.org";
}];
ldap = [{
port = 389;
host = "france.fudo.org";
}];
};
udp = {
domain = [{
port = 53;
host = "nostromo.sea.fudo.org";
}];
kerberos = [{
port = 88;
host = "france.fudo.org";
}];
kerboros-master = [{
port = 88;
host = "france.fudo.org";
}];
kpasswd = [{
port = 464;
host = "france.fudo.org";
}];
};
};
hosts = {
nostromo = {
ip-address = "10.0.0.1";
mac-address = "46:54:76:06:f1:10";
};
lm = {
ip-address = "10.0.0.2";
mac-address = "00:23:7d:e6:d9:ea";
};
lambda = {
ip-address = "10.0.0.3";
mac-address = "02:50:f6:52:9f:9d";
};
switch-master = {
ip-address = "10.0.0.5";
mac-address = "00:14:1C:B6:BB:40";
};
google-wifi = {
ip-address = "10.0.0.7";
mac-address = "7C:D9:5C:9F:6F:E9";
};
cam-entrance = {
ip-address = "10.0.0.31";
mac-address = "9c:8e:cd:0e:99:7b";
};
cam-driveway = {
ip-address = "10.0.0.32";
mac-address = "9c:8e:cd:0d:3b:09";
};
cam-deck = {
ip-address = "10.0.0.33";
mac-address = "9c:8e:cd:0e:98:c8";
};
cargo = {
ip-address = "10.0.0.50";
mac-address = "00:11:32:75:d8:b7";
};
whitedwarf = {
ip-address = "10.0.0.51";
mac-address = "00:11:32:12:14:1d";
};
doraemon = {
ip-address = "10.0.0.52";
mac-address = "00:11:32:0a:06:c5";
};
android = {
ip-address = "10.0.0.81";
mac-address = "00:16:3e:43:39:fc";
};
retro-wired = {
ip-address = "10.0.0.82";
mac-address = "dc:a6:32:6b:57:43";
};
retro = {
ip-address = "10.0.0.83";
mac-address = "dc:a6:32:6b:57:45";
};
monolith = {
ip-address = "10.0.0.100";
mac-address = "6c:62:6d:c8:b0:d8";
};
taipan = {
ip-address = "10.0.0.107";
mac-address = "52:54:00:34:c4:78";
};
spark = {
ip-address = "10.0.0.108";
mac-address = "78:24:af:04:f7:dd";
};
hyperion = {
ip-address = "10.0.0.109";
mac-address = "52:54:00:33:46:de";
};
zbox = {
ip-address = "10.0.0.110";
mac-address = "02:dd:80:52:83:9b";
};
ubiquiti-wifi = {
ip-address = "10.0.0.126";
mac-address = "04:18:d6:20:48:fb";
};
generator-wireless = {
ip-address = "10.0.0.130";
mac-address = "B8:27:EB:A6:32:26";
};
brother-wireless = {
ip-address = "10.0.0.160";
mac-address = "c0:38:96:64:49:65";
};
nest = {
ip-address = "10.0.0.176";
mac-address = "18:b4:30:16:7c:5a";
};
xixi-phone = {
ip-address = "10.0.0.193";
mac-address = "48:43:7c:75:89:42";
};
ipad = {
ip-address = "10.0.0.202";
mac-address = "9c:35:eb:48:6e:71";
};
cam-front = {
ip-address = "10.0.0.203";
mac-address = "c4:d6:55:3e:b4:c3";
};
family-tv = {
ip-address = "10.0.0.205";
mac-address = "84:a4:66:3a:b1:f8";
};
babycam = {
ip-address = "10.0.0.206";
mac-address = "08:ea:40:59:5f:9e";
};
workphone = {
ip-address = "10.0.0.211";
mac-address = "a8:8e:24:5c:12:67";
};
chromecast-2 = {
ip-address = "10.0.0.215";
mac-address = "a4:77:33:59:a2:ba";
};
front-light = {
ip-address = "10.0.0.221";
mac-address = "94:10:3e:48:94:ed";
};
# Ceph network
srv-1 = {
ip-address = "10.0.10.1";
mac-address = "02:65:d7:00:7d:1b";
};
node-1 = {
ip-address = "10.0.10.101";
mac-address = "00:1e:06:36:81:cf";
};
node-2 = {
ip-address = "10.0.10.102";
mac-address = "00:1e:06:36:ec:3e";
};
node-3 = {
ip-address = "10.0.10.103";
mac-address = "00:1e:06:36:ec:4b";
};
node-4 = {
ip-address = "10.0.10.104";
mac-address = "00:1e:06:36:dd:8c";
};
};
}

7
config/profiles.nix Normal file
View File

@ -0,0 +1,7 @@
{ config, lib, pkgs, ... }:
let
host = config.instance.hostname;
host-profile = config.fudo.hosts.${host}.profile;
in { imports = [ "./profiles/${host-profile}.nix" ]; }

View File

@ -0,0 +1,108 @@
{ config, lib, pkgs, ... }:
with lib;
let
hostname = config.instance.hostname;
enable-gui = config.fudo.hosts.${hostname}.enable-gui;
in {
import = [ ./common.nix ];
boot.plymouth.enable = false;
boot.tmpOnTmpfs = true;
services.xserver = mkIf enable-gui {
enable = true;
desktopManager.gnome3.enable = true;
displayManager.gdm.enable = true;
windowManager.stumpwm.enable = true;
# windowManager.session = pkgs.lib.singleton {
# name = "stumpwm";
# start = ''
# ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
# waidPID=$!
# '';
# };
};
sound.enable = true;
hardware.pulseaudio.enable = true;
console.font =
lib.mkDefault "${pkgs.terminus_font}/share/consolefonts/ter-g28n.psf.gz";
services.gnome3 = mkIf enable-gui {
evolution-data-server.enable = mkForce false;
gnome-user-share.enable = mkForce false;
};
fonts = mkIf enable-gui {
enableFontDir = true;
fontconfig.enable = true;
#fontconfig.antialias = true;
#fontconfig.penultimate.enable = true;
#fontconfig.subpixel.lcdfilter = "default";
fonts = with pkgs; [
cantarell_fonts
dejavu_fonts
dina-font
dosemu_fonts
fira-code
fira-code-symbols
freefont_ttf
liberation_ttf
mplus-outline-fonts
nerdfonts
noto-fonts
noto-fonts-cjk
noto-fonts-emoji
proggyfonts
terminus_font
ubuntu_font_family
ucsFonts
ultimate-oldschool-pc-font-pack
unifont
vistafonts
xlibs.fontadobe100dpi
xlibs.fontadobe75dpi
xlibs.fontadobeutopia100dpi
xlibs.fontadobeutopia75dpi
xlibs.fontadobeutopiatype1
xlibs.fontarabicmisc
xlibs.fontbh100dpi
xlibs.fontbh75dpi
xlibs.fontbhlucidatypewriter100dpi
xlibs.fontbhlucidatypewriter75dpi
xlibs.fontbhttf
xlibs.fontbhtype1
xlibs.fontbitstream100dpi
xlibs.fontbitstream75dpi
xlibs.fontbitstreamtype1
xlibs.fontcronyxcyrillic
xlibs.fontcursormisc
xlibs.fontdaewoomisc
xlibs.fontdecmisc
xlibs.fontibmtype1
xlibs.fontisasmisc
xlibs.fontjismisc
xlibs.fontmicromisc
xlibs.fontmisccyrillic
xlibs.fontmiscethiopic
xlibs.fontmiscmeltho
xlibs.fontmiscmisc
xlibs.fontmuttmisc
xlibs.fontschumachermisc
xlibs.fontscreencyrillic
xlibs.fontsonymisc
xlibs.fontsunmisc
xlibs.fontwinitzkicyrillic
xlibs.fontxfree86type1
];
};
}

100
config/profiles/common.nix Normal file
View File

@ -0,0 +1,100 @@
{ config, lib, pkgs, ... }:
with lib;
let
# Available to all users on the system. Keep it minimal.
global-packages = with pkgs; [ emacs openssh_gssapi vim wget ];
in {
environment = {
etc.current-nixos-config.source = ../../.;
systemPackages = global-packages;
environment.shellInit = ''
${pkgs.gnupg}/bin/gpg-connect-agent /bye
export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
'';
};
nixpkgs.config.allowUnfree = true;
security.acme.acceptTerms = true;
system.autoUpgrade.enable = true;
services = {
emacs = {
enable = true;
defaultEditor = true;
};
openssh = {
enable = true;
startWhenNeeded = true;
useDns = true;
permitRootLogin = "prohibit-password";
extraConfig = ''
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes
'';
# FIXME: add all the hosts we know about
knownHosts = {
# publicKey, hostNames
};
};
xserver = {
layout = "us";
xkbVariant = "dvp";
xkbOptions = "ctrl:nocaps";
};
# pcscd.enable = true;
# udev.packages = with pkgs; [ yubikey-personalization ];
};
console.useXkbConfig = true;
i18n.defaultLocale = "en_US.UTF-8";
programs = {
mosh.enable = true;
bash.enableCompletion = true;
fish.enable = true;
gnupg.agent = {
enable = true;
enableSSHSupport = true;
# pinentryFlavor = if cfg.enable-gui then "gnome3" else "curses";
};
ssh = {
# Use GPG agent instead
startAgent = false;
package = pkgs.openssh_gssapi;
extraConfig = ''
GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes
'';
};
};
security.pam = {
enableSSHAgentAuth = true;
services = {
sshd = {
makeHomeDir = true;
sshAgentAuth = true;
# This isn't supposed to ask for a code unless ~/.google_authenticator exists...but it does
# googleAuthenticator.enable = true;
};
};
};
services.dbus.socketActivated = true;
}

View File

@ -0,0 +1,7 @@
{ config, lib, pkgs, ... }:
with lib; {
imports = [ ./common-ui.nix ];
config = { networking = { networkmanager.enable = mkForce false; }; };
}

View File

@ -0,0 +1,30 @@
{ config, lib, pkgs, ... }:
let
hostname = config.instance.hostname;
host-config = config.fudo.hosts.${hostname};
external-interface = host-config.gateway-config.external-interface;
internal-interfaces = host-config.gateway-config.internal-interfaces;
in {
imports = [ ./server.nix ];
config = {
networking = {
nat = {
enable = true;
externalInterface = external-interface;
internalInterfaces = internal-interfaces;
};
firewall = {
enable = true;
trustedInterfaces = internal-interfaces;
interfaces."${external-interface}" = {
allowedTCPPorts = host-config.gateway-config.external-tcp-ports;
allowedUDPPorts = host-config.gateway-config.external-udp-ports;
};
};
};
};
}

View File

@ -0,0 +1,24 @@
{ config, lib, pkgs, ... }:
{
options.fudo.profile.laptop = {
use-network-manager =
mkEnableOption "Use NetworkManager instead of wpa_supplicant.";
};
environment.systemPackages = with pkgs; [ acpi upower wpa_supplicant ];
networking = if (config.fudo.profile.laptop.use-network-manager) then {
networkmanager.enable = true;
} else {
networkmanager.enable = false;
wireless = {
enable = true;
userControlled = {
enable = true;
group = "wheel";
};
networks = config.fudo.wireless-networks;
};
};
}

View File

@ -0,0 +1,71 @@
{ config, lib, pkgs, ... }:
with lib;
let
reboot-if-necessary = pkgs.writeShellScriptBin "reboot-if-necessary" ''
if [ $# -ne 1 ]; then
echo "FAILED: no sync file provided."
exit 1
fi
WALL=${pkgs.utillinux}/bin/wall
if [ -f $1 ]; then
$WALL "$1 exists, rebooting system"
${pkgs.systemd}/bin/reboot
else
$WALL "$1 does not exist, aborting reboot."
fi
exit 0
'';
test-config = pkgs.writeShellScriptBin "fudo-test-config" ''
if [ $# -gt 1 ]; then
echo "usage: $0 [timeout]"
exit 1
elif [ $# -eq 1 ]; then
TIMEOUT=$1
else
TIMEOUT=15m
fi
SYNCFILE=$TMP/sync-$(date +"%Y%m%d-%H%M%N")
touch $SYNCFILE
${pkgs.utillinux}/bin/wall "Launching config. System will restart in $TIMEOUT if $SYNCFILE still exists."
systemd-run --on-active=$TIMEOUT ${reboot-if-necessary} $SYNCFILE
nixos-rebuild test
exit 0
'';
in {
imports = [ ./common.nix ];
config = {
environment = {
systemPackages = with pkgs; [
emacs-nox
ldns
ldns.examples
jdk12_headless
racket-minimal
reboot-if-necessary
test-config
];
noXlibs = true;
};
security = { hideProcessInformation = true; };
networking.networkmanager.enable = mkForce false;
boot.tmpOnTmpfs = true;
services.xserver.enable = false;
sound.enable = false;
hardware.pulseaudio.enable = false;
};
}

59
config/sites.nix Normal file
View File

@ -0,0 +1,59 @@
{ config, lib, pkgs, ... }:
{
config.fudo.sites = {
seattle = {
gateway-v4 = "10.0.0.1";
nameservers = [ "10.0.0.1" ];
timezone = "America/Los_Angeles";
gateway-host = "nostromo";
# FIXME: good idea?
network-mounts = {
"/mnt/documents" = {
device = "whitedwarf:/volume1/Documents";
fsType = "nfs4";
};
"/mnt/downloads" = {
device = "whitedwarf:/volume1/Downloads";
fsType = "nfs4";
};
"/mnt/music" = {
device = "doraemon:/volume1/Music";
fsType = "nfs4";
};
"/mnt/video" = {
device = "doraemon:/volume1/Video";
fsType = "nfs4";
};
"/mnt/cargo_video" = {
device = "cargo:/volume1/video";
fsType = "nfs4";
};
"/mnt/photo" = {
device = "cargo:/volume1/pictures";
fsType = "nfs4";
};
};
};
portage = {
gateway-v4 = "208.81.3.113";
# gateway-v6 = "265:e200:d200:1::1";
nameservers = [ "1.1.1.1" "208.81.7.14" "2606:4700:4700::1111" ];
timezone = "America/Winnipeg";
};
russell = {
gateway-v4 = "10.0.0.1";
nameservers = [ "10.0.0.1" ];
timezone = "America/Winnipeg";
gateway-host = "clunk";
};
joes-datacenter-0 = {
gateway-v4 = "172.86.179.17";
nameservers = [ "1.1.1.1" "2606:4700:4700::1111" ];
timezone = "America/Winnipeg";
};
};
}

455
config/users.nix Normal file
View File

@ -0,0 +1,455 @@
{ config, lib, pkgs, ... }:
{
config.fudo.users = {
niten = {
uid = 10000;
primary-group = "admin";
common-name = "Peter Selby";
ldap-hashed-password = "{SSHA}dF/5NGkafL8M1kpa3LYZKdh0Pc7a02gA";
login-hashed-password =
"$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/";
ssh-authorized-keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDoWkjyeIfgwm0b78weToVYOQSD0RQ0qbNzpsN5NokbIFv2/980kLtnYrQEgIJ/JwMLlT3uJYacbCT5/a6Fb8oLxNpj0AF1EKaWZ3Rrlg72Sq+9SEwJwWWmZizX83sovMwUBMaUp6jWLhAhPpzBW5pfc5YWoc89wxGbELSwzgt5EgHbSJgvDnaHSp3fVaY01wfDXbL/oO160iNe7wv2HLMZu/FkWBkIjz6HmoGJJzYM89bUpHbyYG28lmCHB/8UPog5/BsjOn3/qupgf4zh6mMdMsXLvbR2jVwVjxcEMj9N5nCvc+Y3oi7Mij6VNrWbhkaAJMEzeMhWYrF3/pFQxUqG37aK3d0gw9kp5tMDLIlAPX4y1lfA87pIzoa0+Alql0CJQA1IJvp9SFG7lBmSthWQLmZvwwfoGg/ZjF6rOgsVoZ8TizpQnydWJDr6NboU9LL9Oa64OM5Rs0AU3cR2UbOF4QIcWFJ/7oDe3dOnfZ8QYqx9eXJyxoAUpDanaaTHYBiAKkeOBwQU+MVLKCcONKw9FZclf/1TpDB5b3/JeUFANjHQTv0UXA4YYU7iCx6H7XB4qwwtU9O19CGQYYfCfULX12/fRpYJw6VJaQWyyU4Bn5dk/dcB2nGI36jwbLMfhbUTIApujioAnd/GQIMakHEZ1+syPhMx9BxMkZb99B0A1Q== openpgp:0x4EC95B64"
];
home = "/home/niten";
};
andrew = {
uid = 10001;
primary-group = "selby";
common-name = "Andrew Selby";
ldap-hashed-password = "";
};
animus = {
uid = 10002;
primary-group = "fudo";
common-name = "James Frazer";
ldap-hashed-password = "";
};
ark = {
uid = 10005;
primary-group = "fudo";
common-name = "Roger Wong";
ldap-hashed-password = "";
};
ben = {
uid = 10007;
primary-group = "fudo";
common-name = "Ben";
ldap-hashed-password = "{MD5}v0jY5bADu30cAR1Uu/eWYQ==";
};
chad = {
uid = 10011;
primary-group = "fudo";
common-name = "Chad Isbister";
ldap-hashed-password = "{MD5}fQ309GUF2DvHlJ3R+5wNuA==";
};
ckoo = {
uid = 10014;
primary-group = "fudo";
common-name = "Jason Bush";
ldap-hashed-password = "{MD5}KMFeaBc7e/gVzL/QUT0mYw==";
};
dana = {
uid = 10015;
primary-group = "fudo";
common-name = "Dana Eftodie";
ldap-hashed-password = "{MD5}+ijTylKau4uot2kGMqKSTA==";
};
jill = {
uid = 10030;
primary-group = "fudo";
common-name = "Jill Isbister";
ldap-hashed-password = "{MD5}fQ309GUF2DvHlJ3R+5wNuA==";
};
joker4ever = {
uid = 10033;
primary-group = "fudo";
common-name = "Jack Clarke";
ldap-hashed-password = "{SSHA}w78XwSax9WywIDujMxEoO7o87d2LDJRo";
};
ken = {
uid = 10035;
primary-group = "selby";
common-name = "Ken Selby";
ldap-hashed-password = "{SSHA}YvtkEpqsReXcMdrzlui/ZmhIUKN42YO1";
login-hashed-password =
"$6$EwK9fpbH8$gYVzYY1IYw2/G0wCeUxXrZZqvjWCkCZbBqCOhxowbMuYtC5G0vp.AoYhVKWOJcHJM2c7TdPmAdnhLIe2KYStf.";
};
reaper = {
uid = 10049;
primary-group = "admin";
common-name = "Jonathan Stewart";
ldap-hashed-password = "{MD5}EBvifhJ6z9dIDx0KWkAPoQ==";
login-hashed-password =
"$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/";
home = "/home/reaper";
};
slickoil = {
uid = 10052;
primary-group = "fudo";
common-name = "Connor Cooley";
ldap-hashed-password = "{MD5}8Qrpagi8TYnZQdFoYe02rA==";
};
splat1 = {
uid = 10053;
primary-group = "fudo";
common-name = "Matt Evans";
ldap-hashed-password = "{MD5}JeHNutGTBMHOqFgVlYjfpw==";
};
swaff = {
uid = 10055;
primary-group = "fudo";
common-name = "Mark Swaffer";
ldap-hashed-password = "{MD5}C5gIsLsaKSvIPydu4uzhNg==";
};
brian = {
uid = 10056;
primary-group = "selby";
common-name = "Brian Selby";
ldap-hashed-password = "{crypt}$1$npZLTPEO$p2bTx8TTlCg7XNiivTJsC1";
};
rob = {
uid = 10057;
primary-group = "selby";
common-name = "Robert Selby";
ldap-hashed-password = "{crypt}HD1ESf1hAGdks";
};
tarbash = {
uid = 10059;
primary-group = "fudo";
common-name = "Neville";
ldap-hashed-password = "{crypt}$1$cE6lVNbC$PLjlE9vK77SKNKwJBKiT//";
};
darryl = {
uid = 10060;
primary-group = "selby";
common-name = "Darryl Kissick";
ldap-hashed-password = "{crypt}$1$oUNTMyKU$oUs6JqBRTPKE9A/sEzlSY0";
};
ayumi = {
uid = 10061;
primary-group = "fudo";
common-name = "Ayumi Kira";
ldap-hashed-password = "{MD5}5OkpooOLxw94nF1lOfn/ZQ==";
};
saphira = {
uid = 10063;
primary-group = "fudo";
common-name = "Elizabeth Stewart";
ldap-hashed-password = "{crypt}$1$cQ/Zq25x$fUQfUtpMB.f3rBWzttPns.";
};
banen = {
uid = 10064;
primary-group = "fudo";
common-name = "Travis Neis";
ldap-hashed-password = "{crypt}$1$cyfM/Vni$vIuirRln.MnWActOR6t8S.";
};
xiaoxuan = {
uid = 10065;
primary-group = "fudo";
common-name = "Xiaoxuan Jin";
ldap-hashed-password = "{MD5}iecbyMpyVkmOaMBzSFy58Q==";
login-hashed-password =
"$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0";
};
thibor = {
uid = 10066;
primary-group = "fudo";
common-name = "";
ldap-hashed-password = "{crypt}$1$HzQOn3zV$ogkeS5ByWrFstYo0FhXB/.";
};
flowchart = {
uid = 10067;
primary-group = "fudo";
common-name = "BH Bieterse";
ldap-hashed-password = "{crypt}$1$lQMZ42RZ$aAOsLHP0i.yfvD1a1EVsA/";
};
gubbs = {
uid = 10068;
primary-group = "fudo";
common-name = "Lorcan Gavin";
ldap-hashed-password = "{MD5}AIf4bJZyHCnvJVL3YHRnIg==";
};
debo = {
uid = 10069;
primary-group = "fudo";
common-name = "Deborah Osti";
ldap-hashed-password = "{crypt}$1$5wEBGh/8$Ggp2JAI/rQiBXxJ89G0iq1";
};
leefolio = {
uid = 10070;
primary-group = "fudo";
common-name = "Ze Artiste";
ldap-hashed-password = "{crypt}$1$LRlAYBst$sS1bPu8yEPrdYkQhoZhAq1";
};
zimm = {
uid = 10071;
primary-group = "fudo";
common-name = "Ross Drinkwater";
ldap-hashed-password = "{SSHA}er1cgYDNPJsfLwtqYLopKMGMxiZZRGdY";
};
gaijin = {
uid = 10072;
primary-group = "fudo";
common-name = "Tetsuo Torigai";
ldap-hashed-password = "{crypt}$1$bw8hyDXm$pMLLUtlDlVLwBTZiC0Lzf0";
};
anorthe = {
uid = 10073;
primary-group = "fudo";
common-name = "Bonnie Wong";
ldap-hashed-password = "{crypt}$1$DORfHzbp$nJkk0OXd7WzYDxx8LbdMK.";
};
stewartd = {
uid = 10076;
primary-group = "fudo";
common-name = "Dwight Stewart";
ldap-hashed-password = "{MD5}e2GSmH+l4ZZ808snWsFNYw==";
};
jess = {
uid = 10078;
primary-group = "selby";
common-name = "Jessica Selby";
ldap-hashed-password = "{MD5}2tbtZre16apUTNtRIK98nQ==";
};
kevin = {
uid = 10079;
primary-group = "selby";
common-name = "Kevin Selby";
ldap-hashed-password = "{crypt}$1$UYKrkMEe$SAABgc1pCBYgPFIMepNrM.";
};
theblacksun = {
uid = 10080;
primary-group = "fudo";
common-name = "Brendan Goodfellow";
ldap-hashed-password = "{MD5}Hmw6pFYYT87nmpLp0QxcQw==";
};
kris = {
uid = 10082;
primary-group = "selby";
common-name = "Kris Huberdeau";
ldap-hashed-password = "{SSHA}RUYeAEUyblnCWa9uBzY9nwsmoksy8P3Y";
};
jun = {
uid = 10083;
primary-group = "fudo";
common-name = "Junichi Suzuki";
ldap-hashed-password = "{crypt}$1$ExfgQXb8$b1ihvMRbG2dWbnlmzzI/h.";
};
jinny = {
uid = 10084;
primary-group = "fudo";
common-name = "Hye-jin Kim";
ldap-hashed-password = "{crypt}$1$6cld82N8$5a9ovCPXSacDmK3TWDaF30";
};
helen = {
uid = 10086;
primary-group = "selby";
common-name = "Helen Selby";
ldap-hashed-password = "{SSHA}uckUXX09MjYq9++sF3f9b2IY8a9UBIxm";
};
vee = {
uid = 10087;
primary-group = "selby";
common-name = "Vee Selby";
ldap-hashed-password = "snoinuer";
};
dabar = {
uid = 10088;
primary-group = "fudo";
common-name = "Dan Bernardic";
ldap-hashed-password = "{MD5}ULrk46YUeUZQrl0+wAQiWA==";
};
r3d3 = {
uid = 10089;
primary-group = "fudo";
common-name = "Derek Veroni";
ldap-hashed-password = "{SHA}2XyijGDovUhA1/Z/XR+9h9Ia4fY=";
};
laura = {
uid = 10090;
primary-group = "selby";
common-name = "Laura Selby";
ldap-hashed-password = "{MD5}MI65czN0duIudMhYH+BU9Q==";
};
tuk = {
uid = 10091;
primary-group = "fudo";
common-name = "Taku Koba";
ldap-hashed-password = "{MD5}DQuoQluy50128r8MxAmFkQ==";
};
aki = {
uid = 10092;
primary-group = "fudo";
common-name = "Akihito Mori";
ldap-hashed-password = "{MD5}oGAt2kJGKMqX+CmfV1w/GA==";
};
ansyg = {
uid = 10095;
primary-group = "fudo";
common-name = "Anseok Joo";
ldap-hashed-password = "{MD5}AHhHl02D3uDmWhPJZ6QPOw==";
};
jackie = {
uid = 10097;
primary-group = "selby";
common-name = "Jackie Selby";
ldap-hashed-password = "{MD5}fa6JfWySlH63sITsxrTt0Q==";
};
mtopf = {
uid = 10100;
primary-group = "fudo";
common-name = "Michael Topf";
ldap-hashed-password = "{MD5}/pleD8SiLhmnRr1RVspNcA==";
};
tat = {
uid = 10101;
primary-group = "fudo";
common-name = "Tatsuro Akano";
ldap-hashed-password = "{MD5}fAV5GX8UdjsXIFjU0Ex4SA==";
};
blatzkrieg = {
uid = 10102;
primary-group = "fudo";
common-name = "Brendan Blatz";
ldap-hashed-password = "{MD5}1nE/ndFwGbfH/wLagxvt8w==";
};
ellie = {
uid = 10103;
primary-group = "fudo";
common-name = "Ellie Lee";
ldap-hashed-password = "{MD5}gzjwt+kw2nmvJ1FKFTpSZA==";
};
alan = {
uid = 10104;
primary-group = "fudo";
common-name = "Alan Wong";
ldap-hashed-password = "{MD5}WhohVE4xfo9RIOw1kG3s1Q==";
};
omefire = {
uid = 10105;
primary-group = "fudo";
common-name = "Omar Mefire";
ldap-hashed-password = "{SSHA}W6KWo26wl/nawpV++wMqsKdwrIwrait5";
};
gordon = {
uid = 10106;
primary-group = "fudo";
common-name = "Gordon Stewart";
ldap-hashed-password = "{SSHA}jaCOc1ZjCI9klVR+v676lIBOidEg7/u0";
};
jeramy = {
uid = 10107;
primary-group = "selby";
common-name = "Jeramy Ewbank";
ldap-hashed-password = "{MD5}8j8vTniyRzylmeTNUoRwWA==";
};
lauren = {
uid = 10108;
primary-group = "selby";
common-name = "Lauren Hotel";
ldap-hashed-password = "{SSHA}1q/MC5LKROlIT1nDrKrMvcFAXFtcQXIR";
# ldap-hashed-password = "{SSHA}DKnhrycmXSu4HKWFPeBXA9xvZ0ytgXIpZA10tg==";
};
# Used to send alerts from grafana
metrics = {
uid = 10109;
primary-group = "fudo";
common-name = "Fudo Metrics";
ldap-hashed-password = "{SSHA}FveEVy6kljQZey0xp0nF62SMlO5nATJ1";
};
testuser = {
uid = 10110;
primary-group = "fudo";
common-name = "Test User";
ldap-hashed-password = "{SSHA}LSz1WjWfjRwAM3xm+QZ71vFj997dnZC6";
};
# Used to send messages from the chat server
chat = {
uid = 10111;
primary-group = "fudo";
common-name = "Fudo Chat";
ldap-hashed-password = "{SSHA}XDYAM2JE4PXssywRzO4tVSbn5lUZOgg7";
};
kevinyinjunjie = {
uid = 10112;
primary-group = "fudo";
common-name = "Kevin";
ldap-hashed-password = "{SSHA}1onx6HPMKCJvmLnRf1tiWFJ1D92DEtnl";
};
netinfo = {
uid = 10113;
primary-group = "fudo";
common-name = "Network Info Mailer";
ldap-hashed-password = "{SSHA}UQHfW0IzjIbRU6VV+DraxvZFWt0to3oc";
};
selby-forum = {
uid = 10114;
primary-group = "selby";
common-name = "Selby Forum";
ldap-hashed-password = "{SSHA}f7eDNuwFXRhvants5cJJ/FGtkCKheY2Q";
};
};
}

View File

@ -0,0 +1,11 @@
{ config, lib, pkgs, ... }:
{
config.fudo.wireless-networks = {
"sea.fudo.org" = { key = "DahHaocheiD5"; };
"Pixel_9041" = { key = "ea72027e4e6"; };
"rus.selby.ca" = { key = "r204t683s2341"; };
};
}

10
default.nix Normal file
View File

@ -0,0 +1,10 @@
{ config, lib, pkgs, local-hostname ? builtins.readFile ./instance-hostname.txt
, ... }:
let local-hostname = builtins.readFile ./instance-hostname.txt;
in {
lib = lib // { fudo = import ./lib/fudolib.nix { }; };
instance.hostname = local-hostname;
imports = [ ./lib ./config ./hardware.nix ];
}

View File

@ -157,8 +157,8 @@ in {
};
environment.shellInit = ''
gpg-connect-agent /bye
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
${pkgs.gnupg}/bin/gpg-connect-agent /bye
export SSH_AUTH_SOCK=$(${pkgs.gnupg}/bin/gpgconf --list-dirs agent-ssh-socket)
'';
security.pam = {

View File

@ -11,11 +11,7 @@ with lib;
};
};
config = mkIf (config.fudo.common.profile == "laptop") {
environment.systemPackages = with pkgs; [
acpi
upower
wpa_supplicant
];
environment.systemPackages = with pkgs; [ acpi upower wpa_supplicant ];
networking = if (config.fudo.laptop.use-network-manager) then {
networkmanager.enable = true;
@ -25,15 +21,11 @@ with lib;
enable = true;
userControlled = {
enable = true;
group = "wheel";
group = "wheel";
};
networks = {
"sea.fudo.org" = {
psk = "DahHaocheiD5";
};
"Pixel_9041" = {
psk = "ea72027e4e6";
};
"sea.fudo.org" = { psk = "DahHaocheiD5"; };
"Pixel_9041" = { psk = "ea72027e4e6"; };
};
};
};

View File

@ -8,7 +8,7 @@ let
gateway = "10.0.0.1";
nameservers = ["10.0.0.1"];
nameservers = [ "10.0.0.1" ];
in {
@ -16,26 +16,23 @@ in {
time.timeZone = "America/Los_Angeles";
services.printing = {
enable = true;
};
services.printing = { enable = true; };
services.cron = {
mailto = admin;
};
services.cron = { mailto = admin; };
krb5.libdefaults.default_realm = "FUDO.ORG";
networking = {
domain = local-domain;
search = [local-domain "fudo.org"];
search = [ local-domain "fudo.org" ];
firewall.enable = false;
nameservers = nameservers;
# Don't set the gateway if we ARE the gateway.
# This is the most generic way I can think of to do that. local-network is really
# about running all the local servers (DNS, DHCP, and providing gateway).
defaultGateway = optionalString (config.fudo.local-network.enable != true) gateway;
defaultGateway =
optionalString (config.fudo.local-network.enable != true) gateway;
enableIPv6 = true;
@ -43,7 +40,10 @@ in {
# needs the full reverse-lookup name of the server, the latter wants
# `hostname` to return just the host itself.
hosts = {
"127.0.0.1" = [ "${config.networking.hostName}.${local-domain}" config.networking.hostName];
"127.0.0.1" = [
"${config.networking.hostName}.${local-domain}"
config.networking.hostName
];
};
};
@ -52,27 +52,32 @@ in {
isNormalUser = true;
uid = 1000;
description = "Guest User";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
extraGroups =
[ "audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input" ];
};
ken = {
isNormalUser = true;
uid = 10035;
createHome = true;
description = "Ken Selby";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
extraGroups =
[ "audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input" ];
group = "users";
home = "/home/selby/ken";
hashedPassword = "$6$EwK9fpbH8$gYVzYY1IYw2/G0wCeUxXrZZqvjWCkCZbBqCOhxowbMuYtC5G0vp.AoYhVKWOJcHJM2c7TdPmAdnhLIe2KYStf.";
hashedPassword =
"$6$EwK9fpbH8$gYVzYY1IYw2/G0wCeUxXrZZqvjWCkCZbBqCOhxowbMuYtC5G0vp.AoYhVKWOJcHJM2c7TdPmAdnhLIe2KYStf.";
};
xiaoxuan = {
isNormalUser = true;
uid = 10065;
createHome = true;
description = "Xiaoxuan Jin";
extraGroups = ["audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input"];
extraGroups =
[ "audio" "video" "disk" "floppy" "lp" "cdrom" "tape" "input" ];
group = "users";
home = "/home/xiaoxuan";
hashedPassword = "$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0";
hashedPassword =
"$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0";
};
kevin = {
isNormalUser = true;
@ -122,7 +127,8 @@ in {
kdc = "nostromo";
photo = "doraemon";
music = "doraemon";
panopticon = "hyperion";
panopticon = "lambda";
panopticon-od = "lambda";
ipfs = "nostromo";
hole = "nostromo";
pihole = "nostromo";
@ -310,7 +316,6 @@ in {
mac-address = "94:10:3e:48:94:ed";
};
# Ceph network
srv-1 = {
ip-address = "10.0.10.1";

6
hardware.nix Normal file
View File

@ -0,0 +1,6 @@
{ config, ... }:
{
imports =
[ config.fudo.hosts."${config.fudo.instance.hostname}".hardware-config ];
}

106
home-manager/niten.nix Normal file
View File

@ -0,0 +1,106 @@
{ config, lib, pkgs, ... }:
let
name = "Niten";
email = "niten@fudo.org";
packages = with pkgs; [
asdf
atop
binutils
btrfs-progs
bundix
byobu
cdrtools
cargo
curl
doomEmacsInit
enca
file
fortune
git
gnupg
guile
imagemagick
ipfs
iptables
jq
leiningen
libisofs
lispPackages.quicklisp
lsof
lshw
mkpasswd
mtr
nixfmt
nix-index
nix-prefetch-git
nmap
openldap
pciutils
pv
pwgen
ruby
rustc
sbcl
signal-desktop
stdenv
telnet
texlive.combined.scheme-basic
tmux
unzip
xclip
yubikey-manager
yubikey-personalization
];
in {
programs = {
bash = { enable = true; };
git = {
enable = true;
userName = name;
userEmail = email;
};
};
xresources.properties = {
"Xft.antialias" = 1;
"Xft.autohint" = 0;
"Xft.dpi" = 192;
"Xft.hinting" = 1;
"Xft.hintstyle" = "hintfull";
"Xft.lcdfilter" = "lcddefault";
};
services.gpg-agent.enable = true;
home = {
packages = packages;
file = {
".doom.d" = {
source = pkgs.doom-emacs-config;
recursive = true;
onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh";
};
".k5login" = {
source = pkgs.writeText "niten-k5login" ''
niten@FUDO.ORG
niten/root@FUDO.ORG
niten@INFORMIS.LAND
niten/root@INFORMIS.LAND
'';
};
};
sessionVariables = {
EDITOR = "emacsclient -t";
ALTERNATE_EDITOR = "";
HISTCONTROL = "ignoredups:ignorespace";
};
};
}

39
home-manager/root.nix Normal file
View File

@ -0,0 +1,39 @@
{ config, lib, pkgs, ... }:
let
name = "Root";
email = "root@fudo.org";
in {
programs = {
git = {
enable = true;
userName = name;
userEmail = email;
};
};
home = {
file = {
".doom.d" = {
source = pkgs.doom-emacs-config;
recursive = true;
onChange = "${pkgs.doomEmacsInit}/bin/doom-emacs-init.sh";
};
".k5login" = {
source = pkgs.writeText "niten-k5login" ''
niten/root@FUDO.ORG
niten/root@INFORMIS.LAND
'';
};
};
sessionVariables = {
EDITOR = "emacsclient -t";
ALTERNATE_EDITOR = "";
HISTCONTROL = "ignoredups:ignorespace";
};
};
}

View File

@ -12,16 +12,11 @@ in {
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
boot = {
runSize = "50%";
};
boot = { runSize = "50%"; };
hardware.bluetooth.enable = false;
imports = [
../defaults.nix
../hardware-configuration.nix
];
imports = [ ../defaults.nix ../hardware-configuration.nix ];
fudo.common = {
profile = "server";
@ -66,7 +61,7 @@ in {
intif0 = {
useDHCP = false;
# Result of:
# Result of:
# echo clunk-intif0|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
macAddress = "02:44:d1:eb:c3:6b";
ipv4.addresses = [
@ -86,7 +81,7 @@ in {
nat = {
enable = true;
externalInterface = "enp1s0";
internalInterfaces = ["intif0"];
internalInterfaces = [ "intif0" ];
};
};
@ -105,13 +100,11 @@ in {
#"https://9.9.9.9/dns-query"
];
bootstrap-dns = "1.1.1.1";
listen-ips = [dns-proxy-ip];
listen-ips = [ dns-proxy-ip ];
};
};
environment.systemPackages = with pkgs; [
dnsproxy
];
environment.systemPackages = with pkgs; [ dnsproxy ];
virtualisation = {
docker = {
@ -124,11 +117,7 @@ in {
docker-containers = {
pihole = {
image = "pihole/pihole:v5.1.2";
ports = [
"5353:53/tcp"
"5353:53/udp"
"3080:80/tcp"
];
ports = [ "5353:53/tcp" "5353:53/udp" "3080:80/tcp" ];
environment = {
ServerIP = host-internal-ip;
VIRTUAL_HOST = "dns-hole.rus.selby.ca";
@ -163,12 +152,12 @@ in {
proxyPass = "http://127.0.0.1:3080";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
'';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
'';
};
};
};

View File

@ -191,26 +191,48 @@ in {
api-address = "/ip4/${host-internal-ip}/tcp/5001";
};
security.acme.certs."sea-camera.fudo.link".email = "niten@fudo.org";
security.acme.certs."sea-camera-od.fudo.link".email = "niten@fudo.org";
services = {
nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedTlsSettings = true;
recommendedProxySettings = true;
virtualHosts = {
"pihole.sea.fudo.org" = {
serverAliases = [ "dns-hole.sea.fudo.org" "hole.sea.fudo.org" ];
"sea-camera.fudo.link" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://127.0.0.1:3080";
proxyPass = "http://panopticon.sea.fudo.org/";
extraConfig = ''
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-By $server_addr:$server_port;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
'';
};
};
"sea-camera-od.fudo.link" = {
enableACME = true;
forceSSL = true;
locations."/" = {
proxyPass = "http://panopticon-od.sea.fudo.org/";
extraConfig = ''
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
'';
};
};
"pihole.sea.fudo.org" = {
serverAliases = [ "dns-hole.sea.fudo.org" "hole.sea.fudo.org" ];
locations."/" = { proxyPass = "http://127.0.0.1:3000"; };
};
};
};
};

36
lib/default.nix Normal file
View File

@ -0,0 +1,36 @@
{ lib, config, pkgs, ... }:
with lib; {
imports = [
./instance.nix
./fudo/acme-for-hostname.nix
./fudo/authentication.nix
./fudo/backplane
./fudo/chat.nix
./fudo/client/dns.nix
./fudo/dns.nix
./fudo/garbage-collector.nix
./fudo/git.nix
./fudo/grafana.nix
./fudo/ipfs.nix
./fudo/kdc.nix
./fudo/ldap.nix
./fudo/local-network.nix
./fudo/mail.nix
./fudo/mail-container.nix
./fudo/minecraft-server.nix
./fudo/netinfo-email.nix
./fudo/node-exporter.nix
./fudo/password.nix
./fudo/postgres.nix
./fudo/prometheus.nix
./fudo/secure-dns-proxy.nix
./fudo/slynk.nix
./fudo/system.nix
./fudo/vpn.nix
./fudo/webmail.nix
./informis/cl-gemini.nix
];
}

65
lib/fudo/common.nix Normal file
View File

@ -0,0 +1,65 @@
# General Fudo config, shared across packages
{ config, lib, pkgs, ... }:
with lib; {
options.fudo.common = {
hostname = mkOption {
type = types.str;
description = ''
Hostname of the local host (without domain).
'';
};
# domain = mkOption {
# type = types.str;
# description = ''
# Domain of the local network.
# '';
# };
# local-networks = mkOption {
# type = with types; listOf str;
# description = ''
# A list of networks to consider 'local'. Used by various services to
# limit access to the external world.
# '';
# default = [ ];
# };
# profile = mkOption {
# type = with types; nullOr str;
# example = "desktop";
# description = ''
# The profile to use for this host. This will do some profile-dependent
# configuration, for example removing X-libs from servers and adding UI
# packages to desktops.
# '';
# default = null;
# };
# site = mkOption {
# type = with types; nullOr str;
# example = "seattle";
# description = ''
# The site at which this host is located. This will do some site-dependent
# configuration.
# '';
# default = null;
# };
# www-root = mkOption {
# type = types.path;
# description = "Path at which to store www files for serving.";
# example = /var/www;
# };
# admin-email = mkOption {
# type = types.str;
# description = "Email for administrator of this system.";
# default = "admin@fudo.org";
# };
# enable-gui = mkEnableOption "Install desktop GUI software.";
};
}

View File

@ -7,14 +7,14 @@ let
join-lines = concatStringsSep "\n";
hostOpts = { host, ...}: {
hostOpts = { host, ... }: {
options = {
ip-addresses = mkOption {
type = with types; listOf str;
description = ''
A list of IPv4 addresses assigned to this host.
'';
default = [];
default = [ ];
};
ipv6-addresses = mkOption {
@ -22,7 +22,7 @@ let
description = ''
A list of IPv6 addresses assigned to this host.
'';
default = [];
default = [ ];
};
ssh-fingerprints = mkOption {
@ -30,7 +30,7 @@ let
description = ''
A list of DNS SSHFP records for this host.
'';
default = [];
default = [ ];
};
description = mkOption {
@ -74,96 +74,101 @@ let
};
};
domainOpts = { domain, ... }: with types; {
options = {
hosts = mkOption {
type = loaOf (submodule hostOpts);
default = {};
description = "A map of hostname to { host_attributes }.";
};
domainOpts = { domain, ... }:
with types; {
options = {
hosts = mkOption {
type = loaOf (submodule hostOpts);
default = { };
description = "A map of hostname to { host_attributes }.";
};
dnssec = mkOption {
type = bool;
description = "Enable DNSSEC security for this zone.";
default = true;
};
dnssec = mkOption {
type = bool;
description = "Enable DNSSEC security for this zone.";
default = true;
};
mx = mkOption {
type = listOf str;
description = "A list of mail servers serving this domain.";
default = [];
};
mx = mkOption {
type = listOf str;
description = "A list of mail servers serving this domain.";
default = [ ];
};
srv-records = mkOption {
type = attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
description = "Map of traffic type to srv records.";
default = {};
example = {
tcp = {
kerberos = {
port = 88;
host = "auth-host.my-domain.com";
srv-records = mkOption {
type = attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
description = "Map of traffic type to srv records.";
default = { };
example = {
tcp = {
kerberos = {
port = 88;
host = "auth-host.my-domain.com";
};
};
};
};
};
aliases = mkOption {
type = loaOf str;
default = {};
description = "A mapping of host-alias => hostnames to add to DNS.";
example = {
"music" = "host.dom.com.";
"mail" = "hostname";
aliases = mkOption {
type = loaOf str;
default = { };
description = "A mapping of host-alias => hostnames to add to DNS.";
example = {
"music" = "host.dom.com.";
"mail" = "hostname";
};
};
extra-dns-records = mkOption {
type = listOf str;
description = "Records to be inserted verbatim into the DNS zone.";
example = [ "some-host IN CNAME base-host" ];
default = [ ];
};
dmarc-report-address = mkOption {
type = nullOr str;
description = "The email to use to recieve DMARC reports, if any.";
example = "admin-user@domain.com";
default = null;
};
default-host = mkOption {
type = nullOr str;
description =
"IP of the host which will act as the default server for this domain, if any.";
default = null;
};
};
extra-dns-records = mkOption {
type = listOf str;
description = "Records to be inserted verbatim into the DNS zone.";
example = ["some-host IN CNAME base-host"];
default = [];
};
dmarc-report-address = mkOption {
type = nullOr str;
description = "The email to use to recieve DMARC reports, if any.";
example = "admin-user@domain.com";
default = null;
};
default-host = mkOption {
type = nullOr str;
description = "IP of the host which will act as the default server for this domain, if any.";
default = null;
};
};
};
hostRecords = host: data:
join-lines ((map (ip: "${host} IN A ${ip}") data.ip-addresses) ++
(map (ip: "${host} IN AAAA ${ip}") data.ipv6-addresses) ++
(map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints) ++
(optional (data.rp != null) "${host} IN RP ${data.rp}") ++
(optional (data.description != null) "${host} IN TXT ${data.description}"));
join-lines ((map (ip: "${host} IN A ${ip}") data.ip-addresses)
++ (map (ip: "${host} IN AAAA ${ip}") data.ipv6-addresses)
++ (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints)
++ (optional (data.rp != null) "${host} IN RP ${data.rp}")
++ (optional (data.description != null)
"${host} IN TXT ${data.description}"));
makeSrvRecords = protocol: type: records:
join-lines (map (record: "_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${toString record.host}.")
records);
join-lines (map (record:
"_${type}._${protocol} IN SRV ${toString record.priority} ${
toString record.weight
} ${toString record.port} ${toString record.host}.") records);
makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types);
makeSrvProtocolRecords = protocol: types:
join-lines (mapAttrsToList (makeSrvRecords protocol) types);
cnameRecord = alias: host: "${alias} IN CNAME ${host}";
mxRecords = mxs:
concatStringsSep "\n"
(map (mx: "@ IN MX 10 ${mx}.") mxs);
mxRecords = mxs: concatStringsSep "\n" (map (mx: "@ IN MX 10 ${mx}.") mxs);
dmarcRecord = dmarc-email:
optionalString (dmarc-email != null)
''_dmarc IN TXT "v=DMARC1;p=quarantine;sp=quarantine;rua=mailto:${dmarc-email};"'';
optionalString (dmarc-email != null) ''
_dmarc IN TXT "v=DMARC1;p=quarantine;sp=quarantine;rua=mailto:${dmarc-email};"'';
nsRecords = dom: ns-hosts: join-lines (mapAttrsToList (host: _: "@ IN NS ${host}.${dom}.") ns-hosts);
nsRecords = dom: ns-hosts:
join-lines (mapAttrsToList (host: _: "@ IN NS ${host}.${dom}.") ns-hosts);
in {
@ -177,7 +182,7 @@ in {
example = {
"ns1.domain.com" = {
ip-addresses = [ "1.1.1.1" ];
ipv6-addresses = [];
ipv6-addresses = [ ];
description = "my fancy dns server";
};
};
@ -190,14 +195,14 @@ in {
domains = mkOption {
type = loaOf (submodule domainOpts);
default = {};
default = { };
description = "A map of domain to domain options.";
};
listen-ips = mkOption {
type = listOf str;
description = "A list of IPs on which to listen for DNS queries.";
example = ["1.2.3.4"];
example = [ "1.2.3.4" ];
};
};
@ -221,7 +226,8 @@ in {
6w
5m)
${optionalString (dom-cfg.default-host != null) "@ IN A ${dom-cfg.default-host}"}
${optionalString (dom-cfg.default-host != null)
"@ IN A ${dom-cfg.default-host}"}
${mxRecords dom-cfg.mx}
@ -232,7 +238,8 @@ in {
${dmarcRecord dom-cfg.dmarc-report-address}
${join-lines (mapAttrsToList makeSrvProtocolRecords dom-cfg.srv-records)}
${join-lines
(mapAttrsToList makeSrvProtocolRecords dom-cfg.srv-records)}
${join-lines (mapAttrsToList hostRecords dom-cfg.hosts)}
${join-lines (mapAttrsToList cnameRecord dom-cfg.aliases)}
${join-lines dom-cfg.extra-dns-records}

52
lib/fudo/domains.nix Normal file
View File

@ -0,0 +1,52 @@
{ config, lib, pkgs, ... }:
let
domainOpts = { domain, ... }: {
options = {
domain = mkOption {
type = types.str;
description = "Domain name.";
default = domain;
};
local-networks = mkOption {
type = with types; listOf str;
description =
"A list of networks to be considered trusted on this network.";
default = [ ];
};
local-users = mkOption {
type = with types; listOf str;
description =
"A list of users who should have local (i.e. login) access to _all_ hosts in this domain.";
default = [ ];
};
local-admins = mkOption {
type = with types; listOf str;
description =
"A list of users who should have admin access to _all_ hosts in this domain.";
default = [ ];
};
admin-email = mkOption {
type = types.str;
description = "Email for the administrator of this domain.";
default = "admin@fudo.org";
};
gssapi-realm = mkOption {
type = with types; nullOr str;
description = "GSSAPI (i.e. Kerberos) realm of this domain.";
};
};
};
in {
options.fudo.domains = mkOption {
type = with types; attrsOf (submodule domainOpts);
description = "Domain configurations for all domains known to the system.";
default = { };
};
}

107
lib/fudo/hosts.nix Normal file
View File

@ -0,0 +1,107 @@
{ config, lib, pkgs, ... }:
with lib;
let
hostOpts = { hostname, ... }: {
options = {
hostname = mkOption {
type = types.str;
description = "Hostname (without domain name).";
default = hostname;
};
domain = mkOption {
type = types.str;
description =
"Domain to which the host belongs, in the form of a domain name.";
default = "fudo.org";
};
local-networks = mkOption {
type = with types; listof str;
description =
"A list of networks to be considered trusted by this host.";
default = [ "127.0.0.0/8" ];
};
profile = mkOption {
# FIXME: get this list from profiles directly
type = with types;
listof (enum "desktop" "laptop" "server" "gateway-server");
description =
"The profile to be applied to the host, determining what software is included.";
};
admin-email = mkOption {
type = with types; nullOr str;
description = "Email for the administrator of this host.";
default = null;
};
hardware-configuration = mkOption {
type = types.attrs;
description =
"The hardware configuration of the host (i.e. the contents of hardware-configuration.nix)";
};
local-users = mkOption {
type = with types; listOf str;
description =
"List of users who should have local (i.e. login) access to the host.";
default = [ ];
};
local-admins = mkOption {
type = with types; listOf str;
description =
"A list of users who should have admin access to this host.";
default = [ ];
};
enable-gui = mkEnableOption "Install desktop GUI software.";
docker-server = mkEnableOption "Enable Docker on the current host.";
};
};
in {
options.fudo.hosts = mkOption {
type = with types; attrsOf (submodule hostOpts);
description = "Host configurations for all hosts known to the system.";
default = { };
};
config = let
hostname = config.instance.hostname;
host-cfg = config.fudo.hosts.${hostname};
site-name = host-cfg.site;
site = config.fudo.site.${site-name};
domain-name = host-cfg.domain;
domain = config.fudo.domain.${domain-name};
in {
networking = {
hostName = config.instance.hostname;
nameservers = site.nameservers;
defaultGateway = site.gateway-v4;
defaultGateway6 = site.gateway-v6;
# Necessary to ensure that Kerberos and Avahi both work. Kerberos needs
# the fqdn of the host, whereas Avahi wants just the simple hostname.`
hosts = { "127.0.0.1" = [ "${hostname}.${domain-name}" "${hostname}" ]; };
};
krb5.libdefaults.default_realm = domain.gssapi-realm;
services.cron.mailto = domain.admin-email;
environment.systemPackages = with pkgs;
mkIf (cfg.docker-server) [ docker nix-prefetch-docker ];
virtualisation.docker = mkIf (cfg.docker-server) {
enable = true;
enableOnBoot = true;
autoprune.enable = true;
};
};
}

View File

@ -0,0 +1,142 @@
# THROW THIS AWAY, NOT USED
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.fudo.hosts.local-network;
gatewayServerOpts = { ... }: {
options = {
enable = mkEnableOption "Turn this host into a network gateway.";
internal-interfaces = mkOption {
type = with types; listOf str;
description =
"List of internal interfaces from which to forward traffic.";
default = [ ];
};
external-interface = mkOption {
type = types.str;
description =
"Interface facing public internet, to which traffic is forwarded.";
};
external-tcp-ports = mkOption {
type = with types; listOf port;
description = "List of TCP ports to open to the outside world.";
default = [ ];
};
external-udp-ports = mkOption {
type = with types; listOf port;
description = "List of UDP ports to open to the outside world.";
default = [ ];
};
};
};
dnsOverHttpsProxy = {
options = {
enable = mkEnableOption "Enable a DNS-over-HTTPS proxy server.";
listen-port = mkOption {
type = types.port;
description = "Port on which to listen for DNS requests.";
default = 53;
};
upstream-dns = mkOption {
type = with types; listOf str;
description = "List of DoH DNS servers to use for recursion.";
default = [ ];
};
bootstrap-dns = mkOption {
type = types.str;
description = "DNS server used to bootstrap the proxy server.";
default = "1.1.1.1";
};
};
};
networkDhcpServerOpts = mkOption {
options = {
enable = mkEnableOption "Enable local DHCP server.";
dns-servers = mkOption {
type = with types; listOf str;
description = "List of DNS servers for clients to use.";
default = [ ];
};
listen-interfaces = mkOption {
type = with types; listOf str;
description = "List of interfaces on which to serve DHCP requests.";
default = [ ];
};
server-ip = mkOption {
type = types.str;
description = "IP address of the server host.";
};
};
};
networkServerOpts = {
options = {
enable = mkEnableOption "Enable local networking server (DNS & DHCP).";
domain = mkOption {
type = types.str;
description = "Local network domain which this host will serve.";
};
dns-listen-addrs = mkOption {
type = with types; listOf str;
description = "List of IP addresses on which to listen for requests.";
default = [ ];
};
dhcp = mkOption {
type = types.submodule networkDhcpServerOpts;
description = "Local DHCP server options.";
};
};
};
in {
options.fudo.hosts.local-network = with types; {
recursive-resolvers = mkOption {
type = listOf str;
description = "DNS server to use for recursive lookups.";
example = "1.2.3.4 port 53";
};
gateway-server = mkOption {
type = submodule gatewayServerOpts;
description = "Gateway server options.";
};
dns-over-https-proxy = mkOption {
type = submodule dnsOverHttpsProxy;
description = "DNS-over-HTTPS proxy server.";
};
networkServerOpts = mkOption {
type = submodule networkServerOpts;
description = "Networking (DNS & DHCP) server for a local network.";
};
};
config = {
fudo.secure-dns-proxy = mkIf cfg.dns-over-https-proxy.enable {
enable = true;
port = cfg.dns-over-https-proxy.listen-port;
upstream-dns = cfg.dns-over-https-proxy.upstream-dns;
bootstrap-dns = cfg.dns-over-https-proxy.bootstrap-dns;
listen-ips = cfg.dns-over-https-proxy.listen-ips;
};
};
}

View File

@ -19,6 +19,7 @@ let
description = ''
The password for this user, hashed with ldappasswd.
'';
default = "";
};
};
};
@ -41,7 +42,7 @@ let
members = mkOption {
type = with types; listOf str;
default = [];
default = [ ];
description = ''
A list of usernames representing the members of this group.
'';
@ -94,6 +95,7 @@ let
description = ''
The password for this user, hashed with ldappasswd.
'';
default = "";
};
};
};
@ -102,12 +104,12 @@ let
if (length attrList) == 0 then
""
else
foldr(lAttr: rAttr: "${lAttr}${joiner}${rAttr}") (last attrList) (init attrList);
foldr (lAttr: rAttr: "${lAttr}${joiner}${rAttr}") (last attrList)
(init attrList);
getUserGidNumber = user: group-map: group-map.${user.group}.gid;
attrOr = attrs: attr: value:
if attrs ? ${attr} then attrs.${attr} else value;
attrOr = attrs: attr: value: if attrs ? ${attr} then attrs.${attr} else value;
mkHomeDir = username: user-opts:
if (user-opts.group == "admin") then
@ -115,7 +117,6 @@ let
else
"/home/${user-opts.group}/${username}";
userLdif = base: name: group-map: opts: ''
dn: uid=${name},ou=members,${base}
uid: ${name}
@ -123,15 +124,15 @@ let
objectClass: shadowAccount
objectClass: posixAccount
cn: ${opts.common-name}
uidNumber: ${toString(opts.uid)}
gidNumber: ${toString(getUserGidNumber opts group-map)}
uidNumber: ${toString (opts.uid)}
gidNumber: ${toString (getUserGidNumber opts group-map)}
homeDirectory: ${mkHomeDir name opts}
description: ${opts.description}
shadowLastChange: 12230
shadowMax: 99999
shadowWarning: 7
userPassword: ${opts.hashed-password}
'';
'';
systemUserLdif = base: name: opts: ''
dn: cn=${name},${base}
@ -140,7 +141,7 @@ let
cn: ${name}
description: ${opts.description}
userPassword: ${opts.hashed-password}
'';
'';
toMemberList = userList:
stringJoin "\n" (map (username: "memberUid: ${username}") userList);
@ -149,25 +150,22 @@ let
dn: cn=${name},ou=groups,${base}
objectClass: posixGroup
cn: ${name}
gidNumber: ${toString(opts.gid)}
gidNumber: ${toString (opts.gid)}
description: ${opts.description}
${toMemberList opts.members}
'';
'';
systemUsersLdif = base: user-map:
stringJoin "\n" (mapAttrsToList (name: opts:
systemUserLdif base name opts
) user-map);
stringJoin "\n"
(mapAttrsToList (name: opts: systemUserLdif base name opts) user-map);
groupsLdif = base: group-map:
stringJoin "\n" (mapAttrsToList (name: opts:
groupLdif base name opts
) group-map);
stringJoin "\n"
(mapAttrsToList (name: opts: groupLdif base name opts) group-map);
usersLdif = base: group-map: user-map:
stringJoin "\n" (mapAttrsToList (name: opts:
userLdif base name group-map opts
) user-map);
stringJoin "\n"
(mapAttrsToList (name: opts: userLdif base name group-map opts) user-map);
in {
@ -236,19 +234,16 @@ in {
};
listen-uris = mkOption {
default = [];
default = [ ];
type = with types; listOf str;
description = ''
A list of URIs on which the ldap server should listen.
'';
example = [
"ldap://auth.fudo.org"
"ldaps://auth.fudo.org"
];
example = [ "ldap://auth.fudo.org" "ldaps://auth.fudo.org" ];
};
users = mkOption {
default = {};
default = { };
type = with types; loaOf (submodule ldapUserOpts);
example = {
tester = {
@ -263,14 +258,12 @@ in {
};
groups = mkOption {
default = {};
default = { };
type = with types; loaOf (submodule ldapGroupOpts);
example = {
admin = {
gid = 1099;
members = [
"tester"
];
members = [ "tester" ];
};
};
description = ''
@ -279,7 +272,7 @@ in {
};
system-users = mkOption {
default = {};
default = { };
type = with types; loaOf (submodule ldapSystemUserOpts);
example = {
replicator = {
@ -313,9 +306,7 @@ in {
};
systemd.services.openldap = {
environment = {
KRB5_KTNAME = cfg.kerberos-keytab;
};
environment = { KRB5_KTNAME = cfg.kerberos-keytab; };
};
services.openldap = {
@ -330,7 +321,8 @@ in {
TLSCertificateFile ${cfg.sslCert}
TLSCertificateKeyFile ${cfg.sslKey}
${optionalString (cfg.sslCACert != null) "TLSCACertificateFile ${cfg.sslCACert}"}
${optionalString (cfg.sslCACert != null)
"TLSCACertificateFile ${cfg.sslCACert}"}
authz-regexp "^uid=auth/([^.]+)\.fudo\.org,cn=fudo\.org,cn=gssapi,cn=auth$" "cn=$1,ou=hosts,dc=fudo,dc=org"
authz-regexp "^uid=[^,/]+/root,cn=fudo\.org,cn=gssapi,cn=auth$" "cn=admin,dc=fudo,dc=org"
@ -341,55 +333,55 @@ in {
'';
extraDatabaseConfig = ''
# access to dn=base=""
# by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
# by * read
# access to dn=base=""
# by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
# by * read
access to attrs=userPassword,shadowLastChange
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by group.exact="cn=admin,ou=members,${cfg.base}" write
by dn.exact="cn=auth_reader,${cfg.base}" read
by dn.exact="cn=replicator,${cfg.base}" read
by self write
by * auth
access to attrs=userPassword,shadowLastChange
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by group.exact="cn=admin,ou=members,${cfg.base}" write
by dn.exact="cn=auth_reader,${cfg.base}" read
by dn.exact="cn=replicator,${cfg.base}" read
by self write
by * auth
access to dn.exact="cn=admin,ou=groups,${cfg.base}"
by dn.exact="cn=admin,${cfg.base}" write
by users read
by * none
access to dn.exact="cn=admin,ou=groups,${cfg.base}"
by dn.exact="cn=admin,${cfg.base}" write
by users read
by * none
access to dn.subtree="ou=groups,${cfg.base}" attrs=memberUid
by dn.regex="cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" write
by group.exact="cn=admin,ou=groups,${cfg.base}" write
by users read
by * none
access to dn.subtree="ou=groups,${cfg.base}" attrs=memberUid
by dn.regex="cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" write
by group.exact="cn=admin,ou=groups,${cfg.base}" write
by users read
by * none
access to dn.subtree="ou=members,${cfg.base}" attrs=cn,sn,homeDirectory,loginShell,gecos,description,homeDirectory,uidNumber,gidNumber
by group.exact="cn=admin,ou=groups,${cfg.base}" write
by dn.exact="cn=user_db_reader,${cfg.base}" read
by users read
by * none
access to dn.subtree="ou=members,${cfg.base}" attrs=cn,sn,homeDirectory,loginShell,gecos,description,homeDirectory,uidNumber,gidNumber
by group.exact="cn=admin,ou=groups,${cfg.base}" write
by dn.exact="cn=user_db_reader,${cfg.base}" read
by users read
by * none
access to dn.exact="cn=admin,ou=groups,${cfg.base}"
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by users read
by * none
access to dn.exact="cn=admin,ou=groups,${cfg.base}"
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by users read
by * none
access to dn.subtree="ou=groups,${cfg.base}" attrs=memberUid
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by dn.regex="cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" write
by group.exact="cn=admin,ou=groups,${cfg.base}" write
by users read
by * none
access to dn.subtree="ou=groups,${cfg.base}" attrs=memberUid
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by dn.regex="cn=[a-zA-Z][a-zA-Z0-9_]+,ou=hosts,${cfg.base}" write
by group.exact="cn=admin,ou=groups,${cfg.base}" write
by users read
by * none
access to *
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by users read
by * none
access to *
by dn.exact=gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth manage
by users read
by * none
index objectClass,uid eq
'';
index objectClass,uid eq
'';
declarativeContents = ''
dn: ${cfg.base}

View File

@ -4,8 +4,6 @@ with lib;
let
cfg = config.fudo.postgresql;
utils = import ../../lib/utils.nix { inherit lib; };
join-lines = lib.concatStringsSep "\n";
userDatabaseOpts = { database, ... }: {
@ -18,8 +16,9 @@ let
entity-access = mkOption {
type = with types; attrsOf str;
description = "A list of entities mapped to the access this user should have.";
default = {};
description =
"A list of entities mapped to the access this user should have.";
default = { };
example = {
"TABLE users" = "SELECT,DELETE";
"ALL SEQUENCES IN public" = "SELECT";
@ -39,13 +38,11 @@ let
databases = mkOption {
type = with types; attrsOf (submodule userDatabaseOpts);
description = "Map of databases to required database/table perms.";
default = {};
default = { };
example = {
my_database = {
access = "ALL PRIVILEGES";
entity-access = {
"ALL TABLES" = "SELECT";
};
entity-access = { "ALL TABLES" = "SELECT"; };
};
};
};
@ -56,8 +53,9 @@ let
options = {
users = mkOption {
type = with types; listOf str;
description = "A list of users who should have full access to this database.";
default = [];
description =
"A list of users who should have full access to this database.";
default = [ ];
};
};
};
@ -91,16 +89,14 @@ let
exit 2
fi
${join-lines
(mapAttrsToList
(user: opts: password-setter-script user opts.password-file "$OUTPUT_FILE")
(filterPasswordedUsers users))}
${join-lines (mapAttrsToList (user: opts:
password-setter-script user opts.password-file "$OUTPUT_FILE")
(filterPasswordedUsers users))}
'';
userDatabaseAccess = user: databases:
mapAttrs' (database: databaseOpts:
nameValuePair "DATABASE ${database}" databaseOpts.access)
databases;
nameValuePair "DATABASE ${database}" databaseOpts.access) databases;
makeEntry = nw:
"host all all ${nw} gss include_realm=0 krb_realm=FUDO.ORG";
@ -108,21 +104,22 @@ let
makeNetworksEntry = networks: join-lines (map makeEntry networks);
makeLocalUserPasswordEntries = users:
join-lines (mapAttrsToList
(user: opts: join-lines
(map (db: ''
local ${db} ${user} md5
host ${db} ${user} 127.0.0.1/16 md5
host ${db} ${user} ::1/128 md5
'') (attrNames opts.databases)))
(filterPasswordedUsers users));
join-lines (mapAttrsToList (user: opts:
join-lines (map (db: ''
local ${db} ${user} md5
host ${db} ${user} 127.0.0.1/16 md5
host ${db} ${user} ::1/128 md5
'') (attrNames opts.databases))) (filterPasswordedUsers users));
userTableAccessSql = user: entity: access: "GRANT ${access} ON ${entity} TO ${user};";
userTableAccessSql = user: entity: access:
"GRANT ${access} ON ${entity} TO ${user};";
userDatabaseAccessSql = user: database: dbOpts: ''
\c ${database}
${join-lines (mapAttrsToList (userTableAccessSql user) dbOpts.entity-access)}
${join-lines
(mapAttrsToList (userTableAccessSql user) dbOpts.entity-access)}
'';
userAccessSql = user: userOpts: join-lines (mapAttrsToList (userDatabaseAccessSql user) userOpts.databases);
userAccessSql = user: userOpts:
join-lines (mapAttrsToList (userDatabaseAccessSql user) userOpts.databases);
usersAccessSql = users: join-lines (mapAttrsToList userAccessSql users);
in {
@ -148,10 +145,8 @@ in {
local-networks = mkOption {
type = with types; listOf str;
description = "A list of networks from which to accept connections.";
example = [
"10.0.0.1/16"
];
default = [];
example = [ "10.0.0.1/16" ];
default = [ ];
};
users = mkOption {
@ -163,20 +158,18 @@ in {
databases = {
some_database = {
access = "CONNECT";
entity-access = {
"TABLE some_table" = "SELECT,UPDATE";
};
entity-access = { "TABLE some_table" = "SELECT,UPDATE"; };
};
};
};
};
default = {};
default = { };
};
databases = mkOption {
type = with types; loaOf (submodule databaseOpts);
description = "A map of databases to database options.";
default = {};
default = { };
};
socket-directory = mkOption {
@ -194,13 +187,13 @@ in {
local-users = mkOption {
type = with types; listOf str;
description = "Users able to access the server via local socket.";
default = [];
default = [ ];
};
required-services = mkOption {
type = with types; listOf str;
description = "List of services that should run before postgresql.";
default = [];
default = [ ];
example = [ "password-generator.service" ];
};
};
@ -208,9 +201,7 @@ in {
config = mkIf cfg.enable {
environment = {
systemPackages = with pkgs; [
postgresql_11_gssapi
];
systemPackages = with pkgs; [ postgresql_11_gssapi ];
etc = {
"postgresql/private/privkey.pem" = {
@ -237,9 +228,7 @@ in {
};
users.groups = {
${cfg.socket-group} = {
members = ["postgres"] ++ cfg.local-users;
};
${cfg.socket-group} = { members = [ "postgres" ] ++ cfg.local-users; };
};
services.postgresql = {
@ -247,20 +236,14 @@ in {
package = pkgs.postgresql_11_gssapi;
enableTCPIP = true;
ensureDatabases = mapAttrsToList (name: value: name) cfg.databases;
ensureUsers = ((mapAttrsToList
(username: attrs:
{
name = username;
ensurePermissions = userDatabaseAccess username attrs.databases;
})
cfg.users) ++ (flatten (mapAttrsToList
(database: opts:
(map (username: {
name = username;
ensurePermissions = {
"DATABASE ${database}" = "ALL PRIVILEGES";
};
}) opts.users)) cfg.databases)));
ensureUsers = ((mapAttrsToList (username: attrs: {
name = username;
ensurePermissions = userDatabaseAccess username attrs.databases;
}) cfg.users) ++ (flatten (mapAttrsToList (database: opts:
(map (username: {
name = username;
ensurePermissions = { "DATABASE ${database}" = "ALL PRIVILEGES"; };
}) opts.users)) cfg.databases)));
extraConfig = ''
krb_server_keyfile = '/etc/postgresql/private/postgres.keytab'
@ -294,25 +277,29 @@ in {
postgresql-password-setter = let
passwords-script = passwords-setter-script cfg.users;
password-wrapper-script = pkgs.writeScriptBin "password-script-wrapper.sh" ''
#!${pkgs.bash}/bin/bash
TMPDIR=$(${pkgs.coreutils}/bin/mktemp -d -t postgres-XXXXXXXXXX)
echo "using temp dir $TMPDIR"
PASSWORD_SQL_FILE=$TMPDIR/user-passwords.sql
echo "password file $PASSWORD_SQL_FILE"
touch $PASSWORD_SQL_FILE
chown ${config.services.postgresql.superUser} $PASSWORD_SQL_FILE
chmod go-rwx $PASSWORD_SQL_FILE
${passwords-script}/bin/postgres-set-passwords.sh $PASSWORD_SQL_FILE
echo "executing $PASSWORD_SQL_FILE"
${pkgs.postgresql}/bin/psql --port ${toString config.services.postgresql.port} -d postgres -f $PASSWORD_SQL_FILE
echo rm $PASSWORD_SQL_FILE
echo "Postgresql user passwords set.";
exit 0
'';
password-wrapper-script =
pkgs.writeScriptBin "password-script-wrapper.sh" ''
#!${pkgs.bash}/bin/bash
TMPDIR=$(${pkgs.coreutils}/bin/mktemp -d -t postgres-XXXXXXXXXX)
echo "using temp dir $TMPDIR"
PASSWORD_SQL_FILE=$TMPDIR/user-passwords.sql
echo "password file $PASSWORD_SQL_FILE"
touch $PASSWORD_SQL_FILE
chown ${config.services.postgresql.superUser} $PASSWORD_SQL_FILE
chmod go-rwx $PASSWORD_SQL_FILE
${passwords-script}/bin/postgres-set-passwords.sh $PASSWORD_SQL_FILE
echo "executing $PASSWORD_SQL_FILE"
${pkgs.postgresql}/bin/psql --port ${
toString config.services.postgresql.port
} -d postgres -f $PASSWORD_SQL_FILE
echo rm $PASSWORD_SQL_FILE
echo "Postgresql user passwords set.";
exit 0
'';
in {
description = "A service to set postgresql user passwords after the server has started.";
description =
"A service to set postgresql user passwords after the server has started.";
after = [ "postgresql.service" ] ++ cfg.required-services;
requires = [ "postgresql.service" ] ++ cfg.required-services;
serviceConfig = {
@ -326,11 +313,14 @@ in {
allow-user-login = user: "ALTER ROLE ${user} WITH LOGIN;";
extra-settings-sql = pkgs.writeText "settings.sql" ''
${concatStringsSep "\n" (map allow-user-login (mapAttrsToList (key: val: key) cfg.users))}
${concatStringsSep "\n"
(map allow-user-login (mapAttrsToList (key: val: key) cfg.users))}
${usersAccessSql cfg.users}
'';
in ''
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${pkgs.postgresql}/bin/psql --port ${toString config.services.postgresql.port} -d postgres -f ${extra-settings-sql}
${pkgs.sudo}/bin/sudo -u ${config.services.postgresql.superUser} ${pkgs.postgresql}/bin/psql --port ${
toString config.services.postgresql.port
} -d postgres -f ${extra-settings-sql}
${pkgs.coreutils}/bin/chgrp ${cfg.socket-group} ${cfg.socket-directory}/.s.PGSQL*
'';
};

47
lib/fudo/sites.nix Normal file
View File

@ -0,0 +1,47 @@
{ config, lib, pkgs, ... }:
let
siteOpts = { site, ... }: {
options = {
site = mkOption {
type = types.str;
description = "Site name.";
default = site;
};
gateway-v4 = mkOption {
type = with types; nullOr str;
description = "Gateway to use for public ipv4 internet access.";
default = null;
};
gateway-v6 = mkOption {
type = with types; nullOr str;
description = "Gateway to use for public ipv6 internet access.";
default = null;
};
gateway-host = mkOption {
type = with types; nullOr str;
description = "Identity of the host to act as a gateway.";
default = null;
};
enable-monitoring =
mkEnableOption "Enable site-wide monitoring with prometheus.";
nameservers = mkOption {
type = with types; listOf str;
description = "List of nameservers to be used by hosts at this site.";
default = [ ];
};
};
};
in {
options.fudo.sites = mkOption {
type = with types; attrsOf (submodule domainOpts);
description = "Site configurations for all sites known to the system.";
default = { };
};
}

212
lib/fudo/users.nix Normal file
View File

@ -0,0 +1,212 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.fudo.users;
systemUserOpts = { username, ... }: {
options = {
username = mkOption {
type = types.str;
description = "The system user's login name.";
default = username;
};
description = mkOption {
type = types.str;
description = "Description of this system user's purpose or role";
};
ldap-hashed-password = mkOption {
type = types.str;
description =
"LDAP-formatted hashed password for this user. Generate with slappasswd.";
};
};
};
userOpts = { username, ... }: {
options = {
username = mkOption {
type = types.str;
description = "The user's login name.";
default = username;
};
uidNumber = mkOption {
type = types.int;
description = "Unique UID number for the user.";
};
common-name = mkOption {
type = types.str;
description = "The user's common or given name.";
};
primary-group = mkOption {
type = types.str;
description = "Primary group to which the user belongs.";
};
login-shell = mkOption {
type = with types; nullOr shellPackage;
description = "The user's preferred shell.";
};
description = mkOption {
type = types.str;
default = "Fudo Member";
description = "A description of this user's role.";
};
ldap-hashed-passwd = mkOption {
type = with types; nullOr str;
description =
"LDAP-formatted hashed password, used for email and other services. Use slappasswd to generate the properly-formatted password.";
default = null;
};
login-hashed-passwd = mkOption {
type = with types; nullOr str;
description =
"Hashed password for shell, used for shell access to hosts. Use mkpasswd to generate the properly-formatted password.";
default = null;
};
ssh-authorized-keys = mkOption {
type = with types; listOf str;
description = "SSH public keys this user can use to log in.";
default = [ ];
};
home-manager-config = mkOption {
type = with types; nullOr attrs;
description = "Home Manager configuration for the given user.";
default = null;
};
home-directory = mkOption {
type = types.str;
description = "Default home directory for the given user.";
};
};
};
groupOpts = { group-name, ... }: {
options = {
group-name = mkOption {
type = with types; nullOr str;
default = group-name;
description = "Group name.";
};
description = mkOption {
type = types.str;
description = "Description of the group or it's purpose.";
};
members = mkOption {
type = with types; listOf str;
default = [ ];
description = "A list of users who are members of the current group.";
};
gidNumber = mkOption {
type = types.int;
description = "GID number of the group.";
};
};
};
in {
options.fudo = {
users = mkOption {
type = with types; attrsOf (submodule userOpts);
description = "Users";
default = { };
};
groups = mkOption {
type = with types; attrsOf (submodule groupOpts);
description = "Groups";
default = { };
};
system-users = mkOption {
type = with types; attrsOf (submodule systemUserOpts);
description = "System users (probably not what you're looking for!)";
default = { };
};
};
config = let
local-host = config.fudo.common.hostname;
local-domain = config.fudo.common.domain;
local-user-list = config.fudo.hosts."${local-host}".local-users;
domain-user-list = config.fudo.domains."${local-domain}".local-users;
local-users = getAttrs (local-user-list ++ domain-user-list) cfg.users;
local-group-list = config.fudo.hosts."${local-host}".local-groups;
domain-group-list = config.fudo.domains."${local-domain}".local-groups;
local-groups = getAttrs (local-group-list ++ domain-group-list) cfg.groups;
in {
fudo.auth.ldap = let
ldapUsers = (filterAttrs
(username: userOpts: userOpts.ldap-hashed-password != null)) cfg.users;
list-includes = list: el: isNull (findFirst (this: this == el) list null);
filterExistingUsers = users: group-members:
let user-list = attrNames users;
in filter (username: list-includes user-list username) users;
in {
users = mapAttrs (username: userOpts: {
uid = userOpts.uid;
group = userOpts.primary-group;
common-name = userOpts.common-name;
hashed-password = userOpts.ldap-hashed-password;
}) ldapUsers;
groups = mapAttrs (groupname: groupOpts: {
gid = groupOpts.gid-number;
description = groupOpts.description;
members = filterExistingUsers ldapUsers groupOpts.members;
}) cfg.groups;
system-users = mapAttrs (username: userOpts: {
description = userOpts.description;
hashed-password = userOpts.ldap-hashed-passwd;
}) cfg.system-users;
};
users = {
users = mapAttrs (username: userOpts: {
isNormalUser = true;
uid = userOpts.uidNumber;
createHome = true;
description = userOpts.common-name;
group = userOpts.primary-group;
home = userOpts.home;
hashedPassword = userOpts.login-hashed-passwd;
openssh.authorizedKeys.keys = userOpts.ssh-authorized-keys;
}) local-users;
groups = mapAttrs (groupname: groupOpts: {
gid = groupOpts.gidNumber;
description = groupOpts.description;
members = filterExistingUsers localUsers groupOpts.members;
}) local-groups;
};
home-manager.users = let
home-manager-users =
filterAttrs (username: userOpts: userOpts.home-manager-config != null)
local-users;
in mapAttrs (username: userOpts: userOpts.home-manager-config)
home-manager-users;
};
}

View File

@ -0,0 +1,32 @@
{ config, lib, pkgs, ... }:
with lib;
let
networkOpts = { network, ... }: {
options = {
network = mkOption {
type = types.str;
description = "Name of wireless network.";
default = network;
};
key = mkOption {
type = types.str;
description = "Secret key for wireless network.";
};
};
};
in {
option.fudo.wireless-networks = mkOption {
type = with types; listOf (submodule networkOpts);
description = "A map of wireless networks to attributes (including key).";
default = { };
};
config = {
wireless.networks =
mapAttrs (network: networkOpts: { psk = networkOpts.key; })
config.fudo.wireless-networks;
};
}

6
lib/fudolib.nix Normal file
View File

@ -0,0 +1,6 @@
{ lib, ... }:
{
ip = import ./fudolib/ip.nix { };
dns = import ./fudolib/dns.nix { };
}

View File

@ -1,15 +1,17 @@
{ pkgs ? import <nixpkgs> {}, ... }:
{ lib, ... }:
with pkgs.lib;
with lib;
let
join-lines = concatStringsSep "\n";
makeSrvRecords = protocol: type: records:
join-lines (map (record:
"_${type}._${protocol} IN SRV ${toString record.priority} ${toString record.weight} ${toString record.port} ${record.host}.")
records);
"_${type}._${protocol} IN SRV ${toString record.priority} ${
toString record.weight
} ${toString record.port} ${record.host}.") records);
makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types);
makeSrvProtocolRecords = protocol: types:
join-lines (mapAttrsToList (makeSrvRecords protocol) types);
srvRecordOpts = with types; {
options = {
@ -39,20 +41,25 @@ let
};
srvRecordPair = domain: protocol: type: record: {
"_${type}._${protocol}.${domain}" = "${toString record.priority} ${toString record.weight} ${toString record.port} ${record.host}.";
"_${type}._${protocol}.${domain}" =
"${toString record.priority} ${toString record.weight} ${
toString record.port
} ${record.host}.";
};
in rec {
srvRecords = with types; attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
srvRecordsToBindZone = srvRecords: join-lines (mapAttrsToList makeSrvProtocolRecords srvRecords);
srvRecordsToBindZone = srvRecords:
join-lines (mapAttrsToList makeSrvProtocolRecords srvRecords);
concatMapAttrs = f: attrs: concatMap (x: x) (mapAttrsToList (key: val: f key val) attrs);
concatMapAttrs = f: attrs:
concatMap (x: x) (mapAttrsToList (key: val: f key val) attrs);
srvRecordsToPairs = domain: srvRecords:
listToAttrs
(concatMapAttrs (protocol: types:
concatMapAttrs (type: records: map (srvRecordPair domain protocol type) records) types)
srvRecords);
listToAttrs (concatMapAttrs (protocol: types:
concatMapAttrs
(type: records: map (srvRecordPair domain protocol type) records) types)
srvRecords);
}

80
lib/fudolib/ip.nix Normal file
View File

@ -0,0 +1,80 @@
{ lib, ... }:
with lib;
let
joinString = concatStringsSep;
pow = x: e: if (e == 0) then 1 else x * (pow x (e - 1));
generateNBits = n:
let
helper = n: c:
if (c == n) then pow 2 c else (pow 2 c) + (helper n (c + 1));
in if (n <= 0) then
throw "Can't generate 0 or fewer bits"
else
helper (n - 1) 0;
rightPadBits = int: bits: bitOr int (generateNBits bits);
reverseIpv4 = ip: joinString "." (reverseList (splitString "." ip));
intToBinaryList = int:
let
helper = int: cur:
let curExp = pow 2 cur;
in if (curExp > int) then
[ ]
else
[ (if ((bitAnd curExp int) > 0) then 1 else 0) ]
++ (helper int (cur + 1));
in reverseList (helper int 0);
leftShift = int: n: int * (pow 2 n);
rightShift = int: n: int / (pow 2 n);
in rec {
ipv4ToInt = ip:
let els = map toInt (reverseList (splitString "." ip));
in foldr (a: b: a + b) 0 (imap0 (i: el: (leftShift el (i * 8))) els);
intToIpv4 = int:
joinString "."
(map (i: toString (bitAnd (rightShift int (i * 8)) 255)) [ 3 2 1 0 ]);
maskFromV32Network = network:
let
fullMask = ipv4ToInt "255.255.255.255";
insignificantBits = 32 - (getNetworkMask network);
in intToIpv4
(leftShift (rightShift fullMask insignificantBits) insignificantBits);
networkMinIp = network: intToIpv4 (1 + (ipv4ToInt (getNetworkBase network)));
networkMaxIp = network:
intToIpv4 (rightPadBits (ipv4ToInt (getNetworkBase network))
(32 - (getNetworkMask network)));
# To avoid broadcast IP...
networkMaxButOneIp = network:
intToIpv4 ((rightPadBits (ipv4ToInt (getNetworkBase network))
(32 - (getNetworkMask network))) - 1);
ipv4OnNetwork = ip: network:
let
ip-int = ipv4ToInt ip;
net-min = networkMinIp network;
net-max = networkMaxIp network;
in (ip-int >= networkMinIp) && (ip-int <= networkMaxIp);
getNetworkMask = network: toInt (elemAt (splitString "/" network) 1);
getNetworkBase = network:
let
ip = elemAt (splitString "/" network) 0;
insignificantBits = 32 - (getNetworkMask network);
in intToIpv4
(leftShift (rightShift (ipv4ToInt ip) insignificantBits) insignificantBits);
}

12
lib/instance.nix Normal file
View File

@ -0,0 +1,12 @@
{ config, lib, pkgs, ... }:
{
options.instance = {
hostname = mkOption {
type = types.str;
description = ''
Hostname of this specific host (without domain).
'';
};
};
}

View File

@ -1,63 +0,0 @@
{ pkgs ? import <nixpkgs> {}, ... }:
with pkgs.lib;
let
joinString = concatStringsSep;
pow = x: e: if (e == 0) then 1 else x * (pow x (e - 1));
generateNBits = n: let
helper = n: c: if (c == n) then pow 2 c else (pow 2 c) + (helper n (c + 1));
in if (n <= 0) then throw "Can't generate 0 or fewer bits" else helper (n - 1) 0;
rightPadBits = int: bits: bitOr int (generateNBits bits);
reverseIpv4 = ip: joinString "." (reverseList (splitString "." ip));
intToBinaryList = int: let
helper = int: cur: let
curExp = pow 2 cur;
in if (curExp > int) then
[]
else
[(if ((bitAnd curExp int) > 0) then 1 else 0)] ++ (helper int (cur + 1));
in reverseList (helper int 0);
leftShift = int: n: int * (pow 2 n);
rightShift = int: n: int / (pow 2 n);
in rec {
ipv4ToInt = ip: let
els = map toInt (reverseList (splitString "." ip));
in foldr (a: b: a + b) 0 (imap0 (i: el: (leftShift el (i * 8))) els);
intToIpv4 = int: joinString "." (map (i: toString (bitAnd (rightShift int (i * 8)) 255)) [ 3 2 1 0 ]);
maskFromV32Network = network: let
fullMask = ipv4ToInt "255.255.255.255";
insignificantBits = 32 - (getNetworkMask network);
in intToIpv4 (leftShift (rightShift fullMask insignificantBits) insignificantBits);
networkMinIp = network: intToIpv4 (1 + (ipv4ToInt (getNetworkBase network)));
networkMaxIp = network: intToIpv4 (rightPadBits (ipv4ToInt (getNetworkBase network)) (32 - (getNetworkMask network)));
# To avoid broadcast IP...
networkMaxButOneIp = network: intToIpv4 ((rightPadBits (ipv4ToInt (getNetworkBase network)) (32 - (getNetworkMask network))) - 1);
ipv4OnNetwork = ip: network: let
ip-int = ipv4ToInt ip;
net-min = networkMinIp network;
net-max = networkMaxIp network;
in
(ip-int >= networkMinIp) && (ip-int <= networkMaxIp);
getNetworkMask = network: toInt (elemAt (splitString "/" network) 1);
getNetworkBase = network: let
ip = elemAt (splitString "/" network) 0;
insignificantBits = 32 - (getNetworkMask network);
in intToIpv4 (leftShift (rightShift (ipv4ToInt ip) insignificantBits) insignificantBits);
}

View File

@ -1,14 +0,0 @@
{ lib }:
with lib;
{
recursiveMergeAttrs = a: b: let
commonAttrs = intersectLists (attrNames a) (attrNames b);
aAttrs = subtractLists (attrNames a) commonAttrs;
bAttrs = subtractLists (attrNames b) commonAttrs;
aSide = (filterAttrs (k: v: elem k aAttrs) a);
bSide = (filterAttrs (k: v: elem k bAttrs) b);
common = (foldr (a: b: a // b) {}
(map (k: { ${k} = a.${k} // b.${k}; }) commonAttrs));
in aSide // bSide // common;
}

View File

@ -10,6 +10,8 @@ in {
fetchurl = builtins.fetchurl;
};
minecraft-current = pkgs.minecraft-server_1_16_4;
minecraft-server_1_16_4 = pkgs.minecraft-server.overrideAttrs
(oldAttrs: rec {
version = "1.15.1";
@ -31,13 +33,6 @@ in {
};
});
minecraft-current = pkgs.minecraft.overrideAttrs (oldAttrs: rec {
src = builtins.fetchurl {
url = "https://launcher.mojang.com/download/Minecraft.tar.gz";
sha256 = "1k9gf1v1law4kiz8f7i2fxkj5vq2cm37b3ys95zpyf4aiw5nzg33";
};
});
# DON'T LEAVE THE HASH--Nix will think the package hasn't changed
minecraft-server_1_16_1 = let
version = "1.16.1";