samjeston / openhub Public
123 lines· 4.2 KB ·Bourne Again Shell (bash)
Raw
1#!/usr/bin/env bash
2# Installs or updates openhub as a systemd service. Run it as root on the
3# target machine (scripts/deploy-server.sh builds openhub there and runs this
4# for you):
5#
6# sudo ./install.sh ./openhub [./openhub.service]
7#
8# Each run stops the service, snapshots the database into backups/ in the data
9# directory (keeping the last 5), swaps the binary (the old one stays as
10# openhub.prev) and starts the service again. If the new binary fails its
11# health check, the previous one is put back. Repositories aren't snapshotted:
12# upgrades only migrate the database.
13set -euo pipefail
14
15bin=${1:?usage: install.sh BINARY [UNIT_FILE]}
16unit=${2:-}
17dest=/usr/local/bin/openhub
18unit_dest=/etc/systemd/system/openhub.service
19defaults=/etc/default/openhub
20keep_backups=5
21
22[ "$(id -u)" = 0 ] || { echo "install.sh must run as root, e.g. with sudo." >&2; exit 1; }
23
24# setting NAME DEFAULT: the value the service sees, honouring /etc/default/openhub.
25setting() {
26 (
27 [ -f "$defaults" ] && . "$defaults"
28 printf '%s\n' "${!1:-$2}"
29 )
30}
31
32# put SRC: replace the installed binary without writing into a running executable.
33put() {
34 install -m 0755 "$1" "$dest.new"
35 mv -f "$dest.new" "$dest"
36}
37
38# get URL: succeeds when URL answers without an HTTP error.
39get() {
40 if command -v curl >/dev/null; then
41 curl -fs --max-time 2 -o /dev/null "$1"
42 else
43 wget -q -T 2 -O /dev/null "$1"
44 fi
45}
46
47# Refuse a binary built for another architecture before touching the service.
48new_version=$("$bin" --version) || { echo "$bin doesn't run on this machine. Build it for $(uname -m)." >&2; exit 1; }
49git_bin=$(setting OPENHUB_GIT_BIN git)
50command -v "$git_bin" >/dev/null || { echo "openhub needs git at runtime and can't find $git_bin. Install git first." >&2; exit 1; }
51
52data=$(setting OPENHUB_DATA_DIR /var/lib/openhub)
53db=$data/openhub.db
54addr=$(setting OPENHUB_HTTP_ADDR 127.0.0.1:3000)
55case $addr in
56 0.0.0.0:*) addr=127.0.0.1:${addr#*:} ;;
57 "[::]":*) addr=[::1]:${addr##*:} ;;
58esac
59url=http://$addr/
60
61id openhub >/dev/null 2>&1 || useradd --system --user-group --home-dir /var/lib/openhub --no-create-home --shell /usr/sbin/nologin openhub
62
63if [ ! -f "$defaults" ]; then
64 cat >"$defaults" <<'EOF'
65# Settings for the openhub service; see "Configuration" in the openhub README.
66# Restart after editing: sudo systemctl restart openhub
67#OPENHUB_PUBLIC_URL=https://git.example.com
68#OPENHUB_SSH_HOST=git.example.com
69#OPENHUB_SSH_PORT=2222
70#OPENHUB_DISABLE_REGISTRATION=true
71EOF
72 echo "Wrote $defaults. Set OPENHUB_PUBLIC_URL there, then run: sudo systemctl restart openhub"
73fi
74
75if [ -n "$unit" ] && ! cmp -s "$unit" "$unit_dest"; then
76 install -m 0644 "$unit" "$unit_dest"
77 systemctl daemon-reload
78fi
79[ -f "$unit_dest" ] || { echo "No openhub unit is installed yet. Pass the unit file as the second argument." >&2; exit 1; }
80
81systemctl stop openhub 2>/dev/null || true
82
83snap=
84if [ -f "$db" ]; then
85 backups=$data/backups
86 snap=$backups/$(date +%Y%m%d-%H%M%S)
87 mkdir -p "$snap"
88 # The service is stopped, so the files are consistent; -wal/-shm only exist after an unclean stop.
89 for f in "$db" "$db-wal" "$db-shm"; do
90 if [ -f "$f" ]; then cp -p "$f" "$snap/"; fi
91 done
92 chown -R openhub:openhub "$backups"
93 ls -1d "$backups"/*/ | head -n -"$keep_backups" | xargs -r rm -rf --
94 echo "Database snapshot: $snap"
95fi
96
97if [ -f "$dest" ]; then cp -p "$dest" "$dest.prev"; fi
98put "$bin"
99systemctl enable --quiet openhub
100started=$(date +%s)
101systemctl start openhub
102
103for _ in $(seq 20); do
104 sleep 1
105 if get "$url"; then
106 echo "$new_version is running ($url)."
107 fingerprint=$(journalctl -u openhub --since "@$started" -o cat --no-pager 2>/dev/null | grep -o 'SHA256:[A-Za-z0-9+/]*' | head -n 1 || true)
108 if [ -n "$fingerprint" ]; then echo "SSH host key fingerprint: $fingerprint"; fi
109 echo "Settings: $defaults"
110 echo "Logs: journalctl -u openhub -f"
111 exit 0
112 fi
113done
114
115echo "$new_version failed its health check at $url." >&2
116journalctl -u openhub -n 20 --no-pager >&2 || true
117if [ -f "$dest.prev" ]; then
118 put "$dest.prev"
119 systemctl restart openhub
120 echo "Restored the previous binary ($("$dest" --version))." >&2
121 if [ -n "$snap" ]; then echo "If it can't open the database, stop the service and copy $snap back to $data." >&2; fi
122fi
123exit 1