diff --git a/README.md b/README.md index c96a1c6..e9afc01 100644 --- a/README.md +++ b/README.md @@ -124,34 +124,52 @@ a ani jedno nasazení ji nijak nezabezpečuje. Do internetu to nepatří. ### Proxmox (LXC) -Skript se pouští v terminálu uzlu Proxmoxu jako root. Založí kontejner, +Jeden příkaz v terminálu uzlu Proxmoxu, jako root. Založí kontejner, nastaví ho, stáhne poslední vydanou binárku, ověří kontrolní součet a zapne službu: ```bash -bash deploy/pve-kostky.sh +bash -c "$(curl -fsSL https://gitea.spacilovi.eu/david-spacil/dice-counter/raw/branch/main/deploy/pve-kostky.sh)" ``` Na konci vypíše adresu, na které počitadlo poslouchá. Výchozí nastavení je -1 jádro, 512 MB, 4 GB disku a Debian 13; přebíjí se proměnnými: +1 jádro, 512 MB, 4 GB disku a Debian 13; úložiště si najde samo. Přebíjí se +proměnnými před příkazem: ```bash -MEMORY=1024 STORAGE=local-zfs PORT=8080 bash deploy/pve-kostky.sh +MEMORY=1024 STORAGE=local-zfs PORT=8080 bash -c "$(curl -fsSL ...)" ``` -Aktualizace na novější vydání je totéž s číslem kontejneru: +| Proměnná | Výchozí | +|---|---| +| `CTID` | první volné číslo | +| `CT_HOSTNAME` | `kostky` | +| `CORES`, `MEMORY`, `DISK` | `1`, `512`, `4` | +| `STORAGE` | první aktivní úložiště pro kontejnery | +| `TEMPLATE_STORAGE`, `BRIDGE` | `local`, `vmbr0` | +| `PORT` | `8000` | +| `UNPRIVILEGED`, `OSVERSION` | `1`, `13` | +| `VERSION` | poslední vydání | + +Aktualizace na novější vydání je ten samý příkaz s číslem kontejneru: ```bash -bash deploy/pve-kostky.sh update 123 +CTID=123 MODE=update bash -c "$(curl -fsSL ...)" ``` Podoba je odkoukaná od [community-scripts.org](https://community-scripts.org), ale nic z jejich frameworku se nestahuje — jejich `build.func` si instalační skript hledá natvrdo ve vlastním repozitáři, takže mimo něj nefunguje. -`deploy/lxc-install.sh` o Proxmoxu nic neví, takže se dá pustit i v LXC nebo -virtuálu, který sis založil sám. Je idempotentní; druhé spuštění jen vymění -binárku za nejnovější. +Instalátor, který běží uvnitř kontejneru, je ve skriptu vložený jako text — +přes rouru z curlu na disku hostitele žádný druhý soubor není. O Proxmoxu nic +neví, takže se dá použít i v kontejneru, který sis založil sám: + +```bash +bash pve-kostky.sh instalator > install.sh +``` + +Je idempotentní; druhé spuštění jen vymění binárku za nejnovější. ### Docker diff --git a/deploy/lxc-install.sh b/deploy/lxc-install.sh deleted file mode 100755 index fbdc1c5..0000000 --- a/deploy/lxc-install.sh +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env bash -# Instalace počitadla uvnitř kontejneru. Pouští se přes pve-kostky.sh, ne ručně. -# -# Oddělené od skriptu pro Proxmox schválně: tenhle běží uvnitř Debianu a nic -# o Proxmoxu neví, takže se dá pustit i v LXC, který sis založil sám, nebo ve -# virtuálu. Je idempotentní — po druhém spuštění máš nejnovější binárku. -set -euo pipefail - -GITEA="${GITEA:-https://gitea.spacilovi.eu}" -REPO="${REPO:-david-spacil/dice-counter}" -PORT="${PORT:-8000}" -VERSION="${VERSION:-}" # prázdné = poslední release - -USER_NAME=kostky -HOME_DIR=/opt/kostky -DATA_DIR=/var/lib/kostky - -msg() { echo -e "\e[1;34m →\e[0m $*"; } -ok() { echo -e "\e[1;32m ✓\e[0m $*"; } -die() { echo -e "\e[1;31m ✗\e[0m $*" >&2; exit 1; } - -# --- co vlastně stahovat ----------------------------------------------------- - -case "$(dpkg --print-architecture)" in - amd64) ASSET=kostky-linux-x86_64 ;; - arm64) ASSET=kostky-linux-arm64 ;; - *) die "Pro architekturu $(dpkg --print-architecture) binárka není." ;; -esac - -msg "Doinstalovávám, co je potřeba ke stažení" -export DEBIAN_FRONTEND=noninteractive -apt-get update -qq -apt-get install -y -qq curl ca-certificates >/dev/null -ok "Základ je hotový" - -if [ -z "$VERSION" ]; then - msg "Zjišťuji poslední vydanou verzi" - # Jen tag; adresa přílohy se z něj složí, takže tu nepotřebujeme jq. - VERSION=$(curl -fsSL "$GITEA/api/v1/repos/$REPO/releases/latest" \ - | grep -o '"tag_name":[[:space:]]*"[^"]*"' | head -1 | cut -d'"' -f4) - [ -n "$VERSION" ] || die "Nepodařilo se zjistit poslední verzi z $GITEA." -fi -ok "Instaluje se $VERSION ($ASSET)" - -# --- stažení a ověření ------------------------------------------------------- - -BASE="$GITEA/$REPO/releases/download/$VERSION" -TMP=$(mktemp -d) -trap 'rm -rf "$TMP"' EXIT - -msg "Stahuji binárku" -curl -fsSL -o "$TMP/$ASSET" "$BASE/$ASSET" \ - || die "$ASSET pro $VERSION na releasu není. Vydání pro tuhle architekturu možná ještě neproběhlo." -curl -fsSL -o "$TMP/$ASSET.sha256" "$BASE/$ASSET.sha256" \ - || die "Chybí kontrolní součet — radši nic neinstaluju." - -msg "Ověřuji kontrolní součet" -( cd "$TMP" && sha256sum -c "$ASSET.sha256" >/dev/null ) \ - || die "Kontrolní součet nesedí. Stažený soubor zahazuju." -ok "Součet sedí" - -# --- uživatel, soubory, služba ---------------------------------------------- - -id -u "$USER_NAME" >/dev/null 2>&1 \ - || useradd --system --home-dir "$HOME_DIR" --shell /usr/sbin/nologin "$USER_NAME" - -install -d -o root -g root -m 755 "$HOME_DIR" - -# Služba se zastaví, jen když už běží — při první instalaci ještě neexistuje. -systemctl is-active --quiet kostky && systemctl stop kostky -install -o root -g root -m 755 "$TMP/$ASSET" "$HOME_DIR/kostky" -echo "$VERSION" > "$HOME_DIR/verze" -ok "Binárka je na místě" - -msg "Zapisuji službu" -cat > /etc/systemd/system/kostky.service <&2; exit 1; } header() { echo echo -e "\e[1;36m $APP\e[0m — počitadlo kostek do LXC" - echo -e " \e[2m$REPO_URL\e[0m" + echo -e " \e[2m$GITEA/$REPO\e[0m" echo } -# --- kontroly, než se něco založí ------------------------------------------- +# --- instalátor, který poběží uvnitř kontejneru ------------------------------ +# +# Je tu jako text schválně. Skript se pouští i rourou z curlu, kdy na disku +# hostitele žádný soubor není a nebylo by co poslat dovnitř. Uvozovky kolem +# 'INSTALL' jsou podstatné: nic z toho se tady nesmí rozvinout, všechny +# proměnné patří až tomu, co poběží v kontejneru. +# +# Vypsat se dá i samostatně: `bash pve-kostky.sh instalator > install.sh`, +# což se hodí, když chceš appku dostat do kontejneru, který sis založil sám. +installer() { +cat <<'INSTALL' +#!/usr/bin/env bash +# Instalace počitadla uvnitř kontejneru. O Proxmoxu nic neví, takže se dá +# pustit v jakémkoli Debianu. Je idempotentní — druhé spuštění jen vymění +# binárku za nejnovější. +set -euo pipefail -command -v pct >/dev/null || die "Tohle patří na uzel Proxmoxu — pct tu není." -[ "$(id -u)" -eq 0 ] || die "Spusť to jako root." -[ -f "$INSTALLER" ] || die "Vedle skriptu chybí lxc-install.sh." +GITEA="${GITEA:-https://gitea.spacilovi.eu}" +REPO="${REPO:-david-spacil/dice-counter}" +PORT="${PORT:-8000}" +VERSION="${VERSION:-}" -# --- instalace do kontejneru ------------------------------------------------- +USER_NAME=kostky +HOME_DIR=/opt/kostky +DATA_DIR=/var/lib/kostky + +msg() { echo -e "\e[1;34m →\e[0m $*"; } +ok() { echo -e "\e[1;32m ✓\e[0m $*"; } +die() { echo -e "\e[1;31m ✗\e[0m $*" >&2; exit 1; } + +case "$(dpkg --print-architecture)" in + amd64) ASSET=kostky-linux-x86_64 ;; + arm64) ASSET=kostky-linux-arm64 ;; + *) die "Pro architekturu $(dpkg --print-architecture) binárka není." ;; +esac + +msg "Doinstalovávám, co je potřeba ke stažení" +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq +apt-get install -y -qq curl ca-certificates >/dev/null +ok "Základ je hotový" + +if [ -z "$VERSION" ]; then + msg "Zjišťuji poslední vydanou verzi" + # Jen tag; adresa přílohy se z něj složí, takže tu nepotřebujeme jq. + VERSION=$(curl -fsSL "$GITEA/api/v1/repos/$REPO/releases/latest" \ + | grep -o '"tag_name":[[:space:]]*"[^"]*"' | head -1 | cut -d'"' -f4) + [ -n "$VERSION" ] || die "Nepodařilo se zjistit poslední verzi z $GITEA." +fi +ok "Instaluje se $VERSION ($ASSET)" + +BASE="$GITEA/$REPO/releases/download/$VERSION" +TMP=$(mktemp -d) +trap 'rm -rf "$TMP"' EXIT + +msg "Stahuji binárku" +curl -fsSL -o "$TMP/$ASSET" "$BASE/$ASSET" \ + || die "$ASSET pro $VERSION na releasu není. Vydání pro tuhle architekturu možná ještě neproběhlo." +curl -fsSL -o "$TMP/$ASSET.sha256" "$BASE/$ASSET.sha256" \ + || die "Chybí kontrolní součet — radši nic neinstaluju." + +msg "Ověřuji kontrolní součet" +( cd "$TMP" && sha256sum -c "$ASSET.sha256" >/dev/null ) \ + || die "Kontrolní součet nesedí. Stažený soubor zahazuju." +ok "Součet sedí" + +id -u "$USER_NAME" >/dev/null 2>&1 \ + || useradd --system --home-dir "$HOME_DIR" --shell /usr/sbin/nologin "$USER_NAME" + +install -d -o root -g root -m 755 "$HOME_DIR" + +# Zastavit se dá jen to, co běží — při první instalaci služba ještě není. +if systemctl is-active --quiet kostky; then + systemctl stop kostky +fi + +install -o root -g root -m 755 "$TMP/$ASSET" "$HOME_DIR/kostky" +echo "$VERSION" > "$HOME_DIR/verze" +ok "Binárka je na místě" + +msg "Zapisuji službu" +cat > /etc/systemd/system/kostky.service </dev/null && break + sleep 1 +done +curl -fsS -o /dev/null "http://127.0.0.1:$PORT/" \ + || die "Služba nastartovala, ale neodpovídá. Mrkni na journalctl -u kostky." + +# Verzi bereme ze souboru, ne z binárky. Starší vydání --version neumí +# a místo výpisu by nastartovala server, který by tenhle skript zavěsil. +ok "Počitadlo $(cat "$HOME_DIR/verze") odpovídá na portu $PORT" +INSTALL +} + +# --- společné části ---------------------------------------------------------- install_into() { - local ctid="$1" + local ctid="$1" tmp + tmp=$(mktemp) + installer > "$tmp" msg "Posílám instalátor do kontejneru $ctid" - pct push "$ctid" "$INSTALLER" /root/lxc-install.sh --perms 0755 + pct push "$ctid" "$tmp" /root/kostky-install.sh --perms 0755 + rm -f "$tmp" - pct exec "$ctid" -- env PORT="$PORT" bash /root/lxc-install.sh + pct exec "$ctid" -- env PORT="$PORT" GITEA="$GITEA" REPO="$REPO" \ + VERSION="$VERSION" bash /root/kostky-install.sh } address_of() { - local ctid="$1" - pct exec "$ctid" -- hostname -I 2>/dev/null | awk '{print $1}' + pct exec "$1" -- hostname -I 2>/dev/null | awk '{print $1}' } hotovo() { @@ -80,26 +214,41 @@ hotovo() { echo echo -e " \e[2mDatabáze: /var/lib/kostky/dice.db (uvnitř kontejneru)" echo -e " Log: pct exec $ctid -- journalctl -u kostky -f" - echo -e " Konzole: pct enter $ctid\e[0m" + echo -e " Konzole: pct enter $ctid" + echo -e " Zrušit: pct stop $ctid \&\& pct destroy $ctid\e[0m" echo } +# --- co se má vlastně dělat -------------------------------------------------- +# +# Rourou z curlu se argumenty předávají mizerně, tak jde všechno i proměnnou: +# MODE=update CTID=123. Ze souboru funguje i `bash pve-kostky.sh update 123`. +MODE="${MODE:-${1:-create}}" +[ "$MODE" = "update" ] && CTID="${CTID:-${2:-}}" + +if [ "$MODE" = "instalator" ]; then + installer + exit 0 +fi + +command -v pct >/dev/null || die "Tohle patří na uzel Proxmoxu — pct tu není." +[ "$(id -u)" -eq 0 ] || die "Spusť to jako root." + # --- aktualizace ------------------------------------------------------------- -if [ "${1:-}" = "update" ]; then - ctid="${2:-}" - [ -n "$ctid" ] || die "Řekni který: bash pve-kostky.sh update " - pct status "$ctid" >/dev/null 2>&1 || die "Kontejner $ctid neexistuje." +if [ "$MODE" = "update" ]; then + [ -n "${CTID:-}" ] || die "Řekni který: CTID=123 MODE=update ..." + pct status "$CTID" >/dev/null 2>&1 || die "Kontejner $CTID neexistuje." header - [ "$(pct status "$ctid")" = "status: running" ] || { + if [ "$(pct status "$CTID")" != "status: running" ]; then msg "Startuji kontejner" - pct start "$ctid" + pct start "$CTID" sleep 5 - } + fi - install_into "$ctid" - hotovo "$ctid" + install_into "$CTID" + hotovo "$CTID" exit 0 fi @@ -107,6 +256,19 @@ fi header +# Úložiště se nehádá. local-lvm na ZFS instalacích neexistuje a pct create by +# spadlo až po půlce práce, tak se radši zeptáme systému, co tu opravdu je. +if [ -z "$STORAGE" ]; then + STORAGE=$(pvesm status -content rootdir 2>/dev/null \ + | awk 'NR>1 && $3=="active" {print $1; exit}') + [ -n "$STORAGE" ] || die "Nenašel jsem úložiště pro kontejnery. Zadej STORAGE=; co máš, ukáže pvesm status." + msg "Úložiště: $STORAGE (nalezeno automaticky)" +else + pvesm status -content rootdir 2>/dev/null | awk 'NR>1 {print $1}' | grep -qx "$STORAGE" \ + || die "Úložiště $STORAGE pro kontejnery nesedí. Co máš, ukáže: pvesm status -content rootdir" + msg "Úložiště: $STORAGE" +fi + CTID="${CTID:-$(pvesh get /cluster/nextid)}" msg "Kontejner dostane číslo $CTID" @@ -117,7 +279,7 @@ TEMPLATE=$(pveam available --section system \ [ -n "$TEMPLATE" ] || die "Šablona pro Debian $OSVERSION není k dispozici." if ! pveam list "$TEMPLATE_STORAGE" 2>/dev/null | grep -q "$TEMPLATE"; then - msg "Stahuji $TEMPLATE" + msg "Stahuji $TEMPLATE (asi 120 MB, chvíli to trvá)" pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" >/dev/null fi ok "Šablona $TEMPLATE" @@ -133,7 +295,7 @@ pct create "$CTID" "$TEMPLATE_STORAGE:vztmpl/$TEMPLATE" \ --unprivileged "$UNPRIVILEGED" \ --ostype debian \ --onboot 1 \ - --description "$APP — $REPO_URL" >/dev/null + --description "$APP — $GITEA/$REPO" >/dev/null ok "Kontejner $CTID založen" msg "Startuji" @@ -141,9 +303,10 @@ pct start "$CTID" msg "Čekám na síť" for _ in $(seq 60); do - [ -n "$(address_of "$CTID")" ] \ - && pct exec "$CTID" -- getent hosts deb.debian.org >/dev/null 2>&1 \ - && break + if [ -n "$(address_of "$CTID")" ] \ + && pct exec "$CTID" -- getent hosts deb.debian.org >/dev/null 2>&1; then + break + fi sleep 2 done [ -n "$(address_of "$CTID")" ] || die "Kontejner nedostal adresu. Sedí bridge $BRIDGE?"