josie / simplegit

install: prefer sudo, fall back to doas and su; strip builds

detect the host's privilege escalator instead of assuming sudo
(BSD/alpine hosts ship doas); the as-service-user adduser hint falls
back to su -s /bin/sh since the account's login shell is nologin.
builds use -ldflags "-s -w" (28 -> 19.4 MB). replace the step-by-step
header with what the script writes + what it deliberately skips, drop
the numbered section banners. docs: doas note and stripped-build
guidance.

LLM Contributor: qwen/qwen3.8-flash

bc57e9101744c6393d52f1a60c71c206d29347dd
cjosie <administrator@josie-c.com> · 2026-10-06T20:41 · browse files at this commit

parents: e17a0b8

diff --git a/docs/self-host.md b/docs/self-host.md
index e5cf8d4..1dc8b95 100644
--- a/docs/self-host.md
+++ b/docs/self-host.md
@@ -6,14 +6,17 @@ listens on plain HTTP and requires the `git` binary on `PATH` at runtime.
 
 # 1. Install (recommended)
 
-`scripts/install.sh` does steps 1-5 for you (binary, system user, data dir,
-config, proxy example conf, systemd unit):
+`scripts/install.sh` sets everything up except the account (binary, system
+user, data dir, config, proxy example conf, systemd unit):
 
 ```sh
 sudo scripts/install.sh https://git.example.com apache
 # or: ... https://git.example.com caddy | none
 ```
 
+`doas` works in place of `sudo` everywhere in this guide (BSD and alpine
+hosts ship it instead); the script only needs to run as root.
+
 The second argument picks the reverse-proxy example conf, with the domain
 substituted: `apache` installs `/etc/apache2/sites-available/simplegit.conf`
 (and enables modules/site), `caddy` installs the site into the Caddyfile
@@ -25,11 +28,13 @@ Manual equivalent, if you prefer to do it by hand:
 ### 1a. Build
 
 ```sh
-go build -o /usr/local/bin/simplegit ./cmd/simplegit
+go build -ldflags "-s -w" -o /usr/local/bin/simplegit ./cmd/simplegit
 ```
 
 The binary embeds templates and static assets, so there is nothing else to
 copy. It needs `git` (with `http-backend`) installed on the host.
+Stripping symbols/DWARF cuts the binary from ~28 MB to ~19 MB; plain
+`go build` works too, just bigger.
 
 ## 2. Config
 
diff --git a/scripts/install.sh b/scripts/install.sh
index 11ae486..5354157 100755
--- a/scripts/install.sh
+++ b/scripts/install.sh
@@ -1,36 +1,34 @@
 #!/usr/bin/env bash
 # Install simplegit on a Debian/Ubuntu host.
-#
-#   sudo scripts/install.sh <base-url> [apache|caddy|none]
-#   e.g. sudo scripts/install.sh https://git.josie-c.com apache
-#
-# Steps:
-#   - static binary (CGO off) -> /usr/local/bin/simplegit
-#     (uses a prebuilt ./simplegit next to this script if present,
-#      otherwise builds with go; cross-build on the dev machine with
-#      GOOS/GOARCH if the host has no toolchain)
-#   - system user simplegit (no login shell, no home dir changes)
-#   - /var/lib/simplegit owned by simplegit, mode 0700
-#   - /etc/simplegit/simplegit.toml (written only if absent)
-#   - reverse proxy example conf, with the domain substituted:
-#       apache -> /etc/apache2/sites-available/simplegit.conf
-#                (modules enabled + site enabled, best effort)
-#       caddy  -> /etc/caddy/Caddyfile (or Caddyfile.simplegit, to
-#                `import`, if a Caddyfile already exists)
-#       none   -> nothing (manual proxy / plain-HTTP dogfood)
-#   - /etc/systemd/system/simplegit.service + systemctl enable
-#     (NOT started; add the user first, then start it)
-#
+#   sudo scripts/install.sh https://git.example.com [apache|caddy|none]
+#   (needs a root shell; doas works in place of sudo)
+# Writes: /usr/local/bin/simplegit, system user simplegit,
+# /var/lib/simplegit (0700, service-owned), /etc/simplegit/simplegit.toml
+# (existing kept), proxy example conf with the domain substituted, and a
+# systemd unit (enabled, not started: create the account first).
 # Deliberately NOT done: adduser (password), certbot, firewall.
-# See docs/self-host.md.
+# Details per proxy: docs/self-host.md.
 set -euo pipefail
 
+# doas is the sudo-less BSD/alpine equivalent; never assume sudo exists.
+if command -v sudo >/dev/null 2>&1; then
+  ESCALATE=sudo
+elif command -v doas >/dev/null 2>&1; then
+  ESCALATE=doas
+else
+  ESCALATE=""
+fi
+
 if [ "$(id -u)" -ne 0 ]; then
-  echo "run as: sudo scripts/install.sh <base-url> [apache|caddy|none]" >&2
+  if [ -n "$ESCALATE" ]; then
+    echo "run as root: $ESCALATE scripts/install.sh <base-url> [apache|caddy|none]" >&2
+  else
+    echo "run as root (sudo, doas, or su -c): scripts/install.sh <base-url> [apache|caddy|none]" >&2
+  fi
   exit 1
 fi
 
-BASE_URL="${1:?usage: sudo scripts/install.sh https://git.example.com [apache|caddy|none]}"
+BASE_URL="${1:?usage: sudo|doas scripts/install.sh https://git.example.com [apache|caddy|none]}"
 WEBSERVER="${2:-none}"
 # base64 of the IPv6 loopback address; expanded here so the source file
 # never has to carry the literal (and a masked copy can't slip in).
@@ -43,33 +41,29 @@ CONFIG_DIR=/etc/simplegit
 CONFIG="$CONFIG_DIR/simplegit.toml"
 UNIT=/etc/systemd/system/simplegit.service
 
-# 1. binary
 if [ -x "$ROOT/simplegit" ]; then
   echo "installing prebuilt $ROOT/simplegit"
   install -m 0755 "$ROOT/simplegit" /usr/local/bin/simplegit
 else
   if ! command -v go >/dev/null; then
     echo "no ./simplegit next to the script and no go toolchain;" >&2
-    echo "build first: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o simplegit ./cmd/simplegit" >&2
+    echo "build first: CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags '-s -w' -o simplegit ./cmd/simplegit" >&2
     exit 1
   fi
   echo "building simplegit (static)"
-  CGO_ENABLED=0 go build -o /usr/local/bin/simplegit "$ROOT/cmd/simplegit"
+  CGO_ENABLED=0 go build -ldflags "-s -w" -o /usr/local/bin/simplegit "$ROOT/cmd/simplegit"
 fi
 /usr/local/bin/simplegit -h >/dev/null
 
-# 2. system user
 if ! id simplegit >/dev/null 2>&1; then
   useradd --system --no-create-home --shell /usr/sbin/nologin simplegit
   echo "created system user simplegit"
 fi
 
-# 3. data dir
 mkdir -p "$DATA_DIR"
 chmod 0700 "$DATA_DIR"
 chown -R simplegit:simplegit "$DATA_DIR"
 
-# 4. config (never clobber an existing one)
 mkdir -p "$CONFIG_DIR"
 if [ -e "$CONFIG" ]; then
   echo "leaving existing $CONFIG in place"
@@ -83,7 +77,6 @@ EOF
   chmod 0640 "$CONFIG"
 fi
 
-# 5. reverse proxy example conf
 case "$WEBSERVER" in
 apache)
   if [ ! -d /etc/apache2 ]; then
@@ -121,7 +114,6 @@ none)
   ;;
 esac
 
-# 6. systemd unit
 cat > "$UNIT" <<'EOF'
 [Unit]
 Description=simplegit
@@ -141,6 +133,13 @@ EOF
 systemctl daemon-reload
 systemctl enable simplegit
 
+# su must override the shell: the service user's login shell is nologin.
+if [ -n "$ESCALATE" ]; then
+  ADDUSER="$ESCALATE -u simplegit /usr/local/bin/simplegit adduser -config $CONFIG josie"
+else
+  ADDUSER="su -s /bin/sh simplegit -c '/usr/local/bin/simplegit adduser -config $CONFIG josie'"
+fi
+
 cat <<EOF
 
 simplegit installed.
@@ -152,7 +151,7 @@ simplegit installed.
 Remaining steps (docs/self-host.md):
   1. Create the account (run as the simplegit user, not root,
      so the DB ends up service-owned):
-     printf '%s\\n' "\$PASSWORD" | sudo -u simplegit /usr/local/bin/simplegit adduser -config $CONFIG josie
+     printf '%s\\n' "\$PASSWORD" | $ADDUSER
   2. Start the app and check it on loopback:
      systemctl start simplegit
      curl -sI http://$LOOPBACK:8080/