nix-config/modules/nixos/programs/forgejo/ssh.nix

84 lines
2.8 KiB
Nix

{...}: {
flake.nixosModules.forgejo-ssh = {
lib,
config,
pkgs,
...
}: let
gitUser = config.services.forgejo.settings.server.BUILTIN_SSH_SERVER_USER;
forgejoUser = config.services.forgejo.user;
forgejo = config.services.forgejo.package;
stateDir = config.services.forgejo.stateDir;
forgejoExe = lib.getExe forgejo;
separateUsers = gitUser != forgejoUser;
# Run the AuthorizedKeysCommand as the forgejo user when users differ,
# so it can read app.ini without adding git to the forgejo group.
keysCommandUser =
if separateUsers
then forgejoUser
else gitUser;
forgejoKeysCmd = "FORGEJO_WORK_DIR=${stateDir} ${forgejoExe} keys -e git -u \"$1\" -t \"$2\" -k \"$3\"";
# When the SSH user differs from the forgejo service user, rewrite
# the command= wrapper to use sudo so forgejo serv runs as the user
# that owns the repository data.
forgejoKeysScript = pkgs.writeShellScript "forgejo-keys" (
if separateUsers
then ''
${forgejoKeysCmd} \
| ${pkgs.gnused}/bin/sed 's|command="${forgejoExe}|command="/run/wrappers/bin/sudo -u ${forgejoUser} --preserve-env=SSH_ORIGINAL_COMMAND ${forgejoExe}|'
''
else forgejoKeysCmd
);
forgejoKeysPath = "/run/forgejo-keys";
in {
config = lib.mkIf config.services.forgejo.enable (lib.mkMerge [
{
users.users.${gitUser}.shell = pkgs.bash;
services.openssh.settings.AllowUsers = [gitUser];
# Copy the key lookup script to a root-owned path outside /nix/store.
# sshd StrictModes requires AuthorizedKeysCommand and all parent dirs
# to be owned by root with no group/world writes. /nix/store and /etc
# symlinks both fail this check.
system.activationScripts.forgejo-ssh-keys = lib.stringAfter ["etc"] ''
install -m 0755 -o root -g root ${forgejoKeysScript} ${forgejoKeysPath}
'';
services.openssh.extraConfig = ''
Match User ${gitUser}
AuthorizedKeysCommandUser ${keysCommandUser}
AuthorizedKeysCommand ${forgejoKeysPath} %u %t %k
AuthenticationMethods publickey
KbdInteractiveAuthentication no
PasswordAuthentication no
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
PermitTTY no
'';
}
(lib.mkIf separateUsers {
# Allow the git user to run forgejo serv as the forgejo user
security.sudo.extraRules = [
{
users = [gitUser];
runAs = forgejoUser;
commands = [
{
command = "${forgejoExe} --config=${stateDir}/custom/conf/app.ini serv *";
options = ["NOPASSWD" "SETENV"];
}
];
}
];
})
]);
};
}