Aligne le deploiement Proxmox sur la stack Docker complete
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
WEB_PORT=8080
|
||||||
|
PUBLIC_BASE_URL=http://localhost:8080
|
||||||
KEYCLOAK_DB_NAME=keycloak
|
KEYCLOAK_DB_NAME=keycloak
|
||||||
KEYCLOAK_DB_USER=keycloak
|
KEYCLOAK_DB_USER=keycloak
|
||||||
KEYCLOAK_DB_PASSWORD=change-me
|
KEYCLOAK_DB_PASSWORD=change-me
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ Identifiants d'administration par defaut pour le premier demarrage local :
|
|||||||
|
|
||||||
Ces valeurs peuvent etre surchargees via les variables d'environnement de `.env.example`.
|
Ces valeurs peuvent etre surchargees via les variables d'environnement de `.env.example`.
|
||||||
La base MySQL du site utilise les variables `SITE_DB_*` du meme fichier.
|
La base MySQL du site utilise les variables `SITE_DB_*` du meme fichier.
|
||||||
|
Pour un deploiement hors localhost, `PUBLIC_BASE_URL` doit pointer vers l'URL publique du site et `WEB_PORT` vers le port HTTP expose.
|
||||||
|
|
||||||
Au demarrage, le service `keycloak-init` resynchronise automatiquement le realm courant pour garder l'inscription active et autoriser le flux de connexion integre, meme si la base Keycloak existe deja.
|
Au demarrage, le service `keycloak-init` resynchronise automatiquement le realm courant pour garder l'inscription active et autoriser le flux de connexion integre, meme si la base Keycloak existe deja.
|
||||||
|
|
||||||
@@ -99,9 +100,11 @@ Prerrequis sur la machine qui lance les scripts :
|
|||||||
- en mode distant : `ssh` et `sshpass`
|
- en mode distant : `ssh` et `sshpass`
|
||||||
- en mode local sur l'hote Proxmox : aucun paquet supplementaire n'est installe sur Proxmox
|
- en mode local sur l'hote Proxmox : aucun paquet supplementaire n'est installe sur Proxmox
|
||||||
|
|
||||||
Le deploiement dans le LXC n'utilise pas Docker. Le script clone le depot, publie l'application Blazor dans le conteneur, puis sert le resultat via `nginx`.
|
Le deploiement dans le LXC Proxmox utilise maintenant Docker dans le conteneur pour lancer la meme stack qu'en local : `web`, `auth`, `keycloak`, `postgres` et `mysql`.
|
||||||
|
|
||||||
Attention : la pile Keycloak fournie ici est actuellement prete a l'emploi dans la stack Docker du projet. Les scripts LXC existants ne provisionnent pas encore automatiquement Keycloak ni sa base Postgres.
|
Le script prepare une URL publique pour Keycloak via `PUBLIC_BASE_URL`, installe Docker dans le LXC, puis lance `docker compose up -d --build`.
|
||||||
|
|
||||||
|
Pour un usage confortable, il est recommande de prevoir un LXC avec au moins 2 vCPU, 4 Go de RAM et 10 Go de disque.
|
||||||
|
|
||||||
### Installer un nouveau LXC
|
### Installer un nouveau LXC
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ services:
|
|||||||
keycloak:
|
keycloak:
|
||||||
condition: service_started
|
condition: service_started
|
||||||
ports:
|
ports:
|
||||||
- "8080:80"
|
- "${WEB_PORT:-8080}:80"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
auth:
|
auth:
|
||||||
@@ -53,7 +53,7 @@ services:
|
|||||||
KC_BOOTSTRAP_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USER:-admin}
|
KC_BOOTSTRAP_ADMIN_USERNAME: ${KEYCLOAK_ADMIN_USER:-admin}
|
||||||
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-admin}
|
KC_BOOTSTRAP_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD:-admin}
|
||||||
KC_PROXY_HEADERS: xforwarded
|
KC_PROXY_HEADERS: xforwarded
|
||||||
KC_HOSTNAME: http://localhost:8080/auth
|
KC_HOSTNAME: "${PUBLIC_BASE_URL:-http://localhost:8080}/auth"
|
||||||
KC_HTTP_RELATIVE_PATH: /auth
|
KC_HTTP_RELATIVE_PATH: /auth
|
||||||
KC_HOSTNAME_STRICT: "false"
|
KC_HOSTNAME_STRICT: "false"
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ Options principales:
|
|||||||
--gateway Passerelle si IP statique
|
--gateway Passerelle si IP statique
|
||||||
--bridge Bridge reseau Proxmox (defaut: vmbr0)
|
--bridge Bridge reseau Proxmox (defaut: vmbr0)
|
||||||
--cores Nombre de vCPU du LXC (defaut: 2)
|
--cores Nombre de vCPU du LXC (defaut: 2)
|
||||||
--memory Memoire RAM en Mo (defaut: 1024)
|
--memory Memoire RAM en Mo (defaut: 4096)
|
||||||
--swap Swap en Mo (defaut: 512)
|
--swap Swap en Mo (defaut: 1024)
|
||||||
--disk-gb Taille disque du LXC en Go (defaut: 6)
|
--disk-gb Taille disque du LXC en Go (defaut: 12)
|
||||||
--template-storage Stockage Proxmox pour les templates
|
--template-storage Stockage Proxmox pour les templates
|
||||||
--rootfs-storage Stockage Proxmox pour le disque LXC
|
--rootfs-storage Stockage Proxmox pour le disque LXC
|
||||||
--repo-url Depot Git a deployer
|
--repo-url Depot Git a deployer
|
||||||
@@ -36,6 +36,11 @@ Options principales:
|
|||||||
--ethan-branch Branche Git de l'application Ethan (defaut: main)
|
--ethan-branch Branche Git de l'application Ethan (defaut: main)
|
||||||
--brice-repo-url Depot Git de l'application Brice
|
--brice-repo-url Depot Git de l'application Brice
|
||||||
--brice-branch Branche Git de l'application Brice (defaut: main)
|
--brice-branch Branche Git de l'application Brice (defaut: main)
|
||||||
|
--public-base-url URL publique du site (ex: http://jeu.example.com)
|
||||||
|
--web-port Port HTTP expose dans le LXC (defaut: 80)
|
||||||
|
--keycloak-admin-user Utilisateur admin Keycloak (defaut: admin)
|
||||||
|
--keycloak-admin-password
|
||||||
|
Mot de passe admin Keycloak. Genere si absent
|
||||||
--lxc-password Mot de passe root du LXC. Genere si absent
|
--lxc-password Mot de passe root du LXC. Genere si absent
|
||||||
-h, --help Affiche cette aide
|
-h, --help Affiche cette aide
|
||||||
|
|
||||||
@@ -68,9 +73,9 @@ LXC_IP="dhcp"
|
|||||||
LXC_GATEWAY=""
|
LXC_GATEWAY=""
|
||||||
LXC_BRIDGE="vmbr0"
|
LXC_BRIDGE="vmbr0"
|
||||||
LXC_CORES="2"
|
LXC_CORES="2"
|
||||||
LXC_MEMORY="1024"
|
LXC_MEMORY="4096"
|
||||||
LXC_SWAP="512"
|
LXC_SWAP="1024"
|
||||||
LXC_DISK_GB="6"
|
LXC_DISK_GB="12"
|
||||||
TEMPLATE_STORAGE=""
|
TEMPLATE_STORAGE=""
|
||||||
ROOTFS_STORAGE=""
|
ROOTFS_STORAGE=""
|
||||||
REPO_URL="https://git.jeannerot.fr/christophe/chesscubing.git"
|
REPO_URL="https://git.jeannerot.fr/christophe/chesscubing.git"
|
||||||
@@ -79,6 +84,10 @@ ETHAN_REPO_URL="https://git.jeannerot.fr/Mineloulou/Chesscubing.git"
|
|||||||
ETHAN_REPO_BRANCH="main"
|
ETHAN_REPO_BRANCH="main"
|
||||||
BRICE_REPO_URL="https://git.jeannerot.fr/Lescratcheur/ChessCubing.git"
|
BRICE_REPO_URL="https://git.jeannerot.fr/Lescratcheur/ChessCubing.git"
|
||||||
BRICE_REPO_BRANCH="main"
|
BRICE_REPO_BRANCH="main"
|
||||||
|
PUBLIC_BASE_URL=""
|
||||||
|
WEB_PORT="80"
|
||||||
|
KEYCLOAK_ADMIN_USER="admin"
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD=""
|
||||||
LXC_PASSWORD=""
|
LXC_PASSWORD=""
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
@@ -171,6 +180,22 @@ while [[ $# -gt 0 ]]; do
|
|||||||
BRICE_REPO_BRANCH="${2:-}"
|
BRICE_REPO_BRANCH="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--public-base-url)
|
||||||
|
PUBLIC_BASE_URL="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--web-port)
|
||||||
|
WEB_PORT="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--keycloak-admin-user)
|
||||||
|
KEYCLOAK_ADMIN_USER="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--keycloak-admin-password)
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
--lxc-password)
|
--lxc-password)
|
||||||
LXC_PASSWORD="${2:-}"
|
LXC_PASSWORD="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
@@ -221,6 +246,10 @@ ethan_repo_branch="$6"
|
|||||||
brice_repo_url="$7"
|
brice_repo_url="$7"
|
||||||
brice_repo_branch="$8"
|
brice_repo_branch="$8"
|
||||||
lxc_password="$9"
|
lxc_password="$9"
|
||||||
|
public_base_url="${10}"
|
||||||
|
web_port="${11}"
|
||||||
|
keycloak_admin_user="${12}"
|
||||||
|
keycloak_admin_password="${13}"
|
||||||
|
|
||||||
die() {
|
die() {
|
||||||
printf 'Erreur: %s\n' "$*" >&2
|
printf 'Erreur: %s\n' "$*" >&2
|
||||||
@@ -339,7 +368,8 @@ pct create "$ctid" "$template_ref" \
|
|||||||
--onboot 1 \
|
--onboot 1 \
|
||||||
--ostype debian \
|
--ostype debian \
|
||||||
--password "$lxc_password" \
|
--password "$lxc_password" \
|
||||||
--unprivileged 1
|
--unprivileged 1 \
|
||||||
|
--features nesting=1,keyctl=1
|
||||||
|
|
||||||
pct start "$ctid"
|
pct start "$ctid"
|
||||||
|
|
||||||
@@ -353,21 +383,7 @@ done
|
|||||||
|
|
||||||
pct exec "$ctid" -- true >/dev/null 2>&1 || die "Le LXC n'est pas joignable apres le demarrage."
|
pct exec "$ctid" -- true >/dev/null 2>&1 || die "Le LXC n'est pas joignable apres le demarrage."
|
||||||
|
|
||||||
printf 'Installation de nginx, git, rsync et des prerequis de build dans le conteneur...\n'
|
ct_exec "install -d -m 0755 /opt/chesscubing/repo /opt/chesscubing/ethan-repo /opt/chesscubing/brice-repo /opt/chesscubing/deploy /opt/chesscubing/config"
|
||||||
ct_exec "apt-get update && apt-get install -y ca-certificates curl gpg git nginx rsync"
|
|
||||||
|
|
||||||
ct_exec "install -d -m 0755 /opt/chesscubing/repo /opt/chesscubing/ethan-repo /opt/chesscubing/brice-repo /opt/chesscubing/publish /var/www/chesscubing/current"
|
|
||||||
|
|
||||||
printf 'Clonage du depot %s...\n' "$repo_url"
|
|
||||||
ct_exec "if [ ! -d /opt/chesscubing/repo/.git ]; then \
|
|
||||||
rm -rf /opt/chesscubing/repo/* /opt/chesscubing/repo/.[!.]* /opt/chesscubing/repo/..?* 2>/dev/null || true; \
|
|
||||||
git clone --branch '$repo_branch' --single-branch '$repo_url' /opt/chesscubing/repo; \
|
|
||||||
else \
|
|
||||||
cd /opt/chesscubing/repo && \
|
|
||||||
git fetch origin '$repo_branch' && \
|
|
||||||
if git show-ref --verify --quiet 'refs/heads/$repo_branch'; then git checkout '$repo_branch'; else git checkout -b '$repo_branch' --track 'origin/$repo_branch'; fi && \
|
|
||||||
git pull --ff-only origin '$repo_branch'; \
|
|
||||||
fi"
|
|
||||||
|
|
||||||
ct_exec "cat > /usr/local/bin/update-chesscubing <<'SCRIPT'
|
ct_exec "cat > /usr/local/bin/update-chesscubing <<'SCRIPT'
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
@@ -378,30 +394,52 @@ trap 'printf \"Erreur: echec de la commande [%s] a la ligne %s.\\n\" \"\$BASH_CO
|
|||||||
main_repo_dir='/opt/chesscubing/repo'
|
main_repo_dir='/opt/chesscubing/repo'
|
||||||
ethan_repo_dir='/opt/chesscubing/ethan-repo'
|
ethan_repo_dir='/opt/chesscubing/ethan-repo'
|
||||||
brice_repo_dir='/opt/chesscubing/brice-repo'
|
brice_repo_dir='/opt/chesscubing/brice-repo'
|
||||||
publish_root='/opt/chesscubing/publish'
|
deploy_dir='/opt/chesscubing/deploy'
|
||||||
web_root='/var/www/chesscubing/current'
|
config_dir='/opt/chesscubing/config'
|
||||||
|
env_file=\"\$config_dir/chesscubing.env\"
|
||||||
main_branch=\"\${1:-${repo_branch}}\"
|
main_branch=\"\${1:-${repo_branch}}\"
|
||||||
|
public_base_url_override=\"\${2:-}\"
|
||||||
|
web_port_override=\"\${3:-}\"
|
||||||
|
keycloak_admin_user_override=\"\${4:-}\"
|
||||||
|
keycloak_admin_password_override=\"\${5:-}\"
|
||||||
|
main_repo_url='${repo_url}'
|
||||||
ethan_repo_url='${ethan_repo_url}'
|
ethan_repo_url='${ethan_repo_url}'
|
||||||
ethan_branch='${ethan_repo_branch}'
|
ethan_branch='${ethan_repo_branch}'
|
||||||
brice_repo_url='${brice_repo_url}'
|
brice_repo_url='${brice_repo_url}'
|
||||||
brice_branch='${brice_repo_branch}'
|
brice_branch='${brice_repo_branch}'
|
||||||
|
|
||||||
ensure_dotnet_sdk() {
|
random_secret() {
|
||||||
if command -v dotnet >/dev/null 2>&1; then
|
od -An -N24 -tx1 /dev/urandom | tr -d ' \n'
|
||||||
return 0
|
}
|
||||||
|
|
||||||
|
ensure_base_packages() {
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y ca-certificates curl gpg git rsync
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_docker_stack() {
|
||||||
|
ensure_base_packages
|
||||||
|
|
||||||
|
if ! command -v docker >/dev/null 2>&1 || ! docker compose version >/dev/null 2>&1; then
|
||||||
|
install -m 0755 -d /etc/apt/keyrings
|
||||||
|
|
||||||
|
if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then
|
||||||
|
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f /etc/apt/sources.list.d/docker.list ]]; then
|
||||||
|
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian %s stable\n' \
|
||||||
|
\"\$(dpkg --print-architecture)\" \
|
||||||
|
\"\$(. /etc/os-release && printf '%s' \"\$VERSION_CODENAME\")\" > /etc/apt/sources.list.d/docker.list
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y ca-certificates curl gpg
|
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
|
||||||
if [[ ! -f /etc/apt/sources.list.d/microsoft-prod.list ]]; then
|
|
||||||
curl -fsSL https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -o /tmp/packages-microsoft-prod.deb
|
|
||||||
dpkg -i /tmp/packages-microsoft-prod.deb
|
|
||||||
rm -f /tmp/packages-microsoft-prod.deb
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update
|
systemctl enable docker >/dev/null 2>&1 || true
|
||||||
apt-get install -y dotnet-sdk-10.0
|
systemctl restart docker
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_git_repo() {
|
sync_git_repo() {
|
||||||
@@ -437,111 +475,189 @@ sync_git_repo() {
|
|||||||
git clone --branch \"\$branch\" --single-branch \"\$repo_url\" \"\$repo_dir\"
|
git clone --branch \"\$branch\" --single-branch \"\$repo_url\" \"\$repo_dir\"
|
||||||
}
|
}
|
||||||
|
|
||||||
publish_blazor_app() {
|
get_env_var() {
|
||||||
local repo_dir=\"\$1\"
|
local key=\"\$1\"
|
||||||
local output_dir=\"\$2\"
|
|
||||||
|
|
||||||
ensure_dotnet_sdk
|
[[ -f \"\$env_file\" ]] || return 0
|
||||||
rm -rf \"\$output_dir\"
|
awk -F= -v wanted=\"\$key\" '\$1 == wanted { print substr(\$0, length(wanted) + 2); exit }' \"\$env_file\"
|
||||||
dotnet publish \"\$repo_dir/ChessCubing.App/ChessCubing.App.csproj\" -c Release -o \"\$output_dir\"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
publish_static_tree() {
|
set_env_var() {
|
||||||
local source_dir=\"\$1\"
|
local key=\"\$1\"
|
||||||
local destination_dir=\"\$2\"
|
local value=\"\$2\"
|
||||||
|
|
||||||
install -d -m 0755 \"\$destination_dir\"
|
touch \"\$env_file\"
|
||||||
|
if grep -q \"^\${key}=\" \"\$env_file\" 2>/dev/null; then
|
||||||
rsync -a --delete \
|
sed -i \"s|^\${key}=.*|\${key}=\${value}|\" \"\$env_file\"
|
||||||
--include='*/' \
|
else
|
||||||
--include='*.html' \
|
printf '%s=%s\n' \"\$key\" \"\$value\" >> \"\$env_file\"
|
||||||
--include='*.css' \
|
|
||||||
--include='*.js' \
|
|
||||||
--include='*.mjs' \
|
|
||||||
--include='*.png' \
|
|
||||||
--include='*.jpg' \
|
|
||||||
--include='*.jpeg' \
|
|
||||||
--include='*.svg' \
|
|
||||||
--include='*.webp' \
|
|
||||||
--include='*.ico' \
|
|
||||||
--include='*.pdf' \
|
|
||||||
--include='*.json' \
|
|
||||||
--include='*.webmanifest' \
|
|
||||||
--exclude='*' \
|
|
||||||
\"\$source_dir/\" \"\$destination_dir/\"
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_browser_stub() {
|
|
||||||
local destination_dir=\"\$1\"
|
|
||||||
local stub_path=\"\$destination_dir/cordova.js\"
|
|
||||||
|
|
||||||
if [[ ! -f \"\$stub_path\" ]]; then
|
|
||||||
printf '%s\n' '// Browser stub for Cordova builds.' > \"\$stub_path\"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_git_repo \"\$main_repo_dir\" '${repo_url}' \"\$main_branch\" 'principal'
|
ensure_env_default() {
|
||||||
|
local key=\"\$1\"
|
||||||
|
local fallback=\"\$2\"
|
||||||
|
local value
|
||||||
|
|
||||||
|
value=\"\$(get_env_var \"\$key\")\"
|
||||||
|
if [[ -z \"\$value\" ]]; then
|
||||||
|
value=\"\$fallback\"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set_env_var \"\$key\" \"\$value\"
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_public_base_url() {
|
||||||
|
local value=\"\$1\"
|
||||||
|
printf '%s\n' \"\${value%/}\"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_default_public_base_url() {
|
||||||
|
local port=\"\$1\"
|
||||||
|
local detected_ip
|
||||||
|
|
||||||
|
detected_ip=\"\$(hostname -I | awk '{print \$1}')\"
|
||||||
|
[[ -n \"\$detected_ip\" ]] || return 1
|
||||||
|
|
||||||
|
if [[ \"\$port\" == \"80\" ]]; then
|
||||||
|
printf 'http://%s\n' \"\$detected_ip\"
|
||||||
|
else
|
||||||
|
printf 'http://%s:%s\n' \"\$detected_ip\" \"\$port\"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_env_file() {
|
||||||
|
local current_value
|
||||||
|
local effective_web_port
|
||||||
|
local effective_public_base_url
|
||||||
|
local effective_keycloak_admin_user
|
||||||
|
local effective_keycloak_admin_password
|
||||||
|
|
||||||
|
effective_web_port=\"\$web_port_override\"
|
||||||
|
if [[ -z \"\$effective_web_port\" ]]; then
|
||||||
|
effective_web_port=\"\$(get_env_var WEB_PORT)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_web_port\" ]]; then
|
||||||
|
effective_web_port='80'
|
||||||
|
fi
|
||||||
|
set_env_var WEB_PORT \"\$effective_web_port\"
|
||||||
|
|
||||||
|
effective_public_base_url=\"\$public_base_url_override\"
|
||||||
|
if [[ -z \"\$effective_public_base_url\" ]]; then
|
||||||
|
effective_public_base_url=\"\$(get_env_var PUBLIC_BASE_URL)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_public_base_url\" ]]; then
|
||||||
|
effective_public_base_url=\"\$(build_default_public_base_url \"\$effective_web_port\" || true)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_public_base_url\" ]]; then
|
||||||
|
if [[ \"\$effective_web_port\" == \"80\" ]]; then
|
||||||
|
effective_public_base_url='http://localhost'
|
||||||
|
else
|
||||||
|
effective_public_base_url=\"http://localhost:\$effective_web_port\"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
set_env_var PUBLIC_BASE_URL \"\$(normalize_public_base_url \"\$effective_public_base_url\")\"
|
||||||
|
|
||||||
|
effective_keycloak_admin_user=\"\$keycloak_admin_user_override\"
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_user\" ]]; then
|
||||||
|
effective_keycloak_admin_user=\"\$(get_env_var KEYCLOAK_ADMIN_USER)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_user\" ]]; then
|
||||||
|
effective_keycloak_admin_user='admin'
|
||||||
|
fi
|
||||||
|
set_env_var KEYCLOAK_ADMIN_USER \"\$effective_keycloak_admin_user\"
|
||||||
|
|
||||||
|
effective_keycloak_admin_password=\"\$keycloak_admin_password_override\"
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_password\" ]]; then
|
||||||
|
effective_keycloak_admin_password=\"\$(get_env_var KEYCLOAK_ADMIN_PASSWORD)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_password\" ]]; then
|
||||||
|
effective_keycloak_admin_password=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var KEYCLOAK_ADMIN_PASSWORD \"\$effective_keycloak_admin_password\"
|
||||||
|
|
||||||
|
ensure_env_default KEYCLOAK_DB_NAME keycloak
|
||||||
|
ensure_env_default KEYCLOAK_DB_USER keycloak
|
||||||
|
current_value=\"\$(get_env_var KEYCLOAK_DB_PASSWORD)\"
|
||||||
|
if [[ -z \"\$current_value\" ]]; then
|
||||||
|
current_value=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var KEYCLOAK_DB_PASSWORD \"\$current_value\"
|
||||||
|
|
||||||
|
ensure_env_default SITE_DB_NAME chesscubing_site
|
||||||
|
ensure_env_default SITE_DB_USER chesscubing
|
||||||
|
current_value=\"\$(get_env_var SITE_DB_PASSWORD)\"
|
||||||
|
if [[ -z \"\$current_value\" ]]; then
|
||||||
|
current_value=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var SITE_DB_PASSWORD \"\$current_value\"
|
||||||
|
|
||||||
|
current_value=\"\$(get_env_var SITE_DB_ROOT_PASSWORD)\"
|
||||||
|
if [[ -z \"\$current_value\" ]]; then
|
||||||
|
current_value=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var SITE_DB_ROOT_PASSWORD \"\$current_value\"
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_deploy_tree() {
|
||||||
|
install -d -m 0755 \"\$deploy_dir\" \"\$config_dir\"
|
||||||
|
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='bin/' \
|
||||||
|
--exclude='obj/' \
|
||||||
|
--exclude='.env' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
\"\$main_repo_dir/\" \"\$deploy_dir/\"
|
||||||
|
|
||||||
|
if [[ -d \"\$ethan_repo_dir/.git\" ]]; then
|
||||||
|
rm -rf \"\$deploy_dir/ethan\"
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
\"\$ethan_repo_dir/\" \"\$deploy_dir/ethan/\"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d \"\$brice_repo_dir/.git\" ]]; then
|
||||||
|
rm -rf \"\$deploy_dir/brice\"
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
\"\$brice_repo_dir/\" \"\$deploy_dir/brice/\"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_legacy_nginx() {
|
||||||
|
systemctl disable --now nginx >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy_stack() {
|
||||||
|
cp \"\$env_file\" \"\$deploy_dir/.env\"
|
||||||
|
|
||||||
|
cd \"\$deploy_dir\"
|
||||||
|
docker compose down || true
|
||||||
|
docker compose up -d --build
|
||||||
|
docker compose ps
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_docker_stack
|
||||||
|
sync_git_repo \"\$main_repo_dir\" \"\$main_repo_url\" \"\$main_branch\" 'principal'
|
||||||
sync_git_repo \"\$ethan_repo_dir\" \"\$ethan_repo_url\" \"\$ethan_branch\" 'Ethan'
|
sync_git_repo \"\$ethan_repo_dir\" \"\$ethan_repo_url\" \"\$ethan_branch\" 'Ethan'
|
||||||
sync_git_repo \"\$brice_repo_dir\" \"\$brice_repo_url\" \"\$brice_branch\" 'Brice'
|
sync_git_repo \"\$brice_repo_dir\" \"\$brice_repo_url\" \"\$brice_branch\" 'Brice'
|
||||||
|
sync_deploy_tree
|
||||||
install -d -m 0755 \"\$web_root\" \"\$publish_root\"
|
configure_env_file
|
||||||
|
disable_legacy_nginx
|
||||||
publish_blazor_app \"\$main_repo_dir\" \"\$publish_root/main\"
|
deploy_stack
|
||||||
rsync -a --delete \"\$publish_root/main/wwwroot/\" \"\$web_root/\"
|
|
||||||
publish_static_tree \"\$ethan_repo_dir\" \"\$web_root/ethan\"
|
|
||||||
publish_static_tree \"\$brice_repo_dir/www\" \"\$web_root/brice\"
|
|
||||||
ensure_browser_stub \"\$web_root/brice\"
|
|
||||||
|
|
||||||
chown -R www-data:www-data \"\$web_root\"
|
|
||||||
|
|
||||||
nginx -t
|
|
||||||
systemctl reload nginx
|
|
||||||
SCRIPT
|
SCRIPT
|
||||||
chmod +x /usr/local/bin/update-chesscubing"
|
chmod +x /usr/local/bin/update-chesscubing"
|
||||||
|
|
||||||
ct_exec "cat > /etc/nginx/sites-available/chesscubing.conf <<'NGINX'
|
printf 'Deploiement de la stack Docker complete dans le LXC...\n'
|
||||||
server {
|
ct_exec "/usr/local/bin/update-chesscubing '$repo_branch' '$public_base_url' '$web_port' '$keycloak_admin_user' '$keycloak_admin_password'"
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
root /var/www/chesscubing/current;
|
|
||||||
index index.html;
|
|
||||||
|
|
||||||
location = /ethan {
|
|
||||||
return 301 \$scheme://\$http_host/ethan/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /ethan/ {
|
|
||||||
try_files \$uri \$uri/ /ethan/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /brice {
|
|
||||||
return 301 \$scheme://\$http_host/brice/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /brice/ {
|
|
||||||
try_files \$uri \$uri/ /brice/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files \$uri \$uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* \.(?:css|js|json|mjs|png|jpg|jpeg|svg|webp|ico|pdf|webmanifest)$ {
|
|
||||||
expires -1;
|
|
||||||
add_header Cache-Control 'no-cache, no-store, must-revalidate';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NGINX
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
|
||||||
ln -sf /etc/nginx/sites-available/chesscubing.conf /etc/nginx/sites-enabled/chesscubing.conf"
|
|
||||||
|
|
||||||
printf 'Publication du site dans le LXC...\n'
|
|
||||||
ct_exec "/usr/local/bin/update-chesscubing '$repo_branch'"
|
|
||||||
ct_exec "systemctl enable nginx >/dev/null && systemctl restart nginx"
|
|
||||||
|
|
||||||
container_ip="$(pct exec "$ctid" -- bash -lc "hostname -I | awk '{print \$1}'" 2>/dev/null | tr -d '\r' || true)"
|
container_ip="$(pct exec "$ctid" -- bash -lc "hostname -I | awk '{print \$1}'" 2>/dev/null | tr -d '\r' || true)"
|
||||||
|
public_url="$(pct exec "$ctid" -- bash -lc "awk -F= '/^PUBLIC_BASE_URL=/{print substr(\$0, 17); exit}' /opt/chesscubing/config/chesscubing.env" 2>/dev/null | tr -d '\r' || true)"
|
||||||
|
effective_keycloak_admin_user="$(pct exec "$ctid" -- bash -lc "awk -F= '/^KEYCLOAK_ADMIN_USER=/{print substr(\$0, 21); exit}' /opt/chesscubing/config/chesscubing.env" 2>/dev/null | tr -d '\r' || true)"
|
||||||
|
effective_keycloak_admin_password="$(pct exec "$ctid" -- bash -lc "awk -F= '/^KEYCLOAK_ADMIN_PASSWORD=/{print substr(\$0, 25); exit}' /opt/chesscubing/config/chesscubing.env" 2>/dev/null | tr -d '\r' || true)"
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
@@ -549,7 +665,10 @@ Installation terminee.
|
|||||||
- CTID: $ctid
|
- CTID: $ctid
|
||||||
- Nom du LXC: $lxc_hostname
|
- Nom du LXC: $lxc_hostname
|
||||||
- Mot de passe root du LXC: $lxc_password
|
- Mot de passe root du LXC: $lxc_password
|
||||||
- URL probable: http://${container_ip:-<ip_du_lxc>}
|
- IP detectee du LXC: ${container_ip:-<ip_du_lxc>}
|
||||||
|
- URL publique configuree: ${public_url:-http://${container_ip:-<ip_du_lxc>}}
|
||||||
|
- Admin Keycloak: ${effective_keycloak_admin_user:-admin}
|
||||||
|
- Mot de passe admin Keycloak: ${effective_keycloak_admin_password:-<voir /opt/chesscubing/config/chesscubing.env>}
|
||||||
|
|
||||||
Pour mettre a jour l'application plus tard:
|
Pour mettre a jour l'application plus tard:
|
||||||
./scripts/update-proxmox-lxc.sh --proxmox-host <ip-proxmox> --proxmox-user <user> --proxmox-password '<motdepasse>' --ctid $ctid
|
./scripts/update-proxmox-lxc.sh --proxmox-host <ip-proxmox> --proxmox-user <user> --proxmox-password '<motdepasse>' --ctid $ctid
|
||||||
@@ -576,7 +695,11 @@ if [[ "$LOCAL_MODE" == "1" ]]; then
|
|||||||
"$ETHAN_REPO_BRANCH" \
|
"$ETHAN_REPO_BRANCH" \
|
||||||
"$BRICE_REPO_URL" \
|
"$BRICE_REPO_URL" \
|
||||||
"$BRICE_REPO_BRANCH" \
|
"$BRICE_REPO_BRANCH" \
|
||||||
"$LXC_PASSWORD"
|
"$LXC_PASSWORD" \
|
||||||
|
"$PUBLIC_BASE_URL" \
|
||||||
|
"$WEB_PORT" \
|
||||||
|
"$KEYCLOAK_ADMIN_USER" \
|
||||||
|
"$KEYCLOAK_ADMIN_PASSWORD"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -618,4 +741,8 @@ sshpass -p "$PROXMOX_PASSWORD" \
|
|||||||
"$ETHAN_REPO_BRANCH" \
|
"$ETHAN_REPO_BRANCH" \
|
||||||
"$BRICE_REPO_URL" \
|
"$BRICE_REPO_URL" \
|
||||||
"$BRICE_REPO_BRANCH" \
|
"$BRICE_REPO_BRANCH" \
|
||||||
"$LXC_PASSWORD" < "$payload_script"
|
"$LXC_PASSWORD" \
|
||||||
|
"$PUBLIC_BASE_URL" \
|
||||||
|
"$WEB_PORT" \
|
||||||
|
"$KEYCLOAK_ADMIN_USER" \
|
||||||
|
"$KEYCLOAK_ADMIN_PASSWORD" < "$payload_script"
|
||||||
|
|||||||
@@ -22,11 +22,17 @@ Options principales:
|
|||||||
--local Execute directement sur l'hote Proxmox local
|
--local Execute directement sur l'hote Proxmox local
|
||||||
--ctid CTID du LXC a mettre a jour
|
--ctid CTID du LXC a mettre a jour
|
||||||
--hostname Nom du LXC si le CTID n'est pas fourni (defaut: chesscubing-web)
|
--hostname Nom du LXC si le CTID n'est pas fourni (defaut: chesscubing-web)
|
||||||
|
--repo-url Depot Git principal a deployer
|
||||||
--branch Branche Git a deployer (defaut: main)
|
--branch Branche Git a deployer (defaut: main)
|
||||||
--ethan-repo-url Depot Git de l'application Ethan
|
--ethan-repo-url Depot Git de l'application Ethan
|
||||||
--ethan-branch Branche Git de l'application Ethan (defaut: main)
|
--ethan-branch Branche Git de l'application Ethan (defaut: main)
|
||||||
--brice-repo-url Depot Git de l'application Brice
|
--brice-repo-url Depot Git de l'application Brice
|
||||||
--brice-branch Branche Git de l'application Brice (defaut: main)
|
--brice-branch Branche Git de l'application Brice (defaut: main)
|
||||||
|
--public-base-url URL publique du site (ex: http://jeu.example.com)
|
||||||
|
--web-port Port HTTP expose dans le LXC (defaut: conserve ou 80)
|
||||||
|
--keycloak-admin-user Utilisateur admin Keycloak a forcer
|
||||||
|
--keycloak-admin-password
|
||||||
|
Mot de passe admin Keycloak a forcer
|
||||||
-h, --help Affiche cette aide
|
-h, --help Affiche cette aide
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
@@ -48,11 +54,16 @@ LOCAL_MODE="0"
|
|||||||
|
|
||||||
CTID=""
|
CTID=""
|
||||||
LXC_HOSTNAME="chesscubing-web"
|
LXC_HOSTNAME="chesscubing-web"
|
||||||
|
REPO_URL="https://git.jeannerot.fr/christophe/chesscubing.git"
|
||||||
REPO_BRANCH="main"
|
REPO_BRANCH="main"
|
||||||
ETHAN_REPO_URL="https://git.jeannerot.fr/Mineloulou/Chesscubing.git"
|
ETHAN_REPO_URL="https://git.jeannerot.fr/Mineloulou/Chesscubing.git"
|
||||||
ETHAN_REPO_BRANCH="main"
|
ETHAN_REPO_BRANCH="main"
|
||||||
BRICE_REPO_URL="https://git.jeannerot.fr/Lescratcheur/ChessCubing.git"
|
BRICE_REPO_URL="https://git.jeannerot.fr/Lescratcheur/ChessCubing.git"
|
||||||
BRICE_REPO_BRANCH="main"
|
BRICE_REPO_BRANCH="main"
|
||||||
|
PUBLIC_BASE_URL=""
|
||||||
|
WEB_PORT=""
|
||||||
|
KEYCLOAK_ADMIN_USER=""
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD=""
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
while [[ $# -gt 0 ]]; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -84,6 +95,10 @@ while [[ $# -gt 0 ]]; do
|
|||||||
LXC_HOSTNAME="${2:-}"
|
LXC_HOSTNAME="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--repo-url)
|
||||||
|
REPO_URL="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
--branch)
|
--branch)
|
||||||
REPO_BRANCH="${2:-}"
|
REPO_BRANCH="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
@@ -104,6 +119,22 @@ while [[ $# -gt 0 ]]; do
|
|||||||
BRICE_REPO_BRANCH="${2:-}"
|
BRICE_REPO_BRANCH="${2:-}"
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
--public-base-url)
|
||||||
|
PUBLIC_BASE_URL="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--web-port)
|
||||||
|
WEB_PORT="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--keycloak-admin-user)
|
||||||
|
KEYCLOAK_ADMIN_USER="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--keycloak-admin-password)
|
||||||
|
KEYCLOAK_ADMIN_PASSWORD="${2:-}"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
-h | --help)
|
-h | --help)
|
||||||
usage
|
usage
|
||||||
exit 0
|
exit 0
|
||||||
@@ -133,11 +164,16 @@ trap 'printf "Erreur: echec de la commande [%s] a la ligne %s.\n" "$BASH_COMMAND
|
|||||||
|
|
||||||
ctid="$1"
|
ctid="$1"
|
||||||
lxc_hostname="$2"
|
lxc_hostname="$2"
|
||||||
repo_branch="$3"
|
repo_url="$3"
|
||||||
ethan_repo_url="$4"
|
repo_branch="$4"
|
||||||
ethan_repo_branch="$5"
|
ethan_repo_url="$5"
|
||||||
brice_repo_url="$6"
|
ethan_repo_branch="$6"
|
||||||
brice_repo_branch="$7"
|
brice_repo_url="$7"
|
||||||
|
brice_repo_branch="$8"
|
||||||
|
public_base_url="$9"
|
||||||
|
web_port="${10}"
|
||||||
|
keycloak_admin_user="${11}"
|
||||||
|
keycloak_admin_password="${12}"
|
||||||
|
|
||||||
die() {
|
die() {
|
||||||
printf 'Erreur: %s\n' "$*" >&2
|
printf 'Erreur: %s\n' "$*" >&2
|
||||||
@@ -178,15 +214,28 @@ if [[ -n "$detected_hostname" ]]; then
|
|||||||
lxc_hostname="$detected_hostname"
|
lxc_hostname="$detected_hostname"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! pct status "$ctid" | grep -q "running"; then
|
if pct status "$ctid" | grep -q "running"; then
|
||||||
pct start "$ctid"
|
pct stop "$ctid"
|
||||||
sleep 5
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
pct set "$ctid" --features nesting=1,keyctl=1 >/dev/null
|
||||||
|
pct start "$ctid"
|
||||||
|
|
||||||
|
for _ in $(seq 1 20); do
|
||||||
|
if pct exec "$ctid" -- true >/dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
|
||||||
|
pct exec "$ctid" -- true >/dev/null 2>&1 || die "Le LXC n'est pas joignable apres le redemarrage."
|
||||||
|
|
||||||
ct_exec() {
|
ct_exec() {
|
||||||
pct exec "$ctid" -- bash -lc "$1"
|
pct exec "$ctid" -- bash -lc "$1"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ct_exec "install -d -m 0755 /opt/chesscubing/repo /opt/chesscubing/ethan-repo /opt/chesscubing/brice-repo /opt/chesscubing/deploy /opt/chesscubing/config"
|
||||||
|
|
||||||
ct_exec "cat > /usr/local/bin/update-chesscubing <<'SCRIPT'
|
ct_exec "cat > /usr/local/bin/update-chesscubing <<'SCRIPT'
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -Eeuo pipefail
|
set -Eeuo pipefail
|
||||||
@@ -196,30 +245,52 @@ trap 'printf \"Erreur: echec de la commande [%s] a la ligne %s.\\n\" \"\$BASH_CO
|
|||||||
main_repo_dir='/opt/chesscubing/repo'
|
main_repo_dir='/opt/chesscubing/repo'
|
||||||
ethan_repo_dir='/opt/chesscubing/ethan-repo'
|
ethan_repo_dir='/opt/chesscubing/ethan-repo'
|
||||||
brice_repo_dir='/opt/chesscubing/brice-repo'
|
brice_repo_dir='/opt/chesscubing/brice-repo'
|
||||||
publish_root='/opt/chesscubing/publish'
|
deploy_dir='/opt/chesscubing/deploy'
|
||||||
web_root='/var/www/chesscubing/current'
|
config_dir='/opt/chesscubing/config'
|
||||||
|
env_file=\"\$config_dir/chesscubing.env\"
|
||||||
main_branch=\"\${1:-${repo_branch}}\"
|
main_branch=\"\${1:-${repo_branch}}\"
|
||||||
|
public_base_url_override=\"\${2:-}\"
|
||||||
|
web_port_override=\"\${3:-}\"
|
||||||
|
keycloak_admin_user_override=\"\${4:-}\"
|
||||||
|
keycloak_admin_password_override=\"\${5:-}\"
|
||||||
|
main_repo_url='${repo_url}'
|
||||||
ethan_repo_url='${ethan_repo_url}'
|
ethan_repo_url='${ethan_repo_url}'
|
||||||
ethan_branch='${ethan_repo_branch}'
|
ethan_branch='${ethan_repo_branch}'
|
||||||
brice_repo_url='${brice_repo_url}'
|
brice_repo_url='${brice_repo_url}'
|
||||||
brice_branch='${brice_repo_branch}'
|
brice_branch='${brice_repo_branch}'
|
||||||
|
|
||||||
ensure_dotnet_sdk() {
|
random_secret() {
|
||||||
if command -v dotnet >/dev/null 2>&1; then
|
od -An -N24 -tx1 /dev/urandom | tr -d ' \n'
|
||||||
return 0
|
}
|
||||||
|
|
||||||
|
ensure_base_packages() {
|
||||||
|
apt-get update
|
||||||
|
apt-get install -y ca-certificates curl gpg git rsync
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_docker_stack() {
|
||||||
|
ensure_base_packages
|
||||||
|
|
||||||
|
if ! command -v docker >/dev/null 2>&1 || ! docker compose version >/dev/null 2>&1; then
|
||||||
|
install -m 0755 -d /etc/apt/keyrings
|
||||||
|
|
||||||
|
if [[ ! -f /etc/apt/keyrings/docker.asc ]]; then
|
||||||
|
curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
|
||||||
|
chmod a+r /etc/apt/keyrings/docker.asc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f /etc/apt/sources.list.d/docker.list ]]; then
|
||||||
|
printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian %s stable\n' \
|
||||||
|
\"\$(dpkg --print-architecture)\" \
|
||||||
|
\"\$(. /etc/os-release && printf '%s' \"\$VERSION_CODENAME\")\" > /etc/apt/sources.list.d/docker.list
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y ca-certificates curl gpg
|
apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
|
||||||
|
|
||||||
if [[ ! -f /etc/apt/sources.list.d/microsoft-prod.list ]]; then
|
|
||||||
curl -fsSL https://packages.microsoft.com/config/debian/12/packages-microsoft-prod.deb -o /tmp/packages-microsoft-prod.deb
|
|
||||||
dpkg -i /tmp/packages-microsoft-prod.deb
|
|
||||||
rm -f /tmp/packages-microsoft-prod.deb
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
apt-get update
|
systemctl enable docker >/dev/null 2>&1 || true
|
||||||
apt-get install -y dotnet-sdk-10.0
|
systemctl restart docker
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_git_repo() {
|
sync_git_repo() {
|
||||||
@@ -255,116 +326,194 @@ sync_git_repo() {
|
|||||||
git clone --branch \"\$branch\" --single-branch \"\$repo_url\" \"\$repo_dir\"
|
git clone --branch \"\$branch\" --single-branch \"\$repo_url\" \"\$repo_dir\"
|
||||||
}
|
}
|
||||||
|
|
||||||
publish_blazor_app() {
|
get_env_var() {
|
||||||
local repo_dir=\"\$1\"
|
local key=\"\$1\"
|
||||||
local output_dir=\"\$2\"
|
|
||||||
|
|
||||||
ensure_dotnet_sdk
|
[[ -f \"\$env_file\" ]] || return 0
|
||||||
rm -rf \"\$output_dir\"
|
awk -F= -v wanted=\"\$key\" '\$1 == wanted { print substr(\$0, length(wanted) + 2); exit }' \"\$env_file\"
|
||||||
dotnet publish \"\$repo_dir/ChessCubing.App/ChessCubing.App.csproj\" -c Release -o \"\$output_dir\"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
publish_static_tree() {
|
set_env_var() {
|
||||||
local source_dir=\"\$1\"
|
local key=\"\$1\"
|
||||||
local destination_dir=\"\$2\"
|
local value=\"\$2\"
|
||||||
|
|
||||||
install -d -m 0755 \"\$destination_dir\"
|
touch \"\$env_file\"
|
||||||
|
if grep -q \"^\${key}=\" \"\$env_file\" 2>/dev/null; then
|
||||||
rsync -a --delete \
|
sed -i \"s|^\${key}=.*|\${key}=\${value}|\" \"\$env_file\"
|
||||||
--include='*/' \
|
else
|
||||||
--include='*.html' \
|
printf '%s=%s\n' \"\$key\" \"\$value\" >> \"\$env_file\"
|
||||||
--include='*.css' \
|
|
||||||
--include='*.js' \
|
|
||||||
--include='*.mjs' \
|
|
||||||
--include='*.png' \
|
|
||||||
--include='*.jpg' \
|
|
||||||
--include='*.jpeg' \
|
|
||||||
--include='*.svg' \
|
|
||||||
--include='*.webp' \
|
|
||||||
--include='*.ico' \
|
|
||||||
--include='*.pdf' \
|
|
||||||
--include='*.json' \
|
|
||||||
--include='*.webmanifest' \
|
|
||||||
--exclude='*' \
|
|
||||||
\"\$source_dir/\" \"\$destination_dir/\"
|
|
||||||
}
|
|
||||||
|
|
||||||
ensure_browser_stub() {
|
|
||||||
local destination_dir=\"\$1\"
|
|
||||||
local stub_path=\"\$destination_dir/cordova.js\"
|
|
||||||
|
|
||||||
if [[ ! -f \"\$stub_path\" ]]; then
|
|
||||||
printf '%s\n' '// Browser stub for Cordova builds.' > \"\$stub_path\"
|
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
sync_git_repo \"\$main_repo_dir\" '' \"\$main_branch\" 'principal'
|
ensure_env_default() {
|
||||||
|
local key=\"\$1\"
|
||||||
|
local fallback=\"\$2\"
|
||||||
|
local value
|
||||||
|
|
||||||
|
value=\"\$(get_env_var \"\$key\")\"
|
||||||
|
if [[ -z \"\$value\" ]]; then
|
||||||
|
value=\"\$fallback\"
|
||||||
|
fi
|
||||||
|
|
||||||
|
set_env_var \"\$key\" \"\$value\"
|
||||||
|
}
|
||||||
|
|
||||||
|
normalize_public_base_url() {
|
||||||
|
local value=\"\$1\"
|
||||||
|
printf '%s\n' \"\${value%/}\"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_default_public_base_url() {
|
||||||
|
local port=\"\$1\"
|
||||||
|
local detected_ip
|
||||||
|
|
||||||
|
detected_ip=\"\$(hostname -I | awk '{print \$1}')\"
|
||||||
|
[[ -n \"\$detected_ip\" ]] || return 1
|
||||||
|
|
||||||
|
if [[ \"\$port\" == \"80\" ]]; then
|
||||||
|
printf 'http://%s\n' \"\$detected_ip\"
|
||||||
|
else
|
||||||
|
printf 'http://%s:%s\n' \"\$detected_ip\" \"\$port\"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
configure_env_file() {
|
||||||
|
local current_value
|
||||||
|
local effective_web_port
|
||||||
|
local effective_public_base_url
|
||||||
|
local effective_keycloak_admin_user
|
||||||
|
local effective_keycloak_admin_password
|
||||||
|
|
||||||
|
effective_web_port=\"\$web_port_override\"
|
||||||
|
if [[ -z \"\$effective_web_port\" ]]; then
|
||||||
|
effective_web_port=\"\$(get_env_var WEB_PORT)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_web_port\" ]]; then
|
||||||
|
effective_web_port='80'
|
||||||
|
fi
|
||||||
|
set_env_var WEB_PORT \"\$effective_web_port\"
|
||||||
|
|
||||||
|
effective_public_base_url=\"\$public_base_url_override\"
|
||||||
|
if [[ -z \"\$effective_public_base_url\" ]]; then
|
||||||
|
effective_public_base_url=\"\$(get_env_var PUBLIC_BASE_URL)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_public_base_url\" ]]; then
|
||||||
|
effective_public_base_url=\"\$(build_default_public_base_url \"\$effective_web_port\" || true)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_public_base_url\" ]]; then
|
||||||
|
if [[ \"\$effective_web_port\" == \"80\" ]]; then
|
||||||
|
effective_public_base_url='http://localhost'
|
||||||
|
else
|
||||||
|
effective_public_base_url=\"http://localhost:\$effective_web_port\"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
set_env_var PUBLIC_BASE_URL \"\$(normalize_public_base_url \"\$effective_public_base_url\")\"
|
||||||
|
|
||||||
|
effective_keycloak_admin_user=\"\$keycloak_admin_user_override\"
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_user\" ]]; then
|
||||||
|
effective_keycloak_admin_user=\"\$(get_env_var KEYCLOAK_ADMIN_USER)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_user\" ]]; then
|
||||||
|
effective_keycloak_admin_user='admin'
|
||||||
|
fi
|
||||||
|
set_env_var KEYCLOAK_ADMIN_USER \"\$effective_keycloak_admin_user\"
|
||||||
|
|
||||||
|
effective_keycloak_admin_password=\"\$keycloak_admin_password_override\"
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_password\" ]]; then
|
||||||
|
effective_keycloak_admin_password=\"\$(get_env_var KEYCLOAK_ADMIN_PASSWORD)\"
|
||||||
|
fi
|
||||||
|
if [[ -z \"\$effective_keycloak_admin_password\" ]]; then
|
||||||
|
effective_keycloak_admin_password=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var KEYCLOAK_ADMIN_PASSWORD \"\$effective_keycloak_admin_password\"
|
||||||
|
|
||||||
|
ensure_env_default KEYCLOAK_DB_NAME keycloak
|
||||||
|
ensure_env_default KEYCLOAK_DB_USER keycloak
|
||||||
|
current_value=\"\$(get_env_var KEYCLOAK_DB_PASSWORD)\"
|
||||||
|
if [[ -z \"\$current_value\" ]]; then
|
||||||
|
current_value=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var KEYCLOAK_DB_PASSWORD \"\$current_value\"
|
||||||
|
|
||||||
|
ensure_env_default SITE_DB_NAME chesscubing_site
|
||||||
|
ensure_env_default SITE_DB_USER chesscubing
|
||||||
|
current_value=\"\$(get_env_var SITE_DB_PASSWORD)\"
|
||||||
|
if [[ -z \"\$current_value\" ]]; then
|
||||||
|
current_value=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var SITE_DB_PASSWORD \"\$current_value\"
|
||||||
|
|
||||||
|
current_value=\"\$(get_env_var SITE_DB_ROOT_PASSWORD)\"
|
||||||
|
if [[ -z \"\$current_value\" ]]; then
|
||||||
|
current_value=\"\$(random_secret)\"
|
||||||
|
fi
|
||||||
|
set_env_var SITE_DB_ROOT_PASSWORD \"\$current_value\"
|
||||||
|
}
|
||||||
|
|
||||||
|
sync_deploy_tree() {
|
||||||
|
install -d -m 0755 \"\$deploy_dir\" \"\$config_dir\"
|
||||||
|
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='bin/' \
|
||||||
|
--exclude='obj/' \
|
||||||
|
--exclude='.env' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
\"\$main_repo_dir/\" \"\$deploy_dir/\"
|
||||||
|
|
||||||
|
if [[ -d \"\$ethan_repo_dir/.git\" ]]; then
|
||||||
|
rm -rf \"\$deploy_dir/ethan\"
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
\"\$ethan_repo_dir/\" \"\$deploy_dir/ethan/\"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d \"\$brice_repo_dir/.git\" ]]; then
|
||||||
|
rm -rf \"\$deploy_dir/brice\"
|
||||||
|
rsync -a --delete \
|
||||||
|
--exclude='.git/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
\"\$brice_repo_dir/\" \"\$deploy_dir/brice/\"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_legacy_nginx() {
|
||||||
|
systemctl disable --now nginx >/dev/null 2>&1 || true
|
||||||
|
}
|
||||||
|
|
||||||
|
deploy_stack() {
|
||||||
|
cp \"\$env_file\" \"\$deploy_dir/.env\"
|
||||||
|
|
||||||
|
cd \"\$deploy_dir\"
|
||||||
|
docker compose down || true
|
||||||
|
docker compose up -d --build
|
||||||
|
docker compose ps
|
||||||
|
}
|
||||||
|
|
||||||
|
ensure_docker_stack
|
||||||
|
sync_git_repo \"\$main_repo_dir\" \"\$main_repo_url\" \"\$main_branch\" 'principal'
|
||||||
sync_git_repo \"\$ethan_repo_dir\" \"\$ethan_repo_url\" \"\$ethan_branch\" 'Ethan'
|
sync_git_repo \"\$ethan_repo_dir\" \"\$ethan_repo_url\" \"\$ethan_branch\" 'Ethan'
|
||||||
sync_git_repo \"\$brice_repo_dir\" \"\$brice_repo_url\" \"\$brice_branch\" 'Brice'
|
sync_git_repo \"\$brice_repo_dir\" \"\$brice_repo_url\" \"\$brice_branch\" 'Brice'
|
||||||
|
sync_deploy_tree
|
||||||
install -d -m 0755 \"\$web_root\" \"\$publish_root\"
|
configure_env_file
|
||||||
|
disable_legacy_nginx
|
||||||
publish_blazor_app \"\$main_repo_dir\" \"\$publish_root/main\"
|
deploy_stack
|
||||||
rsync -a --delete \"\$publish_root/main/wwwroot/\" \"\$web_root/\"
|
|
||||||
publish_static_tree \"\$ethan_repo_dir\" \"\$web_root/ethan\"
|
|
||||||
publish_static_tree \"\$brice_repo_dir/www\" \"\$web_root/brice\"
|
|
||||||
ensure_browser_stub \"\$web_root/brice\"
|
|
||||||
|
|
||||||
chown -R www-data:www-data \"\$web_root\"
|
|
||||||
|
|
||||||
nginx -t
|
|
||||||
systemctl reload nginx
|
|
||||||
SCRIPT
|
SCRIPT
|
||||||
chmod +x /usr/local/bin/update-chesscubing"
|
chmod +x /usr/local/bin/update-chesscubing"
|
||||||
|
|
||||||
ct_exec "cat > /etc/nginx/sites-available/chesscubing.conf <<'NGINX'
|
ct_exec "/usr/local/bin/update-chesscubing '$repo_branch' '$public_base_url' '$web_port' '$keycloak_admin_user' '$keycloak_admin_password'"
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
listen [::]:80;
|
|
||||||
server_name _;
|
|
||||||
|
|
||||||
root /var/www/chesscubing/current;
|
|
||||||
index index.html;
|
|
||||||
|
|
||||||
location = /ethan {
|
|
||||||
return 301 \$scheme://\$http_host/ethan/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /ethan/ {
|
|
||||||
try_files \$uri \$uri/ /ethan/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location = /brice {
|
|
||||||
return 301 \$scheme://\$http_host/brice/;
|
|
||||||
}
|
|
||||||
|
|
||||||
location /brice/ {
|
|
||||||
try_files \$uri \$uri/ /brice/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
try_files \$uri \$uri/ /index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~* \.(?:css|js|json|mjs|png|jpg|jpeg|svg|webp|ico|pdf|webmanifest)$ {
|
|
||||||
expires -1;
|
|
||||||
add_header Cache-Control 'no-cache, no-store, must-revalidate';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NGINX
|
|
||||||
rm -f /etc/nginx/sites-enabled/default
|
|
||||||
ln -sf /etc/nginx/sites-available/chesscubing.conf /etc/nginx/sites-enabled/chesscubing.conf"
|
|
||||||
|
|
||||||
pct exec "$ctid" -- /usr/local/bin/update-chesscubing "$repo_branch"
|
|
||||||
|
|
||||||
container_ip="$(pct exec "$ctid" -- bash -lc "hostname -I | awk '{print \$1}'" 2>/dev/null | tr -d '\r' || true)"
|
container_ip="$(pct exec "$ctid" -- bash -lc "hostname -I | awk '{print \$1}'" 2>/dev/null | tr -d '\r' || true)"
|
||||||
|
public_url="$(pct exec "$ctid" -- bash -lc "awk -F= '/^PUBLIC_BASE_URL=/{print substr(\$0, 17); exit}' /opt/chesscubing/config/chesscubing.env" 2>/dev/null | tr -d '\r' || true)"
|
||||||
|
|
||||||
cat <<EOF
|
cat <<EOF
|
||||||
|
|
||||||
Mise a jour terminee.
|
Mise a jour terminee.
|
||||||
- CTID: $ctid
|
- CTID: $ctid
|
||||||
- Nom du LXC: $lxc_hostname
|
- Nom du LXC: $lxc_hostname
|
||||||
- URL probable: http://${container_ip:-<ip_du_lxc>}
|
- IP detectee du LXC: ${container_ip:-<ip_du_lxc>}
|
||||||
|
- URL publique configuree: ${public_url:-http://${container_ip:-<ip_du_lxc>}}
|
||||||
EOF
|
EOF
|
||||||
REMOTE
|
REMOTE
|
||||||
|
|
||||||
@@ -373,11 +522,16 @@ if [[ "$LOCAL_MODE" == "1" ]]; then
|
|||||||
bash "$payload_script" \
|
bash "$payload_script" \
|
||||||
"$CTID" \
|
"$CTID" \
|
||||||
"$LXC_HOSTNAME" \
|
"$LXC_HOSTNAME" \
|
||||||
|
"$REPO_URL" \
|
||||||
"$REPO_BRANCH" \
|
"$REPO_BRANCH" \
|
||||||
"$ETHAN_REPO_URL" \
|
"$ETHAN_REPO_URL" \
|
||||||
"$ETHAN_REPO_BRANCH" \
|
"$ETHAN_REPO_BRANCH" \
|
||||||
"$BRICE_REPO_URL" \
|
"$BRICE_REPO_URL" \
|
||||||
"$BRICE_REPO_BRANCH"
|
"$BRICE_REPO_BRANCH" \
|
||||||
|
"$PUBLIC_BASE_URL" \
|
||||||
|
"$WEB_PORT" \
|
||||||
|
"$KEYCLOAK_ADMIN_USER" \
|
||||||
|
"$KEYCLOAK_ADMIN_PASSWORD"
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -404,8 +558,13 @@ sshpass -p "$PROXMOX_PASSWORD" \
|
|||||||
bash -s -- \
|
bash -s -- \
|
||||||
"$CTID" \
|
"$CTID" \
|
||||||
"$LXC_HOSTNAME" \
|
"$LXC_HOSTNAME" \
|
||||||
|
"$REPO_URL" \
|
||||||
"$REPO_BRANCH" \
|
"$REPO_BRANCH" \
|
||||||
"$ETHAN_REPO_URL" \
|
"$ETHAN_REPO_URL" \
|
||||||
"$ETHAN_REPO_BRANCH" \
|
"$ETHAN_REPO_BRANCH" \
|
||||||
"$BRICE_REPO_URL" \
|
"$BRICE_REPO_URL" \
|
||||||
"$BRICE_REPO_BRANCH" < "$payload_script"
|
"$BRICE_REPO_BRANCH" \
|
||||||
|
"$PUBLIC_BASE_URL" \
|
||||||
|
"$WEB_PORT" \
|
||||||
|
"$KEYCLOAK_ADMIN_USER" \
|
||||||
|
"$KEYCLOAK_ADMIN_PASSWORD" < "$payload_script"
|
||||||
|
|||||||
Reference in New Issue
Block a user