123 lines
3.0 KiB
Nix
123 lines
3.0 KiB
Nix
{
|
|
name,
|
|
pkgs,
|
|
hostInfo,
|
|
dsl,
|
|
lib,
|
|
containers,
|
|
customPkgs,
|
|
...
|
|
}:
|
|
let
|
|
inherit (dsl) mkContainer mkService collectContainers;
|
|
inherit (hostInfo.paths) server secrets;
|
|
dataDir = hostInfo.paths.data;
|
|
|
|
mkSshpiperConfig =
|
|
{
|
|
pipes,
|
|
privateKey ? "/common_id",
|
|
}:
|
|
let
|
|
header = ''
|
|
version: "1.0"
|
|
pipes:
|
|
'';
|
|
mkPipe =
|
|
{
|
|
username,
|
|
host,
|
|
keysName ? username,
|
|
}:
|
|
''
|
|
- from:
|
|
- username: "${username}"
|
|
authorized_keys: /etc/sshpiperd/keys/user_${keysName}/authorized_keys
|
|
to:
|
|
host: ${host}:22
|
|
username: "runner"
|
|
private_key: "${privateKey}"
|
|
ignore_hostkey: true
|
|
'';
|
|
in
|
|
header + lib.concatMapStrings mkPipe pipes;
|
|
|
|
sshPipes = lib.concatMap (
|
|
{ container, data }: map (lib.mergeAttrs { host = container.name; }) data
|
|
) (collectContainers "sshpiperRoutes" containers);
|
|
|
|
sshpiperYaml = pkgs.writeText "sshpiper.yaml" (mkSshpiperConfig {
|
|
pipes = sshPipes;
|
|
});
|
|
in
|
|
{
|
|
${name} = mkContainer {
|
|
inherit name;
|
|
net.access = map (p: {
|
|
to = p.host;
|
|
tcp = [ 22 ];
|
|
}) sshPipes;
|
|
svc.autoStart = true;
|
|
net.forward.tcp = [
|
|
{
|
|
host = 22;
|
|
container = 2222;
|
|
}
|
|
];
|
|
resources.fs = {
|
|
"/etc/sshpiperd/keys" = {
|
|
hostPath = "${dataDir}/core/sshpiper";
|
|
isReadOnly = true;
|
|
};
|
|
"/common_id" = {
|
|
hostPath = "${server}/keypair/id_ed25519";
|
|
isReadOnly = true;
|
|
};
|
|
"/etc/ssh/ssh_host_ed25519_key" = {
|
|
hostPath = "${secrets}/ssh_host_ed25519_key";
|
|
isReadOnly = true;
|
|
};
|
|
"/etc/ssh/ssh_host_rsa_key" = {
|
|
hostPath = "${secrets}/ssh_host_rsa_key";
|
|
isReadOnly = true;
|
|
};
|
|
"/etc/ssh/ssh_host_ecdsa_key" = {
|
|
hostPath = "${secrets}/ssh_host_ecdsa_key";
|
|
isReadOnly = true;
|
|
};
|
|
};
|
|
service =
|
|
{ pkgs, ... }:
|
|
mkService {
|
|
description = "sshpiper SSH multiplexer";
|
|
execStart = "${lib.getExe' customPkgs.sshpiper "sshpiperd"} --log-level trace --server-key '/etc/ssh/ssh_host_*_key' ${lib.getExe' customPkgs.sshpiper "yaml"} --config /run/sshpiperd/config.yaml";
|
|
networkOnline = true;
|
|
serviceConfig = {
|
|
# sshpiperd rejects world-readable configs; copy store (444) -> runtime (600)
|
|
ExecStartPre = "${lib.getExe' pkgs.coreutils "install"} -m 600 ${sshpiperYaml} /run/sshpiperd/config.yaml";
|
|
RuntimeDirectory = "sshpiperd";
|
|
PrivateTmp = true;
|
|
RestrictAddressFamilies = "AF_INET AF_INET6 AF_UNIX";
|
|
};
|
|
};
|
|
};
|
|
|
|
_sshpiperRegister =
|
|
let
|
|
doTranslate =
|
|
self:
|
|
{
|
|
username,
|
|
keysName ? username,
|
|
}:
|
|
{
|
|
inherit username keysName;
|
|
host = self.name;
|
|
};
|
|
in
|
|
args: self: {
|
|
sshpiperRoutes =
|
|
if lib.isAttrs args then [ (doTranslate self args) ] else lib.map (doTranslate self) args;
|
|
};
|
|
}
|