Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/gunnar

deploy/systemd/gunnar.service

# gunnar on your own iron (roadmap phase 5).
#
# The same binary as the cluster form, under systemd instead of a kubelet. The
# hardening below is not decoration: it is the on-prem half of what the pod's
# `securityContext` says, written in the other syntax, so the two deployments
# are one product and not two.
#
#   install -m 0644 deploy/systemd/gunnar.service /etc/systemd/system/
#   install -m 0600 deploy/systemd/gunnar.env.example /etc/gunnar/gunnar.env
#   $EDITOR /etc/gunnar/gunnar.env       # the KEK goes here, and only here
#   systemctl daemon-reload && systemctl enable --now gunnar
#
# `gunnar service install` writes this over D-Bus, in two files: the unit body,
# rendered from a Skidbladnir `ServiceSpec`, and the hardening block below,
# written as a `gunnar.service.d/10-hardening.conf` drop-in because Skidbladnir
# 0.1.12's spec models exactly ONE hardening directive and has no escape hatch
# for the other twenty-four. `gunnar service unit` prints both halves, and
# `service::tests::the_install_carries_every_hardening_line_the_repository_ships`
# compares them against THIS file, so the sentence above is checked rather than
# claimed. What the install does NOT take from here: the `--http-bind` and
# `--metrics-bind` arguments, and the `EnvironmentFile=` — an install has never
# written a KEK file, and giving it one is a different change from that one.

[Unit]
Description=gunnar — a git forge with an unbroken chain of custody
Documentation=https://github.com/vetra-se/gunnar
After=network-online.target
Wants=network-online.target

[Service]
Type=exec
ExecStart=/usr/local/bin/gunnar serve \
    --ssh-bind=0.0.0.0:2222 \
    --http-bind=0.0.0.0:8080 \
    --grpc-bind=127.0.0.1:50051 \
    --metrics-bind=127.0.0.1:9090

# **The KEK lives in this file and nowhere else.** 0600, root-owned, and NOT in
# an `Environment=` line — those are readable to every user on the box through
# `systemctl show`.
EnvironmentFile=/etc/gunnar/gunnar.env

User=gunnar
Group=gunnar
DynamicUser=no
StateDirectory=gunnar
StateDirectoryMode=0700
WorkingDirectory=/var/lib/gunnar

Restart=on-failure
RestartSec=2s

# ── the hardening, matching the pod's securityContext ────────────────────────
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectKernelLogs=yes
ProtectControlGroups=yes
ProtectClock=yes
ProtectHostname=yes
ProtectProc=invisible
RestrictSUIDSGID=yes
RestrictRealtime=yes
RestrictNamespaces=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RemoveIPC=yes
UMask=0077
CapabilityBoundingSet=
AmbientCapabilities=
SystemCallArchitectures=native
SystemCallFilter=@system-service
SystemCallFilter=~@privileged @resources @obsolete
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX

[Install]
WantedBy=multi-user.target