diff --git a/container-creation/configureLDAP.sh b/container-creation/configureLDAP.sh index 950601e2..a9b750fd 100755 --- a/container-creation/configureLDAP.sh +++ b/container-creation/configureLDAP.sh @@ -1,34 +1,70 @@ #!/bin/bash # Script to connect a container to the LDAP server via SSSD -# Last Modified by Maxwell Klema on July 29th, 2025 +# Last Modified by Maxwell Klema, updated October 3rd 2025 by Carter Myers # ----------------------------------------------------- -# Curl Pown.sh script to install SSSD and configure LDAP -pct enter $CONTAINER_ID <&2 + exit 1 + ;; +esac + +# === Wrappers for pct commands === +run_pct_exec() { + local ctid="$1" + shift + if [ -n "$TARGET_HYPERVISOR" ]; then + # Safe quoting for remote execution + local remote_cmd + printf -v remote_cmd '%q ' "$@" + ssh root@$TARGET_HYPERVISOR "pct exec $ctid -- $remote_cmd" + else + pct exec "$ctid" -- "$@" + fi +} + +run_pct() { + if [ -n "$TARGET_HYPERVISOR" ]; then + ssh root@$TARGET_HYPERVISOR "pct $*" + else + pct "$@" + fi +} + +# === LDAP / SSSD Configuration Steps === + +# Curl Pown.sh script to install SSSD and configure LDAP +run_pct_exec $CONTAINER_ID bash -c " cd /root && \ curl -O https://raw.githubusercontent.com/anishapant21/pown.sh/main/pown.sh > /dev/null 2>&1 && \ chmod +x pown.sh -EOF +" # Copy .env file to container ENV_FILE="/var/lib/vz/snippets/.env" -pct enter $CONTAINER_ID < /root/.env -$(cat "$ENV_FILE") -EOT -EOF +ENV_CONTENT=$(<"$ENV_FILE" sed 's/["\$`]/\\&/g') # Escape special characters +run_pct_exec $CONTAINER_ID bash -c "printf '%s\n' \"$ENV_CONTENT\" > /root/.env" # Run the pown.sh script to configure LDAP -pct exec $CONTAINER_ID -- bash -c "cd /root && ./pown.sh" > /dev/null 2>&1 +run_pct_exec $CONTAINER_ID bash -c "cd /root && ./pown.sh" > /dev/null 2>&1 -# remove ldap_tls_cert from /etc/sssd/sssd.conf -pct exec $CONTAINER_ID -- sed -i '/ldap_tls_cacert/d' /etc/sssd/sssd.conf > /dev/null 2>&1 +# Remove ldap_tls_cert from /etc/sssd/sssd.conf +run_pct_exec $CONTAINER_ID sed -i '/ldap_tls_cacert/d' /etc/sssd/sssd.conf > /dev/null 2>&1 # Add TLS_REQCERT to never in ROCKY - if [ "${LINUX_DISTRO^^}" == "ROCKY" ]; then - pct exec $CONTAINER_ID -- bash -c "echo 'TLS_REQCERT never' >> /etc/openldap/ldap.conf" > /dev/null 2>&1 - pct exec $CONTAINER_ID -- bash -c "authselect select sssd --force" > /dev/null 2>&1 - pct exec $CONTAINER_ID -- bash -c "systemctl restart sssd" > /dev/null 2>&1 -fi + run_pct_exec $CONTAINER_ID bash -c "echo 'TLS_REQCERT never' >> /etc/openldap/ldap.conf" > /dev/null 2>&1 + run_pct_exec $CONTAINER_ID bash -c "authselect select sssd --force" > /dev/null 2>&1 + run_pct_exec $CONTAINER_ID bash -c "systemctl restart sssd" > /dev/null 2>&1 +fi \ No newline at end of file diff --git a/container-creation/create-container-new.sh b/container-creation/create-container-new.sh index 62ec9e63..7890ede7 100644 --- a/container-creation/create-container-new.sh +++ b/container-creation/create-container-new.sh @@ -1,6 +1,6 @@ #!/bin/bash # Script to create the pct container, run register container, and migrate container accordingly. -# Last Modified by August 27th, 2025 by Carter Myers +# Last Modified by October 3rd, 2025 by Carter Myers # ----------------------------------------------------- BOLD='\033[1m' @@ -68,13 +68,39 @@ VERSIONS_DICT=$(echo "${21}" | base64 -d) AI_CONTAINER="${22}" # new argument from HTML form echo "PROJECT ROOT: \"$PROJECT_ROOT\"" +echo "AI_CONTAINER: \"$AI_CONTAINER\"" + +# === Determine target PVE host based on AI_CONTAINER === +# PHOENIX -> 10.15.0.6 (existing AI host) +# FORTWAYNE -> 10.250.0.2 (new WireGuard-connected host) +# N -> local execution (no SSH proxy) +case "${AI_CONTAINER^^}" in + PHOENIX) + TARGET_PVE_HOST="10.15.0.6" + ;; + FORTWAYNE) + TARGET_PVE_HOST="10.250.0.2" + ;; + N|"" ) + TARGET_PVE_HOST="" + ;; + *) + echo "Invalid AI_CONTAINER value: $AI_CONTAINER" + exit 1 + ;; +esac + +# Helper: returns true if we're using a remote PVE host (PHOENIX or FORTWAYNE) +is_remote_pve() { + [[ -n "$TARGET_PVE_HOST" ]] +} -# === Wrapper for pct exec (and optionally pct commands for AI) === +# === Wrapper for pct exec (and optionally pct commands for remote PVE) === run_pct_exec() { local ctid="$1" shift - if [ "${AI_CONTAINER^^}" == "Y" ]; then - ssh root@10.15.0.6 "pct exec $ctid -- $*" + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pct exec $ctid -- $*" else pct exec "$ctid" -- "$@" fi @@ -82,25 +108,25 @@ run_pct_exec() { run_pct() { # $@ = full pct command, e.g., clone, set, start, etc. - if [ "${AI_CONTAINER^^}" == "Y" ]; then - ssh root@10.15.0.6 "pct $*" + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pct $*" else pct "$@" fi } run_pveum() { - # Wrapper for pveum commands in AI case - if [ "${AI_CONTAINER^^}" == "Y" ]; then - ssh root@10.15.0.6 "pveum $*" + # Wrapper for pveum commands in remote case + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pveum $*" else pveum "$@" fi } run_pvesh() { - if [ "${AI_CONTAINER^^}" == "Y" ]; then - ssh root@10.15.0.6 "pvesh $*" + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pvesh $*" else pvesh "$@" fi @@ -110,19 +136,21 @@ run_pct_push() { local ctid="$1" local src="$2" local dest="$3" - if [ "${AI_CONTAINER^^}" == "Y" ]; then - ssh root@10.15.0.6 "pct push $ctid $src $dest" + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pct push $ctid $src $dest" else pct push "$ctid" "$src" "$dest" fi } -# === Template Selection === -if [ "${AI_CONTAINER^^}" == "Y" ]; then - echo "⏳ AI container requested. Using debian12-ai-template (CTID 150) on 10.15.0.6..." +# === Template Selection & Clone === +if [[ "${AI_CONTAINER^^}" == "PHOENIX" ]]; then + echo "⏳ Phoenix AI container requested. Using template CTID 163..." CTID_TEMPLATE="163" + # Request cluster nextid from the target (remote if configured, else local via run_pvesh) CONTAINER_ID=$(run_pvesh get /cluster/nextid) + echo "DEBUG: Cloning on TARGET_PVE_HOST=${TARGET_PVE_HOST:-local} CTID_TEMPLATE=${CTID_TEMPLATE} -> CONTAINER_ID=${CONTAINER_ID}" run_pct clone $CTID_TEMPLATE $CONTAINER_ID \ --hostname $CONTAINER_NAME \ --full true @@ -135,11 +163,33 @@ if [ "${AI_CONTAINER^^}" == "Y" ]; then run_pct start $CONTAINER_ID run_pveum aclmod /vms/$CONTAINER_ID --user "$PROXMOX_USERNAME@pve" --role PVEVMUser + +elif [[ "${AI_CONTAINER^^}" == "FORTWAYNE" ]]; then + echo "⏳ Fort Wayne AI container requested. Using template CTID 103 on 10.250.0.2..." + CTID_TEMPLATE="103" + # allocate nextid directly on Fort Wayne + CONTAINER_ID=$(ssh root@10.250.0.2 pvesh get /cluster/nextid) + + echo "DEBUG: Cloning on Fort Wayne (10.250.0.2) CTID_TEMPLATE=${CTID_TEMPLATE} -> CONTAINER_ID=${CONTAINER_ID}" + ssh root@10.250.0.2 pct clone $CTID_TEMPLATE $CONTAINER_ID \ + --hostname $CONTAINER_NAME \ + --full true + + ssh root@10.250.0.2 pct set $CONTAINER_ID \ + --tags "$PROXMOX_USERNAME" \ + --tags "$LINUX_DISTRO" \ + --tags "AI" \ + --onboot 1 + + ssh root@10.250.0.2 pct start $CONTAINER_ID + ssh root@10.250.0.2 pveum aclmod /vms/$CONTAINER_ID --user "$PROXMOX_USERNAME@pve" --role PVEVMUser + else REPO_BASE_NAME=$(basename -s .git "$PROJECT_REPOSITORY") REPO_BASE_NAME_WITH_OWNER=$(echo "$PROJECT_REPOSITORY" | cut -d'/' -f4) TEMPLATE_NAME="template-$REPO_BASE_NAME-$REPO_BASE_NAME_WITH_OWNER" + # Search local and other known PVE (keeps original approach; will find local or remote templates depending on your environment) CTID_TEMPLATE=$( { pct list; ssh root@10.15.0.5 'pct list'; } | awk -v name="$TEMPLATE_NAME" '$3 == name {print $1}') case "${LINUX_DISTRO^^}" in @@ -154,9 +204,10 @@ else esac fi + # For non-AI containers, allocate next ID locally and clone once here CONTAINER_ID=$(pvesh get /cluster/nextid) - echo "⏳ Cloning Container..." + echo "⏳ Cloning Container (non-AI)... CTID_TEMPLATE=${CTID_TEMPLATE} -> CONTAINER_ID=${CONTAINER_ID}" run_pct clone $CTID_TEMPLATE $CONTAINER_ID \ --hostname $CONTAINER_NAME \ --full true @@ -176,8 +227,16 @@ fi if [ -f "/var/lib/vz/snippets/container-public-keys/$PUB_FILE" ]; then echo "⏳ Appending Public Key..." run_pct_exec $CONTAINER_ID touch ~/.ssh/authorized_keys > /dev/null 2>&1 - run_pct_exec $CONTAINER_ID bash -c "cat > ~/.ssh/authorized_keys" < /var/lib/vz/snippets/container-public-keys/$PUB_FILE > /dev/null 2>&1 - rm -rf /var/lib/vz/snippets/container-public-keys/$PUB_FILE > /dev/null 2>&1 + # Use a here-doc to reliably feed the pubkey to the remote pct exec + if is_remote_pve; then + # copy key file to remote PVE host temporarily then pct push it in case pct exec over ssh doesn't accept stdin redirection + scp "/var/lib/vz/snippets/container-public-keys/$PUB_FILE" root@"$TARGET_PVE_HOST":/tmp/"$PUB_FILE" > /dev/null 2>&1 || true + ssh root@"$TARGET_PVE_HOST" "pct push $CONTAINER_ID /tmp/$PUB_FILE /root/.ssh/authorized_keys >/dev/null 2>&1 || (pct exec $CONTAINER_ID -- bash -lc 'cat > ~/.ssh/authorized_keys' < /tmp/$PUB_FILE)" + ssh root@"$TARGET_PVE_HOST" "rm -f /tmp/$PUB_FILE" >/dev/null 2>&1 || true + else + run_pct_exec $CONTAINER_ID bash -c "cat > ~/.ssh/authorized_keys" < /var/lib/vz/snippets/container-public-keys/$PUB_FILE > /dev/null 2>&1 + rm -rf /var/lib/vz/snippets/container-public-keys/$PUB_FILE > /dev/null 2>&1 + fi fi ROOT_PSWD=$(tr -dc 'A-Za-z0-9' &2 + exit 1 + ;; + esac +} + +# run_pct_config function to fetch config +run_pct_config() { + local ctid="$1" + case "${AI_CONTAINER^^}" in + PHOENIX) + ssh root@10.15.0.6 "pct config $ctid" + ;; + FORTWAYNE) + ssh root@10.250.0.2 "pct config $ctid" + ;; + N|"") + pct config "$ctid" + ;; + *) + echo "❌ Invalid AI_CONTAINER value: $AI_CONTAINER" >&2 + exit 1 + ;; + esac } + # Redirect stdout and stderr to a log file LOGFILE="/var/log/pve-hook-$CTID.log" exec > >(tee -a "$LOGFILE") 2>&1 @@ -48,6 +82,9 @@ fi hostname=$(run_pct_exec "$CTID" hostname) os_release=$(run_pct_exec "$CTID" grep '^ID=' /etc/os-release | cut -d'=' -f2 | tr -d '"') +# === NEW: Extract MAC address using cluster-aware function === +mac=$(run_pct_config "$CTID" | grep -oP 'hwaddr=\K([^\s,]+)') + # Check if this container already has a SSH port assigned in PREROUTING existing_ssh_port=$(iptables -t nat -S PREROUTING | grep "to-destination $container_ip:22" | awk -F'--dport ' '{print $2}' | awk '{print $1}' | head -n 1 || true) @@ -115,7 +152,7 @@ if [ ! -z "$ADDITIONAL_PROTOCOLS" ]; then #Update NGINX port map JSON on the remote host safely using a heredoc and positional parameters - ssh root@10.15.20.69 bash -s -- "$hostname" "$container_ip" "$ssh_port" "$http_port" "$ss_protocols" "$ss_ports" "$proxmox_user" "$os_release" <<'EOF' + ssh root@10.15.20.69 bash -s -- "$hostname" "$container_ip" "$ssh_port" "$http_port" "$ss_protocols" "$ss_ports" "$proxmox_user" "$os_release" "$CTID" "$mac" <<'EOF' set -euo pipefail hostname="$1" @@ -126,6 +163,8 @@ protos_json=$(echo "$5" | tr ',' '\n' | jq -R . | jq -s .) ports_json=$(echo "$6" | tr ',' '\n' | jq -R . | jq -s 'map(tonumber)') user="$7" os_release="$8" +ctid="$9" +mac="${10}" jq --arg hn "$hostname" \ --arg ip "$container_ip" \ @@ -135,10 +174,14 @@ jq --arg hn "$hostname" \ --argjson http "$http_port" \ --argjson protos "$protos_json" \ --argjson ports_list "$ports_json" \ + --argjson ctid "$ctid" \ + --arg mac "$mac" \ '. + {($hn): { ip: $ip, user: $user, os_release: $osr, + ctid: $ctid, + mac: $mac, ports: ( reduce range(0; $protos | length) as $i ( {ssh: $ssh, http: $http}; . + { ($protos[$i]): $ports_list[$i]} @@ -150,7 +193,7 @@ nginx -s reload EOF else # Update NGINX port map JSON on the remote host safely using a heredoc and positional parameters - ssh root@10.15.20.69 bash -s -- "$hostname" "$container_ip" "$ssh_port" "$http_port" "$proxmox_user" "$os_release" <<'EOF' + ssh root@10.15.20.69 bash -s -- "$hostname" "$container_ip" "$ssh_port" "$http_port" "$proxmox_user" "$os_release" "$CTID" "$mac" <<'EOF' set -euo pipefail hostname="$1" @@ -159,6 +202,8 @@ ssh_port="$3" http_port="$4" user="$5" os_release="$6" +ctid="$7" +mac="$8" jq --arg hn "$hostname" \ --arg ip "$container_ip" \ @@ -166,10 +211,14 @@ jq --arg hn "$hostname" \ --arg osr "$os_release" \ --argjson http "$http_port" \ --argjson ssh "$ssh_port" \ + --argjson ctid "$ctid" \ + --arg mac "$mac" \ '. + {($hn): { ip: $ip, user: $user, os_release: $osr, + ctid: $ctid, + mac: $mac, ports: {ssh: $ssh, http: $http} }}' /etc/nginx/port_map.json > /tmp/port_map.json.new diff --git a/container-creation/ssh/create-container-new.sh b/container-creation/ssh/create-container-new.sh new file mode 100644 index 00000000..7890ede7 --- /dev/null +++ b/container-creation/ssh/create-container-new.sh @@ -0,0 +1,359 @@ +#!/bin/bash +# Script to create the pct container, run register container, and migrate container accordingly. +# Last Modified by October 3rd, 2025 by Carter Myers +# ----------------------------------------------------- + +BOLD='\033[1m' +BLUE='\033[34m' +MAGENTA='\033[35m' +GREEN='\033[32m' +RESET='\033[0m' + +cleanup() { + echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" + echo "⚠️ Script was abruptly exited. Running cleanup tasks." + echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" + pct_unlock $CTID_TEMPLATE + for file in \ + "/var/lib/vz/snippets/container-public-keys/$PUB_FILE" \ + "/var/lib/vz/snippets/container-port-maps/$PROTOCOL_FILE" \ + "/var/lib/vz/snippets/container-env-vars/$ENV_BASE_FOLDER" \ + "/var/lib/vz/snippets/container-services/$SERVICES_BASE_FILE" + do + [ -f "$file" ] && rm -rf "$file" + done + exit 1 +} + +echoContainerDetails() { + echo -e "📦 ${BLUE}Container ID :${RESET} $CONTAINER_ID" + echo -e "🌐 ${MAGENTA}Internal IP :${RESET} $CONTAINER_IP" + echo -e "🔗 ${GREEN}Domain Name :${RESET} https://$CONTAINER_NAME.opensource.mieweb.org" + echo -e "🛠️ ${BLUE}SSH Access :${RESET} ssh -p $SSH_PORT $PROXMOX_USERNAME@$CONTAINER_NAME.opensource.mieweb.org" + echo -e "🔑 ${BLUE}Container Password :${RESET} Your proxmox account password" + echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" + echo -e "${BOLD}${MAGENTA}NOTE: Additional background scripts are being ran in detached terminal sessions.${RESET}" + echo -e "${BOLD}${MAGENTA}Wait up to two minutes for all processes to complete.${RESET}" + echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" + echo -e "${BOLD}${BLUE}Still not working? Contact Max K. at maxklema@gmail.com${RESET}" + echo -e "${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}" +} + +trap cleanup SIGINT SIGTERM SIGHUP + +CONTAINER_NAME="$1" +GH_ACTION="$2" +HTTP_PORT="$3" +PROXMOX_USERNAME="$4" +USERNAME_ONLY="${PROXMOX_USERNAME%@*}" +PUB_FILE="$5" +PROTOCOL_FILE="$6" + +# Deployment ENVS +DEPLOY_ON_START="$7" +PROJECT_REPOSITORY="$8" +PROJECT_BRANCH="$9" +PROJECT_ROOT="${10}" +INSTALL_COMMAND=$(echo "${11}" | base64 -d) +BUILD_COMMAND=$(echo "${12}" | base64 -d) +START_COMMAND=$(echo "${13}" | base64 -d) +RUNTIME_LANGUAGE=$(echo "${14}" | base64 -d) +ENV_BASE_FOLDER="${15}" +SERVICES_BASE_FILE="${16}" +LINUX_DISTRO="${17}" +MULTI_COMPONENTS="${18}" +ROOT_START_COMMAND="${19}" +SELF_HOSTED_RUNNER="${20}" +VERSIONS_DICT=$(echo "${21}" | base64 -d) +AI_CONTAINER="${22}" # new argument from HTML form + +echo "PROJECT ROOT: \"$PROJECT_ROOT\"" +echo "AI_CONTAINER: \"$AI_CONTAINER\"" + +# === Determine target PVE host based on AI_CONTAINER === +# PHOENIX -> 10.15.0.6 (existing AI host) +# FORTWAYNE -> 10.250.0.2 (new WireGuard-connected host) +# N -> local execution (no SSH proxy) +case "${AI_CONTAINER^^}" in + PHOENIX) + TARGET_PVE_HOST="10.15.0.6" + ;; + FORTWAYNE) + TARGET_PVE_HOST="10.250.0.2" + ;; + N|"" ) + TARGET_PVE_HOST="" + ;; + *) + echo "Invalid AI_CONTAINER value: $AI_CONTAINER" + exit 1 + ;; +esac + +# Helper: returns true if we're using a remote PVE host (PHOENIX or FORTWAYNE) +is_remote_pve() { + [[ -n "$TARGET_PVE_HOST" ]] +} + +# === Wrapper for pct exec (and optionally pct commands for remote PVE) === +run_pct_exec() { + local ctid="$1" + shift + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pct exec $ctid -- $*" + else + pct exec "$ctid" -- "$@" + fi +} + +run_pct() { + # $@ = full pct command, e.g., clone, set, start, etc. + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pct $*" + else + pct "$@" + fi +} + +run_pveum() { + # Wrapper for pveum commands in remote case + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pveum $*" + else + pveum "$@" + fi +} + +run_pvesh() { + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pvesh $*" + else + pvesh "$@" + fi +} + +run_pct_push() { + local ctid="$1" + local src="$2" + local dest="$3" + if is_remote_pve; then + ssh root@"$TARGET_PVE_HOST" "pct push $ctid $src $dest" + else + pct push "$ctid" "$src" "$dest" + fi +} + +# === Template Selection & Clone === +if [[ "${AI_CONTAINER^^}" == "PHOENIX" ]]; then + echo "⏳ Phoenix AI container requested. Using template CTID 163..." + CTID_TEMPLATE="163" + # Request cluster nextid from the target (remote if configured, else local via run_pvesh) + CONTAINER_ID=$(run_pvesh get /cluster/nextid) + + echo "DEBUG: Cloning on TARGET_PVE_HOST=${TARGET_PVE_HOST:-local} CTID_TEMPLATE=${CTID_TEMPLATE} -> CONTAINER_ID=${CONTAINER_ID}" + run_pct clone $CTID_TEMPLATE $CONTAINER_ID \ + --hostname $CONTAINER_NAME \ + --full true + + run_pct set $CONTAINER_ID \ + --tags "$PROXMOX_USERNAME" \ + --tags "$LINUX_DISTRO" \ + --tags "AI" \ + --onboot 1 + + run_pct start $CONTAINER_ID + run_pveum aclmod /vms/$CONTAINER_ID --user "$PROXMOX_USERNAME@pve" --role PVEVMUser + +elif [[ "${AI_CONTAINER^^}" == "FORTWAYNE" ]]; then + echo "⏳ Fort Wayne AI container requested. Using template CTID 103 on 10.250.0.2..." + CTID_TEMPLATE="103" + # allocate nextid directly on Fort Wayne + CONTAINER_ID=$(ssh root@10.250.0.2 pvesh get /cluster/nextid) + + echo "DEBUG: Cloning on Fort Wayne (10.250.0.2) CTID_TEMPLATE=${CTID_TEMPLATE} -> CONTAINER_ID=${CONTAINER_ID}" + ssh root@10.250.0.2 pct clone $CTID_TEMPLATE $CONTAINER_ID \ + --hostname $CONTAINER_NAME \ + --full true + + ssh root@10.250.0.2 pct set $CONTAINER_ID \ + --tags "$PROXMOX_USERNAME" \ + --tags "$LINUX_DISTRO" \ + --tags "AI" \ + --onboot 1 + + ssh root@10.250.0.2 pct start $CONTAINER_ID + ssh root@10.250.0.2 pveum aclmod /vms/$CONTAINER_ID --user "$PROXMOX_USERNAME@pve" --role PVEVMUser + +else + REPO_BASE_NAME=$(basename -s .git "$PROJECT_REPOSITORY") + REPO_BASE_NAME_WITH_OWNER=$(echo "$PROJECT_REPOSITORY" | cut -d'/' -f4) + + TEMPLATE_NAME="template-$REPO_BASE_NAME-$REPO_BASE_NAME_WITH_OWNER" + # Search local and other known PVE (keeps original approach; will find local or remote templates depending on your environment) + CTID_TEMPLATE=$( { pct list; ssh root@10.15.0.5 'pct list'; } | awk -v name="$TEMPLATE_NAME" '$3 == name {print $1}') + + case "${LINUX_DISTRO^^}" in + DEBIAN) PACKAGE_MANAGER="apt-get" ;; + ROCKY) PACKAGE_MANAGER="dnf" ;; + esac + + if [ -z "$CTID_TEMPLATE" ]; then + case "${LINUX_DISTRO^^}" in + DEBIAN) CTID_TEMPLATE="160" ;; + ROCKY) CTID_TEMPLATE="138" ;; + esac + fi + + # For non-AI containers, allocate next ID locally and clone once here + CONTAINER_ID=$(pvesh get /cluster/nextid) + + echo "⏳ Cloning Container (non-AI)... CTID_TEMPLATE=${CTID_TEMPLATE} -> CONTAINER_ID=${CONTAINER_ID}" + run_pct clone $CTID_TEMPLATE $CONTAINER_ID \ + --hostname $CONTAINER_NAME \ + --full true + + echo "⏳ Setting Container Properties..." + run_pct set $CONTAINER_ID \ + --tags "$PROXMOX_USERNAME" \ + --tags "$LINUX_DISTRO" \ + --tags "LDAP" \ + --onboot 1 + + run_pct start $CONTAINER_ID + run_pveum aclmod /vms/$CONTAINER_ID --user "$PROXMOX_USERNAME@pve" --role PVEVMUser +fi + +# === Post-Provisioning (pct exec wrapped) === +if [ -f "/var/lib/vz/snippets/container-public-keys/$PUB_FILE" ]; then + echo "⏳ Appending Public Key..." + run_pct_exec $CONTAINER_ID touch ~/.ssh/authorized_keys > /dev/null 2>&1 + # Use a here-doc to reliably feed the pubkey to the remote pct exec + if is_remote_pve; then + # copy key file to remote PVE host temporarily then pct push it in case pct exec over ssh doesn't accept stdin redirection + scp "/var/lib/vz/snippets/container-public-keys/$PUB_FILE" root@"$TARGET_PVE_HOST":/tmp/"$PUB_FILE" > /dev/null 2>&1 || true + ssh root@"$TARGET_PVE_HOST" "pct push $CONTAINER_ID /tmp/$PUB_FILE /root/.ssh/authorized_keys >/dev/null 2>&1 || (pct exec $CONTAINER_ID -- bash -lc 'cat > ~/.ssh/authorized_keys' < /tmp/$PUB_FILE)" + ssh root@"$TARGET_PVE_HOST" "rm -f /tmp/$PUB_FILE" >/dev/null 2>&1 || true + else + run_pct_exec $CONTAINER_ID bash -c "cat > ~/.ssh/authorized_keys" < /var/lib/vz/snippets/container-public-keys/$PUB_FILE > /dev/null 2>&1 + rm -rf /var/lib/vz/snippets/container-public-keys/$PUB_FILE > /dev/null 2>&1 + fi +fi + +ROOT_PSWD=$(tr -dc 'A-Za-z0-9' /dev/null 2>&1 + +CONTAINER_IP="" +attempts=0 +max_attempts=10 + +while [[ -z "$CONTAINER_IP" && $attempts -lt $max_attempts ]]; do + CONTAINER_IP=$(run_pct_exec "$CONTAINER_ID" hostname -I | awk '{print $1}') + [[ -z "$CONTAINER_IP" ]] && sleep 2 && ((attempts++)) +done + +if [[ -z "$CONTAINER_IP" ]]; then + echo "❌ Timed out waiting for container to get an IP address." + exit 1 +fi + +echo "⏳ Updatng container packages..." +if [[ "${LINUX_DISTRO^^}" == "ROCKY" ]]; then + run_pct_exec $CONTAINER_ID bash -c "dnf upgrade -y" +else + run_pct_exec $CONTAINER_ID bash -c "apt-get update && apt-get upgrade -y" +fi + +echo "⏳ Configuring LDAP connection via SSSD..." +export AI_CONTAINER="$AI_CONTAINER" +source /var/lib/vz/snippets/helper-scripts/configureLDAP.sh + +echo "⏳ Setting up Wazuh-Agent..." +source /var/lib/vz/snippets/Wazuh/register-agent.sh + +if [ "${DEPLOY_ON_START^^}" == "Y" ]; then + source /var/lib/vz/snippets/helper-scripts/deployOnStart.sh + for file in \ + "/var/lib/vz/snippets/container-env-vars/$ENV_BASE_FOLDER" \ + "/var/lib/vz/snippets/container-services/$SERVICES_BASE_FILE" + do + [ -f "$file" ] && rm -rf "$file" > /dev/null 2>&1 + done +fi + +run_pct_exec $CONTAINER_ID bash -c "cd /root && touch container-updates.log" + +echo "⏳ Running Container Provision Script..." +if [ -f "/var/lib/vz/snippets/container-port-maps/$PROTOCOL_FILE" ]; then + /var/lib/vz/snippets/register-container.sh $CONTAINER_ID $HTTP_PORT /var/lib/vz/snippets/container-port-maps/$PROTOCOL_FILE "$USERNAME_ONLY" + rm -rf /var/lib/vz/snippets/container-port-maps/$PROTOCOL_FILE > /dev/null 2>&1 +else + /var/lib/vz/snippets/register-container.sh $CONTAINER_ID $HTTP_PORT "" "$PROXMOX_USERNAME" +fi + +SSH_PORT=$(iptables -t nat -S PREROUTING | grep "to-destination $CONTAINER_IP:22" | awk -F'--dport ' '{print $2}' | awk '{print $1}' | head -n 1 || true) + +echo "Adding container MOTD information..." +# port_map.json remains on central nginx host (10.15.20.69) — leave as-is unless you want to change that behavior +scp 10.15.20.69:/etc/nginx/port_map.json /tmp/port_map.json +CONTAINER_INFO=$(jq -r --arg hn "$CONTAINER_NAME" '.[$hn]' /tmp/port_map.json) + +if [ "$CONTAINER_INFO" != "null" ]; then + HOSTNAME="$CONTAINER_NAME" + IP=$(echo "$CONTAINER_INFO" | jq -r '.ip') + OWNER=$(echo "$CONTAINER_INFO" | jq -r '.user') + OS_RELEASE=$(echo "$CONTAINER_INFO" | jq -r '.os_release') + PORTS=$(echo "$CONTAINER_INFO" | jq -r '.ports | to_entries[] | "\(.key): \(.value)"' | paste -sd ", " -) + PROTOCOLS=$(echo "$CONTAINER_INFO" | jq -r '.ports | keys | join(", ")') + + cat < /tmp/container_motd +Container Information: +---------------------- +Hostname : $HOSTNAME +IP Address : $IP +Ports : $PORTS +Protocols : $PROTOCOLS +Primary Owner : $OWNER +OS Release : $OS_RELEASE +EOF +else + echo "No container info found for $CONTAINER_NAME" > /tmp/container_motd +fi + +run_pct_push $CONTAINER_ID /tmp/container_motd /etc/motd + +echoContainerDetails + +BUILD_COMMAND_B64=$(echo -n "$BUILD_COMMAND" | base64) +RUNTIME_LANGUAGE_B64=$(echo -n "$RUNTIME_LANGUAGE" | base64) +START_COMMAND_B64=$(echo -n "$START_COMMAND" | base64) + +# Only run start_services when this is NOT an AI container (previously referenced undefined $AI) +if [[ "${AI_CONTAINER^^}" != "PHOENIX" && "${AI_CONTAINER^^}" != "FORTWAYNE" ]]; then + CMD=( + bash /var/lib/vz/snippets/start_services.sh + "$CONTAINER_ID" + "$CONTAINER_NAME" + "$REPO_BASE_NAME" + "$REPO_BASE_NAME_WITH_OWNER" + "$SSH_PORT" + "$CONTAINER_IP" + "$PROJECT_ROOT" + "$ROOT_START_COMMAND" + "$DEPLOY_ON_START" + "$MULTI_COMPONENTS" + "$START_COMMAND_B64" + "$BUILD_COMMAND_B64" + "$RUNTIME_LANGUAGE_B64" + "$GH_ACTION" + "$PROJECT_BRANCH" + ) +fi + +QUOTED_CMD=$(printf ' %q' "${CMD[@]}") + +# Create detached tmux session to run the (possibly long) service start process +if [[ -n "${CMD[*]}" ]]; then + tmux new-session -d -s "$CONTAINER_NAME" "$QUOTED_CMD" +fi + +exit 0 \ No newline at end of file diff --git a/create-a-container/create-container-wrapper.sh b/create-a-container/create-container-wrapper.sh index 24ea26bc..1817f58d 100644 --- a/create-a-container/create-container-wrapper.sh +++ b/create-a-container/create-container-wrapper.sh @@ -36,6 +36,16 @@ CONTAINER_NAME="${CONTAINER_NAME,,}" LINUX_DISTRIBUTION="${LINUX_DISTRIBUTION,,}" DEPLOY_ON_START="${DEPLOY_ON_START,,}" +# Optional: AI_CONTAINER (default to "N" if not set) +AI_CONTAINER="${AI_CONTAINER:-N}" +AI_CONTAINER="${AI_CONTAINER^^}" # normalize + +# Validate allowed values +if [[ "$AI_CONTAINER" != "N" && "$AI_CONTAINER" != "PHOENIX" && "$AI_CONTAINER" != "FORTWAYNE" ]]; then + outputError "AI_CONTAINER must be one of: N, PHOENIX, FORTWAYNE." +fi + + # Validate Proxmox credentials using your Node.js authenticateUser USER_AUTHENTICATED=$(node /root/bin/js/runner.js authenticateUser "$PROXMOX_USERNAME" "$PROXMOX_PASSWORD") if [ "$USER_AUTHENTICATED" != "true" ]; then @@ -175,7 +185,7 @@ if [[ -n "$KEY_FILE" ]]; then fi # Run your create-container.sh remotely over SSH with corrected quoting and simplified variable -ssh -t root@10.15.0.4 "bash -c \"/var/lib/vz/snippets/create-container.sh \ +ssh -t root@10.15.0.4 "bash -c \"/var/lib/vz/snippets/create-container-new.sh \ '$CONTAINER_NAME' \ '$GH_ACTION' \ '$HTTP_PORT' \ @@ -195,6 +205,9 @@ ssh -t root@10.15.0.4 "bash -c \"/var/lib/vz/snippets/create-container.sh \ '$LINUX_DISTRIBUTION' \ '${MULTI_COMPONENT:-}' \ '${ROOT_START_COMMAND:-}' \ + '${SELF_HOSTED_RUNNER:-}' \ + '${VERSIONS_DICT:-}' \ + '$AI_CONTAINER' # Corrected: Pass the variable's value in the correct position \"" # Clean up temp files @@ -204,6 +217,7 @@ rm -f "${TEMP_SERVICES_FILE_PATH:-}" rm -rf "${ENV_FOLDER_PATH:-}" # Unset sensitive variables +unset CONFIRM_PASSWORD unset PUBLIC_KEY echo "✅ Container creation wrapper script finished successfully." \ No newline at end of file diff --git a/create-a-container/public/index.html b/create-a-container/public/index.html index 63d37ff1..ee6b6c69 100644 --- a/create-a-container/public/index.html +++ b/create-a-container/public/index.html @@ -19,6 +19,11 @@

Container Creation Login

+
+