Prefix LXCs hotel-manage-*; group in Proxmox pool + tag

This commit is contained in:
jtricerolph 2026-07-01 12:40:28 +00:00
parent d052d0bddf
commit 4622cc3d45
3 changed files with 110 additions and 71 deletions

View file

@ -1,6 +1,6 @@
#!/usr/bin/env bash
# ┌─────────────────────────────────────────────────────────────────────────┐
# │ HNF Manage — Proxmox Stack Installer │
# │ Hotel Manage — Proxmox Stack Installer │
# │ Provisions: postgres · auth · portal · npm · management · noticeboard │
# │ │
# │ Run on the Proxmox host shell: │
@ -97,35 +97,35 @@ ensure_template() {
# ── Collect site config ───────────────────────────────────────────────────────
collect_config() {
SITE_NAME=$(whiptail --title "HNF Stack — Site Config" \
SITE_NAME=$(whiptail --title "Hotel Manage — Site Config" \
--inputbox "Site name:" 8 52 "Hotel Number Four" 3>&1 1>&2 2>&3) || exit 0
DOMAIN=$(whiptail --title "HNF Stack — Site Config" \
DOMAIN=$(whiptail --title "Hotel Manage — Site Config" \
--inputbox "Public domain (e.g. manage.hotelnumberfour.com):" 8 64 "manage.hotelnumberfour.com" \
3>&1 1>&2 2>&3) || exit 0
NPM_LAN_IP=$(whiptail --title "HNF Stack — Site Config" \
NPM_LAN_IP=$(whiptail --title "Hotel Manage — Site Config" \
--inputbox "NPM LXC static LAN IP (from your hotel LAN pool):" 8 64 "10.4.0.50" \
3>&1 1>&2 2>&3) || exit 0
LAN_GW=$(whiptail --title "HNF Stack — Site Config" \
LAN_GW=$(whiptail --title "Hotel Manage — Site Config" \
--inputbox "LAN gateway IP:" 8 52 "10.4.0.1" 3>&1 1>&2 2>&3) || exit 0
OFFICE_IP=$(whiptail --title "HNF Stack — Site Config" \
OFFICE_IP=$(whiptail --title "Hotel Manage — Site Config" \
--inputbox \
"Office IP / CIDR / DDNS hostname for offsite restriction.
Examples: 203.0.113.5 10.4.0.0/22 hotel.dyndns.org
Type 'disabled' to allow access from anywhere:" \
11 64 "disabled" 3>&1 1>&2 2>&3) || exit 0
ADMIN_EMAIL=$(whiptail --title "HNF Stack — Admin Account" \
ADMIN_EMAIL=$(whiptail --title "Hotel Manage — Admin Account" \
--inputbox "Admin user email:" 8 52 "" 3>&1 1>&2 2>&3) || exit 0
ADMIN_PASS=$(whiptail --title "HNF Stack — Admin Account" \
ADMIN_PASS=$(whiptail --title "Hotel Manage — Admin Account" \
--passwordbox "Admin user password:" 8 52 3>&1 1>&2 2>&3) || exit 0
# Deploy source — per-service Forgejo repos (default) or a local copy on this host
FORGEJO_BASE=$(whiptail --title "HNF Stack — Forgejo" \
FORGEJO_BASE=$(whiptail --title "Hotel Manage — Forgejo" \
--inputbox \
"Forgejo org/base URL hosting the per-service repos.
Each service is cloned from <base>/<service>.git
@ -135,7 +135,7 @@ Example: https://git.pterois.co.uk/hotel-manage-stack" \
13 66 "https://git.pterois.co.uk/hotel-manage-stack" 3>&1 1>&2 2>&3) || exit 0
FORGEJO_BASE="${FORGEJO_BASE%/}"
FORGEJO_TOKEN=$(whiptail --title "HNF Stack — Forgejo Token" \
FORGEJO_TOKEN=$(whiptail --title "Hotel Manage — Forgejo Token" \
--passwordbox \
"The repos are PUBLIC — leave this blank.
@ -144,7 +144,7 @@ from Forgejo → Settings → Applications, scope read:repository,
which gets embedded in each LXC's git remote for the updater.)" \
12 66 3>&1 1>&2 2>&3) || exit 0
if whiptail --title "HNF Stack — Deploy Source" --yesno \
if whiptail --title "Hotel Manage — Deploy Source" --yesno \
"Deploy services from Forgejo? (recommended)\n\nNo = copy from a local repo at ${REPO_ROOT}\n(only works if you already copied the repo to this host)" \
11 62; then
USE_FORGEJO=true
@ -152,24 +152,24 @@ which gets embedded in each LXC's git remote for the updater.)" \
USE_FORGEJO=false
fi
BACKUP_REMOTE=$(whiptail --title "HNF Stack — Backup" \
BACKUP_REMOTE=$(whiptail --title "Hotel Manage — Backup" \
--inputbox \
"Backup rsync target (leave blank to skip backup config).
Example: backup@192.168.1.10:/backups/hnf" \
Example: backup@192.168.1.10:/backups/hotel-manage" \
10 64 "" 3>&1 1>&2 2>&3) || exit 0
# Confirm LXC allocation
whiptail --title "HNF Stack — Confirm" --yesno \
whiptail --title "Hotel Manage — Confirm" --yesno \
"LXCs to be created (storage: ${STORAGE}):
ID Hostname IP
──────────────────────────────────────────
100 hnf-postgres 10.10.10.100
101 hnf-auth 10.10.10.101
102 hnf-portal 10.10.10.102
103 hnf-npm 10.10.10.103 / ${NPM_LAN_IP} (dual-homed)
105 hnf-management 10.10.10.105
112 hnf-noticeboard 10.10.10.112
100 hotel-manage-postgres 10.10.10.100
101 hotel-manage-auth 10.10.10.101
102 hotel-manage-portal 10.10.10.102
103 hotel-manage-npm 10.10.10.103 / ${NPM_LAN_IP} (dual-homed)
105 hotel-manage-management 10.10.10.105
112 hotel-manage-noticeboard 10.10.10.112
Domain: ${DOMAIN}
Admin: ${ADMIN_EMAIL}
@ -187,8 +187,8 @@ gen_secrets() {
WEBHOOK_SECRET=$(openssl rand -hex 24)
NPM_ADMIN_PASS=$(openssl rand -base64 12 | tr -dc 'a-zA-Z0-9' | head -c 12)
cat > /root/hnf-credentials.txt <<EOF
# HNF Manage credentials — generated $(date '+%Y-%m-%d %H:%M')
cat > /root/hotel-manage-credentials.txt <<EOF
# Hotel Manage credentials — generated $(date '+%Y-%m-%d %H:%M')
# !! KEEP THIS FILE SAFE — store a copy offsite !!
SITE_NAME=${SITE_NAME}
@ -211,22 +211,22 @@ FORGEJO_TOKEN=${FORGEJO_TOKEN}
BACKUP_REMOTE=${BACKUP_REMOTE}
EOF
chmod 600 /root/hnf-credentials.txt
msg_ok "Secrets generated → /root/hnf-credentials.txt"
chmod 600 /root/hotel-manage-credentials.txt
msg_ok "Secrets generated → /root/hotel-manage-credentials.txt"
}
# ── SSH keypair for management → app LXCs ────────────────────────────────────
gen_mgmt_ssh_key() {
if [[ ! -f /root/.ssh/hnf_management ]]; then
if [[ ! -f /root/.ssh/hotel-manage_deploy ]]; then
msg_info "Generating management SSH keypair"
mkdir -p /root/.ssh
ssh-keygen -t ed25519 -f /root/.ssh/hnf_management -N "" -C "hnf-management-deploy" &>/dev/null
msg_ok "SSH keypair generated → /root/.ssh/hnf_management"
ssh-keygen -t ed25519 -f /root/.ssh/hotel-manage_deploy -N "" -C "hotel-manage-management-deploy" &>/dev/null
msg_ok "SSH keypair generated → /root/.ssh/hotel-manage_deploy"
else
msg_ok "Using existing SSH keypair at /root/.ssh/hnf_management"
msg_ok "Using existing SSH keypair at /root/.ssh/hotel-manage_deploy"
fi
MGMT_PUBKEY=$(cat /root/.ssh/hnf_management.pub)
echo "${MGMT_PUBKEY}" >> /root/hnf-credentials.txt
MGMT_PUBKEY=$(cat /root/.ssh/hotel-manage_deploy.pub)
echo "${MGMT_PUBKEY}" >> /root/hotel-manage-credentials.txt
}
# ── LXC lifecycle helpers ─────────────────────────────────────────────────────
@ -244,16 +244,30 @@ lxc_running() {
pct status "$1" 2>/dev/null | grep -q "running"
}
# Group the stack in a Proxmox resource pool + tag for tidy UI organisation.
POOL="hotel-manage"
POOL_OPT=""
ensure_pool() {
if ! pvesh get "/pools/${POOL}" &>/dev/null; then
msg_info "Creating Proxmox resource pool '${POOL}'"
pvesh create /pools --poolid "${POOL}" --comment "Hotel Manage stack" &>/dev/null || true
pvesh get "/pools/${POOL}" &>/dev/null && msg_ok "Pool '${POOL}' ready" \
|| msg_warn "Could not create pool '${POOL}' — continuing without it"
fi
# Only pass --pool if it actually exists (else pct create would fail)
pvesh get "/pools/${POOL}" &>/dev/null && POOL_OPT="--pool ${POOL}"
}
create_lxc() {
local id=$1 ip=$2 name=$3 mem=${4:-512} cores=${5:-1}
if lxc_exists "$id"; then
msg_warn "LXC $id (hnf-${name}) already exists — skipping creation"
msg_warn "LXC $id (hotel-manage-${name}) already exists — skipping creation"
lxc_running "$id" || pct start "$id"
return
fi
local tmpl; tmpl=$(get_template)
pct create "$id" "$tmpl" \
--hostname "hnf-${name}" \
--hostname "hotel-manage-${name}" \
--memory "$mem" \
--cores "$cores" \
--rootfs "${STORAGE}:8" \
@ -261,6 +275,8 @@ create_lxc() {
--features nesting=1 \
--unprivileged 0 \
--onboot 1 \
--tags "${POOL}" \
${POOL_OPT} \
--start 1 &>/dev/null
sleep 5 # let systemd start
}
@ -268,13 +284,13 @@ create_lxc() {
create_npm_lxc() {
local id=103
if lxc_exists "$id"; then
msg_warn "LXC $id (hnf-npm) already exists — skipping creation"
msg_warn "LXC $id (hotel-manage-npm) already exists — skipping creation"
lxc_running "$id" || pct start "$id"
return
fi
local tmpl; tmpl=$(get_template)
pct create "$id" "$tmpl" \
--hostname "hnf-npm" \
--hostname "hotel-manage-npm" \
--memory 512 \
--cores 1 \
--rootfs "${STORAGE}:8" \
@ -283,6 +299,8 @@ create_npm_lxc() {
--features nesting=1 \
--unprivileged 0 \
--onboot 1 \
--tags "${POOL}" \
${POOL_OPT} \
--start 1 &>/dev/null
sleep 5
}
@ -320,7 +338,7 @@ install_mgmt_key() {
push_file() {
# Write content to a temp file, push into LXC, remove temp
local id=$1 dest=$2; shift 2
local tmp; tmp=$(mktemp /tmp/hnf-push-XXXX)
local tmp; tmp=$(mktemp /tmp/hotel-manage-push-XXXX)
cat > "$tmp" # reads stdin
pct push "$id" "$tmp" "$dest" 2>/dev/null
rm -f "$tmp"
@ -329,14 +347,14 @@ push_file() {
push_dir() {
# tar local dir → push tarball → extract in LXC at parent of dest
local id=$1 src=$2 dest=$3
local tmp; tmp=$(mktemp /tmp/hnf-dir-XXXX.tar.gz)
local tmp; tmp=$(mktemp /tmp/hotel-manage-dir-XXXX.tar.gz)
tar czf "$tmp" -C "$(dirname "$src")" "$(basename "$src")" 2>/dev/null
pct push "$id" "$tmp" /tmp/hnf-deploy.tar.gz 2>/dev/null
pct push "$id" "$tmp" /tmp/hotel-manage-deploy.tar.gz 2>/dev/null
pct exec "$id" -- bash -c "
mkdir -p '$(dirname "$dest")'
tar xzf /tmp/hnf-deploy.tar.gz -C '$(dirname "$dest")'
tar xzf /tmp/hotel-manage-deploy.tar.gz -C '$(dirname "$dest")'
mv '$(dirname "$dest")/$(basename "$src")' '${dest}' 2>/dev/null || true
rm -f /tmp/hnf-deploy.tar.gz
rm -f /tmp/hotel-manage-deploy.tar.gz
" &>/dev/null
rm -f "$tmp"
}
@ -380,7 +398,7 @@ wait_healthy() {
wait_pg() {
local max=30 i=0
while ! pct exec 100 -- bash -c \
"docker exec hnf-postgres pg_isready -U postgres" &>/dev/null; do
"docker exec hotel-manage-postgres pg_isready -U postgres" &>/dev/null; do
sleep 3; ((i++))
[[ $i -ge $max ]] && { msg_warn "Postgres not ready after 90s"; return 1; }
done
@ -407,7 +425,7 @@ deploy_postgres() {
push_file 100 /opt/postgres/docker-compose.yml <<'EOF'
services:
postgres:
container_name: hnf-postgres
container_name: hotel-manage-postgres
image: postgres:16-alpine
environment:
- POSTGRES_USER=postgres
@ -548,7 +566,7 @@ deploy_npm() {
push_file 103 /opt/npm/docker-compose.yml <<'EOF'
services:
npm:
container_name: hnf-npm
container_name: hotel-manage-npm
image: jc21/nginx-proxy-manager:latest
ports:
- "80:80"
@ -591,8 +609,8 @@ deploy_management() {
# Copy the management SSH private key into management container
pct exec 105 -- mkdir -p /root/.ssh
pct push 105 /root/.ssh/hnf_management /root/.ssh/hnf_management &>/dev/null
pct exec 105 -- chmod 600 /root/.ssh/hnf_management
pct push 105 /root/.ssh/hotel-manage_deploy /root/.ssh/hotel-manage_deploy &>/dev/null
pct exec 105 -- chmod 600 /root/.ssh/hotel-manage_deploy
msg_info "Deploying management stack"
deploy_service 105 "management" "${REPO_ROOT}/management" /opt/management
@ -742,7 +760,7 @@ print_summary() {
printf "\n${GN}"
cat <<SUMMARY
╔══════════════════════════════════════════════════════════════╗
║ HNF Manage — Stack Deployed ║
║ Hotel Manage — Stack Deployed ║
╚══════════════════════════════════════════════════════════════╝
SUMMARY
printf "${CL}"
@ -754,18 +772,18 @@ SUMMARY
── Services ──────────────────────────────────────────────────
LXC Hostname IP Port Status
100 hnf-postgres 10.10.10.100 5432 (internal only)
101 hnf-auth 10.10.10.101 3001 /api/auth/*
102 hnf-portal 10.10.10.102 3000 /
103 hnf-npm 10.10.10.3 80/443 entry point
100 hotel-manage-postgres 10.10.10.100 5432 (internal only)
101 hotel-manage-auth 10.10.10.101 3001 /api/auth/*
102 hotel-manage-portal 10.10.10.102 3000 /
103 hotel-manage-npm 10.10.10.3 80/443 entry point
(LAN) ${NPM_LAN_IP} 81 NPM admin
105 hnf-management 10.10.10.105 3002 Uptime Kuma
105 hotel-manage-management 10.10.10.105 3002 Uptime Kuma
9000 Forgejo webhooks
112 hnf-noticeboard 10.10.10.112 3080 /notices/
112 hotel-manage-noticeboard 10.10.10.112 3080 /notices/
── Credentials ───────────────────────────────────────────────
Admin login: ${ADMIN_EMAIL}
Credentials: /root/hnf-credentials.txt (chmod 600)
Credentials: /root/hotel-manage-credentials.txt (chmod 600)
── Next steps ────────────────────────────────────────────────
1. Point DNS: ${DOMAIN}${NPM_LAN_IP}
@ -800,6 +818,7 @@ check_vmbr1
collect_config
gen_secrets
gen_mgmt_ssh_key
ensure_pool
deploy_postgres
deploy_auth