#!/usr/bin/env bash # Install (or update) the lchat server on this box. # # curl -fsSL https://github.com/elevenmessenger/releases/releases/download/server/install.sh | sudo bash # # Downloads the latest STABLE release for this machine's architecture from the # public releases repo, verifies its sha256 against the published checksum, # installs it at /opt/lchat/lchat, and runs `lchat bootstrap` (idempotent: it # installs/refreshes the systemd units, creates /data, enables the router and # the hourly auto-update timer, and installs the public status collectors + # their viewer pages + 5-minute timers). Re-running this script updates the # binary and refreshes the units; it never touches /data, so it's safe on a # live box. # # After install, the box keeps itself current from the stable channel — see # docs/self-hosting.md in the elevenmessenger/messenger repo. set -euo pipefail REPO="${LCHAT_RELEASES_REPO:-elevenmessenger/releases}" BASE="https://github.com/$REPO/releases/download/server" say() { printf '%s\n' "$*"; } fail() { printf 'install: %s\n' "$*" >&2; exit 1; } # Everything runs from main(), invoked on the last line — so a truncated # `curl | bash` transfer fails to parse and executes NOTHING, instead of # running whatever prefix happened to arrive. main() { [ "$(id -u)" = 0 ] || fail "must run as root (it installs systemd units and creates the service user) — re-run with sudo" [ -d /run/systemd/system ] || fail "this box isn't running systemd — lchat's supervision, zero-downtime deploys, and auto-updates are all systemd units (Ubuntu and Debian are the tested platforms)" [ -f /etc/debian_version ] || say "note: not a Debian-family system — Ubuntu/Debian are what we test on; continuing anyway" case "$(uname -m)" in x86_64) ARCH=amd64 ;; aarch64) ARCH=arm64 ;; *) fail "unsupported architecture $(uname -m) — builds are published for x86_64 (amd64) and aarch64 (arm64)" ;; esac BIN="lchat-linux-$ARCH" TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT say "Downloading the latest stable lchat ($ARCH)..." curl -fsSL "$BASE/$BIN" -o "$TMP/$BIN" || fail "download failed — is $BASE/$BIN reachable?" curl -fsSL "$BASE/$BIN.sha256" -o "$TMP/$BIN.sha256" || fail "checksum download failed" (cd "$TMP" && sha256sum -c "$BIN.sha256" >/dev/null) || fail "sha256 verification FAILED — refusing to install (a truncated download, or something is tampering with the download path)" # Temp + rename on the same filesystem, so a crash mid-install never leaves a # half-written binary and a re-run always lands atomically over the old one. mkdir -p /opt/lchat install -m 0755 "$TMP/$BIN" /opt/lchat/lchat.new mv /opt/lchat/lchat.new /opt/lchat/lchat say "Installed $(/opt/lchat/lchat version) at /opt/lchat/lchat" say "Running bootstrap (systemd units, /data, router, auto-update timer)..." /opt/lchat/lchat bootstrap cat <<'EOF' Done. Next: 1. Point a DNS A record at this box, e.g. chat.example.com -> this IP (ports 80 and 443 must be open — TLS certs issue automatically). 2. Create your chat: lchat add-instance chat.example.com It prints a one-click setup link — open it, and you're the admin. Add as many chats as you like (each is fully isolated). This box keeps itself up to date from the stable channel automatically; see `lchat update status`. Everything that matters lives in /data — back that up. Guide: https://github.com/elevenmessenger/releases#readme EOF } main "$@"