diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..947f765
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+configuration.nix
+hardware-configuration.nix
+*~
diff --git a/config/fudo/acme-for-hostname.nix b/config/fudo/acme-for-hostname.nix
index 4dd5f2e..0451170 100644
--- a/config/fudo/acme-for-hostname.nix
+++ b/config/fudo/acme-for-hostname.nix
@@ -6,26 +6,28 @@ with lib;
let
cfg = config.fudo.acme;
- wwwRoot = hostname:
- pkgs.writeTextFile {
- name = "index.html";
+ # wwwRoot = hostname:
+ # pkgs.writeTextFile {
+ # name = "index.html";
- text = ''
-
-
- ${hostname}
-
-
- ${hostname}
-
-
- '';
- destination = "/www";
- };
+ # text = ''
+ #
+ #
+ # ${hostname}
+ #
+ #
+ # ${hostname}
+ #
+ #
+ # '';
+ # destination = "/www";
+ # };
in {
options.fudo.acme = {
+ enable = mkEnableOption "Fetch ACME certs for supplied local hostnames.";
+
hostnames = mkOption {
type = with types; listOf str;
description = "A list of hostnames mapping to this host, for which to acquire SSL certificates.";
@@ -35,9 +37,15 @@ in {
"alt.hostname.com"
];
};
+
+ admin-address = mkOption {
+ type = types.str;
+ description = "The admin address in charge of these addresses.";
+ default = "admin@fudo.org";
+ };
};
- config = {
+ config = mkIf cfg.enable {
services.nginx = {
enable = true;
@@ -49,13 +57,13 @@ in {
{
enableACME = true;
forceSSL = true;
- root = (wwwRoot hostname) + ("/" + "www");
+ # root = (wwwRoot hostname) + ("/" + "www");
})
cfg.hostnames);
};
security.acme.certs = listToAttrs
- (map (hostname: nameValuePair hostname { email = "admin@fudo.org"; })
+ (map (hostname: nameValuePair hostname { email = cfg.admin-address; })
cfg.hostnames);
};
}
diff --git a/config/fudo/chat.nix b/config/fudo/chat.nix
index dfaf28c..ecc03ed 100644
--- a/config/fudo/chat.nix
+++ b/config/fudo/chat.nix
@@ -32,7 +32,7 @@ in {
};
smtp-password-file = mkOption {
- type = types.path;
+ type = types.str;
description = "Path to a file containing the password to use while connecting to the SMTP server.";
};
@@ -61,7 +61,7 @@ in {
};
password-file = mkOption {
- type = types.path;
+ type = types.str;
description = "Path to file containing database password.";
};
};
diff --git a/config/fudo/common.nix b/config/fudo/common.nix
index 93c9823..78f3fd8 100644
--- a/config/fudo/common.nix
+++ b/config/fudo/common.nix
@@ -16,7 +16,7 @@ with lib;
domain = mkOption {
type = types.str;
description = ''
- Domain of the
+ Domain of the local network.
'';
};
@@ -52,5 +52,7 @@ with lib;
description = "Email for administrator of this system.";
default = "admin@fudo.org";
};
+
+ enable-gui = mkEnableOption "Install desktop GUI software.";
};
}
diff --git a/config/fudo/dns.nix b/config/fudo/dns.nix
new file mode 100644
index 0000000..9de4805
--- /dev/null
+++ b/config/fudo/dns.nix
@@ -0,0 +1,218 @@
+{ lib, config, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.fudo.dns;
+
+ ip = import ../../lib/ip.nix { lib = lib; };
+
+ join-lines = concatStringsSep "\n";
+
+ hostOpts = { host, ...}: {
+ options = {
+ ip-addresses = mkOption {
+ type = with types; listOf str;
+ description = ''
+ A list of IPv4 addresses assigned to this host.
+ '';
+ default = [];
+ };
+
+ ipv6-addresses = mkOption {
+ type = with types; listOf str;
+ description = ''
+ A list of IPv6 addresses assigned to this host.
+ '';
+ default = [];
+ };
+
+ ssh-fingerprints = mkOption {
+ type = with types; listOf str;
+ description = ''
+ A list of DNS SSHFP records for this host.
+ '';
+ };
+ };
+ };
+
+ srvRecordOpts = with types; {
+ options = {
+ weight = mkOption {
+ type = int;
+ description = "Weight relative to other records.";
+ default = 1;
+ };
+
+ priority = mkOption {
+ type = int;
+ description = "Priority to give this record.";
+ default = 0;
+ };
+
+ port = mkOption {
+ type = port;
+ description = "Port to use while connecting to this service.";
+ };
+
+ host = mkOption {
+ type = str;
+ description = "Host that provides this service.";
+ example = "my-host.my-domain.com";
+ };
+ };
+ };
+
+ domainOpts = { domain, ... }: with types; {
+ options = {
+ hosts = mkOption {
+ type = loaOf (submodule hostOpts);
+ default = {};
+ description = "A map of hostname to { host_attributes }.";
+ };
+
+ dnssec = mkEnableOption "Enable DNSSEC security for this zone.";
+
+ 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";
+ };
+ };
+ };
+ };
+
+ 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;
+ };
+ };
+ };
+
+ hostARecords = host: data:
+ join-lines ((map (ip: "${host} IN A ${ip}") data.ip-addresses) ++
+ (map (ip: "${host} IN AAAA ${ip}") data.ipv6-addresses));
+
+ 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);
+
+ makeSrvProtocolRecords = protocol: types: join-lines (mapAttrsToList (makeSrvRecords protocol) types);
+
+ cnameRecord = alias: host: "${alias} IN CNAME ${host}";
+
+ hostSshFpRecords = host: data: join-lines (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints);
+
+ 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};"'';
+
+ nsRecords = ns-hosts:
+ join-lines ((mapAttrsToList (host: _: "@ IN NS ${host}.") ns-hosts) ++
+ (mapAttrsToList (host: ip: "${host} IN A ${ip}") ns-hosts));
+
+in {
+
+ options.fudo.dns = with types; {
+ enable = mkEnableOption "Enable master DNS services.";
+
+ # FIXME: This should allow for AAAA addresses too...
+ dns-hosts = mkOption {
+ type = loaOf str;
+ description = "Map of domain nameserver FQDNs to IP.";
+ example = { "ns1.domain.com" = "1.1.1.1"; };
+ };
+
+ domains = mkOption {
+ type = loaOf (submodule domainOpts);
+ 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"];
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.nsd = {
+ enable = true;
+ identity = "procul.informis.land";
+ interfaces = cfg.listen-ips;
+ zones = mapAttrs' (dom: dom-cfg:
+ nameValuePair "${dom}." {
+ dnssec = dom-cfg.dnssec;
+
+ data = ''
+ $ORIGIN ${dom}.
+ $TTL 12h
+
+ @ IN SOA ns1.${dom}. hostmaster.${dom}. (
+ ${toString builtins.currentTime}
+ 5m
+ 2m
+ 6w
+ 5m)
+
+ ${optionalString (dom-cfg.default-host != null) "@ IN A ${dom-cfg.default-host}"}
+
+ ${mxRecords dom-cfg.mx}
+
+ $TTL 6h
+
+ ${nsRecords cfg.dns-hosts}
+
+ ${dmarcRecord dom-cfg.dmarc-report-address}
+
+ ${join-lines (mapAttrsToList makeSrvProtocolRecords dom-cfg.srv-records)}
+ ${join-lines (mapAttrsToList hostARecords dom-cfg.hosts)}
+ ${join-lines (mapAttrsToList hostSshFpRecords dom-cfg.hosts)}
+ ${join-lines (mapAttrsToList cnameRecord dom-cfg.aliases)}
+ ${join-lines dom-cfg.extra-dns-records}
+ '';
+ }) cfg.domains;
+ };
+ };
+}
diff --git a/config/fudo/local-network.nix b/config/fudo/local-network.nix
index 29967c2..4cc653a 100644
--- a/config/fudo/local-network.nix
+++ b/config/fudo/local-network.nix
@@ -1,96 +1,276 @@
-# UNFINISHED!
-#
-# The plan is to bootstrap a local network config: DNS, DHCP, etc.
-
{ lib, config, pkgs, ... }:
with lib;
let
- hostOpts = { config, ... }: {
- options = {
- ipv6Address = mkOption {
- type = types.str;
- description = ''
- The V6 IP of a given host, if any.
- '';
- };
+ cfg = config.fudo.local-network;
- ipv4Address = mkOption {
+ join-lines = concatStringsSep "\n";
+
+ ip = import ../../lib/ip.nix { lib = lib; };
+
+ hostOpts = { hostname, ... }: {
+ options = {
+ ip-address = mkOption {
type = types.str;
description = ''
The V4 IP of a given host, if any.
'';
};
- macAddress = mkOption {
+ mac-address = mkOption {
type = types.str;
description = ''
The MAC address of a given host, if desired for IP reservation.
'';
};
+
+ ssh-fingerprints = mkOption {
+ type = with types; listOf str;
+ description = "A list of DNS SSHFP records for this host.";
+ default = [];
+ };
};
};
- localNameServerOpts = { config, ... }: {
+ traceout = out: builtins.trace out out;
+
+ srvRecordOpts = with types; {
options = {
- ipv6Address = mkOption {
- type = types.str;
- description = ''
- The V6 IP of this nameserver, if any.
- '';
+ weight = mkOption {
+ type = int;
+ description = "Weight relative to other records.";
+ default = 1;
};
- ipv4Address = mkOption {
- type = types.str;
- description = ''
- The V4 IP of this nameserver, if any.
- '';
+ priority = mkOption {
+ type = int;
+ description = "Priority to give this record.";
+ default = 0;
};
- ipv4ReverseDomain = mkOption {
- type = types.str;
- description = ''
- The domain of the IPv4 address range for which this nameserver is responsible.
+ port = mkOption {
+ type = port;
+ description = "Port to use when connecting.";
+ };
- Eg: 0.10.in-addr.arpa
- '';
+ host = mkOption {
+ type = str;
+ description = "Host to contact for this service.";
+ example = "my-host.my-domain.com.";
};
};
};
in {
- options = {
+ options.fudo.local-network = {
- fudo.localNetwork.hosts = mkOption {
- type = types.listOf (submodule hostOpts);
+ enable = mkEnableOption "Enable local network configuration (DHCP & DNS).";
+
+ hosts = mkOption {
+ type = with types; loaOf (submodule hostOpts);
default = {};
- description = ''
- A map of hostname => { host_attributes }.
- '';
+ description = "A map of hostname => { host_attributes }.";
};
- fudo.localNetwork.domain = mkOption {
+ domain = mkOption {
+ type = types.str;
+ description = "The domain to use for the local network.";
+ };
+
+ dns-servers = mkOption {
+ type = with types; listOf str;
+ description = "A list of domain name server to use for the local network.";
+ };
+
+ dhcp-interfaces = mkOption {
+ type = with types; listOf str;
+ description = "A list of interfaces on which to serve DHCP.";
+ };
+
+ dns-serve-ips = mkOption {
+ type = with types; listOf str;
+ description = "A list of IPs on which to server DNS queries.";
+ };
+
+ gateway = mkOption {
+ type = types.str;
+ description = "The gateway to use for the local network.";
+ };
+
+ aliases = mkOption {
+ type = with types; loaOf str;
+ default = {};
+ description = "A mapping of host-alias => hostname to use on the local network.";
+ };
+
+ network = mkOption {
+ type = types.str;
+ description = "Network to treat as local.";
+ };
+
+ enable-reverse-mappings = mkOption {
+ type = types.bool;
+ description = "Genereate PTR reverse lookup records.";
+ default = false;
+ };
+
+ dhcp-dynamic-network = mkOption {
type = types.str;
description = ''
- The domain to use for the local network.
+ The network from which to dynamically allocate IPs via DHCP.
+
+ Must be a subnet of .
'';
};
- fudo.localNetwork.hostAliases = mkOption {
- type = types.attrsOf types.str;
+ recursive-resolver = mkOption {
+ type = types.str;
+ description = "DNS nameserver to use for recursive resolution.";
+ };
+
+ server-ip = mkOption {
+ type = types.str;
+ description = "IP of the DNS server.";
+ };
+
+ extra-dns-records = mkOption {
+ type = with types; listOf str;
+ description = "Records to be inserted verbatim into the DNS zone.";
+ example = ["some-host IN CNAME other-host"];
+ default = [];
+ };
+
+ srv-records = mkOption {
+ type = with types; attrsOf (attrsOf (listOf (submodule srvRecordOpts)));
+ description = "Map of traffic type to srv records.";
default = {};
- description = ''
- A mapping of hostAlias => hostName to use on the local network.
+ example = {
+ tcp = {
+ kerberos = {
+ port = 88;
+ host = "auth-host.my-domain.com";
+ };
+ };
+ };
+ };
+
+ search-domains = mkOption {
+ type = with types; listOf str;
+ description = "A list of domains to search for DNS names.";
+ example = ["my-domain.com" "other-domain.com"];
+ default = [];
+ };
+
+ # TODO: srv records
+ };
+
+ config = mkIf cfg.enable {
+ services.dhcpd4 = {
+ enable = true;
+
+ machines = mapAttrsToList (hostname: hostOpts: {
+ ethernetAddress = hostOpts.mac-address;
+ hostName = hostname;
+ ipAddress = hostOpts.ip-address;
+ }) cfg.hosts;
+
+ interfaces = cfg.dhcp-interfaces;
+
+ extraConfig = ''
+ subnet ${ip.getNetworkBase cfg.network} netmask ${ip.maskFromV32Network cfg.network} {
+ authoritative;
+ option subnet-mask ${ip.maskFromV32Network cfg.network};
+ option broadcast-address ${ip.networkMaxIp cfg.network};
+ option routers ${cfg.gateway};
+ option domain-name-servers ${concatStringsSep " " cfg.dns-servers};
+ option domain-name "${cfg.domain}";
+ option domain-search ${join-lines (map (dom: "\"${dom}\"") ([cfg.domain] ++ cfg.search-domains))};
+ range ${ip.networkMinIp cfg.dhcp-dynamic-network} ${ip.networkMaxButOneIp cfg.dhcp-dynamic-network};
+ }
'';
};
- fudo.localNetwork.localNameServer = mkOption {
- type = (submodule localNameServerOpts);
- description = ''
- The master nameserver of the local network.
- '';
+ services.bind = let
+ blockHostsToZone = block: hosts-data: {
+ master = true;
+ name = "${block}.in-addr.arpa";
+ file = let
+ # We should add these...but need a domain to assign them to.
+ # ip-last-el = ip: toInt (last (splitString "." ip));
+ # used-els = map (host-data: ip-last-el host-data.ip-address) hosts-data;
+ # unused-els = subtractLists used-els (map toString (range 1 255));
+
+ in pkgs.writeText "db.${block}-zone" ''
+ $ORIGIN ${block}.in-addr.arpa.
+ $TTL 1h
+
+ @ IN SOA ns1.${cfg.domain}. hostmaster.${cfg.domain}. (
+ ${toString builtins.currentTime}
+ 1800
+ 900
+ 604800
+ 1800)
+
+ @ IN NS ns1.${cfg.domain}.
+
+ ${join-lines (map hostPtrRecord hosts-data)}
+ '';
+ };
+
+ ipToBlock = ip: concatStringsSep "." (reverseList (take 3 (splitString "." ip)));
+ compactHosts = mapAttrsToList (host: data: data // { host = host; }) cfg.hosts;
+ hostsByBlock = groupBy (host-data: ipToBlock host-data.ip-address) compactHosts;
+ hostPtrRecord = host-data:
+ "${last (splitString "." host-data.ip-address)} IN PTR ${host-data.host}.${cfg.domain}.";
+
+ blockZones = mapAttrsToList blockHostsToZone hostsByBlock;
+
+ hostARecord = host: data: "${host} IN A ${data.ip-address}";
+ hostSshFpRecords = host: data: join-lines (map (sshfp: "${host} IN SSHFP ${sshfp}") data.ssh-fingerprints);
+ cnameRecord = alias: host: "${alias} IN CNAME ${host}";
+
+ makeSrvRecords = protocol: type: records:
+ join-lines (map (record: "_${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);
+
+ in {
+ enable = true;
+ cacheNetworks = [ cfg.network "localhost" "localnets" ];
+ forwarders = [ cfg.recursive-resolver ];
+ listenOn = cfg.dns-serve-ips;
+ zones = [
+ {
+ master = true;
+ name = cfg.domain;
+ file = pkgs.writeText "${cfg.domain}-zone" ''
+ @ IN SOA ns1.${cfg.domain}. hostmaster.${cfg.domain}. (
+ ${toString builtins.currentTime}
+ 5m
+ 2m
+ 6w
+ 5m)
+
+ $TTL 1h
+
+ @ IN NS ns1.${cfg.domain}.
+
+ $ORIGIN ${cfg.domain}.
+
+ $TTL 30m
+
+ ns1 IN A ${cfg.server-ip}
+ ${join-lines (mapAttrsToList hostARecord cfg.hosts)}
+ ${join-lines (mapAttrsToList hostSshFpRecords cfg.hosts)}
+ ${join-lines (mapAttrsToList cnameRecord cfg.aliases)}
+ ${join-lines cfg.extra-dns-records}
+ ${join-lines (mapAttrsToList makeSrvProtocolRecords cfg.srv-records)}
+ '';
+ }
+ ] ++ blockZones;
};
};
}
diff --git a/config/fudo/mail-container.nix b/config/fudo/mail-container.nix
index aa7edb5..e12b9ff 100644
--- a/config/fudo/mail-container.nix
+++ b/config/fudo/mail-container.nix
@@ -160,21 +160,21 @@ in rec {
};
};
- users = {
- users = {
- ${container-mail-user} = {
- isSystemUser = true;
- uid = container-mail-user-id;
- group = "mailer";
- };
- };
+ # users = {
+ # users = {
+ # ${container-mail-user} = {
+ # isSystemUser = true;
+ # uid = container-mail-user-id;
+ # group = "mailer";
+ # };
+ # };
- groups = {
- ${container-mail-group} = {
- members = ["mailer"];
- };
- };
- };
+ # groups = {
+ # ${container-mail-group} = {
+ # members = ["mailer"];
+ # };
+ # };
+ # };
fudo.mail-server = {
enable = true;
@@ -193,10 +193,12 @@ in rec {
dovecot = {
ssl-certificate = "/etc/${container-dovecot-cert}";
ssl-private-key = "/etc/dovecot-certs/key.pem";
- ldap-ca = "/etc/${container-fudo-ca-cert}";
- ldap-urls = cfg.dovecot.ldap-urls;
- ldap-reader-dn = cfg.dovecot.ldap-reader-dn;
- ldap-reader-passwd = cfg.dovecot.ldap-reader-passwd;
+ ldap = {
+ # ca = "/etc/${container-fudo-ca-cert}";
+ server-urls = cfg.dovecot.ldap.server-urls;
+ reader-dn = cfg.dovecot.ldap.reader-dn;
+ reader-passwd = cfg.dovecot.ldap.reader-passwd;
+ };
};
local-domains = cfg.local-domains;
diff --git a/config/fudo/mail.nix b/config/fudo/mail.nix
index 7b664a8..ba350fd 100644
--- a/config/fudo/mail.nix
+++ b/config/fudo/mail.nix
@@ -104,6 +104,7 @@ in {
user-aliases = mkOption {
type = with types; loaOf(listOf str);
description = "A map of real user to list of aliases.";
+ default = {};
example = {
someuser = ["alias0" "alias1"];
};
@@ -167,4 +168,22 @@ in {
./mail/rspamd.nix
./mail/clamav.nix
];
+
+ config = mkIf cfg.enable {
+ users = {
+ users = {
+ mailuser = {
+ isSystemUser = true;
+ uid = cfg.mail-user-id;
+ group = "mailgroup";
+ };
+ };
+
+ groups = {
+ mailgroup = {
+ members = ["mailuser"];
+ };
+ };
+ };
+ };
}
diff --git a/config/fudo/mail/dovecot.nix b/config/fudo/mail/dovecot.nix
index 6c5d4fd..ae994b7 100644
--- a/config/fudo/mail/dovecot.nix
+++ b/config/fudo/mail/dovecot.nix
@@ -23,57 +23,85 @@ let
'';
};
- ldap-conf = filename: uris:
- pkgs.writeText filename ''
- uris = ${concatStringsSep " " uris}
+ ldap-conf = filename: config:
+ let
+ ssl-config = if config.ca == null then ''
+ tls = no
+ tls_require_cert = try
+ '' else ''
+ tls_ca_cert_file = ${config.ca}
+ tls = yes
+ tls_require_cert = try
+ '';
+
+ in
+ pkgs.writeText filename ''
+ uris = ${concatStringsSep " " config.server-urls}
ldap_version = 3
- dn = ${cfg.dovecot.ldap-reader-dn}
- dnpass = ${cfg.dovecot.ldap-reader-passwd}
+ dn = ${config.reader-dn}
+ dnpass = ${config.reader-passwd}
auth_bind = yes
auth_bind_userdn = uid=%u,ou=members,dc=fudo,dc=org
base = dc=fudo,dc=org
- # tls_ca_cert_file = ${cfg.dovecot.ldap-ca}
- # FIXME: turn back on when certs work
- tls = no
- tls_require_cert = try
+ ${ssl-config}
'';
+ ldap-passwd-entry = ldap-config: ''
+ passdb {
+ driver = ldap
+ args = ${ldap-conf "ldap-passdb.conf" ldap-config}
+ }
+ '';
+
+ ldapOpts = {
+ options = with types; {
+ ca = mkOption {
+ type = nullOr str;
+ description = "The path to the CA cert used to sign the LDAP server certificate.";
+ default = null;
+ };
+
+ server-urls = mkOption {
+ type = listOf str;
+ description = "A list of LDAP server URLs used for authentication.";
+ };
+
+ reader-dn = mkOption {
+ type = str;
+ description = ''
+ DN to use for reading user information. Needs access to homeDirectory,
+ uidNumber, gidNumber, and uid, but not password attributes.
+ '';
+ };
+
+ reader-passwd = mkOption {
+ type = str;
+ description = ''
+ Password for the user specified in ldap-reader-dn.
+ '';
+ };
+ };
+ };
+
dovecot-user = config.services.dovecot2.user;
in {
- options.fudo.mail-server.dovecot = {
+ options.fudo.mail-server.dovecot = with types; {
ssl-private-key = mkOption {
- type = types.str;
+ type = str;
description = "Location of the server SSL private key.";
};
ssl-certificate = mkOption {
- type = types.str;
+ type = str;
description = "Location of the server SSL certificate.";
};
- ldap-ca = mkOption {
- type = types.str;
- description = "The path to the CA cert used to sign the LDAP server certificate.";
- };
-
- ldap-urls = mkOption {
- type = with types; listOf str;
- description = "The urls of LDAP servers.";
- };
-
- ldap-reader-dn = mkOption {
- type = types.str;
+ ldap = mkOption {
+ type = nullOr (submodule ldapOpts);
+ default = null;
description = ''
- DN to use for reading user information. Needs access to homeDirectory,
- uidNumber, gidNumber, and uid, but not password attributes.
- '';
- };
-
- ldap-reader-passwd = mkOption {
- type = types.str;
- description = ''
- Password for the user specified in ldap-reader-dn.
+ LDAP auth server configuration. If omitted, the server will use local authentication.
'';
};
};
@@ -93,8 +121,7 @@ in {
enableImap = true;
enableLmtp = true;
enablePop3 = true;
- enablePAM = false;
-
+ enablePAM = cfg.dovecot.ldap == null;
createMailUser = true;
@@ -124,14 +151,16 @@ in {
extraConfig = ''
#Extra Config
- # The prometheus exporter still expects an older style of metrics
- mail_plugins = $mail_plugins old_stats
- service old-stats {
- unix_listener old-stats {
- user = dovecot-exporter
- group = dovecot-exporter
+ ${optionalString cfg.monitoring ''
+ # The prometheus exporter still expects an older style of metrics
+ mail_plugins = $mail_plugins old_stats
+ service old-stats {
+ unix_listener old-stats {
+ user = dovecot-exporter
+ group = dovecot-exporter
+ }
}
- }
+ ''}
${lib.optionalString cfg.debug ''
mail_debug = yes
@@ -170,15 +199,15 @@ in {
}
# Drop privs, since all mail is owned by one user
- user = ${cfg.mail-user}
- group = ${cfg.mail-group}
+ # user = ${cfg.mail-user}
+ # group = ${cfg.mail-group}
+ user = root
}
auth_mechanisms = login plain
- passdb {
- driver = ldap
- args = ${ldap-conf "ldap-passdb.conf" cfg.dovecot.ldap-urls}
- }
+
+ ${optionalString (cfg.dovecot.ldap != null)
+ (ldap-passwd-entry cfg.dovecot.ldap)}
userdb {
driver = static
args = uid=${toString cfg.mail-user-id} home=${cfg.mail-directory}/%u
@@ -189,8 +218,18 @@ in {
unix_listener auth {
mode = 0660
user = "${config.services.postfix.user}"
- group = ${config.services.postfix.group}
+ group = ${cfg.mail-group}
}
+
+ unix_listener auth-userdb {
+ mode = 0660
+ user = "${config.services.postfix.user}"
+ group = ${cfg.mail-group}
+ }
+ }
+
+ service auth-worker {
+ user = root
}
namespace inbox {
@@ -236,7 +275,8 @@ in {
done
chown -R '${dovecot-user}:${cfg.mail-group}' '${state-directory}/imap_sieve'
- chown ${cfg.mail-user}:${cfg.mail-group} ${cfg.mail-directory}
+ chown '${cfg.mail-user}:${cfg.mail-group}' ${cfg.mail-directory}
+ chmod g+w ${cfg.mail-directory}
'';
};
}
diff --git a/config/fudo/mail/postfix.nix b/config/fudo/mail/postfix.nix
index 776c584..d05bf6d 100644
--- a/config/fudo/mail/postfix.nix
+++ b/config/fudo/mail/postfix.nix
@@ -6,6 +6,14 @@ let
cfg = config.fudo.mail-server;
+ # The final newline is important
+ write-entries = filename: entries:
+ let
+ entries-string = (concatStringsSep "\n" entries);
+ in builtins.toFile filename ''
+ ${entries-string}
+ '';
+
make-user-aliases = entries:
concatStringsSep "\n"
(mapAttrsToList (user: aliases:
@@ -39,25 +47,22 @@ let
/^User-Agent:/ IGNORE
/^X-Enigmail:/ IGNORE
'');
-
blacklist-postfix-entry = sender: "${sender} REJECT";
- blacklist-postfix-file = entries:
- concatStringsSep "\n" (map blacklist-postfix-entry entries);
- sender-blacklist-file = builtins.toFile "reject_senders"
- (blacklist-postfix-file cfg.sender-blacklist);
- recipient-blacklist-file = builtins.toFile "reject_recipients"
- (blacklist-postfix-file cfg.recipient-blacklist);
+ blacklist-postfix-file = filename: entries:
+ write-entries filename entries;
+ sender-blacklist-file = blacklist-postfix-file "reject_senders"
+ (map blacklist-postfix-entry cfg.sender-blacklist);
+ recipient-blacklist-file = blacklist-postfix-file "reject_recipients"
+ (map blacklist-postfix-entry cfg.recipient-blacklist);
# A list of domains for which we accept mail
- virtual-mailbox-map-file = builtins.toFile "virtual_mailbox_map"
- (concatStringsSep "\n"
- (map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain])));
+ virtual-mailbox-map-file = write-entries "virtual_mailbox_map"
+ (map (domain: "@${domain} OK") (cfg.local-domains ++ [cfg.domain]));
sender-login-map-file = let
escapeDot = (str: replaceStrings ["."] ["\\."] str);
- in builtins.toFile "sender_login_maps"
- (concatStringsSep "\n"
- (map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain])));
+ in write-entries "sender_login_maps"
+ (map (domain: "/^(.*)@${escapeDot domain}$/ \${1}") (cfg.local-domains ++ [cfg.domain]));
mapped-file = name: "hash:/var/lib/postfix/conf/${name}";
@@ -106,9 +111,8 @@ in {
origin = cfg.domain;
hostname = cfg.hostname;
destination = ["localhost" "localhost.localdomain"];
- # destination = ["localhost" "localhost.localdomain"] ++
- # (map (domain: "localhost.${domain}") cfg.local-domains) ++
- # cfg.local-domains;
+ # destination = ["localhost" "localhost.localdomain" cfg.hostname] ++
+ # cfg.local-domains;;
enableHeaderChecks = true;
enableSmtp = true;
@@ -133,7 +137,7 @@ in {
sslKey = cfg.postfix.ssl-private-key;
config = {
- virtual_mailbox_domains = builtins.toFile "domain-list" (concatStringsSep "\n" cfg.local-domains);
+ virtual_mailbox_domains = cfg.local-domains ++ [cfg.domain];
# virtual_mailbox_base = "${cfg.mail-directory}/";
virtual_mailbox_maps = mapped-file "virtual_mailbox_map";
diff --git a/config/fudo/secure-dns-proxy.nix b/config/fudo/secure-dns-proxy.nix
new file mode 100644
index 0000000..3f481e1
--- /dev/null
+++ b/config/fudo/secure-dns-proxy.nix
@@ -0,0 +1,62 @@
+{ lib, pkgs, config, ... }:
+
+with lib;
+let
+ cfg = config.fudo.secure-dns-proxy;
+
+in {
+ options.fudo.secure-dns-proxy = {
+ enable = mkEnableOption "Enable a DNS server using an encrypted upstream source.";
+
+ port = mkOption {
+ type = types.port;
+ description = "Port on which to listen for DNS queries.";
+ default = 53;
+ };
+
+ upstream-dns = mkOption {
+ type = with types; listOf str;
+ description = ''
+ The upstream DNS services to use, in a format useable by dnsproxy.
+
+ See: https://github.com/AdguardTeam/dnsproxy
+ '';
+ default = ["https://cloudflare-dns.com/dns-query"];
+ };
+
+ bootstrap-dns = mkOption {
+ type = types.str;
+ description = "A simple DNS server from which HTTPS DNS can be bootstrapped, if necessary.";
+ default = "1.1.1.1";
+ };
+
+ listen-ips = mkOption {
+ type = with types; listOf str;
+ description = "A list of local IP addresses on which to listen.";
+ default = ["0.0.0.0"];
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [
+ dnsproxy
+ ];
+
+ systemd.services.secure-dns-proxy = {
+ enable = true;
+ wantedBy = [ "multi-user.target" ];
+ after = [ "network.target" ];
+ description = "DNS Proxy for secure DNS lookups";
+ serviceConfig = let
+ upstreams = map (upstream: "-u ${upstream}") cfg.upstream-dns;
+ upstream-line = concatStringsSep " " upstreams;
+ listen-line = concatStringsSep " "
+ (map (listen: "-l ${listen}") cfg.listen-ips);
+ cmd = "${pkgs.dnsproxy}/bin/dnsproxy -p ${toString cfg.port} ${upstream-line} ${listen-line} -b ${cfg.bootstrap-dns}";
+
+ in {
+ ExecStart = cmd;
+ };
+ };
+ };
+}
diff --git a/config/fudo/slynk.nix b/config/fudo/slynk.nix
new file mode 100644
index 0000000..8ae12ed
--- /dev/null
+++ b/config/fudo/slynk.nix
@@ -0,0 +1,70 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.fudo.slynk;
+
+ initScript = port: load-paths: let
+ load-path-string =
+ concatStringsSep " " (map (path: "\"${path}\"") load-paths);
+ in pkgs.writeText "slynk.lisp" ''
+ (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))
+ (ql:quickload :slynk)
+ (setf asdf:*central-registry*
+ (append asdf:*central-registry*
+ (list ${load-path-string})))
+ (slynk:create-server :port ${toString port} :dont-close t)
+ (dolist (var '("LD_LIBRARY_PATH"))
+ (format t "~S: ~S~%" var (sb-unix::posix-getenv var)))
+
+ (loop (sleep 60))
+ '';
+
+ lisp-libs = with pkgs.lispPackages; [
+ alexandria
+ asdf-package-system
+ asdf-system-connections
+ cl_plus_ssl
+ cl-ppcre
+ quicklisp
+ quri
+ uiop
+ usocket
+ ];
+
+in {
+ options.fudo.slynk = {
+ enable = mkEnableOption "Enable Slynk emacs common lisp server.";
+
+ port = mkOption {
+ type = types.int;
+ description = "Port on which to open a Slynk server.";
+ default = 4005;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.user.services.slynk = {
+ description = "Slynk Common Lisp server.";
+
+ serviceConfig = let
+ load-paths = (map (pkg: "${pkg}/lib/common-lisp/") lisp-libs);
+ in {
+ ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init";
+ ExecStart = "${pkgs.sbcl}/bin/sbcl --load ${initScript cfg.port load-paths}";
+ Restart = "on-failure";
+ PIDFile = "/run/slynk.$USERNAME.pid";
+ };
+
+ path = with pkgs; [
+ gcc
+ glibc # for getent
+ file
+ ];
+
+ environment = {
+ LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib";
+ };
+ };
+ };
+}
diff --git a/config/fudo/webmail.nix b/config/fudo/webmail.nix
index d2c4f4e..cf93502 100644
--- a/config/fudo/webmail.nix
+++ b/config/fudo/webmail.nix
@@ -186,7 +186,7 @@ let
};
password-file = mkOption {
- type = types.path;
+ type = types.str;
description = "Password to use when connecting to the database.";
};
};
diff --git a/config/informis/cl-gemini.nix b/config/informis/cl-gemini.nix
new file mode 100644
index 0000000..172a92b
--- /dev/null
+++ b/config/informis/cl-gemini.nix
@@ -0,0 +1,212 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.informis.cl-gemini;
+
+ lisp-libs = with pkgs.lispPackages; [
+ asdf-package-system
+ asdf-system-connections
+ alexandria
+ asdf-package-system
+ asdf-system-connections
+ cl_plus_ssl
+ cl-ppcre
+ quicklisp
+ quri
+ uiop
+ usocket
+ ];
+
+ launchServer = ip: port: root: public-dir: key: cert: slynk-port: feeds-string: textfiles-archive:
+ pkgs.writeText "launch-server.lisp" ''
+ (load (merge-pathnames "quicklisp/setup.lisp" (user-homedir-pathname)))
+ (ql:quickload :slynk)
+ (ql:quickload :cl-gemini)
+ ${optionalString (slynk-port != null) "(slynk:create-server :port ${toString slynk-port} :dont-close t)"}
+ ${feeds-string}
+ (cl-gemini:start-gemini-server "${ip}" "${key}" "${cert}"
+ :port ${toString port}
+ :document-root "${root}"
+ :textfiles-root "${textfiles-archive}"
+ :file-cmd "${pkgs.file}/bin/file"
+ :log-stream *standard-output*
+ :threaded t
+ :separate-thread t)
+ (loop (sleep 60))
+ '';
+
+ sbcl-with-ssl = pkgs.sbcl.overrideAttrs (oldAttrs: rec {
+ extraLibs = with pkgs; [
+ openssl_1_1.dev
+ ];
+ });
+
+ feedOpts = with types; {
+ options = {
+ url = mkOption {
+ type = str;
+ description = "Base URI of the feed, i.e. the URI corresponding to the feed path.";
+ example = "gemini://my.server/path/to/feedfiles";
+ };
+
+ title = mkOption {
+ type = str;
+ description = "Title of given feed.";
+ example = "My Fancy Feed";
+ };
+
+ path = mkOption {
+ type = str;
+ description = "Path to Gemini files making up the feed.";
+ example = "/path/to/feed";
+ };
+ };
+ };
+
+ register-feed = name: opts: ''
+ (cl-gemini:register-feed :name "${name}" :title "${opts.title}" :path "${opts.path}" :base-uri "${opts.url}")'';
+
+ register-feeds = feeds:
+ concatStringsSep "\n"
+ (mapAttrsToList register-feed feeds);
+
+
+in {
+ options.informis.cl-gemini = with types; {
+ enable = mkEnableOption "Enable the cl-gemini server.";
+
+ port = mkOption {
+ type = port;
+ description = "Port on which to serve Gemini traffic.";
+ default = 1965;
+ };
+
+ server-ip = mkOption {
+ type = str;
+ description = "IP on which to serve Gemini traffic.";
+ example = "1.2.3.4";
+ };
+
+ document-root = mkOption {
+ type = str;
+ description = "Root at which to look for gemini files.";
+ example = "/my/gemini/root";
+ };
+
+ user-public = mkOption {
+ type = str;
+ description = "Subdirectory of user homes to check for gemini files.";
+ default = "gemini-public";
+ };
+
+ ssl-private-key = mkOption {
+ type = path;
+ description = "Path to the pem-encoded server private key.";
+ example = /path/to/secret/key.pem;
+ };
+
+ ssl-certificate = mkOption {
+ type = path;
+ description = "Path to the pem-encoded server public certificate.";
+ example = /path/to/cert.pem;
+ };
+
+ slynk-port = mkOption {
+ type = nullOr port;
+ description = "Port on which to open a slynk server, if any.";
+ default = null;
+ };
+
+ feeds = mkOption {
+ type = loaOf (submodule feedOpts);
+ description = "Feeds to generate and make available (as eg. /feed/name.xml).";
+ example = {
+ diary = {
+ title = "My Diary";
+ path = "/path/to/my/gemfiles/";
+ url = "gemini://my.host/blog-path/";
+ };
+ };
+ default = {};
+ };
+
+ textfiles-archive = mkOption {
+ type = str;
+ description = "A path containing only gemini & text files.";
+ example = "/path/to/textfiles/";
+ };
+ };
+
+ config = mkIf cfg.enable {
+
+ environment.systemPackages = with pkgs; [
+ cl-gemini
+ ];
+
+ users.users = {
+ cl-gemini = {
+ isSystemUser = true;
+ group = "nogroup";
+ createHome = true;
+ home = "/var/lib/cl-gemini";
+ };
+ };
+
+ environment.etc = {
+ "cl-gemini/key.pem" = {
+ mode = "0400";
+ user = "cl-gemini";
+ source = cfg.ssl-private-key;
+ };
+
+ "cl-gemini/cert.pem" = {
+ mode = "0444";
+ user = "cl-gemini";
+ source = cfg.ssl-certificate;
+ };
+ };
+
+ systemd.services.cl-gemini = {
+ description = "cl-gemini Gemini server (https://gemini.circumlunar.space/)";
+
+ serviceConfig = let
+ feed-registrations = register-feeds cfg.feeds;
+ in {
+ ExecStartPre = "${pkgs.lispPackages.quicklisp}/bin/quicklisp init";
+ ExecStart = "${sbcl-with-ssl}/bin/sbcl --load ${
+ launchServer
+ cfg.server-ip
+ cfg.port
+ cfg.document-root
+ cfg.user-public
+ "/etc/cl-gemini/key.pem"
+ "/etc/cl-gemini/cert.pem"
+ cfg.slynk-port
+ feed-registrations
+ cfg.textfiles-archive
+ }";
+ Restart = "on-failure";
+ PIDFile = "/run/cl-gemini.$USERNAME.uid";
+ User = "cl-gemini";
+ };
+
+ environment = {
+ LD_LIBRARY_PATH = "${pkgs.openssl_1_1.out}/lib";
+ CL_SOURCE_REGISTRY = concatStringsSep ":"
+ (["${config.users.users.cl-gemini.home}/quicklisp/quicklisp"] ++
+ (map
+ (pkg: "${pkg}//")
+ (lisp-libs ++ [pkgs.cl-gemini])));
+ };
+
+ path = with pkgs; [
+ gcc
+ file
+ getent
+ ];
+
+ wantedBy = [ "default.target" ];
+ };
+ };
+}
diff --git a/config/local.nix b/config/local.nix
index 0e3b01f..a3e43b2 100644
--- a/config/local.nix
+++ b/config/local.nix
@@ -7,19 +7,25 @@ with lib;
./fudo/authentication.nix
./fudo/chat.nix
./fudo/common.nix
+ ./fudo/dns.nix
./fudo/git.nix
./fudo/grafana.nix
./fudo/kdc.nix
./fudo/ldap.nix
+ ./fudo/local-network.nix
./fudo/mail.nix
./fudo/mail-container.nix
./fudo/minecraft-server.nix
./fudo/node-exporter.nix
./fudo/postgres.nix
./fudo/prometheus.nix
+ ./fudo/secure-dns-proxy.nix
+ ./fudo/slynk.nix
./fudo/system.nix
./fudo/webmail.nix
+ ./informis/cl-gemini.nix
+
../fudo/profiles
../fudo/sites
];
diff --git a/configuration.nix b/configuration.nix
deleted file mode 120000
index 4de3171..0000000
--- a/configuration.nix
+++ /dev/null
@@ -1 +0,0 @@
-./hosts/france.nix
\ No newline at end of file
diff --git a/defaults.nix b/defaults.nix
index 8e9334b..c6099b9 100644
--- a/defaults.nix
+++ b/defaults.nix
@@ -18,6 +18,7 @@
autoconf
automake
bash
+ boot
bind
binutils
btrfs-progs
@@ -28,8 +29,11 @@
certbot
clang
curl
+ dpkg
emacs
+ enca
fail2ban
+ file
fortune
gcc
git
@@ -44,6 +48,7 @@
jdk
kerberos
libisofs
+ libstdcxxHook
lispPackages.alexandria
lispPackages.cl-ppcre
lispPackages.clx
@@ -51,6 +56,8 @@
lshw
mkpasswd
ncurses5
+ nix-index
+ nix-prefetch-git
nmap
oidentd
openldap
@@ -58,6 +65,7 @@
openssl_1_1
openssh_gssapi
pciutils
+ pinentry.curses
pv
pwgen
racket
@@ -73,19 +81,28 @@
unzip
vim
wget
+ yubikey-manager
+ yubikey-personalization
];
- system.stateVersion = "19.09";
+ system.stateVersion = "20.03";
system.autoUpgrade.enable = true;
environment.etc.current-nixos-config.source = ./.;
krb5.enable = true;
- krb5.libdefaults.default_realm = "FUDO.ORG";
krb5.kerberos = pkgs.heimdalFull;
- console.keyMap = "dvp";
+ services.xserver = {
+ layout = "us";
+ xkbVariant = "dvp";
+ xkbOptions = "ctrl:nocaps";
+ };
+
+ console = {
+ useXkbConfig = true;
+ };
i18n = {
defaultLocale = "en_US.UTF-8";
@@ -95,6 +112,8 @@
mosh.enable = true;
ssh = {
+ startAgent = false;
+
extraConfig = ''
GSSAPIAuthentication yes
GSSAPIDelegateCredentials yes
@@ -129,8 +148,21 @@
GSSAPICleanupCredentials yes
'';
};
+
+ pcscd = {
+ enable = true;
+ };
+
+ udev.packages = with pkgs; [
+ yubikey-personalization
+ ];
};
+ environment.shellInit = ''
+ gpg-connect-agent /bye
+ export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
+ '';
+
security.pam = {
enableSSHAgentAuth = true;
# TODO: add yubico?
@@ -167,6 +199,9 @@
group = "users";
home = "/home/niten";
hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/";
+ openssh.authorizedKeys.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"
+ ];
};
reaper = {
isNormalUser = true;
diff --git a/fudo/profiles/common-ui.nix b/fudo/profiles/common-ui.nix
new file mode 100644
index 0000000..424fbbf
--- /dev/null
+++ b/fudo/profiles/common-ui.nix
@@ -0,0 +1,179 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ profile = config.fudo.common.profile;
+
+ common-packages = with pkgs; [
+ ffmpeg-full
+ libfixposix
+ mono
+ nomacs
+ python37Packages.youtube-dl
+ sqlite
+ system-config-printer
+ ];
+
+ gui-packages = with pkgs; [
+ cool-retro-term
+ corefonts
+ chrome-gnome-shell
+ chromium
+ evince
+ firefox
+ gimp
+ glxinfo
+ gnome3.gnome-shell
+ gnome3.gnome-session
+ google-chrome
+ gtk2
+ gtk2-x11
+ gtk3
+ gtkimageview
+ i3lock
+ mplayer
+ mpv
+ pdftk
+ redshift
+ rhythmbox
+ shotwell
+ spotify
+ (steam.override {
+ nativeOnly = true;
+ extraPkgs = pkgs: [
+ mono
+ fmodex
+ gtk3
+ gtk3-x11
+ libgdiplus
+ zlib
+ ];
+ withJava = true;
+ }).run
+ virtmanager
+ xorg.xev
+ xzgv
+ virtmanager-qt
+ ];
+
+ cfg = config.fudo.common;
+
+in mkIf ((profile == "desktop") || (profile == "laptop")) {
+ environment.systemPackages =
+ common-packages ++ (if cfg.enable-gui then gui-packages else []);
+
+ nixpkgs.config.allowBroken = true;
+
+ services.avahi = {
+ enable = true;
+ browseDomains = [config.fudo.common.domain];
+ domainName = config.fudo.common.domain;
+ };
+
+ # splash screen
+ boot.plymouth.enable = false;
+
+ boot.tmpOnTmpfs = true;
+
+ services.xserver = if cfg.enable-gui then {
+ enable = true;
+
+ layout = "us";
+ xkbVariant = "dvp";
+ xkbOptions = "ctrl:nocaps";
+
+ desktopManager.gnome3.enable = true;
+
+ displayManager.gdm.enable = true;
+
+ displayManager.defaultSession = "gnome";
+
+ windowManager.session = pkgs.lib.singleton {
+ name = "stumpwm";
+ start = ''
+ ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
+ waidPID=$!
+ '';
+ };
+ } else {
+ layout = "us";
+ xkbVariant = "dvp";
+ xkbOptions = "ctrl:nocaps";
+ };
+
+ services.gnome3 = mkIf cfg.enable-gui {
+ evolution-data-server.enable = pkgs.lib.mkForce false;
+ gnome-user-share.enable = pkgs.lib.mkForce false;
+ };
+
+ services.dbus.socketActivated = true;
+
+ sound.enable = true;
+
+ hardware.pulseaudio.enable = true;
+
+ fonts = mkIf cfg.enable-gui {
+ enableFontDir = true;
+ #fontconfig.antialias = true;
+ fontconfig.enable = 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
+ ];
+ };
+}
diff --git a/fudo/profiles/default.nix b/fudo/profiles/default.nix
index e327416..a4c5892 100644
--- a/fudo/profiles/default.nix
+++ b/fudo/profiles/default.nix
@@ -2,7 +2,9 @@
{
imports = [
+ ./common-ui.nix
./desktop.nix
+ ./laptop.nix
./server.nix
];
}
diff --git a/fudo/profiles/desktop.nix b/fudo/profiles/desktop.nix
index 302fcc9..5d70746 100644
--- a/fudo/profiles/desktop.nix
+++ b/fudo/profiles/desktop.nix
@@ -1,154 +1,8 @@
{ config, lib, pkgs, ... }:
with lib;
-{
- config = mkIf (config.fudo.common.profile == "desktop") {
- environment.systemPackages = with pkgs; [
- cool-retro-term
- chrome-gnome-shell
- chromium
- ffmpeg-full
- firefox
- gimp
- glxinfo
- gnome3.gnome-shell
- gnome3.gnome-session
- google-chrome
- gtk2
- gtk2-x11
- gtk3
- gtkimageview
- i3lock
- libfixposix
- minecraft
- mplayer
- nomacs
- openssl_1_1
- redshift
- rhythmbox
- shotwell
- spotify
- sqlite
- steam
- system-config-printer
- virtmanager
- xorg.xev
- xzgv
- virtmanager-qt
- ];
-
- # Splash screen
- boot.plymouth.enable = true;
-
- services.avahi = {
- enable = true;
- browseDomains = [config.fudo.domain];
- domainName = config.fudo.domain;
- };
-
- boot.tmpOnTmpfs = true;
-
- services.xserver = {
- enable = true;
-
- layout = "us";
- xkbVariant = "dvp";
- xkbOptions = "ctrl:nocaps";
-
- desktopManager.gnome3.enable = true;
- desktopManager.default = "gnome3";
-
- displayManager.gdm.enable = true;
-
- windowManager.session = pkgs.lib.singleton {
- name = "stumpwm";
- start = ''
- ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
- waidPID=$!
- '';
- };
- };
-
- services.printing = {
- enable = true;
- };
-
- services.gnome3 = {
- evolution-data-server.enable = pkgs.lib.mkForce false;
- gnome-user-share.enable = pkgs.lib.mkForce false;
- };
-
- services.dbus.socketActivated = true;
-
- services.openssh.forwardX11 = true;
-
- programs.ssh.forwardX11 = true;
-
- sound.enable = true;
-
- hardware.pulseaudio.enable = true;
-
- fonts = {
- enableCoreFonts = true;
- enableFontDir = true;
- enableGhostscriptFonts = false;
- fontconfig.ultimate.enable = true;
-
- 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
- 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
- ];
- };
+mkIf (config.fudo.common.profile == "desktop") {
+ networking = {
+ networkmanager.enable = mkForce false;
};
}
diff --git a/fudo/profiles/laptop.nix b/fudo/profiles/laptop.nix
new file mode 100644
index 0000000..dfb41fc
--- /dev/null
+++ b/fudo/profiles/laptop.nix
@@ -0,0 +1,41 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+{
+ options.fudo.laptop = {
+ use-network-manager = mkOption {
+ type = types.bool;
+ description = "Use NetworkManager instead of wpa_supplicant.";
+ default = false;
+ };
+ };
+ config = mkIf (config.fudo.common.profile == "laptop") {
+ environment.systemPackages = with pkgs; [
+ acpi
+ upower
+ wpa_supplicant
+ ];
+
+ networking = if (config.fudo.laptop.use-network-manager) then {
+ networkmanager.enable = true;
+ } else {
+ networkmanager.enable = false;
+ wireless = {
+ enable = true;
+ userControlled = {
+ enable = true;
+ group = "wheel";
+ };
+ networks = {
+ "sea.fudo.org" = {
+ psk = "DahHaocheiD5";
+ };
+ "Pixel_9041" = {
+ psk = "ea72027e4e6";
+ };
+ };
+ };
+ };
+ };
+}
diff --git a/fudo/profiles/server.nix b/fudo/profiles/server.nix
index 1011659..7e1b7c3 100644
--- a/fudo/profiles/server.nix
+++ b/fudo/profiles/server.nix
@@ -51,6 +51,8 @@ in {
config = mkIf (config.fudo.common.profile == "server") {
environment = {
systemPackages = with pkgs; [
+ ldns
+ ldns.examples
test-config
reboot-if-necessary
];
diff --git a/fudo/sites/default.nix b/fudo/sites/default.nix
index 6caa1b3..fd59359 100644
--- a/fudo/sites/default.nix
+++ b/fudo/sites/default.nix
@@ -2,6 +2,7 @@
{
imports = [
+ ./joes.nix
./portage.nix
./seattle.nix
];
diff --git a/fudo/sites/joes.nix b/fudo/sites/joes.nix
new file mode 100644
index 0000000..5fcb5a7
--- /dev/null
+++ b/fudo/sites/joes.nix
@@ -0,0 +1,55 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ hostname = config.networking.hostName;
+
+ gateway = "172.86.179.17";
+
+ local-domain = "informis.land";
+
+ admin = "admin@${local-domain}";
+
+in {
+ config = mkIf (config.fudo.common.site == "joes") {
+ time.timeZone = "America/Winnipeg";
+
+ services.cron = {
+ mailto = admin;
+ };
+
+ networking = {
+ domain = local-domain;
+ search = [ local-domain "fudo.org" ];
+ firewall.enable = false;
+
+ defaultGateway = gateway;
+ # defaultGateway6 = gateway6;
+
+ hosts = {
+ "127.0.0.1" = [
+ "${config.networking.hostName}.${local-domain}"
+ config.networking.hostName
+ ];
+ };
+ };
+
+ krb5.libdefaults.default_realm = "INFORMIS.LAND";
+
+ fudo.node-exporter = {
+ enable = false;
+ hostname = hostname;
+ };
+
+ security.acme.certs."${hostname}.${local-domain}" = {
+ email = "admin@${local-domain}";
+ };
+
+ services.nginx = {
+ enable = true;
+ recommendedGzipSettings = true;
+ recommendedOptimisation = true;
+ recommendedTlsSettings = true;
+ };
+ };
+}
diff --git a/fudo/sites/seattle.nix b/fudo/sites/seattle.nix
index 12246a2..3a48232 100644
--- a/fudo/sites/seattle.nix
+++ b/fudo/sites/seattle.nix
@@ -6,24 +6,45 @@ let
local-domain = "sea.fudo.org";
+ gateway = "10.0.0.1";
+
+ nameservers = ["10.0.0.1"];
+
in {
config = mkIf (config.fudo.common.site == "seattle") {
time.timeZone = "America/Los_Angeles";
+ services.printing = {
+ enable = true;
+ };
+
services.cron = {
mailto = admin;
};
+ krb5.libdefaults.default_realm = "FUDO.ORG";
+
networking = {
domain = local-domain;
search = [local-domain "fudo.org"];
firewall.enable = false;
- networkmanager.enable = pkgs.lib.mkForce false;
+ nameservers = nameservers;
- # Until Comcast gets it's shit together... :(
- enableIPv6 = false;
+ # 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;
+
+ enableIPv6 = true;
+
+ # Necessary to make sure than Kerberos and Avahi both work (the former
+ # 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];
+ };
};
users.extraUsers = {
@@ -53,6 +74,12 @@ in {
home = "/home/xiaoxuan";
hashedPassword = "$6$C8lYHrK7KvdKm/RE$cHZ2hg5gEOEjTV8Zoayik8sz5h.Vh0.ClCgOlQn8l/2Qx/qdxqZ7xCsAZ1GZ.IEyESfhJeJbjLpykXDwPpfVF0";
};
+ kevin = {
+ isNormalUser = true;
+ createHome = true;
+ home = "/home/kevin";
+ hashedPassword = "";
+ };
};
fileSystems."/mnt/documents" = {
@@ -84,118 +111,207 @@ in {
fsType = "nfs4";
};
- # Should use this eventually...
- # fudo.localNetwork = {
- # masterNameServer = {
- # ip = "10.0.0.1";
- # ipReverseDomain = "0.10.in-addr.arpa";
- # };
+ fudo.common.domain = "sea.fudo.org";
- # domain = "${local-domain}";
+ fudo.local-network = {
- # hostAliases = {
- # kadmin = "slab";
- # kdc = "slab";
- # photo = "doraemon";
- # music = "doraemon";
- # panopticon = "hyperion";
- # hole = "dnshole";
- # ipfs = "nostromo";
- # };
+ domain = "${local-domain}";
- # hosts = {
- # slab = {
- # ipv4Address = "10.0.0.1";
- # };
- # volsung = {
- # ipv4Address = "10.0.0.106";
- # macAddress = "ac:bc:32:7b:75:a5";
- # };
- # nest = {
- # ipv4Address = "10.0.0.176";
- # macAddress = "18:b4:30:16:7c:5a";
- # };
- # monolith = {
- # ipv4Address = "10.0.0.100";
- # macAddress = "6c:62:6d:c8:b0:d8";
- # };
- # brother-wireless = {
- # ipv4Address = "10.0.0.160";
- # macAddress = "c0:38:96:64:49:65";
- # };
- # doraemon = {
- # ipv4Address = "10.0.0.52";
- # macAddress = "00:11:32:0a:06:c5";
- # };
- # lm = {
- # ipv4Address = "10.0.0.21";
- # macAddress = "52:54:00:D8:34:92";
- # };
- # ubiquiti-wifi = {
- # ipv4Address = "10.0.0.126";
- # macAddress = "04:18:d6:20:48:fb";
- # };
- # front-light = {
- # ipv4Address = "10.0.0.221";
- # macAddress = "94:10:3e:48:94:ed";
- # };
- # ipad = {
- # ipv4Address = "10.0.0.202";
- # macAddress = "9c:35:eb:48:6e:71";
- # };
- # chromecast-2 = {
- # ipv4Address = "10.0.0.215";
- # macAddress = "a4:77:33:59:a2:ba";
- # };
- # taipan = {
- # ipv4Address = "10.0.0.107";
- # macAddress = "52:54:00:34:c4:78";
- # };
- # dns-hole = {
- # ipv4Address = "10.0.0.185";
- # macAddress = "b8:27:eb:b2:95:fd";
- # };
- # family-tv = {
- # ipv4Address = "10.0.0.205";
- # macAddress = "84:a4:66:3a:b1:f8";
- # };
- # spark = {
- # ipv4Address = "10.0.0.108";
- # macAddress = "78:24:af:04:f7:dd";
- # };
- # babycam = {
- # ipv4Address = "10.0.0.206";
- # macAddress = "08:ea:40:59:5f:9e";
- # };
- # hyperion = {
- # ipv4Address = "10.0.0.109";
- # macAddress = "52:54:00:33:46:de";
- # };
- # cargo = {
- # ipv4Address = "10.0.0.50";
- # macAddress = "00:11:32:75:d8:b7";
- # };
- # cam-entrance = {
- # ipv4Address = "10.0.0.31";
- # macAddress = "9c:8e:cd:0e:99:7b";
- # };
- # cam-driveway = {
- # ipv4Address = "10.0.0.32";
- # macAddress = "9c:8e:cd:0d:3b:09";
- # };
- # cam-deck = {
- # ipv4Address = "10.0.0.33";
- # macAddress = "9c:8e:cd:0e:98:c8";
- # };
- # nostromo = {
- # ipv4Address = "10.0.0.2";
- # macAddress = "14:fe:b5:ca:a2:c9";
- # };
- # zbox = {
- # ipv4Address = "10.0.0.110";
- # macAddress = "18:60:24:91:CC:27";
- # };
- # };
- # };
+ aliases = {
+ kadmin = "slab";
+ kdc = "slab";
+ photo = "doraemon";
+ music = "doraemon";
+ panopticon = "hyperion";
+ ipfs = "nostromo";
+ hole = "nostromo";
+ pihole = "nostromo";
+ dns-hole = "nostromo";
+ };
+
+ 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";
+ };
+ switch-master = {
+ ip-address = "10.0.0.5";
+ mac-address = "00:14:1C:B6:BB:40";
+ };
+ # lm = {
+ # ip-address = "10.0.0.21";
+ # mac-address = "52:54:00:D8:34:92";
+ # };
+ 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";
+ };
+ 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";
+ };
+
+
+ # Storage network
+ 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";
+ };
+ };
+ };
};
}
diff --git a/hardware-configuration.nix b/hardware-configuration.nix
deleted file mode 100644
index e6d1fe0..0000000
--- a/hardware-configuration.nix
+++ /dev/null
@@ -1,31 +0,0 @@
-# Do not modify this file! It was generated by ‘nixos-generate-config’
-# and may be overwritten by future invocations. Please make changes
-# to /etc/nixos/configuration.nix instead.
-{ config, lib, pkgs, ... }:
-
-{
- imports =
- [
- ];
-
- boot.initrd.availableKernelModules = [ "uhci_hcd" "ehci_pci" "ata_piix" "ahci" "usb_storage" "floppy" "sd_mod" "sr_mod" ];
- boot.initrd.kernelModules = [ "dm-snapshot" ];
- boot.kernelModules = [ "kvm-intel" ];
- boot.extraModulePackages = [ ];
-
- fileSystems."/" =
- { device = "/dev/disk/by-uuid/87833c39-299b-4e84-9854-beda4a8e0115";
- fsType = "ext4";
- };
-
- fileSystems."/boot" =
- { device = "/dev/disk/by-uuid/bfb464c0-c259-4c29-8e8f-b3011bd30c95";
- fsType = "ext4";
- };
-
- swapDevices =
- [ { device = "/dev/disk/by-uuid/ac0fe2b7-dd7a-4e86-aaa0-942acf3d541d"; }
- ];
-
- nix.maxJobs = lib.mkDefault 8;
-}
diff --git a/hosts/atom.nix b/hosts/atom.nix
new file mode 100644
index 0000000..2a8aef4
--- /dev/null
+++ b/hosts/atom.nix
@@ -0,0 +1,46 @@
+{ config, pkgs, ... }:
+
+let
+ hostname = "atom";
+
+in {
+
+ imports = [
+ ../defaults.nix
+ ../hardware-configuration.nix
+ ];
+
+ boot.loader.grub.enable = true;
+ boot.loader.grub.version = 2;
+ boot.loader.grub.device = "/dev/sda";
+
+ networking.hostName = hostname;
+
+ environment.systemPackages = with pkgs; [
+ glxinfo
+ hll2380dw-cups
+ usbutils
+ ];
+
+ fudo.common = {
+ profile = "laptop";
+ site = "seattle";
+ };
+
+ hardware.cpu.amd.updateMicrocode = true;
+
+ programs = {
+ bash.enableCompletion = true;
+ };
+
+ fudo.laptop.use-network-manager = false;
+ fudo.common.enable-gui = false;
+
+ hardware.opengl.driSupport32Bit = true;
+ hardware.opengl.extraPackages32 = with pkgs.pkgsi686Linux; [ libva ];
+ hardware.opengl.driSupport = true;
+
+ hardware.pulseaudio.support32Bit = true;
+
+ hardware.bluetooth.enable = true;
+}
diff --git a/hosts/france.nix b/hosts/france.nix
index 34c00ec..4158f01 100644
--- a/hosts/france.nix
+++ b/hosts/france.nix
@@ -239,11 +239,13 @@ in {
state-directory = "${system-mail-directory}/var";
mail-directory = "${system-mail-directory}/mailboxes";
- dovecot.ldap-reader-dn = "cn=user_db_reader,dc=fudo,dc=org";
- dovecot.ldap-reader-passwd = fileContents /srv/ldap/secure/user_db.passwd;
+ dovecot.ldap = {
+ reader-dn = "cn=user_db_reader,dc=fudo,dc=org";
+ reader-passwd = fileContents /srv/ldap/secure/user_db.passwd;
- # FIXME: use SSL once I can figure out Acme SSL cert CA for LDAP.
- dovecot.ldap-urls = [ "ldap://france.fudo.org" ];
+ # FIXME: use SSL once I can figure out Acme SSL cert CA for LDAP.
+ server-urls = [ "ldap://france.fudo.org" ];
+ };
clamav.enable = true;
@@ -265,7 +267,7 @@ in {
name = "webmail";
hostname = "localhost";
user = "webmail";
- password-file = /srv/webmail/secure/db.passwd;
+ password-file = "/srv/webmail/secure/db.passwd";
};
};
@@ -279,7 +281,7 @@ in {
name = "webmail";
hostname = "localhost";
user = "webmail";
- password-file = /srv/webmail/secure/db.passwd;
+ password-file = "/srv/webmail/secure/db.passwd";
};
};
@@ -292,7 +294,7 @@ in {
name = "webmail";
hostname = "localhost";
user = "webmail";
- password-file = /srv/webmail/secure/db.passwd;
+ password-file = "/srv/webmail/secure/db.passwd";
};
};
};
@@ -305,12 +307,12 @@ in {
site-name = "Fudo Chat";
smtp-server = "france.fudo.org";
smtp-user = "chat";
- smtp-password-file = /srv/mattermost/secure/smtp.passwd;
+ smtp-password-file = "/srv/mattermost/secure/smtp.passwd";
database = {
name = "mattermost";
hostname = "localhost";
user = "mattermost";
- password-file = /srv/mattermost/secure/db.passwd;
+ password-file = "/srv/mattermost/secure/db.passwd";
};
};
diff --git a/hosts/nostromo.nix b/hosts/nostromo.nix
index 578b30e..fc8967b 100644
--- a/hosts/nostromo.nix
+++ b/hosts/nostromo.nix
@@ -1,7 +1,9 @@
-{ config, pkgs, ... }:
+{ lib, config, pkgs, ... }:
let
- hostname = "nostromo.sea.fudo.org";
+ hostname = "nostromo";
+ host-internal-ip = "10.0.0.1";
+ inherit (lib.strings) concatStringsSep;
in {
@@ -9,77 +11,214 @@ in {
boot.loader.grub.enable = true;
boot.loader.grub.version = 2;
- boot.loader.grub.device = "/dev/sdb";
+ boot.loader.grub.device = "/dev/sda";
+
+ hardware.bluetooth.enable = false;
imports = [
../defaults.nix
- ../networks/sea.fudo.org.nix
- ../profiles/server.nix
../hardware-configuration.nix
- # ../profiles/services/local_nameserver.nix
];
- fudo.postgresql = {
- enable = true;
- ssl-private-key = "/srv/nostromo.sea.fudo.org/certs/private/privkey.pem";
- ssl-certificate = "/srv/nostromo.sea.fudo.org/certs/cert.pem";
- keytab = "/srv/nostromo.sea.fudo.org/keytabs/postgres.keytab";
+ fudo.common = {
+ profile = "server";
+ site = "seattle";
+ };
- local-networks = [
- "10.0.0.1/24"
- ];
+ fudo.local-network = {
+ enable = true;
+ # See fudo/sites/seattle.nix for general settings
+ dns-servers = [ host-internal-ip ];
+ gateway = host-internal-ip;
+ dhcp-interfaces = [ "intif0" ];
+ dns-serve-ips = [ host-internal-ip "127.0.0.1" "127.0.1.1" ];
+ # Using a pihole running in docker, see below
+ recursive-resolver = "${host-internal-ip} port 5353";
+ # recursive-resolver = "1.1.1.1";
+ server-ip = host-internal-ip;
+ };
+
+ fudo.slynk = {
+ enable = true;
};
networking = {
hostName = hostname;
- defaultGateway = "10.0.0.1";
-
- nameservers = [ "10.0.0.1" ];
-
- # Turn off for hypervisor: dhcp by default everywhere is a fuckin pain.
- dhcpcd.enable = false;
+ nameservers = [ host-internal-ip ];
# Create a bridge for VMs to use
- macvlans.intlan0 = {
- interface = "eno1";
- mode = "bridge";
+ macvlans = {
+ intif0 = {
+ interface = "eno1";
+ mode = "bridge";
+ };
};
interfaces = {
- intlan0 = {
+ eno1.useDHCP = false;
+ eno3.useDHCP = false;
+ eno4.useDHCP = false;
+ enp33s0f0.useDHCP = false;
+ enp33s0f1.useDHCP = false;
+ enp9s0f0.useDHCP = false;
+ enp9s0f1.useDHCP = false;
+
+ eno2.useDHCP = true;
+
+ intif0 = {
+ useDHCP = false;
macAddress = "46:54:76:06:f1:10";
ipv4.addresses = [
{
- address = "10.0.0.2";
- prefixLength = 23;
+ address = host-internal-ip;
+ prefixLength = 22;
+ }
+ {
+ address = "10.0.10.2";
+ prefixLength = 24;
}
];
};
};
+
+ nat = {
+ enable = true;
+ externalInterface = "eno2";
+ internalInterfaces = ["intif0"];
+ };
};
- hardware.bluetooth.enable = false;
+ fudo = {
+ postgresql = {
+ enable = true;
+ ssl-private-key = "/srv/nostromo/certs/private/privkey.pem";
+ ssl-certificate = "/srv/nostromo/certs/cert.pem";
+ keytab = "/srv/nostromo/keytabs/postgres.keytab";
+
+ local-networks = [
+ "10.0.0.1/24"
+ "127.0.0.1/8"
+ ];
+ };
+
+ secure-dns-proxy = {
+ enable = true;
+ port = 3535;
+ upstream-dns = [
+ "https://cloudflare-dns.com/dns-query"
+ # "https://dns.adguard.com/dns-query"
+ ];
+ bootstrap-dns = "1.1.1.1";
+ };
+ };
environment.systemPackages = with pkgs; [
- ipfs
+ dnsproxy
libguestfs-with-appliance
libvirt
virtmanager
];
- virtualisation.libvirtd = {
- enable = true;
- qemuPackage = pkgs.qemu_kvm;
- onShutdown = "shutdown";
+ virtualisation = {
+ docker = {
+ enable = true;
+ autoPrune.enable = true;
+ enableOnBoot = true;
+ };
+
+ libvirtd = {
+ enable = true;
+ qemuPackage = pkgs.qemu_kvm;
+ onShutdown = "shutdown";
+ };
};
- services.ipfs = {
- enable = true;
- enableGC = true;
- autoMount = false;
- defaultMode = "online";
- apiAddress = "/ip4/10.0.0.2/tcp/5001";
- gatewayAddress = "/ipv4/10.0.0.2/tcp/8080";
+ docker-containers = {
+ pihole = {
+ image = "pihole/pihole:4.3.2-1";
+ ports = [
+ "5353:53/tcp"
+ "5353:53/udp"
+ "3080:80/tcp"
+ ];
+ environment = {
+ ServerIP = host-internal-ip;
+ VIRTUAL_HOST = "dns-hole.sea.fudo.org";
+ DNS1 = "1.1.1.1";
+ DNS2 = "8.8.8.8";
+ };
+ volumes = [
+ "/srv/pihole/etc-pihole/:/etc/pihole/"
+ "/srv/pihole/etc-dnsmasq.d/:/etc/dnsmasq.d/"
+ ];
+ # TODO: DNS-over-HTTPS via cloudflared
+ # extraDockerOptions = [
+ # "--dns=1.1.1.1"
+ # ];
+ };
+ };
+
+ services = {
+ dhcpd6.enable = false;
+
+ # glusterfs = {
+ # enable = true;
+ # enableGlustereventsd = true;
+ # useRpcbind = true;
+ # };
+
+ nginx = {
+ enable = true;
+
+ virtualHosts = {
+ "pihole.sea.fudo.org" = {
+ serverAliases = [
+ "dns-hole.sea.fudo.org"
+ "hole.sea.fudo.org"
+ ];
+
+ 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;
+ '';
+ };
+ };
+ };
+ };
+
+ # ceph = {
+ # enable = true;
+
+ # global = {
+ # clusterName = "sea-data";
+ # clusterNetwork = "10.0.10.0/24";
+ # fsid = "d443e192-896d-4102-a60f-f8f0777eb2a3";
+ # monHost = "10.0.10.2";
+ # monInitialMembers = "mon-1";
+ # publicNetwork = "10.0.0.0/22";
+ # };
+
+ # mds = {
+ # enable = true;
+ # daemons = ["srv-2"];
+ # };
+
+ # mgr = {
+ # enable = true;
+ # daemons = ["srv-2"];
+ # };
+
+ # mon = {
+ # enable = true;
+ # daemons = ["srv-2"];
+ # };
+ # };
};
}
diff --git a/hosts/procul.nix b/hosts/procul.nix
new file mode 100644
index 0000000..2276e63
--- /dev/null
+++ b/hosts/procul.nix
@@ -0,0 +1,285 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+let
+ hostname = "procul";
+ domain = "informis.land";
+ mail-hostname = hostname;
+ host_ipv4 = "172.86.179.18";
+ host-fqdn = "${hostname}.${domain}";
+ all-hostnames = [];
+
+ acme-private-key = hostname: "/var/lib/acme/${hostname}/key.pem";
+ acme-certificate = hostname: "/var/lib/acme/${hostname}/fullchain.pem";
+ acme-ca = "/etc/nixos/static/letsencryptauthorityx3.pem";
+
+ fudo-ca = "/etc/nixos/static/fudo_ca.pem";
+
+in {
+
+ boot.loader.grub = {
+ enable = true;
+ version = 2;
+ device = "/dev/sdb";
+ };
+
+ imports = [
+ ../hardware-configuration.nix
+
+ ../defaults.nix
+
+ ../informis/users.nix
+ ];
+
+ environment.systemPackages = with pkgs; [
+ multipath-tools
+ ];
+
+ networking = {
+ hostName = hostname;
+
+ # provided by secure-dns-proxy
+ nameservers = [ "127.0.0.1" ];
+
+ dhcpcd.enable = false;
+ useDHCP = false;
+
+ # TODO: fix IPv6
+ enableIPv6 = true;
+
+ # Create a bridge for VMs to use
+ macvlans = {
+ extif0 = {
+ interface = "enp0s25";
+ mode = "bridge";
+ };
+ };
+
+ interfaces = {
+ extif0 = {
+ # result of:
+ # echo $FQDN-extif|md5sum|sed 's/^\(..\)\(..\)\(..\)\(..\)\(..\).*$/02:\1:\2:\3:\4:\5/'
+ macAddress = "02:e2:b7:db:e8:af";
+ ipv4.addresses = [
+ {
+ address = host_ipv4;
+ prefixLength = 29;
+ }
+ ];
+ };
+ };
+ };
+
+ hardware.bluetooth.enable = false;
+
+ users = {
+ users = {
+ gituser = {
+ isSystemUser = true;
+ group = "nogroup";
+ };
+ };
+ };
+
+ fudo = {
+
+ common = {
+ # Sets some server-common settings. See /etc/nixos/fudo/profiles/...
+ profile = "server";
+
+ # Sets some common site-specific settings: gateway, monitoring, etc. See /etc/nixos/fudo/sites/...
+ site = "joes";
+
+ domain = domain;
+
+ admin-email = "admin@${domain}";
+
+ local-networks = [
+ "172.86.179.16/29"
+ "208.81.1.128/28"
+ "208.81.3.112/28"
+ "172.17.0.0/16"
+ "127.0.0.0/8"
+ ];
+ };
+
+ # Not all users need access to procul; don't allow LDAP-user access.
+ authentication.enable = false;
+
+ auth.kdc = {
+ enable = true;
+ database-path = "/var/heimdal/heimdal";
+ realm = "INFORMIS.LAND";
+ mkey-file = "/srv/heimdal/secure/m-key";
+ acl-file = "/etc/heimdal/kdc.acl";
+ bind-addresses = [
+ host_ipv4
+ "127.0.0.1"
+ "127.0.1.1"
+ ];
+ };
+
+ secure-dns-proxy = {
+ enable = true;
+ upstream-dns = [ "https://cloudflare-dns.com/dns-query" ];
+ bootstrap-dns = "1.1.1.1";
+ listen-ips = [ "127.0.0.1" ];
+ port = 53;
+ };
+
+ dns = {
+ enable = true;
+
+ dns-hosts = {
+ "ns1.informis.land" = "172.86.179.18";
+ "ns2.informis.land" = "172.86.179.18";
+ };
+
+ listen-ips = [host_ipv4];
+
+ domains = {
+ "informis.land" = import ../informis/informis.land.nix {
+ inherit host_ipv4 config;
+ };
+ };
+ };
+
+ mail-server = {
+ enable = true;
+ debug = true;
+
+ domain = domain;
+ hostname = "${host-fqdn}";
+ monitoring = false;
+ mail-user = "mailuser";
+ mail-user-id = 525;
+ mail-group = "mailgroup";
+ clamav.enable = true;
+ dkim.signing = true;
+
+ dovecot = {
+ ssl-certificate = acme-certificate "imap.${domain}";
+ ssl-private-key = acme-private-key "imap.${domain}";
+ };
+
+ postfix = {
+ ssl-certificate = acme-certificate "smtp.${domain}";
+ ssl-private-key = acme-private-key "smtp.${domain}";
+ };
+
+ # This should NOT include the primary domain
+ local-domains = [
+ host-fqdn
+ "smtp.${domain}"
+ ];
+
+ mail-directory = "/srv/mailserver/mail";
+ state-directory = "/srv/mailserver/state";
+
+ trusted-networks = [
+ "172.86.179.16/29"
+ "127.0.0.0/16"
+ ];
+
+ alias-users = {
+ root = ["niten"];
+ postmaster = ["niten"];
+ hostmaster = ["niten"];
+ webmaster = ["niten"];
+ system = ["niten"];
+ admin = ["niten"];
+ dmarc-report = ["niten"];
+ };
+ };
+
+ postgresql = {
+ enable = true;
+ ssl-certificate = (acme-certificate host-fqdn);
+ ssl-private-key = (acme-private-key host-fqdn);
+ keytab = "/srv/postgres/secure/postgres.keytab";
+
+ local-networks = [
+ "172.86.179.16/29"
+ "127.0.0.0/16"
+ ];
+
+ users = {
+ gituser = {
+ password = fileContents "/srv/git/secure/db.passwd";
+ databases = {
+ git = "ALL PRIVILEGES";
+ };
+ };
+ };
+
+ databases = {
+ git = ["niten"];
+ };
+ };
+
+ git = {
+ enable = true;
+ hostname = "git.informis.land";
+ site-name = "informis git";
+ user = "gituser";
+ repository-dir = /srv/git/repo;
+ state-dir = /srv/git/state;
+ database = {
+ user = "gituser";
+ password-file = /srv/git/secure/db.passwd;
+ hostname = "127.0.0.1";
+ name = "git";
+ };
+ };
+
+ acme = {
+ enable = true;
+
+ admin-address = "admin@${domain}";
+
+ hostnames = [
+ "informis.land"
+ "imap.informis.land"
+ "smtp.informis.land"
+ "gemini.informis.land"
+ ];
+ };
+ };
+
+ security.acme.certs.${host-fqdn}.email = "admin@${domain}";
+
+ services.nginx = {
+ enable = true;
+
+ recommendedGzipSettings = true;
+ recommendedOptimisation = true;
+ recommendedTlsSettings = true;
+
+ virtualHosts = {
+ "${host-fqdn}" = {
+ enableACME = true;
+ forceSSL = true;
+ };
+ };
+ };
+
+ informis.cl-gemini = {
+ enable = true;
+
+ server-ip = host_ipv4;
+ document-root = "/srv/gemini/root";
+ ssl-private-key = "/srv/gemini/private/key.pem";
+ ssl-certificate = "/srv/gemini/private/cert.pem";
+ slynk-port = 4005;
+
+ textfiles-archive = "/srv/gemini/textfiles";
+
+ feeds = {
+ viator = {
+ title = "viator's phlog";
+ path = "/home/viator/gemini-public/feed/";
+ url = "gemini://informis.land/user/viator/feed/";
+ };
+ };
+ };
+}
diff --git a/hosts/zbox.nix b/hosts/zbox.nix
index eb74542..aab9ea9 100644
--- a/hosts/zbox.nix
+++ b/hosts/zbox.nix
@@ -4,34 +4,87 @@ let
hostname = "zbox";
in {
- imports = [
- ../defaults.nix
- ../networks/sea.fudo.org.nix
- ../profiles/desktop.nix
- ../hardware-configuration.nix
- ];
-
- environment.systemPackages = with pkgs; [
- glxinfo
- ];
# Use the systemd-boot EFI boot loader.
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
+ imports = [
+ ../defaults.nix
+ ../hardware-configuration.nix
+ ];
+
+ environment.systemPackages = with pkgs; [
+ androidenv.androidPkgs_9_0.platform-tools
+ android-studio
+ dnsproxy
+ glxinfo
+ hll2380dw-cups
+ nodejs
+ signal-desktop
+ thunderbird
+ usbutils
+ ];
+
+ fudo.common = {
+ profile = "desktop";
+ site = "seattle";
+ enable-gui = true;
+ };
+
+ fudo.slynk = {
+ enable = true;
+ };
+
hardware.cpu.intel.updateMicrocode = true;
- programs.bash.enableCompletion = true;
+ programs = {
+ adb.enable = true;
+ bash.enableCompletion = true;
+ };
services.xserver = {
videoDrivers = ["nvidia"];
- displayManager.gdm.wayland = false;
+ # displayManager.gdm.wayland = false;
};
hardware.opengl.driSupport32Bit = true;
+ hardware.opengl.extraPackages32 = with pkgs.pkgsi686Linux; [ libva ];
hardware.opengl.driSupport = true;
- networking.hostName = hostname;
+ hardware.pulseaudio.support32Bit = true;
+
+ networking = {
+ hostName = hostname;
+
+ macvlans = {
+ intif0 = {
+ interface = "eno1";
+ mode = "bridge";
+ };
+ };
+
+ interfaces = {
+ eno1.useDHCP = false;
+ intif0 = {
+ macAddress = "02:dd:80:52:83:9b";
+ useDHCP = false;
+ ipv4.addresses = [
+ {
+ address = "10.0.0.110";
+ prefixLength = 24;
+ }
+ ];
+ };
+ };
+ };
hardware.bluetooth.enable = true;
+
+ users.users.niten = {
+ extraGroups = ["adbusers"];
+ };
+
+ virtualisation.lxd.enable = true;
+
}
diff --git a/informis/informis.land.nix b/informis/informis.land.nix
new file mode 100644
index 0000000..acce31d
--- /dev/null
+++ b/informis/informis.land.nix
@@ -0,0 +1,98 @@
+{ host_ipv4, config }:
+
+{
+ dnssec = true;
+
+ mx = ["smtp.informis.land"];
+
+ hosts = {
+ procul = {
+ ip-addresses = [ "172.86.179.18" ];
+ ssh-fingerprints = [
+ "4 1 2a8e086d3589ce50b58c55bc35638af8da23988e"
+ "4 2 55a9f7c0addf08bb24c62ced954574db6e95eff38ee56d6a2cff312d20eb910e"
+ "1 1 d089902f60751b3d35b5329bf7b906df254d5fa7"
+ "1 2 8deebf42bbc40881a327f561bffd5d7bd328a4fc94d4e4ce8c502a9c6cbdfb92"
+ ];
+ };
+ };
+
+ default-host = "172.86.179.18";
+
+ srv-records = {
+ tcp = {
+ domain = [{
+ host = "ns1.informis.land";
+ port = 53;
+ }];
+ ssh = [{
+ host = "procul.informis.land";
+ port = 22;
+ }];
+ submission = [{
+ host = "procul.informis.land";
+ port = 587;
+ }];
+ kerberos = [{
+ host = "procul.informis.land";
+ port = 88;
+ }];
+ kerberos-adm = [{
+ host = "procul.informis.land";
+ port = 749;
+ }];
+ imaps = [{
+ host = "procul.informis.land";
+ port = 993;
+ priority = 0;
+ }];
+ pop3s = [{
+ host = "procul.informis.land";
+ port = 995;
+ priority = 10;
+ }];
+ http = [{
+ host = "procul.informis.land";
+ port = 80;
+ }];
+ https = [{
+ host = "procul.informis.land";
+ port = 443;
+ }];
+ };
+
+ udp = {
+ domain = [{
+ host = "ns1.informis.land";
+ port = 53;
+ }];
+ kerberos = [{
+ host = "procul.informis.land";
+ port = 88;
+ }];
+ kerberos-master = [{
+ host = "procul.informis.land";
+ port = 88;
+ }];
+ kpasswd = [{
+ host = "procul.informis.land";
+ port = 464;
+ }];
+ };
+ };
+
+ aliases = {
+ smtp = "procul.informis.land.";
+ imap = "procul.informis.land.";
+ gemini = "procul.informis.land.";
+ git = "procul.informis.land.";
+ };
+
+ extra-dns-records = [
+ ''_kerberos IN TXT "INFORMIS.LAND"''
+ ''@ IN TXT "v=spf1 mx ip4:${host_ipv4}/29 -all"''
+ ''@ IN SPF "v=spf1 mx ip4:${host_ipv4}/29 -all"''
+ ];
+
+ dmarc-report-address = "dmarc-report@informis.land";
+}
diff --git a/informis/users.nix b/informis/users.nix
new file mode 100644
index 0000000..b858c6e
--- /dev/null
+++ b/informis/users.nix
@@ -0,0 +1,14 @@
+{ config, ... }:
+
+{
+ config = {
+ users.users = {
+ viator = {
+ isNormalUser = true;
+ description = "Viator";
+ createHome = true;
+ hashedPassword = "$6$a1q2Duoe35hd5$IaZGXPfqyGv9uq5DQm7DZq0vIHsUs39sLktBiBBqMiwl/f/Z4jSvNZLJp9DZJYe5u2qGBYh1ca.jsXvQA8FPZ/";
+ };
+ };
+ };
+}
diff --git a/lib/ip.nix b/lib/ip.nix
new file mode 100644
index 0000000..7f55bf0
--- /dev/null
+++ b/lib/ip.nix
@@ -0,0 +1,56 @@
+{ lib }:
+
+with lib;
+let
+ joinString = lib.concatStringsSep;
+
+ pow = x: e: if (e == 0) then 1 else x * (pow x (e - 1));
+
+in rec {
+
+ 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;
+
+ 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);
+
+ 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 ]);
+
+ rightPadBits = int: bits: bitOr int (generateNBits bits);
+
+ maskFromV32Network = network: let
+ fullMask = ipv4ToInt "255.255.255.255";
+ insignificantBits = 32 - (getNetworkMask network);
+ in intToIpv4 (leftShift (rightShift fullMask insignificantBits) insignificantBits);
+
+ 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);
+
+ 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);
+}
diff --git a/packages/cl-gemini.nix b/packages/cl-gemini.nix
new file mode 100644
index 0000000..22ef42c
--- /dev/null
+++ b/packages/cl-gemini.nix
@@ -0,0 +1,24 @@
+{ stdenv, fetchgit, pkgs }:
+
+let
+ url = "https://git.informis.land/viator/cl-gemini.git";
+ version = "0.1";
+
+in stdenv.mkDerivation {
+ name = "cl-gemini-${version}";
+
+ src = fetchgit {
+ url = "https://git.informis.land/viator/cl-gemini.git";
+ rev = "3de4d1945fc91d0c9f8f65a5d4b0d3f39fbdaa80";
+ sha256 = "1xzfsp5vp36a3yas5pnhj2a1dd72r72fw3l49ah19hvbapaikhsw";
+ fetchSubmodules = false;
+ };
+
+ phases = ["installPhase"];
+
+ installPhase = ''
+ mkdir -p "$out/lib/common-lisp/cl-gemini"
+ cp "$src/cl-gemini.asd" "$out/lib/common-lisp/cl-gemini"
+ cp -R "$src/src" "$out/lib/common-lisp/cl-gemini"
+ '';
+}
diff --git a/packages/hll2380dw-cups.nix b/packages/hll2380dw-cups.nix
new file mode 100644
index 0000000..b0ed6dd
--- /dev/null
+++ b/packages/hll2380dw-cups.nix
@@ -0,0 +1,40 @@
+{ stdenv, fetchurl, makeWrapper, cups, dpkg, a2ps, ghostscript, gnugrep, gnused, coreutils, file, perl, which }:
+
+stdenv.mkDerivation rec {
+ pname = "hll2380dw-cups";
+ version = "3.2.0-1";
+ platform = "i386";
+
+ src = fetchurl {
+ url = "https://download.brother.com/welcome/dlf101772/hll2380dwcupswrapper-${version}.i386.deb";
+ sha256 = "08g3kx5lgwzb3f9ypj8knmpkkj0h3kv1i4gd20rzjxrx6vx1wbpl";
+ };
+
+ nativeBuildInputs = [ makeWrapper ];
+ buildInputs = [ cups ghostscript dpkg a2ps ];
+
+ dontUnpack = true;
+
+ installPhase = ''
+ dpkg-deb -x $src $out
+ wrapProgram $out/opt/brother/Printers/HLL2380DW/cupswrapper/paperconfigml1 \
+ --prefix PATH : ${stdenv.lib.makeBinPath [
+ coreutils ghostscript gnugrep gnused
+ ]}
+ mkdir -p $out/lib/cups/filter/
+ ln -s $out/opt/brother/Printers/HLL2380DW/cupswrapper/brother_lpdwrapper_HLL2380W \
+ $out/lib/cups/filter/brother_lpdwrapper_HLL2380DW
+ ln -s $out/opt/brother/Printers/HLL2380DW/paperconfigml1 \
+ $out/lib/cups/filter/
+ mkdir -p $out/share/cups/model
+ ln -s $out/opt/brother/Printers/HLL2380DW/cupswrapper/brother-HLL2380DW-cups-en.ppd $out/share/cups/model/
+ '';
+
+ meta = with stdenv.lib; {
+ homepage = http://www.brother.com/;
+ description = "Brother HL-L2380DW combined print driver";
+ license = licenses.unfree;
+ platforms = [ "x86_64-linux" ];
+ downloadPage = http://support.brother.com/g/b/downloadlist.aspx?c=us_ot&lang=en&prod=hll2380dw_us&os=128;
+ };
+}
diff --git a/packages/local.nix b/packages/local.nix
index 60725a8..7e72555 100644
--- a/packages/local.nix
+++ b/packages/local.nix
@@ -15,11 +15,10 @@
};
});
- minecraft-server_1_15_2 = pkgs.minecraft-server.overrideAttrs (oldAttrs: rec {
- version = "1.15.2";
+ minecraft-current = pkgs.minecraft.overrideAttrs (oldAttrs: rec {
src = builtins.fetchurl {
- url = "https://launcher.mojang.com/v1/objects/bb2b6b1aefcd70dfd1892149ac3a215f6c636b07/server.jar";
- sha256 = "12kynrpxgcdg8x12wcvwkxka0fxgm5siqg8qq0nnmv0443f8dkw0";
+ url = "https://launcher.mojang.com/download/Minecraft.tar.gz";
+ sha256 = "1k9gf1v1law4kiz8f7i2fxkj5vq2cm37b3ys95zpyf4aiw5nzg33";
};
});
@@ -45,5 +44,15 @@
configureFlags = oldAttrs.configureFlags ++ [ "--with-gssapi" ];
buildInputs = oldAttrs.buildInputs ++ [ pkgs.krb5 ];
});
+
+ hll2380dw-cups = import ./hll2380dw-cups.nix {
+ inherit (pkgs) stdenv fetchurl makeWrapper cups dpkg a2ps ghostscript gnugrep gnused coreutils file perl which;
+ };
+
+ cl-gemini = import ./cl-gemini.nix {
+ pkgs = pkgs;
+ stdenv = pkgs.stdenv;
+ fetchgit = pkgs.fetchgit;
+ };
};
}
diff --git a/static/niten@fudo.org.pubkey b/static/niten@fudo.org.pubkey
new file mode 100644
index 0000000..08d57bb
--- /dev/null
+++ b/static/niten@fudo.org.pubkey
@@ -0,0 +1,109 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+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
+qCVCWa+H/Pev226LSn2PVKK5AlBbs6uSNx/Phg==
+=8Fyj
+-----END PGP PUBLIC KEY BLOCK-----