Compare commits

..

3 commits

3 changed files with 52 additions and 25 deletions

View file

@ -19,3 +19,4 @@ SKYNET00017,bumblebee,Active,193.1.99.91,Debian-12,Game server - Minecraft
SKYNET00018,calculon,Active,193.1.99.82,Nixos-24.05,"Public Services such as binary cache, Open Governance and Keyserver" SKYNET00018,calculon,Active,193.1.99.82,Nixos-24.05,"Public Services such as binary cache, Open Governance and Keyserver"
SKYNET00019,deepthought,Active,193.1.99.112,Nixos-24.05,Backup Test Server using restic SKYNET00019,deepthought,Active,193.1.99.112,Nixos-24.05,Backup Test Server using restic
SKYNET00020,ariia,Active,193.1.99.83,Nixos-24.05,"Metrics, Grafana and Prometheus" SKYNET00020,ariia,Active,193.1.99.83,Nixos-24.05,"Metrics, Grafana and Prometheus"
SKYNET00021,ash,Active,193.1.99.114,NA,Server Room Network access
1 Index Name Status IP_Address OS Description
19 SKYNET00018 calculon Active 193.1.99.82 Nixos-24.05 Public Services such as binary cache, Open Governance and Keyserver
20 SKYNET00019 deepthought Active 193.1.99.112 Nixos-24.05 Backup Test Server using restic
21 SKYNET00020 ariia Active 193.1.99.83 Nixos-24.05 Metrics, Grafana and Prometheus
22 SKYNET00021 ash Active 193.1.99.114 NA Server Room Network access

View file

@ -13,11 +13,14 @@
current_date = self.lastModified; current_date = self.lastModified;
# this gets a list of all domains we have records for # this gets a list of all domains we have records for
domains = lib.lists.naturalSort ( domains = lib.lists.naturalSort (lib.lists.unique (
lib.lists.unique (
lib.lists.forEach records (x: x.domain) lib.lists.forEach records (x: x.domain)
) ));
);
# get the ip's of our servers
servers = lib.lists.naturalSort (lib.lists.unique (
lib.lists.forEach (sort_records_a_server records) (x: x.value)
));
domains_owned = [ domains_owned = [
# for historic reasons we own this # for historic reasons we own this
@ -30,9 +33,12 @@
# gets a list of records that match this type # gets a list of records that match this type
filter_records_type = records: r_type: builtins.filter (x: x.r_type == r_type) records; filter_records_type = records: r_type: builtins.filter (x: x.r_type == r_type) records;
filter_records_server = records: builtins.filter (x: builtins.hasAttr "server" x && x.server) (filter_records_type records "A"); # Get all the A records that are for servers (base record for them)
filter_records_a_server = records: builtins.filter (x: builtins.hasAttr "server" x && x.server) (filter_records_type records "A");
# Every other A record
filter_records_a = records: builtins.filter (x: builtins.hasAttr "server" x && !x.server) (filter_records_type records "A"); filter_records_a = records: builtins.filter (x: builtins.hasAttr "server" x && !x.server) (filter_records_type records "A");
# These functions are to get the final 3 digits of an IP address so we can use them for reverse pointer
process_ptr = records: lib.lists.forEach records (x: process_ptr_sub x); process_ptr = records: lib.lists.forEach records (x: process_ptr_sub x);
process_ptr_sub = record: { process_ptr_sub = record: {
record = builtins.substring 9 3 record.record; record = builtins.substring 9 3 record.record;
@ -41,39 +47,49 @@
}; };
ip_ptr_to_int = ip: lib.strings.toInt (builtins.substring 9 3 ip); ip_ptr_to_int = ip: lib.strings.toInt (builtins.substring 9 3 ip);
sort_records_server = records: builtins.sort (a: b: a.record < b.record) (filter_records_server records); # filter and sort records so we cna group them in the right place later
sort_records_a_server = records: builtins.sort (a: b: a.record < b.record) (filter_records_a_server records);
sort_records_a = records: builtins.sort (a: b: (ip_ptr_to_int a.value) < (ip_ptr_to_int b.value)) (filter_records_a records); sort_records_a = records: builtins.sort (a: b: (ip_ptr_to_int a.value) < (ip_ptr_to_int b.value)) (filter_records_a records);
sort_records_cname = records: builtins.sort (a: b: a.value < b.value) (filter_records_type records "CNAME"); sort_records_cname = records: builtins.sort (a: b: a.value < b.value) (filter_records_type records "CNAME");
sort_records_ptr = records: builtins.sort (a: b: (lib.strings.toInt a.record) < (lib.strings.toInt b.record)) (process_ptr (filter_records_type records "PTR")); sort_records_ptr = records: builtins.sort (a: b: (lib.strings.toInt a.record) < (lib.strings.toInt b.record)) (process_ptr (filter_records_type records "PTR"));
sort_records_srv = records: builtins.sort (a: b: a.record < b.record) (filter_records_type records "SRV"); sort_records_srv = records: builtins.sort (a: b: a.record < b.record) (filter_records_type records "SRV");
# a tad overkill but type guarding is useful
max = x: y: max = x: y:
assert builtins.isInt x; assert builtins.isInt x;
assert builtins.isInt y; assert builtins.isInt y;
if x < y if x < y
then y then y
else x; else x;
# get teh max length of a list of strings
max_len = records: lib.lists.foldr (a: b: (max a b)) 0 (lib.lists.forEach records (record: lib.strings.stringLength record.record)); max_len = records: lib.lists.foldr (a: b: (max a b)) 0 (lib.lists.forEach records (record: lib.strings.stringLength record.record));
# now that we can get teh max lenth of a list of strings
# we can pad it out to the max len +1
# this is so that teh generated file is easier for a human to read
format_records = records: let format_records = records: let
offset = (max_len records) + 1; offset = (max_len records) + 1;
in in
lib.strings.concatMapStrings (x: "${padString x.record offset} IN ${padString x.r_type 5} ${x.value}\n") records; lib.strings.concatMapStrings (x: "${padString x.record offset} IN ${padString x.r_type 5} ${x.value}\n") records;
# small function to trim it down a tad # small function to add spaces until it reaches teh required length
padString = text: length: fixedWidthString_post length " " text; padString = text: length: fixedWidthString_post length " " text;
# like lib.strings.fixedWidthString but postfix # like lib.strings.fixedWidthString but postfix
# recursive function to extend a string up to a limit
fixedWidthString_post = width: filler: str: let fixedWidthString_post = width: filler: str: let
strw = lib.stringLength str; strw = lib.stringLength str;
reqWidth = width - (lib.stringLength filler); reqWidth = width - (lib.stringLength filler);
in in
# this is here because we were manually setting teh length, now max_len does that for us
assert lib.assertMsg (strw <= width) "fixedWidthString_post: requested string length (${toString width}) must not be shorter than actual length (${toString strw})"; assert lib.assertMsg (strw <= width) "fixedWidthString_post: requested string length (${toString width}) must not be shorter than actual length (${toString strw})";
if strw == width if strw == width
then str then str
else (fixedWidthString_post reqWidth filler str) + filler; else (fixedWidthString_post reqWidth filler str) + filler;
# base config for domains we own (skynet.ie, csn.ul.ie, ulcompsoc.ie) # base config for domains we own (skynet.ie, csn.ul.ie, ulcompsoc.ie)
# ";" are comments in this file
get_config_file = ( get_config_file = (
domain: records: '' domain: records: ''
$TTL 60 ; 1 minute $TTL 60 ; 1 minute
@ -94,7 +110,7 @@
; ------------------------------------------ ; ------------------------------------------
; Server Names (A Records) ; Server Names (A Records)
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_server records)} ${format_records (sort_records_a_server records)}
; ------------------------------------------ ; ------------------------------------------
; A (non server names ; A (non server names
@ -120,13 +136,11 @@
; SRV ; SRV
; ------------------------------------------ ; ------------------------------------------
${format_records (sort_records_srv records)} ${format_records (sort_records_srv records)}
'' ''
); );
# https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-bind-configuration-zone-reverse # https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/4/html/reference_guide/s2-bind-configuration-zone-reverse
# config for our reverse dnspointers (not properly working) # config for our reverse dns pointers (not properly working)
get_config_file_rev = ( get_config_file_rev = (
domain: '' domain: ''
$ORIGIN 64-64.99.1.193.in-addr.arpa. $ORIGIN 64-64.99.1.193.in-addr.arpa.
@ -151,31 +165,33 @@
'' ''
); );
# arrys of teh two nameservers # arrays of teh two nameservers
tmp1 = ["193.1.99.109"]; nameserver_1 = ["193.1.99.109"];
tmp2 = ["193.1.99.120"]; nameserver_2 = ["193.1.99.120"];
primaries = ( primaries = (
if cfg.server.primary if cfg.server.primary
then then
# primary servers have no primaries (ones they listen to) # primary servers have no primaries (ones they listen to)
[] []
else if builtins.elem cfg.server.ip tmp1 else if builtins.elem cfg.server.ip nameserver_1
then tmp2 then nameserver_2
else tmp1 else nameserver_1
); );
secondaries = ( secondaries = (
if cfg.server.primary if cfg.server.primary
then then
if builtins.elem cfg.server.ip tmp1 if builtins.elem cfg.server.ip nameserver_1
then tmp2 then nameserver_2
else tmp1 else nameserver_1
else [] else []
); );
# small function to tidy up the spam of the cache networks, would use teh subnet except all external traffic has the ip of teh router # small function to tidy up the spam of the cache networks, would use teh subnet except all external traffic has the ip of teh router
create_cache_networks = map (x: "193.1.99.${toString x}/32") (lib.lists.range 71 126); # now limited explicitly to servers that we are administering
# See i24-09-30_050 for more information
create_cache_networks = map (x: "${toString x}/32") servers;
# standard function to create the etc file, pass in the text and domain and it makes it # standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc_sub = domain: text: { create_entry_etc_sub = domain: text: {
@ -187,17 +203,19 @@
# The UNIX file mode bits # The UNIX file mode bits
mode = "0664"; mode = "0664";
# content of the file
text = text; text = text;
}; };
}; };
# (text.owned "csn.ul.ie")
# standard function to create the etc file, pass in the text and domain and it makes it # standard function to create the etc file, pass in the text and domain and it makes it
create_entry_etc = domain: type: let create_entry_etc = domain: type: let
domain_records = lib.lists.filter (x: x.domain == domain) records; domain_records = lib.lists.filter (x: x.domain == domain) records;
in in
# this is the main type of record that most folks are used to
if type == "owned" if type == "owned"
then create_entry_etc_sub domain (get_config_file domain domain_records) then create_entry_etc_sub domain (get_config_file domain domain_records)
# reverse lookups allow for using an IP to find domains pointing to it
else if type == "reverse" else if type == "reverse"
then create_entry_etc_sub domain (get_config_file_rev domain) then create_entry_etc_sub domain (get_config_file_rev domain)
else {}; else {};
@ -238,7 +256,7 @@
*/ */
++ builtins.concatLists ( ++ builtins.concatLists (
lib.attrsets.mapAttrsToList ( lib.attrsets.mapAttrsToList (
key: value: value.config.services.skynet."${name}".records key: value: value.config.services.skynet.dns.records
) )
nodes nodes
); );
@ -329,6 +347,7 @@ in {
group = "named"; group = "named";
}; };
# basic but ensure teh dns ports are open
networking.firewall = { networking.firewall = {
allowedTCPPorts = [53]; allowedTCPPorts = [53];
allowedUDPPorts = [53]; allowedUDPPorts = [53];

View file

@ -12,6 +12,13 @@
config = { config = {
skynet.records = skynet.records =
[ [
# wifi in server room
{
record = "ash";
r_type = "A";
value = "193.1.99.114";
server = true;
}
{ {
record = "optimus"; record = "optimus";
r_type = "A"; r_type = "A";