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;
|
||||
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 {
|
||||
modules = [
|
||||
({ config, ... }: {
|
||||
|
@ -51,6 +52,12 @@ testers.runNixOSTest {
|
|||
|
||||
imports = [
|
||||
serviceConfig.simulacrum.settings
|
||||
./nowhere
|
||||
{
|
||||
nodes.nowhere.imports = [
|
||||
config.flake.nixosModules.port-magic
|
||||
];
|
||||
}
|
||||
] ++ allAugments;
|
||||
|
||||
_module.args = {
|
||||
|
@ -73,12 +80,15 @@ testers.runNixOSTest {
|
|||
${hour.interfaces.primary.link} = {
|
||||
useDHCP = lib.mkForce false;
|
||||
virtual = true;
|
||||
ipv4.addresses = lib.mkForce [
|
||||
ipv4.addresses = lib.mkForce ([
|
||||
{
|
||||
address = hour.interfaces.primary.addr;
|
||||
prefixLength = 32;
|
||||
}
|
||||
];
|
||||
] ++ lib.optional hour.interfaces.primary.isNat {
|
||||
address = hour.interfaces.primary.addrPublic;
|
||||
prefixLength = 32;
|
||||
});
|
||||
};
|
||||
eth1.ipv4.routes = lib.pipe nodes [
|
||||
(lib.filter (n: n != node))
|
||||
|
@ -95,6 +105,7 @@ testers.runNixOSTest {
|
|||
firewall.extraCommands = lib.mkAfter (lib.optionalString (hour.interfaces.primary.isNat) ''
|
||||
# self-nat
|
||||
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}
|
||||
'');
|
||||
};
|
||||
|
|
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