Installeur streambox : one-liner sans registry (tar / ssh save-load)
This commit is contained in:
1 parent
02c60ddfb0
commit
28d0742091
3 files changed
+313
-1
No files matched your search
@@ -1,3 +1,83 @@
|
|||||||
# streambox-install
|
# streambox-install
|
||||||
|
|
||||||
One-liner d installation streambox (public, sans secret)
|
One-liner d'installation / mise à jour de **streambox AIO**. Dépôt **public** :
|
||||||
|
il ne contient que le script et le `docker-compose.yml`, aucun secret (les
|
||||||
|
configs vivent dans `config/` sur la machine cible). Le code source reste dans
|
||||||
|
`hamriou/StreamBox`, privé.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://git.les2ter.fr/gitea/hamriou/streambox-install/raw/branch/main/install.sh | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Sans registry : l'image doit déjà être présente sur la machine (`docker load`).
|
||||||
|
|
||||||
|
### Depuis une archive
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL .../install.sh | sudo bash -s -- --tar /tmp/streambox-aio-v49.tar --tag v49
|
||||||
|
```
|
||||||
|
|
||||||
|
`--tar` accepte aussi une URL.
|
||||||
|
|
||||||
|
### Depuis une autre machine du LAN
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL .../install.sh | sudo bash -s -- --from-ssh lab --tag v49
|
||||||
|
```
|
||||||
|
|
||||||
|
Équivalent à `ssh lab 'sudo docker save streambox-aio:v49' | docker load`, puis
|
||||||
|
`up -d`. Aucun port entrant à ouvrir, aucune authentification registry.
|
||||||
|
|
||||||
|
### Depuis un registry (option)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -fsSL .../install.sh | sudo bash -s -- --image git.les2ter.fr/hamriou/streambox-aio:v49
|
||||||
|
```
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Rôle |
|
||||||
|
|---|---|
|
||||||
|
| `--dir DIR` | répertoire d'installation (défaut `~/aio`) |
|
||||||
|
| `--tag TAG` | tag de l'image (défaut `latest`) |
|
||||||
|
| `--tar FICHIER\|URL` | charger l'image par `docker load` |
|
||||||
|
| `--from-ssh HOST` | `ssh HOST 'docker save …' \| docker load` |
|
||||||
|
| `--image REPO:TAG` | `docker pull` puis tag local |
|
||||||
|
| `--wait N` | attente max du health check (défaut 90 s) |
|
||||||
|
| `--dry-run` | affiche les actions sans rien modifier |
|
||||||
|
|
||||||
|
## Mise à jour
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# sur la machine source
|
||||||
|
docker save streambox-aio:v50 | ssh vps 'sudo docker load'
|
||||||
|
# sur le VPS
|
||||||
|
curl -fsSL .../install.sh | sudo bash -s -- --tag v50
|
||||||
|
```
|
||||||
|
|
||||||
|
L'installeur sauvegarde le `docker-compose.yml` précédent en `.bak.<date>` s'il
|
||||||
|
change, et ne touche jamais `config/`, `data/` ni `log/`.
|
||||||
|
|
||||||
|
## Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/aio && IMAGE_TAG=v49 docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
L'image précédente doit être encore présente (`docker image ls streambox-aio`).
|
||||||
|
|
||||||
|
## Vérification
|
||||||
|
|
||||||
|
Après démarrage : `running` + HTTP 200 sur `http://<hôte>:3005/`. En cas d'échec
|
||||||
|
l'installeur sort en erreur avec la commande de logs à lancer.
|
||||||
|
|
||||||
|
## Pourquoi pas le registry Gitea
|
||||||
|
|
||||||
|
Le registry de cette instance (`git.les2ter.fr`) refuse les jetons
|
||||||
|
authentifiés : `/v2/token` renvoie un JWT `UserID: -1` avec un `Scope` vide,
|
||||||
|
car `ENABLE_BASIC_AUTHENTICATION = false` (instance YunoHost en SSO). Docker
|
||||||
|
n'obtient un token registry que par HTTP Basic → « Login Succeeded » puis
|
||||||
|
`unauthorized`. `docker save | docker load` contourne le problème sans toucher
|
||||||
|
à `app.ini` ni affaiblir le SSO.
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
# streambox AIO — compose d'installation (dépôt public)
|
||||||
|
#
|
||||||
|
# L'image est chargée localement (docker load / docker save | docker load),
|
||||||
|
# jamais tirée d'un registry : d'où `pull_policy: never`.
|
||||||
|
#
|
||||||
|
# IMAGE_TAG=v49 docker compose up -d
|
||||||
|
# Rollback : IMAGE_TAG=v48 docker compose up -d (config/ et data/ intacts)
|
||||||
|
#
|
||||||
|
# Mêmes ports, volumes et politique de restart que la production VPS.
|
||||||
|
|
||||||
|
services:
|
||||||
|
streambox-aio:
|
||||||
|
image: streambox-aio:${IMAGE_TAG:-latest}
|
||||||
|
pull_policy: never
|
||||||
|
container_name: streambox-aio
|
||||||
|
restart: unless-stopped
|
||||||
|
network_mode: bridge
|
||||||
|
shm_size: 64m
|
||||||
|
ports:
|
||||||
|
- "13000:3000"
|
||||||
|
- "3005:3005"
|
||||||
|
- "5055:5055"
|
||||||
|
- "5690:5690"
|
||||||
|
- "6500:6500"
|
||||||
|
- "7878:7878"
|
||||||
|
- "7879:7879"
|
||||||
|
- "8096:8096"
|
||||||
|
- "8191:8191"
|
||||||
|
- "8989:8989"
|
||||||
|
- "8990:8990"
|
||||||
|
- "9696:9696"
|
||||||
|
volumes:
|
||||||
|
- ./config:/config
|
||||||
|
- ./data:/data
|
||||||
|
- ./log:/log
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Paris
|
||||||
|
AIO_LOG_DIR: /log
|
||||||
|
AIO_UI_PORT: "3005"
|
||||||
|
DEBIAN_FRONTEND: noninteractive
|
||||||
|
HOME: /config
|
||||||
|
DOTNET_RUNNING_IN_CONTAINER: "true"
|
||||||
|
DOTNET_CLI_TELEMETRY_OPTOUT: "1"
|
||||||
|
LANG: fr_FR.UTF-8
|
||||||
|
LC_ALL: fr_FR.UTF-8
|
||||||
|
CHROME_BIN: /usr/bin/chromium
|
||||||
|
CHROMEDRIVER_PATH: /usr/bin/chromedriver
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: "20m"
|
||||||
|
max-file: "3"
|
||||||
Executable
+180
@@ -0,0 +1,180 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# =============================================================================
|
||||||
|
# streambox — installation / mise à jour en une ligne
|
||||||
|
#
|
||||||
|
# Rapide (image déjà présente sur la machine, ex. après un `docker load`) :
|
||||||
|
# curl -fsSL https://git.les2ter.fr/gitea/hamriou/streambox-install/raw/branch/main/install.sh | sudo bash
|
||||||
|
#
|
||||||
|
# Depuis une archive :
|
||||||
|
# curl -fsSL .../install.sh | sudo bash -s -- --tar /tmp/streambox-aio-v49.tar --tag v49
|
||||||
|
#
|
||||||
|
# Depuis une autre machine du LAN (docker save | docker load, sans registry) :
|
||||||
|
# curl -fsSL .../install.sh | sudo bash -s -- --from-ssh lab --tag v49
|
||||||
|
#
|
||||||
|
# Aucun registry, aucun token, aucun secret. Le compose vient de ce dépôt public.
|
||||||
|
# =============================================================================
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
BASE_URL="${BASE_URL:-https://git.les2ter.fr/gitea/hamriou/streambox-install/raw/branch/main}"
|
||||||
|
INSTALL_DIR="${INSTALL_DIR:-$HOME/aio}"
|
||||||
|
IMAGE_TAG="${IMAGE_TAG:-latest}"
|
||||||
|
IMAGE_REPO="${IMAGE_REPO:-streambox-aio}"
|
||||||
|
UI_PORT="${UI_PORT:-3005}"
|
||||||
|
|
||||||
|
SRC_TAR=""
|
||||||
|
SRC_REF=""
|
||||||
|
SRC_SSH=""
|
||||||
|
DRY=0
|
||||||
|
WAIT="${WAIT:-90}"
|
||||||
|
|
||||||
|
log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
|
||||||
|
ok() { printf '\033[1;32m ok\033[0m %s\n' "$*"; }
|
||||||
|
warn() { printf '\033[1;33m !!\033[0m %s\n' "$*" >&2; }
|
||||||
|
die() { printf '\033[1;31mERREUR:\033[0m %s\n' "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<'EOF'
|
||||||
|
streambox — installeur
|
||||||
|
|
||||||
|
--dir DIR répertoire d'installation (défaut: ~/aio)
|
||||||
|
--tag TAG tag de l'image (défaut: latest)
|
||||||
|
--image REPO:TAG tirer l'image depuis un registry
|
||||||
|
--tar FICHIER charger l'image depuis une archive (docker load), chemin ou URL
|
||||||
|
--from-ssh HOST charger l'image depuis HOST (ssh HOST 'docker save ...' | docker load)
|
||||||
|
--wait SECONDES attente max du health check (défaut: 90)
|
||||||
|
--dry-run afficher les actions sans rien modifier
|
||||||
|
-h, --help cette aide
|
||||||
|
|
||||||
|
Sans --image / --tar / --from-ssh, l'installeur utilise l'image locale
|
||||||
|
streambox-aio:<tag> si elle existe déjà (cas d'une mise à jour).
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
while [ $# -gt 0 ]; do
|
||||||
|
case "$1" in
|
||||||
|
--dir) INSTALL_DIR="${2:?}"; shift 2 ;;
|
||||||
|
--tag) IMAGE_TAG="${2:?}"; shift 2 ;;
|
||||||
|
--image) SRC_REF="${2:?}"; shift 2 ;;
|
||||||
|
--tar) SRC_TAR="${2:?}"; shift 2 ;;
|
||||||
|
--from-ssh) SRC_SSH="${2:?}"; shift 2 ;;
|
||||||
|
--wait) WAIT="${2:?}"; shift 2 ;;
|
||||||
|
--dry-run) DRY=1; shift ;;
|
||||||
|
-h|--help) usage; exit 0 ;;
|
||||||
|
*) die "argument inconnu: $1 (voir --help)" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
FULL_IMAGE="$IMAGE_REPO:$IMAGE_TAG"
|
||||||
|
COMPOSE="$INSTALL_DIR/docker-compose.yml"
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------- 1. prérequis
|
||||||
|
log "Prérequis"
|
||||||
|
command -v docker >/dev/null || die "docker absent"
|
||||||
|
command -v curl >/dev/null || die "curl absent"
|
||||||
|
if [ "$DRY" = 0 ]; then
|
||||||
|
docker info >/dev/null 2>&1 || die "docker injoignable (droits ? lance avec sudo)"
|
||||||
|
docker compose version >/dev/null 2>&1 || die "docker compose v2 absent"
|
||||||
|
fi
|
||||||
|
ok "docker + compose v2"
|
||||||
|
|
||||||
|
# --------------------------------------------------------- 2. répertoire + compose
|
||||||
|
log "Répertoire $INSTALL_DIR"
|
||||||
|
if [ "$DRY" = 0 ]; then
|
||||||
|
mkdir -p "$INSTALL_DIR"/{config,data,log}
|
||||||
|
tmp="$(mktemp)"
|
||||||
|
curl -fsSL "$BASE_URL/docker-compose.yml" -o "$tmp" || die "compose introuvable sur $BASE_URL"
|
||||||
|
grep -q 'streambox-aio' "$tmp" || die "compose téléchargé invalide"
|
||||||
|
if [ -f "$COMPOSE" ] && ! cmp -s "$tmp" "$COMPOSE"; then
|
||||||
|
cp "$COMPOSE" "$COMPOSE.bak.$(date +%Y%m%d%H%M%S)"
|
||||||
|
warn "compose précédent sauvegardé (.bak)"
|
||||||
|
fi
|
||||||
|
mv "$tmp" "$COMPOSE"
|
||||||
|
ok "compose à jour"
|
||||||
|
else
|
||||||
|
printf ' [dry-run] mkdir -p %s/{config,data,log}\n' "$INSTALL_DIR"
|
||||||
|
printf ' [dry-run] curl %s/docker-compose.yml -> %s\n' "$BASE_URL" "$COMPOSE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------- 3. l'image
|
||||||
|
log "Image $FULL_IMAGE"
|
||||||
|
|
||||||
|
have_local() {
|
||||||
|
[ "$DRY" = 1 ] && return 1
|
||||||
|
docker image inspect "$FULL_IMAGE" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -n "$SRC_TAR" ]; then
|
||||||
|
tar_path="$SRC_TAR"
|
||||||
|
if printf '%s' "$SRC_TAR" | grep -qE '^https?://'; then
|
||||||
|
tar_path="/tmp/$(basename "${SRC_TAR%%\?*}")"
|
||||||
|
log "Téléchargement de l'archive"
|
||||||
|
[ "$DRY" = 1 ] && printf ' [dry-run] curl -fL %s -o %s\n' "$SRC_TAR" "$tar_path" \
|
||||||
|
|| curl -fL --retry 2 "$SRC_TAR" -o "$tar_path"
|
||||||
|
fi
|
||||||
|
[ "$DRY" = 1 ] && printf ' [dry-run] docker load -i %s\n' "$tar_path" \
|
||||||
|
|| { docker load -i "$tar_path" || die "docker load a échoué"; }
|
||||||
|
ok "image chargée depuis $tar_path"
|
||||||
|
|
||||||
|
elif [ -n "$SRC_SSH" ]; then
|
||||||
|
log "Transfert depuis $SRC_SSH (docker save | docker load)"
|
||||||
|
if [ "$DRY" = 1 ]; then
|
||||||
|
printf ' [dry-run] ssh %s "sudo docker save %s" | docker load\n' "$SRC_SSH" "$FULL_IMAGE"
|
||||||
|
else
|
||||||
|
ssh "$SRC_SSH" "sudo docker save $FULL_IMAGE" | docker load \
|
||||||
|
|| die "transfert depuis $SRC_SSH échoué (image absente là-bas, ou clé SSH ?)"
|
||||||
|
ok "image transférée"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elif [ -n "$SRC_REF" ]; then
|
||||||
|
[ "$DRY" = 1 ] && printf ' [dry-run] docker pull %s\n' "$SRC_REF" \
|
||||||
|
|| { docker pull "$SRC_REF" || die "pull de $SRC_REF échoué"; }
|
||||||
|
SRC_REF_ID="$(docker image inspect -f '{{.Id}}' "$SRC_REF" 2>/dev/null || true)"
|
||||||
|
if [ "$DRY" = 0 ] && [ -n "$SRC_REF_ID" ]; then
|
||||||
|
docker tag "$SRC_REF" "$FULL_IMAGE"
|
||||||
|
fi
|
||||||
|
ok "image tirée"
|
||||||
|
|
||||||
|
elif have_local; then
|
||||||
|
ok "image locale déjà présente"
|
||||||
|
elif [ "$DRY" = 1 ]; then
|
||||||
|
printf ' [dry-run] (image locale %s supposée présente)\n' "$FULL_IMAGE"
|
||||||
|
else
|
||||||
|
die "aucune image $FULL_IMAGE en local. Utilise --tar, --from-ssh, ou --image REPO:TAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------- 4. démarrage
|
||||||
|
log "Démarrage"
|
||||||
|
if [ "$DRY" = 1 ]; then
|
||||||
|
printf ' [dry-run] cd %s && IMAGE_TAG=%s docker compose up -d\n' "$INSTALL_DIR" "$IMAGE_TAG"
|
||||||
|
else
|
||||||
|
( cd "$INSTALL_DIR" && IMAGE_TAG="$IMAGE_TAG" docker compose up -d ) || die "docker compose up a échoué"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# --------------------------------------------------------------- 5. health check
|
||||||
|
log "Health check (max ${WAIT}s)"
|
||||||
|
if [ "$DRY" = 1 ]; then
|
||||||
|
printf ' [dry-run] curl http://127.0.0.1:%s/ jusqu à 200\n' "$UI_PORT"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
state=""
|
||||||
|
for _ in $(seq 1 "$WAIT"); do
|
||||||
|
state="$(docker inspect -f '{{.State.Status}}' streambox-aio 2>/dev/null || echo absente)"
|
||||||
|
if [ "$state" = "running" ] && curl -fsS -o /dev/null -m 2 "http://127.0.0.1:$UI_PORT/" 2>/dev/null; then
|
||||||
|
echo
|
||||||
|
ok "conteneur running, HTTP 200 sur le port $UI_PORT"
|
||||||
|
printf '\n État : %s\n' "$state"
|
||||||
|
printf ' Image : %s\n' "$FULL_IMAGE"
|
||||||
|
printf ' Dossier: %s\n' "$INSTALL_DIR"
|
||||||
|
printf ' UI : http://%s:%s\n' "$(hostname -I 2>/dev/null | awk '{print $1}')" "$UI_PORT"
|
||||||
|
printf ' Logs : cd %s && docker compose logs -f\n' "$INSTALL_DIR"
|
||||||
|
printf ' Rollback: IMAGE_TAG=<tag précédent> docker compose up -d\n'
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
|
||||||
|
echo
|
||||||
|
warn "conteneur '$state' mais pas de 200 sur :$UI_PORT après ${WAIT}s"
|
||||||
|
docker inspect -f '{{.State.Status}} {{if .State.Health}}{{.State.Health.Status}}{{end}}' streambox-aio 2>/dev/null || true
|
||||||
|
die "démarrage incomplet — voir: cd $INSTALL_DIR && docker compose logs --tail 50"
|
||||||
Reference in new issue
Block a user