diff --git a/clanModules/flake-module.nix b/clanModules/flake-module.nix index e6ad9109f..0b379c354 100644 --- a/clanModules/flake-module.nix +++ b/clanModules/flake-module.nix @@ -11,6 +11,7 @@ moonlight = ./moonlight.nix; sunshine = ./sunshine.nix; syncthing = ./syncthing.nix; + sshd = ./sshd.nix; vm-user = ./vm-user.nix; graphical = ./graphical.nix; xfce = ./xfce.nix; diff --git a/clanModules/sshd.nix b/clanModules/sshd.nix new file mode 100644 index 000000000..ee4d09b94 --- /dev/null +++ b/clanModules/sshd.nix @@ -0,0 +1,18 @@ +{ config, pkgs, ... }: { + services.openssh.enable = true; + + services.openssh.hostKeys = [{ + path = config.clanCore.secrets.borgbackup.secrets."ssh.id_ed25519".path; + type = "ed25519"; + }]; + + clanCore.secrets.openssh = { + secrets."ssh.id_ed25519" = { }; + facts."ssh.id_ed25519.pub" = { }; + generator.path = [ pkgs.coreutils pkgs.openssh ]; + generator.script = '' + ssh-keygen -t ed25519 -N "" -f $secrets/ssh.id_ed25519 + mv $secrets/ssh.id_ed25519.pub $facts/ssh.id_ed25519.pub + ''; + }; +} diff --git a/nixosModules/clanCore/secrets/default.nix b/nixosModules/clanCore/secrets/default.nix index fae55c3a1..94a0191b4 100644 --- a/nixosModules/clanCore/secrets/default.nix +++ b/nixosModules/clanCore/secrets/default.nix @@ -100,6 +100,7 @@ config' = config; in lib.mkOption { + default = { }; type = lib.types.attrsOf (lib.types.submodule ({ config, name, ... }: { options = { name = lib.mkOption { diff --git a/pkgs/clan-cli/clan_cli/secrets/generate.py b/pkgs/clan-cli/clan_cli/secrets/generate.py index d87f8d99b..13721559e 100644 --- a/pkgs/clan-cli/clan_cli/secrets/generate.py +++ b/pkgs/clan-cli/clan_cli/secrets/generate.py @@ -2,6 +2,7 @@ import argparse import importlib import logging import os +import subprocess from collections.abc import Callable from pathlib import Path from tempfile import TemporaryDirectory @@ -19,6 +20,15 @@ from .modules import SecretStoreBase log = logging.getLogger(__name__) +def read_multiline_input(prompt: str = "Finish with Ctrl-D") -> str: + """ + Read multi-line input from stdin. + """ + print(prompt, flush=True) + proc = subprocess.run(["cat"], stdout=subprocess.PIPE, text=True) + return proc.stdout + + def generate_service_secrets( machine: Machine, service: str, @@ -128,7 +138,12 @@ def generate_secrets( fact_store = facts_module.FactStore(machine=machine) if prompt is None: - prompt = lambda text: input(f"{text}: ") + + def prompt_func(text: str) -> str: + print(f"{text}: ") + return read_multiline_input() + + prompt = prompt_func with TemporaryDirectory() as tmp: tmpdir = Path(tmp)