- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
# Copyright 2026 Shota FUJI <pockawoooh@gmail.com>
# SPDX-License-Identifier: MIT
{
config,
lib,
pkgs,
...
}:
let
# Directory managed by soft-serve.
softserveData = "/opt/soft";
softserveEnvDir = "/opt/soft-admin";
softserveAdminKeyEnv = "${softserveEnvDir}/admin.env";
write-initial-admin-keys = pkgs.writeShellApplication {
name = "write-initial-admin-keys";
text = ''
echo "SOFT_SERVE_INITIAL_ADMIN_KEYS=\"$(cat)\"" > ${softserveAdminKeyEnv}
'';
};
in
{
system.stateVersion = "26.11";
boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true;
networking.firewall.enable = false;
users.groups.git = { };
systemd.tmpfiles.rules = [
"d ${softserveData} 0750 soft git -"
"d ${softserveEnvDir} 0770 soft git -"
];
users.users = {
soft = {
isSystemUser = true;
group = "git";
};
legit = {
isSystemUser = true;
group = "git";
};
admin = {
isNormalUser = true;
password = "pass";
group = "git";
};
};
security.polkit = {
enable = true;
# Password-less poweroff / reboot
extraConfig = ''
polkit.addRule(function(action, subject) {
const isPowerOff = [
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.power-off",
"org.freedesktop.login1.power-off-multiple-sessions",
].indexOf(action.id) > -1;
if (subject.user === "admin" && isPowerOff) {
return polkit.Result.YES;
}
})
'';
};
services.getty.autologinUser = "admin";
environment.systemPackages = with pkgs; [
curl
soft-serve
write-initial-admin-keys
];
systemd.paths.soft-serve-adminenv = {
description = "availability of initial admin env file";
wantedBy = [ "default.target" ];
pathConfig = {
PathExists = softserveAdminKeyEnv;
Unit = "soft-serve.service";
};
};
# Service definition in nixpkgs isn't good.
systemd.services.soft-serve =
let
yaml = pkgs.formats.yaml { };
configFile = yaml.generate "soft-serve.yaml" {
name = "soft-serve & legit demo";
log_format = "text";
ssh.listen_addr = ":22222";
http.listen_addr = ":8080";
};
in
{
description = "Git server for the command-line";
after = [ "network.target" ];
restartTriggers = [
configFile
softserveAdminKeyEnv
];
wantedBy = lib.mkForce [ ];
environment = {
SOFT_SERVE_DATA_PATH = softserveData;
SOFT_SERVE_CONFIG_LOCATION = configFile;
};
serviceConfig = {
User = "soft";
Group = "git";
Type = "simple";
ExecStart = "${lib.getExe pkgs.soft-serve} serve";
EnvironmentFile = [ softserveAdminKeyEnv ];
WorkingDirectory = softserveData;
};
};
services.legit = {
enable = true;
config = {
repo.scanPath = "${softserveData}/repos";
meta.robotsTxt = builtins.toFile "robots.txt" ''
User-Agent: *
Disallow: /
'';
};
user = "legit";
group = "git";
};
services.caddy = {
enable = true;
configFile = pkgs.writeText "Caddyfile" ''
{
auto_https off
}
:80 {
reverse_proxy :5555
}
'';
};
}