This commit is contained in:
Shelvacu
2024-10-23 19:12:43 -07:00
parent 79c4c5ada6
commit aee5440fde
15 changed files with 303 additions and 217 deletions

View File

@@ -1,4 +1,5 @@
{ lib, config, ... }:{
{ lib, config, ... }:
{
imports = [
./makeWrapper.nix
];

View File

@@ -4,55 +4,90 @@
...
}:
let
inherit (lib) optionals optional mapAttrsFlatten concatMap escapeShellArg escapeShellArgs;
inherit (lib)
optionals
optional
mapAttrsFlatten
concatMap
escapeShellArg
escapeShellArgs
;
in
{
config.vacu.vaculib.makeWrapper = {
original,
new,
argv0 ? null,
inherit_argv0 ? false,
resolve_argv0 ? false,
set ? {},
set_default ? {},
unset ? [],
chdir ? null,
run ? [],
prepend_flags ? [],
add_flags ? [],
append_flags ? [],
}@args: let
prependFlags = prepend_flags ++ add_flags;
escapeFlags = flags: builtins.concatStringsSep " " (map escapeShellArg flags);
originalBin = if lib.isDerivation original then lib.getExe original else original;
makeWrapperFlags =
(optionals (argv0 != null) [ "--argv0" argv0]) ++
(optional inherit_argv0 "--inherit-argv0") ++
(optional resolve_argv0 "--resolve-argv0") ++
(mapAttrsFlatten (k: v: [ "--set" k v ] ) set) ++
(mapAttrsFlatten (k: v: [ "--set-default" k v ] ) set_default) ++
(concatMap (k: [ "--unset" k ]) unset) ++
(optionals (chdir != null) [ "--chdir" chdir ]) ++
(concatMap (k: [ "--run" k ]) run) ++
(optionals (prependFlags != []) [ "--add-flags" (escapeFlags prependFlags) ]) ++
(optionals (append_flags != []) [ "--append-flags" (escapeFlags append_flags) ])
;
in pkgs.stdenvNoCC.mkDerivation {
name = new;
config.vacu.vaculib.makeWrapper =
{
original,
new,
argv0 ? null,
inherit_argv0 ? false,
resolve_argv0 ? false,
set ? { },
set_default ? { },
unset ? [ ],
chdir ? null,
run ? [ ],
prepend_flags ? [ ],
add_flags ? [ ],
append_flags ? [ ],
}@args:
let
prependFlags = prepend_flags ++ add_flags;
escapeFlags = flags: builtins.concatStringsSep " " (map escapeShellArg flags);
originalBin = if lib.isDerivation original then lib.getExe original else original;
makeWrapperFlags =
(optionals (argv0 != null) [
"--argv0"
argv0
])
++ (optional inherit_argv0 "--inherit-argv0")
++ (optional resolve_argv0 "--resolve-argv0")
++ (mapAttrsFlatten (k: v: [
"--set"
k
v
]) set)
++ (mapAttrsFlatten (k: v: [
"--set-default"
k
v
]) set_default)
++ (concatMap (k: [
"--unset"
k
]) unset)
++ (optionals (chdir != null) [
"--chdir"
chdir
])
++ (concatMap (k: [
"--run"
k
]) run)
++ (optionals (prependFlags != [ ]) [
"--add-flags"
(escapeFlags prependFlags)
])
++ (optionals (append_flags != [ ]) [
"--append-flags"
(escapeFlags append_flags)
]);
in
pkgs.stdenvNoCC.mkDerivation {
name = new;
nativeBuildInputs = [ pkgs.makeWrapper ];
nativeBuildInputs = [ pkgs.makeWrapper ];
phases = [ "installPhase" ];
phases = [ "installPhase" ];
installPhase = ''
runHook preInstall
installPhase = ''
runHook preInstall
mkdir -p $out/bin
makeWrapper ${escapeShellArg originalBin} $out/bin/${escapeShellArg new} ${escapeShellArgs makeWrapperFlags}
mkdir -p $out/bin
makeWrapper ${escapeShellArg originalBin} $out/bin/${escapeShellArg new} ${escapeShellArgs makeWrapperFlags}
runHook postInstall
'';
runHook postInstall
'';
meta.mainProgram = new;
};
meta.mainProgram = new;
};
}

View File

@@ -76,7 +76,7 @@ in
''
];
vacu.ssh.authorizedKeys = {
vacu.ssh.authorizedKeys = {
# pixel6pro-termux = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC4LYvUe9dsQb9OaTDFI4QKPtMmOHOGLwWsXsEmcJW86";
# t460s = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHcYwYy9/0Gu/GsqS72Nkz6OkId+zevqXA/aTIcvqflp";
# pixel6pro-nod = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFsErA6M9LSHj2hPlLuHD8Lpei7WjMup1JxI1vxA6B8W";

View File

@@ -26,7 +26,10 @@ let
wrappedBashPkg = vaculib.makeWrapper {
original = pkgs.bash;
new = "vacuinit-bash";
prepend_flags = [ "--init-file" vacuInitFile ];
prepend_flags = [
"--init-file"
vacuInitFile
];
};
wrappedBash = lib.getExe wrappedBashPkg;
in

View File

@@ -9,36 +9,38 @@ let
userKeys = lib.attrValues config.vacu.ssh.authorizedKeys;
liamKey = config.vacu.ssh.knownHosts.liam.publicKey;
ssh-to-age = lib.getExe pkgs.ssh-to-age;
sopsConfig = pkgs.runCommand "sops.yaml" { env.sshUserKeys = lib.concatStringsSep "\n" userKeys; } ''
set -xe
liamKey="$(echo "${liamKey}" | ${ssh-to-age})"
declare -a userKeys
mapfile -t userKeys < <(echo "$sshUserKeys" | ${ssh-to-age})
declare -p userKeys
cat <<END >> $out
creation_rules:
- path_regex: ^secrets/misc/
key_groups:
- age:
END
for k in "''${userKeys[@]}"; do
echo " - $k" >> $out
done
cat <<END >> $out
- path_regex: ^secrets/liam/
key_groups:
- age:
- $liamKey
END
for k in "''${userKeys[@]}"; do
echo " - $k" >> $out
done
cat <<END >> $out
- path_regex: ^tests/test_secrets
key_groups:
- age: age1eqv5759uknu7d46rqyyzsmgt43qumsge33yp2xygapprnt8zu3sqx6kt8w
END
'';
sopsConfig =
pkgs.runCommand "sops.yaml" { env.sshUserKeys = lib.concatStringsSep "\n" userKeys; }
''
set -xe
liamKey="$(echo "${liamKey}" | ${ssh-to-age})"
declare -a userKeys
mapfile -t userKeys < <(echo "$sshUserKeys" | ${ssh-to-age})
declare -p userKeys
cat <<END >> $out
creation_rules:
- path_regex: ^secrets/misc/
key_groups:
- age:
END
for k in "''${userKeys[@]}"; do
echo " - $k" >> $out
done
cat <<END >> $out
- path_regex: ^secrets/liam/
key_groups:
- age:
- $liamKey
END
for k in "''${userKeys[@]}"; do
echo " - $k" >> $out
done
cat <<END >> $out
- path_regex: ^tests/test_secrets
key_groups:
- age: age1eqv5759uknu7d46rqyyzsmgt43qumsge33yp2xygapprnt8zu3sqx6kt8w
END
'';
in
{
options.vacu.sopsConfig = mkOption {

View File

@@ -38,7 +38,7 @@ in
#vacu.ssh.authorizedKeys = mkOption { type = types.listOf types.str; };
vacu.ssh.authorizedKeys = mkOption {
type = types.attrsOf types.str;
default = {};
default = { };
};
vacu.ssh.config = mkOption { type = types.lines; };
# Straight copied from nixpkgs

View File

@@ -99,11 +99,15 @@
x86 = "x86_64-linux";
arm = "aarch64-linux";
lib = import "${nixpkgs}/lib";
mkPkgs = arg:
mkPkgs =
arg:
let
argAttr = if builtins.isString arg then { system = arg; } else arg;
config = { allowUnfree = true; } // (argAttr.config or {});
in import nixpkgs (argAttr // { inherit config; });
config = {
allowUnfree = true;
} // (argAttr.config or { });
in
import nixpkgs (argAttr // { inherit config; });
pkgs = mkPkgs x86;
mkNixosConfig =
{
@@ -349,7 +353,9 @@
# snmpb = pkgs.libsForQt5.callPackage ./packages/snmpb/package.nix { };
# snmp-mibs-downloader = pkgs.callPackage ./packages/snmp-mibs-downloader.nix { };
authorizedKeys = pkgs.writeText "authorizedKeys" (
lib.concatStringsSep "\n" (lib.mapAttrsToList (k: v: "${v} ${k}") plain.config.vacu.ssh.authorizedKeys)
lib.concatStringsSep "\n" (
lib.mapAttrsToList (k: v: "${v} ${k}") plain.config.vacu.ssh.authorizedKeys
)
);
sopsConfig = plain.config.vacu.sopsConfig;
nixvim = inputs.nixvim.legacyPackages.${system}.makeNixvimWithModule {

View File

@@ -4,7 +4,13 @@
...
}:
let
inherit (lib.strings) concatStringsSep splitString match replaceStrings concatStrings;
inherit (lib.strings)
concatStringsSep
splitString
match
replaceStrings
concatStrings
;
inherit (lib.lists) reverseList length elemAt;
email_folders = [
"24nm-domain@shelvacu.com"

View File

@@ -3,7 +3,7 @@
writers,
curl,
sops,
lib
lib,
}:
let
sopsCommand = [
@@ -21,7 +21,7 @@ let
];
in
writers.writeScriptBin "update-gitea-keys" ''
age_key=$(ssh-to-age -private-key -i $HOME/.ssh/id_ed25519)
gitea_api_key="$(SOPS_AGE_KEY="$age_key" sops --config ${../.sops.yaml} --extract '["git.uninsane.org"]' -d ${../secrets/misc/git-keys.json})"
curl
age_key=$(ssh-to-age -private-key -i $HOME/.ssh/id_ed25519)
gitea_api_key="$(SOPS_AGE_KEY="$age_key" sops --config ${../.sops.yaml} --extract '["git.uninsane.org"]' -d ${../secrets/misc/git-keys.json})"
curl
''

View File

@@ -22,17 +22,17 @@ let
(lib.filter (c: c.enable))
];
serviceValidDomainAssertions = map (proxiedConfig: {
assertion = lib.any (availableDomain:
(lib.hasSuffix ("." + availableDomain) proxiedConfig.domain) ||
(proxiedConfig.domain == availableDomain)
assertion = lib.any (
availableDomain:
(lib.hasSuffix ("." + availableDomain) proxiedConfig.domain)
|| (proxiedConfig.domain == availableDomain)
) domains;
message = "proxiedService ${proxiedConfig.name}'s `domain` does not match any of the known domains";
}) proxied;
mapListToAttrs = f: list: lib.listToAttrs (map f list);
in
{
assertions = [ ]
++ serviceValidDomainAssertions;
assertions = [ ] ++ serviceValidDomainAssertions;
security.acme.acceptTerms = true;
security.acme.defaults = {
email = "nix-acme@shelvacu.com";
@@ -44,8 +44,8 @@ in
postRun = "${pkgs.nixos-container}/bin/nixos-container run frontproxy -- systemctl reload haproxy";
};
security.acme.certs = mapListToAttrs (domain:
lib.nameValuePair domain { extraDomainNames = [ "*.${domain}" ]; }
security.acme.certs = mapListToAttrs (
domain: lib.nameValuePair domain { extraDomainNames = [ "*.${domain}" ]; }
) domains;
users.groups.acme.gid = 993;
@@ -69,10 +69,13 @@ in
autoStart = true;
restartIfChanged = true;
ephemeral = true;
bindMounts = mapListToAttrs (d: lib.nameValuePair "/certs/${d}" {
hostPath = outer_config.security.acme.certs.${d}.directory;
isReadOnly = true;
}) domains;
bindMounts = mapListToAttrs (
d:
lib.nameValuePair "/certs/${d}" {
hostPath = outer_config.security.acme.certs.${d}.directory;
isReadOnly = true;
}
) domains;
config =
{ config, ... }:
{

View File

@@ -6,93 +6,103 @@
}:
let
enableKeylog = false;
cleanName = name: lib.replaceStrings ["-" " "] [ "_" "_" ] name;
cleanName =
name:
lib.replaceStrings
[
"-"
" "
]
[
"_"
"_"
]
name;
aclName = config: "host_" + (cleanName config.name);
backendName = config: "backend_" + (cleanName config.name);
concatMap = sep: f: list: lib.concatStringsSep sep (map f list);
concatMap =
sep: f: list:
lib.concatStringsSep sep (map f list);
mapLines = f: list: concatMap "\n" f list;
certs = concatMap " " (d: "crt /certs/${d}/full.pem") domains;
in
''
${lib.optionalString enableKeylog ''
# ssl keylogging
${lib.optionalString enableKeylog ''
# ssl keylogging
global
tune.ssl.keylog on
lua-load ${./sslkeylog.lua}
''}
global
tune.ssl.keylog on
lua-load ${./sslkeylog.lua}
''}
global
close-spread-time 1s
hard-stop-after 3s
description "triple-dezert frontproxy"
no insecure-fork-wanted
log stdout format short daemon
numa-cpu-mapping
tune.listener.default-shards by-thread
tune.ssl.lifetime 24h
zero-warning
log 127.0.0.1 syslog debug
close-spread-time 1s
hard-stop-after 3s
description "triple-dezert frontproxy"
no insecure-fork-wanted
log stdout format short daemon
numa-cpu-mapping
tune.listener.default-shards by-thread
tune.ssl.lifetime 24h
zero-warning
log 127.0.0.1 syslog debug
defaults
# https://world.hey.com/goekesmi/haproxy-chrome-tcp-preconnect-and-error-408-a-post-preserved-from-the-past-2497d1f7
timeout server 30s
timeout client 10s
timeout connect 10s
option http-ignore-probes
defaults
# https://world.hey.com/goekesmi/haproxy-chrome-tcp-preconnect-and-error-408-a-post-preserved-from-the-past-2497d1f7
timeout server 30s
timeout client 10s
timeout connect 10s
option http-ignore-probes
timeout tunnel 1h
log global
mode http
option httplog
frontend main
bind :80
bind :443 ssl ${certs}
mode http
acl has_sni ssl_fc_sni -m found
acl has_host_hdr req.fhdr(host) -m found
http-request set-var(req.host) req.fhdr(host),host_only
# Check whether the client is attempting domain fronting.
acl ssl_sni_http_host_match ssl_fc_sni,strcmp(req.host) eq 0
${mapLines (c:
'' acl ${aclName c} var(req.host) -m str "${c.domain}"''
) proxied}
http-after-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" if { ssl_fc }
http-request deny status 400 if !{ req.fhdr_cnt(host) eq 1 }
http-request deny status 421 if has_sni has_host_hdr !ssl_sni_http_host_match
http-request return lf-string "%ci\n" content-type text/plain if { var(req.host) -m str "shelvacu.com" } { path /ip }
http-request redirect scheme https code 301 if !{ ssl_fc }
# garunteed ssl-only from here on
${mapLines (d:
'' http-request redirect location "https://${d}%[capture.req.uri]" code 301 if { var(req.host) -m str "www.${d}" }''
) domains}
http-request return string "Shelvacu is awesome" content-type text/plain if { path / } { var(req.host) -m str "shelvacu.com" }
http-request return string "Jean-luc is awesome" content-type text/plain if { path / } { var(req.host) -m str "jean-luc.org" }
${mapLines (c:
'' http-request allow if ${aclName c}''
) proxied}
http-request return status 404 string "not found" content-type text/plain
${mapLines (c:
'' use_backend ${backendName c} if ${aclName c}''
) proxied}
${concatMap "\n\n" (c:
''
backend ${backendName c}
timeout tunnel 1h
log global
mode http
${lib.optionalString c.forwardFor "option forwardfor"}
server main ${c.name}:${builtins.toString c.port} check maxconn ${builtins.toString c.maxConnections} ${if c.useSSL then "ssl verify none ssl-reuse" else "proto h1"}
''
) proxied}
option httplog
frontend main
bind :80
bind :443 ssl ${certs}
mode http
acl has_sni ssl_fc_sni -m found
acl has_host_hdr req.fhdr(host) -m found
http-request set-var(req.host) req.fhdr(host),host_only
# Check whether the client is attempting domain fronting.
acl ssl_sni_http_host_match ssl_fc_sni,strcmp(req.host) eq 0
${mapLines (c: ''acl ${aclName c} var(req.host) -m str "${c.domain}"'') proxied}
http-after-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" if { ssl_fc }
http-request deny status 400 if !{ req.fhdr_cnt(host) eq 1 }
http-request deny status 421 if has_sni has_host_hdr !ssl_sni_http_host_match
http-request return lf-string "%ci\n" content-type text/plain if { var(req.host) -m str "shelvacu.com" } { path /ip }
http-request redirect scheme https code 301 if !{ ssl_fc }
# garunteed ssl-only from here on
${
mapLines (
d:
''http-request redirect location "https://${d}%[capture.req.uri]" code 301 if { var(req.host) -m str "www.${d}" }''
) domains
}
http-request return string "Shelvacu is awesome" content-type text/plain if { path / } { var(req.host) -m str "shelvacu.com" }
http-request return string "Jean-luc is awesome" content-type text/plain if { path / } { var(req.host) -m str "jean-luc.org" }
${mapLines (c: ''http-request allow if ${aclName c}'') proxied}
http-request return status 404 string "not found" content-type text/plain
${mapLines (c: ''use_backend ${backendName c} if ${aclName c}'') proxied}
${concatMap "\n\n" (c: ''
backend ${backendName c}
mode http
${lib.optionalString c.forwardFor "option forwardfor"}
server main ${c.name}:${builtins.toString c.port} check maxconn ${builtins.toString c.maxConnections} ${
if c.useSSL then "ssl verify none ssl-reuse" else "proto h1"
}
'') proxied}
''

View File

@@ -3,12 +3,14 @@ let
inherit (lib) mkOption types;
outerConfig = config;
ip4Segment = ''[0-9]{1,3}'';
ip4Address = types.addCheck
(types.strMatching (lib.concatStringsSep ''\.'' [ip4Segment ip4Segment ip4Segment ip4Segment]))
(s:
lib.all (p: (lib.toInt p) < 255) (lib.splitString "." s)
)
;
ip4Address = types.addCheck (types.strMatching (
lib.concatStringsSep ''\.'' [
ip4Segment
ip4Segment
ip4Segment
ip4Segment
]
)) (s: lib.all (p: (lib.toInt p) < 255) (lib.splitString "." s));
# Note: This accepts plenty of strings that aren't valid ipv6 addresses, this is just to catch when you accidentally put an ipv4 or something else in
ip6Address = types.strMatching ''([a-fA-F0-9]{4}::?){1,7}[a-fA-F0-9]{4}'';
ipAddress = types.either ip4Address ip6Address;
@@ -16,41 +18,58 @@ in
{
# vacu.proxiedServices.habitat
options.vacu.proxiedServices = mkOption {
default = {};
type = types.attrsOf (types.submodule ({name, config, ...}: {
options = {
enable = mkOption { type = types.bool; default = false; };
default = { };
type = types.attrsOf (
types.submodule (
{ name, config, ... }:
{
options = {
enable = mkOption {
type = types.bool;
default = false;
};
name = mkOption {
default = name;
type = types.str;
};
name = mkOption {
default = name;
type = types.str;
};
fromContainer = mkOption {
default = null;
type = types.nullOr types.str;
};
fromContainer = mkOption {
default = null;
type = types.nullOr types.str;
};
port = mkOption { type = types.port; };
port = mkOption { type = types.port; };
ipAddress = mkOption {
type = ipAddress;
};
ipAddress = mkOption {
type = ipAddress;
};
domain = mkOption { type = types.str; };
domain = mkOption { type = types.str; };
forwardFor = mkOption { type = types.bool; default = false; };
forwardFor = mkOption {
type = types.bool;
default = false;
};
maxConnections = mkOption { type = types.int; default = 500; };
maxConnections = mkOption {
type = types.int;
default = 500;
};
useSSL = mkOption { type = types.bool; default = false; };
};
useSSL = mkOption {
type = types.bool;
default = false;
};
};
config = lib.mkMerge [
(lib.mkIf (config.fromContainer != null) {
ipAddress = outerConfig.containers.${config.fromContainer}.localAddress;
})
];
}));
config = lib.mkMerge [
(lib.mkIf (config.fromContainer != null) {
ipAddress = outerConfig.containers.${config.fromContainer}.localAddress;
})
];
}
)
);
};
}

View File

@@ -1,4 +1,5 @@
{ ... }: {
{ ... }:
{
vacu.proxiedServices.habitat = {
domain = "habitat.pwrhs.win";
ipAddress = "10.78.79.114";

View File

@@ -1,5 +1,6 @@
{
config, ...
config,
...
}:
let
contain = config.containers.llm;

View File

@@ -25,13 +25,12 @@
isReadOnly = true;
};
config =
{
system.stateVersion = "23.11";
networking.firewall.enable = false;
config = {
system.stateVersion = "23.11";
networking.firewall.enable = false;
services.nginx.enable = true;
services.nginx.virtualHosts."tulpaudcast.jean-luc.org".root = "/static-stuff/tulpaudcast.jean-luc.org";
};
services.nginx.enable = true;
services.nginx.virtualHosts."tulpaudcast.jean-luc.org".root = "/static-stuff/tulpaudcast.jean-luc.org";
};
};
}