Root User Provisioning Service#
This is one of the more controversial services I have, but I needed a way to restore the system without anything except the ISO and a password.
With this service I am setting up root provisioning via a web link. I will curl the link with a post request and then it will add SSH keys to the root user on the server.
Is this dangerous? Yes, however I understand the risks associated. I also tried to design the service to only run if the system was net new. The service will exit if the done file already exists /var/lib/nik3sx/boot-unlock-service/done.
Generate a bcrypt password:
nix-shell -p whois --run "mkpasswd -m bcrypt -R 14 Password123"
echo "$2b$14$5y4Nqyb368wTd46jtRyq.e6GblLWW7U3Krmc5Ts7P.E2XPS59nq0u" > /var/lib/nik3sx/boot-unlock-service/password.hash
chmod 600 /var/lib/boot-unlock-service/password.hash
chown root:root /var/lib/boot-unlock-service/password.hashTo Build:
CGO_ENABLED=0 go build -o boot_unlock_service main.goThe functions to note include writeTLSSecret:
...
type UnlockRequest struct {
PasswordInput string `json:"password_input"`
SSHPublicKey string `json:"ssh_public_key"`
}
...
const (
certDir = "/var/lib/nik3sx/boot-unlock-service/certs"
doneFile = "/var/lib/nik3sx/boot-unlock-service/done"
)
...
func main() {
outFile := "/var/lib/nik3sx/boot-unlock-service/boot-unlock-tls.yaml"
secretName := "boot-unlock-tls"
namespace := "kube-system"
writeTLSSecret(certDir, outFile, secretName, namespace)
if fileExists(doneFile) {
log.Println("Already done")
os.Exit(0)
}
os.MkdirAll(certDir, 0700)
caCert, caKey := ensureCA()
serverCert, serverKey := ensureServerCert(caCert, caKey)
writeTLSSecret(certDir, outFile, secretName, namespace)
mux := http.NewServeMux()
mux.HandleFunc("/health", func(w http.ResponseWriter, _ *http.Request) {
w.Write([]byte("ok"))
})
mux.HandleFunc("/unlock", unlockHandler)
srv := &http.Server{
Addr: ":8443",
Handler: mux,
}
startCAHTTPServer()
log.Println("HTTPS server listening on :8443")
log.Fatal(srv.ListenAndServeTLS(serverCert, serverKey))
}
...
// writeTLSSecret generates a Kubernetes TLS Secret YAML from cert/key files and writes it to outFile
func writeTLSSecret(certDir, outFile, secretName, namespace string) {
crtFile := filepath.Join(certDir, "server.crt")
keyFile := filepath.Join(certDir, "server.key")
// Check if both files exist
if !fileExists(crtFile) {
log.Printf("Certificate file does not exist: %s", crtFile)
return
}
if !fileExists(keyFile) {
log.Printf("Key file does not exist: %s", keyFile)
return
}
crtEncoded := encodeFile(crtFile)
keyEncoded := encodeFile(keyFile)
yamlContent := fmt.Sprintf(`apiVersion: v1
kind: Secret
metadata:
name: %s
namespace: %s
type: kubernetes.io/tls
data:
tls.crt: %s
tls.key: %s
`, secretName, namespace, crtEncoded, keyEncoded)
if err := os.WriteFile(outFile, []byte(yamlContent), 0644); err != nil {
log.Fatalf("Failed to write YAML file: %v", err)
}
fmt.Printf("Secret YAML written to %s\n", outFile)
}
...
func checkPassword(input string) error {
hashBytes, err := os.ReadFile("/var/lib/nik3sx/boot-unlock-service/password.hash")
if err != nil {
return err
}
hash := strings.TrimSpace(string(hashBytes))
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(input))
}
func validateSSHPublicKey(key string) error {
_, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key))
return err
}
...
func addRootKey(pubkey string) error {
dir := "/root/.ssh"
authKeys := dir + "/authorized_keys"
if err := os.MkdirAll(dir, 0700); err != nil {
return err
}
f, err := os.OpenFile(authKeys,
os.O_APPEND|os.O_CREATE|os.O_WRONLY,
0600,
)
if err != nil {
return err
}
defer f.Close()
_, err = f.WriteString(pubkey + "\n")
return err
}modules/boot-unlock-service.nix#
{
pkgs,
lib,
...
}: {
environment.etc."boot_unlock_service/boot_unlock_service".source = ../boot-unlock-service/bin/boot_unlock_service;
environment.etc."boot_unlock_service/password.hash".source = ../secrets/password.hash;
# Ensure /var/lib folders exist
systemd.tmpfiles.rules = [
"d /var/lib/nik3sx/boot-unlock-service 0755 root root -"
"d /var/lib/nik3sx/boot-unlock-service/certs 0700 root root -"
# Optional: copy the binary here (could also run from Nix store directly)
"f /var/lib/nik3sx/boot-unlock-service/password.hash 0700 root root - /etc/boot_unlock_service/password.hash"
"f /var/lib/nik3sx/boot-unlock-service/boot_unlock_service 0755 root root - /etc/boot_unlock_service/boot_unlock_service"
];
# Systemd service
systemd.services.boot-unlock-service = {
description = "Self-Signed HTTPS Boot Unlock Service";
after = ["network-online.target"];
wants = ["network-online.target"];
serviceConfig = {
Type = "oneshot";
ConditionPathExists = "!/var/lib/nik3sx/boot-unlock-service/done";
ExecStartPre = "${pkgs.coreutils}/bin/install -Dm700 /etc/boot_unlock_service/password.hash /var/lib/nik3sx/boot-unlock-service/password.hash";
ExecStart = "${pkgs.bash}/bin/bash -c '/var/lib/nik3sx/boot-unlock-service/boot_unlock_service'"; # points to copied binary
ExecStartPost = "${pkgs.coreutils}/bin/touch /var/lib/nik3sx/boot-unlock-service/done";
User = "root";
Group = "root";
ReadWritePaths = ["/var/lib/nik3sx/boot-unlock-service" "/root/.ssh"];
CapabilityBoundingSet = "";
NoNewPrivileges = false;
PrivateTmp = true;
RemainAfterExit = "no";
};
wantedBy = ["multi-user.target"];
};
}