refactor install.sh to match update.sh

This commit is contained in:
Chris Wanstrath 2026-03-03 13:19:01 -08:00
parent 7274910a26
commit aee5bb1099
2 changed files with 61 additions and 178 deletions

View File

@ -3,115 +3,112 @@ set -euo pipefail
##
# toes installer
# Usage: curl -sSL https://toes.dev/install | bash
# Must be run as the 'toes' user.
# Usage: curl -fsSL https://toes.dev/install | sh
#
# Installs or updates toes on a Raspberry Pi.
# Must be run as the 'toes' user with passwordless sudo.
DEST=~/toes
REPO="https://git.nose.space/defunkt/toes"
DEST=~/toes
APPS_DIR=~/apps
DATA_DIR=~/data
BUNDLED_APPS="clock code cron env git metrics"
# ── Helpers ──────────────────────────────────────────────
quiet() { "$@" > /dev/null 2>&1; }
info() { echo ">> $1"; }
fail() { echo "ERROR: $1" >&2; exit 1; }
# ── Preflight ────────────────────────────────────────────
echo ""
echo " ╔══════════════════════════════════╗"
echo " ║ 🐾 toes - personal web appliance ║"
echo " ╚══════════════════════════════════╝"
echo " toes - personal web appliance"
echo ""
# Must be running as toes
if [ "$(whoami)" != "toes" ]; then
echo "ERROR: This script must be run as the 'toes' user."
echo "Create the user during Raspberry Pi OS setup."
exit 1
fi
[ "$(whoami)" = "toes" ] || fail "Must be run as the 'toes' user."
sudo -n true 2>/dev/null || fail "Requires passwordless sudo."
# Must have passwordless sudo (can't prompt when piped from curl)
if ! sudo -n true 2>/dev/null; then
echo "ERROR: This script requires passwordless sudo."
echo "On Raspberry Pi OS, the default user has this already."
exit 1
fi
# ── System packages ──────────────────────────────────────
# -- System packages --
echo ">> Updating system packages"
info "Updating system packages"
quiet sudo apt-get update
quiet sudo apt-get install -y git libcap2-bin avahi-utils fish unzip
echo ">> Setting fish as default shell"
if [ "$(getent passwd toes | cut -d: -f7)" != "/usr/bin/fish" ]; then
info "Setting fish as default shell"
quiet sudo chsh -s /usr/bin/fish toes
fi
# -- Bun --
# ── Bun ──────────────────────────────────────────────────
BUN_REAL="$HOME/.bun/bin/bun"
BUN_SYMLINK="/usr/local/bin/bun"
BUN="$HOME/.bun/bin/bun"
if [ ! -x "$BUN_REAL" ]; then
echo ">> Installing bun"
if [ ! -x "$BUN" ]; then
info "Installing bun"
curl -fsSL https://bun.sh/install | bash > /dev/null 2>&1
if [ ! -x "$BUN_REAL" ]; then
echo "ERROR: bun installation failed"
exit 1
fi
[ -x "$BUN" ] || fail "bun installation failed."
fi
if [ ! -x "$BUN_SYMLINK" ]; then
sudo ln -sf "$BUN_REAL" "$BUN_SYMLINK"
if [ ! -x /usr/local/bin/bun ]; then
sudo ln -sf "$BUN" /usr/local/bin/bun
fi
echo ">> Setting CAP_NET_BIND_SERVICE on bun"
sudo setcap 'cap_net_bind_service=+ep' "$BUN_REAL"
sudo setcap 'cap_net_bind_service=+ep' "$BUN"
# -- Clone --
# ── Clone or pull ────────────────────────────────────────
if [ ! -d "$DEST" ]; then
echo ">> Cloning toes"
git clone "$REPO" "$DEST"
if [ -d "$DEST/.git" ]; then
info "Pulling latest toes"
git -C "$DEST" fetch origin main
git -C "$DEST" reset --hard origin/main
else
echo ">> Updating toes"
cd "$DEST" && git pull origin main
info "Cloning toes"
git clone "$REPO" "$DEST"
fi
# -- Directories --
# ── Directories ──────────────────────────────────────────
mkdir -p ~/data ~/apps
mkdir -p "$APPS_DIR" "$DATA_DIR"
# -- Dependencies & build --
# ── Dependencies & build ─────────────────────────────────
echo ">> Installing dependencies"
cd "$DEST" && bun install
info "Installing dependencies"
cd "$DEST" && quiet bun install
echo ">> Building client"
cd "$DEST" && bun run build
info "Building"
cd "$DEST" && quiet bun run build
# -- Bundled apps --
# ── Bundled apps ─────────────────────────────────────────
echo ">> Installing bundled apps"
BUNDLED_APPS="clock code cron env git metrics"
info "Installing bundled apps"
for app in $BUNDLED_APPS; do
if [ -d "$DEST/apps/$app" ]; then
[ -d "$DEST/apps/$app" ] || continue
echo " $app"
cp -r "$DEST/apps/$app" ~/apps/
if [ -f ~/apps/"$app"/package.json ]; then
quiet bun install --frozen-lockfile --cwd ~/apps/"$app"
fi
cp -r "$DEST/apps/$app" "$APPS_DIR/"
if [ -f "$APPS_DIR/$app/package.json" ]; then
quiet bun install --frozen-lockfile --cwd "$APPS_DIR/$app" || quiet bun install --cwd "$APPS_DIR/$app"
fi
done
# -- Systemd --
# ── Systemd ──────────────────────────────────────────────
echo ">> Installing toes service"
sudo install -m 644 -o root -g root "$DEST/scripts/toes.service" /etc/systemd/system/toes.service
info "Installing toes service"
sudo install -m 644 "$DEST/scripts/toes.service" /etc/systemd/system/toes.service
sudo systemctl daemon-reload
sudo systemctl enable toes
echo ">> Starting toes"
info "Restarting toes"
sudo systemctl restart toes
# -- Done --
# ── Done ─────────────────────────────────────────────────
VERSION=$(cd "$DEST" && git describe --tags --always 2>/dev/null || echo "unknown")
echo ""
echo " toes is installed and running!"
echo " Visit: http://$(hostname).local"
echo " toes $VERSION is running!"
echo " http://$(hostname).local"
echo ""

View File

@ -1,114 +0,0 @@
#!/usr/bin/env bash
set -euo pipefail
##
# toes install / update
# Usage: curl -fsSL https://toes.dev/update | sh
#
# Installs or updates toes on a Raspberry Pi.
# Must be run as the 'toes' user with passwordless sudo.
REPO="https://git.nose.space/defunkt/toes"
DEST=~/toes
APPS_DIR=~/apps
DATA_DIR=~/data
BUNDLED_APPS="clock code cron env git metrics"
# ── Helpers ──────────────────────────────────────────────
quiet() { "$@" > /dev/null 2>&1; }
info() { echo ">> $1"; }
fail() { echo "ERROR: $1" >&2; exit 1; }
# ── Preflight ────────────────────────────────────────────
echo ""
echo " toes - personal web appliance"
echo ""
[ "$(whoami)" = "toes" ] || fail "Must be run as the 'toes' user."
sudo -n true 2>/dev/null || fail "Requires passwordless sudo."
# ── System packages ──────────────────────────────────────
info "Updating system packages"
quiet sudo apt-get update
quiet sudo apt-get install -y git libcap2-bin avahi-utils fish unzip
if [ "$(getent passwd toes | cut -d: -f7)" != "/usr/bin/fish" ]; then
info "Setting fish as default shell"
quiet sudo chsh -s /usr/bin/fish toes
fi
# ── Bun ──────────────────────────────────────────────────
BUN="$HOME/.bun/bin/bun"
if [ ! -x "$BUN" ]; then
info "Installing bun"
curl -fsSL https://bun.sh/install | bash > /dev/null 2>&1
[ -x "$BUN" ] || fail "bun installation failed."
fi
if [ ! -x /usr/local/bin/bun ]; then
sudo ln -sf "$BUN" /usr/local/bin/bun
fi
sudo setcap 'cap_net_bind_service=+ep' "$BUN"
# ── Clone or pull ────────────────────────────────────────
if [ -d "$DEST/.git" ]; then
info "Pulling latest toes"
git -C "$DEST" fetch origin main
git -C "$DEST" reset --hard origin/main
else
info "Cloning toes"
git clone "$REPO" "$DEST"
fi
# ── Directories ──────────────────────────────────────────
mkdir -p "$APPS_DIR" "$DATA_DIR"
# ── Dependencies & build ─────────────────────────────────
info "Installing dependencies"
cd "$DEST" && quiet bun install
info "Building"
cd "$DEST" && quiet bun run build
# ── Bundled apps ─────────────────────────────────────────
info "Installing bundled apps"
for app in $BUNDLED_APPS; do
[ -d "$DEST/apps/$app" ] || continue
echo " $app"
cp -r "$DEST/apps/$app" "$APPS_DIR/"
if [ -f "$APPS_DIR/$app/package.json" ]; then
quiet bun install --frozen-lockfile --cwd "$APPS_DIR/$app" || quiet bun install --cwd "$APPS_DIR/$app"
fi
done
# ── Systemd ──────────────────────────────────────────────
info "Installing toes service"
sudo install -m 644 "$DEST/scripts/toes.service" /etc/systemd/system/toes.service
sudo systemctl daemon-reload
sudo systemctl enable toes
info "Restarting toes"
sudo systemctl restart toes
# ── Done ─────────────────────────────────────────────────
VERSION=$(cd "$DEST" && git describe --tags --always 2>/dev/null || echo "unknown")
echo ""
echo " toes $VERSION is running!"
echo " http://$(hostname).local"
echo ""