The Simulacrum: Stage 1 #108
3 changed files with 131 additions and 3 deletions
|
@ -17,7 +17,8 @@ let
|
||||||
};
|
};
|
||||||
|
|
||||||
nodes = lib.attrNames config.gods.fromLight;
|
nodes = lib.attrNames config.gods.fromLight;
|
||||||
digits = lib.attrsets.listToAttrs (lib.zipListsWith lib.nameValuePair nodes (lib.range 1 255));
|
nodes' = lib.attrNames (config.gods.fromLight // { nowhere = null; });
|
||||||
|
digits = lib.attrsets.listToAttrs (lib.zipListsWith lib.nameValuePair nodes' (lib.range 1 255));
|
||||||
depot' = extendModules {
|
depot' = extendModules {
|
||||||
modules = [
|
modules = [
|
||||||
({ config, ... }: {
|
({ config, ... }: {
|
||||||
|
@ -51,6 +52,12 @@ testers.runNixOSTest {
|
||||||
|
|
||||||
imports = [
|
imports = [
|
||||||
serviceConfig.simulacrum.settings
|
serviceConfig.simulacrum.settings
|
||||||
|
./nowhere
|
||||||
|
{
|
||||||
|
nodes.nowhere.imports = [
|
||||||
|
config.flake.nixosModules.port-magic
|
||||||
|
];
|
||||||
|
}
|
||||||
] ++ allAugments;
|
] ++ allAugments;
|
||||||
|
|
||||||
_module.args = {
|
_module.args = {
|
||||||
|
@ -73,12 +80,15 @@ testers.runNixOSTest {
|
||||||
${hour.interfaces.primary.link} = {
|
${hour.interfaces.primary.link} = {
|
||||||
useDHCP = lib.mkForce false;
|
useDHCP = lib.mkForce false;
|
||||||
virtual = true;
|
virtual = true;
|
||||||
ipv4.addresses = lib.mkForce [
|
ipv4.addresses = lib.mkForce ([
|
||||||
{
|
{
|
||||||
address = hour.interfaces.primary.addr;
|
address = hour.interfaces.primary.addr;
|
||||||
prefixLength = 32;
|
prefixLength = 32;
|
||||||
}
|
}
|
||||||
];
|
] ++ lib.optional hour.interfaces.primary.isNat {
|
||||||
|
address = hour.interfaces.primary.addrPublic;
|
||||||
|
prefixLength = 32;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
eth1.ipv4.routes = lib.pipe nodes [
|
eth1.ipv4.routes = lib.pipe nodes [
|
||||||
(lib.filter (n: n != node))
|
(lib.filter (n: n != node))
|
||||||
|
@ -95,6 +105,7 @@ testers.runNixOSTest {
|
||||||
firewall.extraCommands = lib.mkAfter (lib.optionalString (hour.interfaces.primary.isNat) ''
|
firewall.extraCommands = lib.mkAfter (lib.optionalString (hour.interfaces.primary.isNat) ''
|
||||||
# self-nat
|
# self-nat
|
||||||
iptables -t nat -A PREROUTING -d ${hour.interfaces.primary.addrPublic} -j DNAT --to-destination ${hour.interfaces.primary.addr}
|
iptables -t nat -A PREROUTING -d ${hour.interfaces.primary.addrPublic} -j DNAT --to-destination ${hour.interfaces.primary.addr}
|
||||||
|
iptables -t nat -A OUTPUT -d ${hour.interfaces.primary.addrPublic} -j DNAT --to-destination ${hour.interfaces.primary.addr}
|
||||||
iptables -t nat -A POSTROUTING -s ${hour.interfaces.primary.addr} -j SNAT --to-source ${hour.interfaces.primary.addrPublic}
|
iptables -t nat -A POSTROUTING -s ${hour.interfaces.primary.addr} -j SNAT --to-source ${hour.interfaces.primary.addrPublic}
|
||||||
'');
|
'');
|
||||||
};
|
};
|
||||||
|
|
101
cluster/simulacrum/nowhere/default.nix
Normal file
101
cluster/simulacrum/nowhere/default.nix
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
{ cluster, config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
lift = config;
|
||||||
|
|
||||||
|
cfsslConfigIntermediateCA = pkgs.writeText "simulacrum-cfssl-config.json" (builtins.toJSON {
|
||||||
|
signing = {
|
||||||
|
default.expiry = "8760h";
|
||||||
|
profiles.intermediate = {
|
||||||
|
expiry = "8760h";
|
||||||
|
usages = [
|
||||||
|
"cert sign"
|
||||||
|
"crl sign"
|
||||||
|
];
|
||||||
|
ca_constraint = {
|
||||||
|
is_ca = true;
|
||||||
|
max_path_len = 1;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
caCsr = pkgs.writeText "simulacrum-ca-csr.json" (builtins.toJSON {
|
||||||
|
CN = "Simulacrum Root CA";
|
||||||
|
});
|
||||||
|
|
||||||
|
ca = pkgs.runCommand "simulacrum-snakeoil-ca" {
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.cfssl
|
||||||
|
];
|
||||||
|
} ''
|
||||||
|
mkdir $out
|
||||||
|
cfssl gencert --initca ${caCsr} | cfssljson --bare $out/ca
|
||||||
|
'';
|
||||||
|
|
||||||
|
genCert = extraFlags: csrData: let
|
||||||
|
csr = pkgs.writeText "simulacrum-csr.json" (builtins.toJSON csrData);
|
||||||
|
in pkgs.runCommand "simulacrum-snakeoil-cert" {
|
||||||
|
nativeBuildInputs = [
|
||||||
|
pkgs.cfssl
|
||||||
|
];
|
||||||
|
} ''
|
||||||
|
mkdir $out
|
||||||
|
cfssl gencert ${lib.escapeShellArgs ([
|
||||||
|
"--ca=file:${ca}/ca.pem"
|
||||||
|
"--ca-key=file:${ca}/ca-key.pem"
|
||||||
|
] ++ extraFlags ++ [
|
||||||
|
csr
|
||||||
|
])} | cfssljson --bare $out/cert
|
||||||
|
'';
|
||||||
|
|
||||||
|
genHostCert = hostname: genCert [ "--hostname=${hostname}" ] { CN = hostname; };
|
||||||
|
|
||||||
|
getNodeAddr = node: (builtins.head config.nodes.${node}.networking.interfaces.eth1.ipv4.addresses).address;
|
||||||
|
in
|
||||||
|
|
||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./options.nix
|
||||||
|
];
|
||||||
|
defaults = {
|
||||||
|
networking.hosts."${getNodeAddr "nowhere"}" = lib.attrNames config.nowhere.names;
|
||||||
|
security.pki.certificateFiles = [
|
||||||
|
"${ca}/ca.pem"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
nowhere.certs = {
|
||||||
|
inherit ca;
|
||||||
|
intermediate = genCert [ "--config=${cfsslConfigIntermediateCA}" "--profile=intermediate" ] {
|
||||||
|
CN = "Simulacrum Intermediate CA";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.nowhere = { config, depot, ... }: {
|
||||||
|
networking = {
|
||||||
|
firewall.allowedTCPPorts = [ 443 ];
|
||||||
|
interfaces.eth1.ipv4.routes = lib.mapAttrsToList (name: hour: {
|
||||||
|
address = hour.interfaces.primary.addrPublic;
|
||||||
|
prefixLength = 32;
|
||||||
|
via = getNodeAddr name;
|
||||||
|
}) depot.gods.fromLight;
|
||||||
|
nameservers = map (name: depot.hours.${name}.interfaces.primary.addrPublic) cluster.config.services.dns.nodes.authoritative;
|
||||||
|
};
|
||||||
|
services.nginx = {
|
||||||
|
enable = true;
|
||||||
|
recommendedProxySettings = true;
|
||||||
|
virtualHosts = lib.mapAttrs (name: link: let
|
||||||
|
cert = genHostCert name;
|
||||||
|
in {
|
||||||
|
forceSSL = true;
|
||||||
|
sslCertificate = "${cert}/cert.pem";
|
||||||
|
sslCertificateKey = "${cert}/cert-key.pem";
|
||||||
|
locations."/" = {
|
||||||
|
proxyPass = config.links.${link}.url;
|
||||||
|
extraConfig = "proxy_ssl_verify off;";
|
||||||
|
};
|
||||||
|
}) lift.nowhere.names;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
16
cluster/simulacrum/nowhere/options.nix
Normal file
16
cluster/simulacrum/nowhere/options.nix
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{ lib, ... }:
|
||||||
|
|
||||||
|
{
|
||||||
|
options.nowhere = {
|
||||||
|
names = lib.mkOption {
|
||||||
|
description = "Hostnames that point Nowhere.";
|
||||||
|
type = with lib.types; attrsOf str;
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
certs = lib.mkOption {
|
||||||
|
description = "Snakeoil certificate packages.";
|
||||||
|
type = with lib.types; attrsOf package;
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue