Files
myoffice_public/proxmox/myoffice.sh
T

566 lines
19 KiB
Bash

#!/usr/bin/env bash
# MyOffice Proxmox LXC installer (community-scripts style).
#
# One-liner (optional arg = IP for CT /etc/hosts → mygit hostname, when hairpin DNS fails):
# bash -c "$(curl -fsSL https://mygit.ase.com.ua/alexandr/myoffice_public/raw/branch/master/proxmox/myoffice.sh)" 192.168.100.10
# Or: curl -fsSL …/myoffice.sh | bash -s -- 192.168.100.10
# Or: export GITEA_HOSTS_IP=192.168.100.10 then run without arg
#
# Creates one LXC with PostgreSQL + ASP.NET runtime + app from Gitea Release.
# No Docker, no nginx, no git/SDK/Node in the CT (use your existing proxy LXC in front).
set -euo pipefail
GITEA_URL="${GITEA_URL:-https://mygit.ase.com.ua}"
GITEA_OWNER="${GITEA_OWNER:-alexandr}"
GITEA_REPO="${GITEA_REPO:-myoffice_public}"
GITEA_BRANCH="${GITEA_BRANCH:-master}"
RELEASE_TAG="${RELEASE_TAG:-latest}"
RELEASE_ASSET_URL="${RELEASE_ASSET_URL:-}"
GITEA_TOKEN="${GITEA_TOKEN:-}"
GITEA_HOSTS_NAME="${GITEA_HOSTS_NAME:-mygit.ase.com.ua}"
# Optional CT hosts override: env, or positional IP.
# bash -c "…" IP → IP is $0 ; bash -s -- IP → IP is $1
is_ipv4() { [[ "${1:-}" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; }
if [[ -z "${GITEA_HOSTS_IP:-}" ]]; then
if is_ipv4 "${1:-}"; then
GITEA_HOSTS_IP="$1"
elif is_ipv4 "${0:-}"; then
GITEA_HOSTS_IP="$0"
else
GITEA_HOSTS_IP=""
fi
fi
if [[ -z "${REPO_RAW_BASE:-}" ]]; then
REPO_RAW_BASE="${GITEA_URL%/}/${GITEA_OWNER}/${GITEA_REPO}/raw/branch/${GITEA_BRANCH}"
fi
# Derive GITEA_* from REPO_RAW_BASE when only raw base is set:
# https://host/owner/repo/raw/branch/master
if [[ "$REPO_RAW_BASE" =~ ^(https?://[^/]+)/([^/]+)/([^/]+)/raw/branch/([^/]+) ]]; then
GITEA_URL="${BASH_REMATCH[1]}"
GITEA_OWNER="${BASH_REMATCH[2]}"
GITEA_REPO="${BASH_REMATCH[3]}"
GITEA_BRANCH="${BASH_REMATCH[4]}"
elif [[ "$REPO_RAW_BASE" =~ ^(https?://[^/]+)/([^/]+)/([^/]+)/raw/ ]]; then
GITEA_URL="${BASH_REMATCH[1]}"
GITEA_OWNER="${BASH_REMATCH[2]}"
GITEA_REPO="${BASH_REMATCH[3]}"
fi
APP="MyOffice"
APP_DIR="/opt/myoffice"
YW=$'\033[33m'
BL=$'\033[36m'
RD=$'\033[01;31m'
BGN=$'\033[4;92m'
GN=$'\033[1;92m'
DGN=$'\033[32m'
CL=$'\033[m'
BOLD=$'\033[1m'
BFR=$'\r\033[K'
TAB=$' '
CM="${TAB}✔️${TAB}${CL}"
CROSS="${TAB}✖️${TAB}${CL}"
INFO="${TAB}💡${TAB}${CL}"
OS="${TAB}🖥️${TAB}${CL}"
CONTAINERTYPE="${TAB}📦${TAB}${CL}"
DISKSIZE="${TAB}💾${TAB}${CL}"
CPUCORE="${TAB}🧠${TAB}${CL}"
RAMSIZE="${TAB}🛠️${TAB}${CL}"
CONTAINERID="${TAB}🆔${TAB}${CL}"
HOSTNAME="${TAB}🏠${TAB}${CL}"
BRIDGE="${TAB}🌉${TAB}${CL}"
GATEWAY="${TAB}🌐${TAB}${CL}"
DEFAULT="${TAB}⚙️${TAB}${CL}"
CREATING="${TAB}🚀${TAB}${CL}"
ADVANCED="${TAB}🧩${TAB}${CL}"
header_info() {
clear
cat <<"EOF"
__ ___ ____ ____________
/ |/ /_ __/ __ \/ __/ __/ _/______
/ /|_/ / / / / / / / /_/ /_ / // ___/ _ \
/ / / / /_/ / /_/ / __/ __// // /__/ __/
/_/ /_/\__, /\____/_/ /_/ /___/\___/\___/
/____/ Proxmox LXC (Gitea release)
EOF
}
msg_info() { echo -ne "${TAB}${YW}${1}${CL}"; }
msg_ok() { echo -e "${BFR}${CM}${GN}${1}${CL}"; }
msg_error() { echo -e "${BFR}${CROSS}${RD}${1}${CL}"; }
error_handler() {
local exit_code=$?
local line_number=$1
local command=$2
echo -e "\n${RD}[ERROR]${CL} line ${RD}${line_number}${CL}: exit ${RD}${exit_code}${CL}: ${YW}${command}${CL}\n"
if [[ -n "${CTID:-}" ]] && pct status "$CTID" &>/dev/null; then
echo -e "${INFO}CT ${CTID} exists; destroy with: pct stop ${CTID}; pct destroy ${CTID}"
fi
exit "$exit_code"
}
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
exit_script() {
clear
echo -e "\n${CROSS}${RD}User exited script${CL}\n"
exit 0
}
check_root() {
if [[ "$(id -u)" -ne 0 ]]; then
msg_error "Please run this script as root on the Proxmox host."
exit 1
fi
}
pve_check() {
if ! command -v pveversion >/dev/null 2>&1; then
msg_error "This script must run on a Proxmox VE host (pveversion not found)."
exit 1
fi
if ! command -v whiptail >/dev/null 2>&1; then
msg_error "whiptail is required (apt install whiptail)."
exit 1
fi
}
arch_check() {
if [[ "$(dpkg --print-architecture)" != "amd64" ]]; then
msg_error "Only amd64 is supported."
exit 1
fi
}
get_valid_nextid() {
local try_id
try_id=$(pvesh get /cluster/nextid)
while true; do
if [[ -f "/etc/pve/qemu-server/${try_id}.conf" ]] || [[ -f "/etc/pve/lxc/${try_id}.conf" ]]; then
try_id=$((try_id + 1))
continue
fi
break
done
echo "$try_id"
}
select_storage() {
local STORAGE_MENU=()
local MSG_MAX_LENGTH=0
local line TAG TYPE FREE ITEM OFFSET VALID
while read -r line; do
TAG=$(echo "$line" | awk '{print $1}')
TYPE=$(echo "$line" | awk '{printf "%-10s", $2}')
FREE=$(echo "$line" | numfmt --field 4-6 --from-unit=K --to=iec --format %.2f 2>/dev/null | awk '{printf("%9sB", $6)}' || echo "?")
ITEM=" Type: $TYPE Free: $FREE "
OFFSET=2
if [[ $((${#ITEM} + OFFSET)) -gt ${MSG_MAX_LENGTH:-0} ]]; then
MSG_MAX_LENGTH=$((${#ITEM} + OFFSET))
fi
STORAGE_MENU+=("$TAG" "$ITEM" "OFF")
done < <(pvesm status -content rootdir | awk 'NR>1')
VALID=$(pvesm status -content rootdir | awk 'NR>1')
if [[ -z "$VALID" ]]; then
msg_error "Unable to detect a valid storage location (rootdir)."
exit 1
elif [[ $((${#STORAGE_MENU[@]} / 3)) -eq 1 ]]; then
STORAGE=${STORAGE_MENU[0]}
else
while [[ -z "${STORAGE:+x}" ]]; do
STORAGE=$(whiptail --backtitle "MyOffice Proxmox" --title "Storage Pools" --radiolist \
"Which storage pool for ${HN}?\n(Spacebar to select)\n" \
16 $((MSG_MAX_LENGTH + 23)) 6 \
"${STORAGE_MENU[@]}" 3>&1 1>&2 2>&3) || exit_script
done
fi
msg_ok "Using ${CL}${BL}${STORAGE}${CL}${GN} for storage."
}
ask_ip_cpu_ram_disk() {
# Always prompt: IP, CPU (default 2), RAM MiB (default 2048), disk GiB (default 10).
while true; do
if CORE_COUNT=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "CPU cores" 8 58 "${CORE_COUNT:-2}" --title "CPU" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
[[ -z "$CORE_COUNT" ]] && CORE_COUNT="2"
if [[ "$CORE_COUNT" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${CPUCORE}${BOLD}${DGN}CPU Cores: ${BGN}${CORE_COUNT}${CL}"
break
fi
whiptail --backtitle "MyOffice Proxmox" --title "INVALID" --msgbox "CPU cores must be a positive integer." 8 58
else
exit_script
fi
done
while true; do
if RAM_SIZE=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "RAM in MiB" 8 58 "${RAM_SIZE:-2048}" --title "MEMORY" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
[[ -z "$RAM_SIZE" ]] && RAM_SIZE="2048"
if [[ "$RAM_SIZE" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${RAMSIZE}${BOLD}${DGN}RAM: ${BGN}${RAM_SIZE} MiB${CL}"
break
fi
whiptail --backtitle "MyOffice Proxmox" --title "INVALID" --msgbox "RAM must be a positive integer (MiB)." 8 58
else
exit_script
fi
done
while true; do
if DISK_SIZE=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Disk size in GiB" 8 58 "${DISK_SIZE:-10}" --title "DISK" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
DISK_SIZE=$(echo "${DISK_SIZE:-10}" | tr -d ' Gg')
[[ -z "$DISK_SIZE" ]] && DISK_SIZE="10"
if [[ "$DISK_SIZE" =~ ^[1-9][0-9]*$ ]]; then
echo -e "${DISKSIZE}${BOLD}${DGN}Disk: ${BGN}${DISK_SIZE}G${CL}"
break
fi
whiptail --backtitle "MyOffice Proxmox" --title "INVALID" --msgbox "Disk must be a positive integer (GiB)." 8 58
else
exit_script
fi
done
if whiptail --backtitle "MyOffice Proxmox" --title "NETWORK" --yesno "Use DHCP for IP?\n\nYes = DHCP\nNo = static IP" --yes-button DHCP --no-button Static 12 58; then
NET="dhcp"
GATEWAY_IP=""
echo -e "${GATEWAY}${BOLD}${DGN}IP: ${BGN}DHCP${CL}"
else
while true; do
if NET=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Static IP with CIDR\n(e.g. 192.168.1.120/24)" 10 58 "${NET:-}" --title "IP ADDRESS" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [[ -n "$NET" && "$NET" == */* ]]; then
break
fi
whiptail --backtitle "MyOffice Proxmox" --title "INVALID" --msgbox "Enter IP/CIDR, e.g. 192.168.1.120/24" 8 58
else
exit_script
fi
done
while true; do
if GATEWAY_IP=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Gateway\n(e.g. 192.168.1.1)" 10 58 "${GATEWAY_IP:-}" --title "GATEWAY" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
if [[ -n "$GATEWAY_IP" ]]; then
break
fi
whiptail --backtitle "MyOffice Proxmox" --title "INVALID" --msgbox "Gateway is required for static IP." 8 58
else
exit_script
fi
done
echo -e "${GATEWAY}${BOLD}${DGN}IP: ${BGN}${NET} gw ${GATEWAY_IP}${CL}"
fi
}
default_settings() {
CTID=$(get_valid_nextid)
HN="myoffice"
CORE_COUNT="2"
RAM_SIZE="2048"
DISK_SIZE="10"
BRG="vmbr0"
NET="dhcp"
GATEWAY_IP=""
API_PORT="9100"
PUBLIC_URL="" # filled after CT IP known
START_CT="yes"
METHOD="default"
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CTID}${CL}"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
echo -e "${OS}${BOLD}${DGN}OS: ${BGN}Debian 12${CL}"
ask_ip_cpu_ram_disk
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
echo -e "${DEFAULT}${BOLD}${DGN}API listen: ${BGN}:${API_PORT}${CL} (SPA from release wwwroot)"
echo -e "${CONTAINERTYPE}${BOLD}${DGN}Stack: ${BGN}PostgreSQL + ASP.NET + Gitea release${CL}"
echo -e "${CREATING}${BOLD}${DGN}Creating MyOffice LXC${CL}"
}
advanced_settings() {
METHOD="advanced"
[[ -z "${CTID:-}" ]] && CTID=$(get_valid_nextid)
CORE_COUNT="${CORE_COUNT:-2}"
RAM_SIZE="${RAM_SIZE:-2048}"
DISK_SIZE="${DISK_SIZE:-10}"
NET="${NET:-dhcp}"
GATEWAY_IP="${GATEWAY_IP:-}"
while true; do
if CTID=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Set Container ID" 8 58 "$CTID" --title "CONTAINER ID" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
[[ -z "$CTID" ]] && CTID=$(get_valid_nextid)
if pct status "$CTID" &>/dev/null || qm status "$CTID" &>/dev/null; then
echo -e "${CROSS}${RD}ID $CTID is already in use${CL}"
sleep 2
continue
fi
echo -e "${CONTAINERID}${BOLD}${DGN}Container ID: ${BGN}${CTID}${CL}"
break
else
exit_script
fi
done
if HN_IN=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Set Hostname" 8 58 myoffice --title "HOSTNAME" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
HN=$(echo "${HN_IN:-myoffice}" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9-' '-' | sed 's/^-//;s/-$//' || true)
[[ -z "$HN" ]] && HN="myoffice"
echo -e "${HOSTNAME}${BOLD}${DGN}Hostname: ${BGN}${HN}${CL}"
else
exit_script
fi
ask_ip_cpu_ram_disk
if BRG=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Bridge" 8 58 vmbr0 --title "BRIDGE" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
[[ -z "$BRG" ]] && BRG="vmbr0"
echo -e "${BRIDGE}${BOLD}${DGN}Bridge: ${BGN}${BRG}${CL}"
else
exit_script
fi
if API_PORT=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Kestrel listen port" 8 58 9100 --title "API PORT" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
[[ -z "$API_PORT" ]] && API_PORT="9100"
else
exit_script
fi
echo -e "${DEFAULT}${BOLD}${DGN}API listen: ${BGN}:${API_PORT}${CL}"
if PUBLIC_URL=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Browser public URL (empty = http://CT_IP:PORT). Use your nginx proxy URL if any." 10 70 "" --title "PUBLIC URL" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
PUBLIC_URL=$(echo "$PUBLIC_URL" | sed 's:/*$::')
else
exit_script
fi
if RELEASE_TAG=$(whiptail --backtitle "MyOffice Proxmox" --inputbox "Gitea release tag (latest or v1.2.3)" 8 58 "${RELEASE_TAG}" --title "RELEASE TAG" --cancel-button Exit-Script 3>&1 1>&2 2>&3); then
[[ -z "$RELEASE_TAG" ]] && RELEASE_TAG="latest"
else
exit_script
fi
echo -e "${DEFAULT}${BOLD}${DGN}Release: ${BGN}${RELEASE_TAG}${CL}"
if whiptail --backtitle "MyOffice Proxmox" --title "START CONTAINER" --yesno "Start CT when created?" 10 58; then
START_CT="yes"
else
START_CT="no"
fi
if whiptail --backtitle "MyOffice Proxmox" --title "ADVANCED SETTINGS" --yesno "Ready to create MyOffice LXC?" --no-button Do-Over 10 58; then
echo -e "${CREATING}${BOLD}${DGN}Creating MyOffice LXC with advanced settings${CL}"
else
header_info
echo -e "${ADVANCED}${BOLD}${RD}Using Advanced Settings${CL}"
advanced_settings
fi
}
start_script() {
if whiptail --backtitle "MyOffice Proxmox" --title "SETTINGS" --yesno "Use Default Settings?" --no-button Advanced 10 58; then
header_info
echo -e "${BL}Using Default Settings${CL}"
default_settings
else
header_info
echo -e "${RD}Using Advanced Settings${CL}"
advanced_settings
fi
}
ensure_template() {
local template="debian-12-standard"
local store="local"
msg_info "Ensuring Debian 12 LXC template..."
if ! pveam list "$store" 2>/dev/null | grep -q "$template"; then
pveam update >/dev/null
local remote
remote=$(pveam available -section system | awk '/debian-12-standard/ {print $2; exit}')
if [[ -z "$remote" ]]; then
msg_error "Could not find debian-12-standard template in pveam available."
exit 1
fi
pveam download "$store" "$remote"
fi
TEMPLATE_REF=$(pveam list "$store" | awk '/debian-12-standard/ {print $1; exit}')
if [[ -z "${TEMPLATE_REF:-}" ]]; then
msg_error "Debian 12 template not found after download."
exit 1
fi
msg_ok "Template ${CL}${BL}${TEMPLATE_REF}${CL}"
}
create_container() {
local net_cfg
if [[ "$NET" == "dhcp" ]]; then
net_cfg="name=eth0,bridge=${BRG},ip=dhcp"
else
net_cfg="name=eth0,bridge=${BRG},ip=${NET},gw=${GATEWAY_IP}"
fi
msg_info "Creating LXC ${CTID} (${HN})..."
pct create "$CTID" "$TEMPLATE_REF" \
--hostname "$HN" \
--cores "$CORE_COUNT" \
--memory "$RAM_SIZE" \
--swap 512 \
--rootfs "${STORAGE}:${DISK_SIZE}" \
--net0 "$net_cfg" \
--unprivileged 1 \
--ostype debian \
--onboot 1 \
--timezone host \
--tags "myoffice" \
--description "MyOffice: PostgreSQL + ASP.NET Core from Gitea release. Proxy via external nginx LXC."
msg_ok "Created CT ${CL}${BL}${CTID}${CL}"
if [[ "$START_CT" == "yes" ]]; then
msg_info "Starting CT ${CTID}..."
pct start "$CTID"
msg_ok "Started CT ${CTID}"
else
msg_error "CT created but not started (Start=no). Start with: pct start ${CTID}"
exit 0
fi
}
wait_for_network() {
msg_info "Waiting for CT network..."
local i ip
for i in $(seq 1 60); do
ip=$(pct exec "$CTID" -- bash -c "ip -4 -o addr show eth0 2>/dev/null | awk '{print \$4}' | cut -d/ -f1 | head -1" 2>/dev/null || true)
if [[ -n "$ip" ]]; then
CT_IP="$ip"
msg_ok "CT IP ${CL}${BL}${CT_IP}${CL}"
return 0
fi
sleep 2
done
msg_error "Timed out waiting for CT IP."
exit 1
}
# Optional CT /etc/hosts: GITEA_HOSTS_IP → GITEA_HOSTS_NAME (skip if empty).
ensure_ct_gitea_hosts() {
if [[ -z "${GITEA_HOSTS_IP}" ]]; then
return 0
fi
msg_info "CT /etc/hosts: ${GITEA_HOSTS_IP} ${GITEA_HOSTS_NAME}"
pct exec "$CTID" -- bash -c "
sed -i '/[[:space:]]${GITEA_HOSTS_NAME}\$/d' /etc/hosts
echo '${GITEA_HOSTS_IP} ${GITEA_HOSTS_NAME}' >> /etc/hosts
"
msg_ok "CT hosts updated"
}
resolve_script_dir() {
if [[ -n "${BASH_SOURCE[0]:-}" && -f "${BASH_SOURCE[0]}" ]]; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
else
SCRIPT_DIR=""
fi
}
push_install_assets() {
local dest_dir="/tmp/myoffice-proxmox"
pct exec "$CTID" -- mkdir -p "$dest_dir"
if [[ -n "${SCRIPT_DIR}" && -f "${SCRIPT_DIR}/install-in-ct.sh" ]]; then
for f in install-in-ct.sh fetch-release.sh myoffice-api.service update.sh; do
pct push "$CTID" "${SCRIPT_DIR}/${f}" "${dest_dir}/${f}"
done
else
msg_info "Downloading install assets from REPO_RAW_BASE..."
for f in install-in-ct.sh fetch-release.sh myoffice-api.service update.sh; do
curl -fsSL "${REPO_RAW_BASE}/proxmox/${f}" -o "/tmp/${f}"
pct push "$CTID" "/tmp/${f}" "${dest_dir}/${f}"
done
msg_ok "Downloaded install assets"
fi
pct exec "$CTID" -- chmod +x "${dest_dir}/install-in-ct.sh" "${dest_dir}/fetch-release.sh" "${dest_dir}/update.sh"
}
# CT often cannot reach Gitea (isolated LAN). Download release on the Proxmox host, then push in.
download_release_on_host() {
local host_tar="/tmp/myoffice-publish.tar.gz"
local fetch_src
msg_info "Downloading release on Proxmox host..."
if [[ -n "${SCRIPT_DIR}" && -f "${SCRIPT_DIR}/fetch-release.sh" ]]; then
fetch_src="${SCRIPT_DIR}/fetch-release.sh"
else
curl -fsSL "${REPO_RAW_BASE}/proxmox/fetch-release.sh" -o /tmp/fetch-release.sh
fetch_src=/tmp/fetch-release.sh
fi
# shellcheck disable=SC1090
GITEA_URL="$GITEA_URL" \
GITEA_OWNER="$GITEA_OWNER" \
GITEA_REPO="$GITEA_REPO" \
RELEASE_TAG="$RELEASE_TAG" \
RELEASE_ASSET_URL="$RELEASE_ASSET_URL" \
GITEA_TOKEN="$GITEA_TOKEN" \
bash -c 'source "'"$fetch_src"'" && download_asset_to "'"$host_tar"'"'
pct push "$CTID" "$host_tar" "/tmp/myoffice-publish.tar.gz"
msg_ok "Release pushed into CT"
}
run_ct_install() {
if [[ -z "${PUBLIC_URL}" ]]; then
PUBLIC_URL="http://${CT_IP}:${API_PORT}"
fi
if [[ -z "${GITEA_URL}" || -z "${GITEA_OWNER}" ]] && [[ -z "${RELEASE_ASSET_URL}" ]]; then
msg_error "Set GITEA_URL + GITEA_OWNER (and GITEA_REPO), or RELEASE_ASSET_URL, before install."
exit 1
fi
download_release_on_host
msg_info "Installing PostgreSQL + ASP.NET runtime + Gitea release..."
pct exec "$CTID" -- env \
REPO_RAW_BASE="$REPO_RAW_BASE" \
APP_DIR="$APP_DIR" \
PUBLIC_URL="$PUBLIC_URL" \
API_PORT="$API_PORT" \
ASSETS_DIR="/tmp/myoffice-proxmox" \
GITEA_URL="$GITEA_URL" \
GITEA_OWNER="$GITEA_OWNER" \
GITEA_REPO="$GITEA_REPO" \
RELEASE_TAG="$RELEASE_TAG" \
RELEASE_ASSET_URL="$RELEASE_ASSET_URL" \
GITEA_TOKEN="$GITEA_TOKEN" \
LOCAL_RELEASE_TAR="/tmp/myoffice-publish.tar.gz" \
GITEA_HOSTS_IP="$GITEA_HOSTS_IP" \
GITEA_HOSTS_NAME="$GITEA_HOSTS_NAME" \
bash /tmp/myoffice-proxmox/install-in-ct.sh
msg_ok "Stack installed"
}
# --- main ---
header_info
echo -e "\n Loading..."
check_root
arch_check
pve_check
if ! whiptail --backtitle "MyOffice Proxmox" --title "MyOffice LXC" --yesno \
"This will create a new LXC with:\n\n • PostgreSQL\n • ASP.NET Core runtime\n • App from Gitea Release\n\nNo Docker, no nginx (point your proxy LXC at :9100).\n\nProceed?" 16 58; then
exit_script
fi
start_script
select_storage
ensure_template
resolve_script_dir
create_container
wait_for_network
ensure_ct_gitea_hosts
push_install_assets
run_ct_install
echo -e "\n${GN}${BOLD}Completed successfully!${CL}\n"
echo -e "${INFO}${YW}Stack in CT ${CTID}:${CL} PostgreSQL + ASP.NET + release ${RELEASE_TAG}"
echo -e "${GATEWAY}${BGN}Public URL ${PUBLIC_URL}${CL}"
echo -e "${GATEWAY}${BGN}Upstream http://${CT_IP}:${API_PORT}${CL} (for your nginx proxy)"
echo -e "${INFO}Demo login: user_UAH@user_UAH.userUAH / user_UAH"
echo -e "${INFO}Update: pct enter ${CTID} then ${APP_DIR}/proxmox/update.sh"
echo