* feat: Add script installation tracking with Container ID detection
- Add installed_scripts table to database schema
- Implement Container ID parsing from terminal output
- Add installation tracking for both local and SSH executions
- Create InstalledScriptsTab component with filtering and search
- Add tab navigation to main page (Scripts | Installed Scripts)
- Add tRPC endpoints for installed scripts CRUD operations
- Track installation status, server info, and output logs
- Support both local and SSH execution modes
* fix: Resolve SQL syntax error in database queries
- Change table alias from 'is' to 'inst' in SQL queries
- 'is' is a reserved keyword in SQLite causing syntax errors
- Fixes getAllInstalledScripts, getInstalledScriptById, and getInstalledScriptsByServer methods
* feat: Enhance Container ID detection and add manual editing
- Add comprehensive Container ID detection patterns for various script formats
- Add debug logging to help identify detection issues
- Add manual Container ID editing feature in the frontend
- Add updateInstalledScript tRPC mutation for updating records
- Improve Container ID column with inline editing UI
- Test and verify Container ID detection is working (detected 132 from 2fauth script)
* fix: Improve Container ID detection with ANSI code handling
- Add ANSI color code stripping before pattern matching
- Add primary pattern for exact format: 🆔 Container ID: 113
- Test patterns on both original and cleaned output
- Add better debug logging to show matched text
- This should fix Container ID detection for Proxmox scripts
* feat: Add script update functionality with terminal output
- Add Update button for each installed script (only shows when container_id exists)
- Add WebSocket support for update action (pct enter <ct-id> -- update)
- Add updateScript tRPC endpoint for initiating updates
- Add startScriptUpdate, startLocalScriptUpdate, startSSHScriptUpdate methods
- Modify Terminal component to handle update operations
- Display real-time terminal output for update commands
- Support both local and SSH execution modes for updates
- Show 'Update Container <ID>' in terminal title for update operations
* fix: Fix SSH update functionality
- Replace sshService.executeScript with direct sshpass command
- Use bash -c to execute SSH command: sshpass -p 'password' ssh -o StrictHostKeyChecking=no user@ip 'pct enter <ct-id> -- update'
- This fixes the 'Permission denied' and rsync errors
- SSH updates now work properly for remote containers
* fix: Fix WebSocket update action handling
- Add containerId to WebSocketMessage typedef
- Extract containerId from message in handleMessage function
- Remove debug logging from Terminal component
- This fixes the 'containerId is not defined' error
- Update action should now work properly without creating script records
* feat: Add Update functionality for installed scripts
- Add Update button to InstalledScriptsTab for scripts with Container ID
- Modify Terminal component to handle update operations with isUpdate and containerId props
- Add startUpdateExecution method to WebSocket handler
- Implement local update execution using 'pct enter <CT ID> -c update'
- Implement SSH update execution for remote servers
- Update WebSocket message parsing to handle update parameters
- Users can now update installed scripts by entering the LXC container and running update command
* fix: Fix SSH update execution by using direct command execution
- Add executeCommand method to SSH service for direct command execution
- Update startSSHUpdateExecution to use executeCommand instead of executeScript
- This fixes the rsync permission denied error when updating scripts via SSH
- Update functionality now works properly for both local and SSH installations
* fix: Add server credentials fetching for SSH updates
- Create servers router with getServerById endpoint
- Update handleUpdateScript to fetch full server details including credentials
- This fixes the permission denied error by providing user/password for SSH authentication
- SSH updates now have access to complete server configuration
* fix: Simplify server credentials fetching for SSH updates
- Add server_user and server_password to database query
- Update InstalledScript interface to include server credentials
- Simplify handleUpdateScript to use data already available
- Remove complex tRPC server fetching that was causing errors
- SSH updates now work with complete server authentication data
* fix: Correct pct enter command sequence for updates
- Change from 'pct enter <CT ID> -c "update"' to proper sequence
- First run 'pct enter <CT ID>' to enter container shell
- Then send 'update' command after entering the container
- Apply fix to both local and SSH update execution methods
- Add 1-second delay to ensure container shell is ready before sending update command
* fix: Increase delay to 4 seconds before sending update command
- Change delay from 1 second to 4 seconds for both local and SSH updates
- Ensures container shell is fully ready before sending update command
- Prevents premature command execution that could fail
* cleanup: Remove all debug console.log statements
- Remove debug logging from server.js WebSocket handlers
- Remove debug logging from Terminal component
- Remove debug logging from page.tsx
- Remove debug logging from ExecutionModeModal component
- Remove debug logging from githubJsonService.ts
- Keep only essential server startup messages and error logging
- Clean up codebase for production readiness
* fix: Resolve all build and linter errors
- Fix React Hook useEffect missing dependencies in Terminal.tsx
- Fix TypeScript unsafe argument error in installedScripts.ts by properly typing updateData
- Add missing isUpdate and containerId properties to WebSocketMessage type definition
- Add proper type annotations for callback parameters in server.js
- Fix TypeScript errors with execution.process by adding type assertions
- Remove duplicate updateInstalledScript method in installedScripts.ts
- Build now passes successfully with no errors or warnings
207 lines
7.5 KiB
Plaintext
Executable File
207 lines
7.5 KiB
Plaintext
Executable File
# Copyright (c) 2021-2025 michelroegl-brunner
|
|
# Author: michelroegl-brunner
|
|
# License: MIT
|
|
# https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE
|
|
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
printf "\r\e[2K%b" '\033[93m Setup Source \033[m' >&2
|
|
apt-get update >/dev/null 2>&1
|
|
apt-get install -y curl >/dev/null 2>&1
|
|
fi
|
|
# core.func is included in FUNCTIONS_FILE_PATH
|
|
load_functions
|
|
# This function enables IPv6 if it's not disabled and sets verbose mode
|
|
verb_ip6() {
|
|
set_std_mode # Set STD mode based on VERBOSE
|
|
|
|
if [ "$DISABLEIPV6" == "yes" ]; then
|
|
echo "net.ipv6.conf.all.disable_ipv6 = 1" >>/etc/sysctl.conf
|
|
$STD sysctl -p
|
|
fi
|
|
}
|
|
|
|
# This function sets error handling options and defines the error_handler function to handle errors
|
|
catch_errors() {
|
|
set -Eeuo pipefail
|
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
}
|
|
|
|
# This function handles errors
|
|
error_handler() {
|
|
printf "\e[?25h"
|
|
local exit_code="$?"
|
|
local line_number="$1"
|
|
local command="$2"
|
|
local error_message="${RD}[ERROR]${CL} in line ${RD}$line_number${CL}: exit code ${RD}$exit_code${CL}: while executing command ${YW}$command${CL}"
|
|
echo -e "\n$error_message"
|
|
if [[ "$line_number" -eq 51 ]]; then
|
|
echo -e "The silent function has suppressed the error, run the script with verbose mode enabled, which will provide more detailed output.\n"
|
|
post_update_to_api "failed" "No error message, script ran in silent mode"
|
|
else
|
|
post_update_to_api "failed" "${command}"
|
|
fi
|
|
}
|
|
|
|
# This function sets up the Container OS by generating the locale, setting the timezone, and checking the network connection
|
|
setting_up_container() {
|
|
msg_info "Setting up Container OS"
|
|
for ((i = RETRY_NUM; i > 0; i--)); do
|
|
if [ "$(hostname -I)" != "" ]; then
|
|
break
|
|
fi
|
|
echo 1>&2 -en "${CROSS}${RD} No Network! "
|
|
sleep $RETRY_EVERY
|
|
done
|
|
if [ "$(hostname -I)" = "" ]; then
|
|
echo 1>&2 -e "\n${CROSS}${RD} No Network After $RETRY_NUM Tries${CL}"
|
|
echo -e "${NETWORK}Check Network Settings"
|
|
exit 1
|
|
fi
|
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
|
systemctl disable -q --now systemd-networkd-wait-online.service
|
|
msg_ok "Set up Container OS"
|
|
#msg_custom "${CM}" "${GN}" "Network Connected: ${BL}$(hostname -I)"
|
|
msg_ok "Network Connected: ${BL}$(hostname -I)"
|
|
}
|
|
|
|
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
|
# This function checks the network connection by pinging a known IP address and prompts the user to continue if the internet is not connected
|
|
network_check() {
|
|
set +e
|
|
trap - ERR
|
|
ipv4_connected=false
|
|
ipv6_connected=false
|
|
sleep 1
|
|
|
|
# Check IPv4 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
|
if ping -c 1 -W 1 1.1.1.1 &>/dev/null || ping -c 1 -W 1 8.8.8.8 &>/dev/null || ping -c 1 -W 1 9.9.9.9 &>/dev/null; then
|
|
msg_ok "IPv4 Internet Connected"
|
|
ipv4_connected=true
|
|
else
|
|
msg_error "IPv4 Internet Not Connected"
|
|
fi
|
|
|
|
# Check IPv6 connectivity to Google, Cloudflare & Quad9 DNS servers.
|
|
if ping6 -c 1 -W 1 2606:4700:4700::1111 &>/dev/null || ping6 -c 1 -W 1 2001:4860:4860::8888 &>/dev/null || ping6 -c 1 -W 1 2620:fe::fe &>/dev/null; then
|
|
msg_ok "IPv6 Internet Connected"
|
|
ipv6_connected=true
|
|
else
|
|
msg_error "IPv6 Internet Not Connected"
|
|
fi
|
|
|
|
# If both IPv4 and IPv6 checks fail, prompt the user
|
|
if [[ $ipv4_connected == false && $ipv6_connected == false ]]; then
|
|
read -r -p "No Internet detected, would you like to continue anyway? <y/N> " prompt
|
|
if [[ "${prompt,,}" =~ ^(y|yes)$ ]]; then
|
|
echo -e "${INFO}${RD}Expect Issues Without Internet${CL}"
|
|
else
|
|
echo -e "${NETWORK}Check Network Settings"
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# DNS resolution checks for GitHub-related domains (IPv4 and/or IPv6)
|
|
GIT_HOSTS=("github.com" "raw.githubusercontent.com" "api.github.com" "git.community-scripts.org")
|
|
GIT_STATUS="Git DNS:"
|
|
DNS_FAILED=false
|
|
|
|
for HOST in "${GIT_HOSTS[@]}"; do
|
|
RESOLVEDIP=$(getent hosts "$HOST" | awk '{ print $1 }' | grep -E '(^([0-9]{1,3}\.){3}[0-9]{1,3}$)|(^[a-fA-F0-9:]+$)' | head -n1)
|
|
if [[ -z "$RESOLVEDIP" ]]; then
|
|
GIT_STATUS+="$HOST:($DNSFAIL)"
|
|
DNS_FAILED=true
|
|
else
|
|
GIT_STATUS+=" $HOST:($DNSOK)"
|
|
fi
|
|
done
|
|
|
|
if [[ "$DNS_FAILED" == true ]]; then
|
|
fatal "$GIT_STATUS"
|
|
else
|
|
msg_ok "$GIT_STATUS"
|
|
fi
|
|
|
|
set -e
|
|
trap 'error_handler $LINENO "$BASH_COMMAND"' ERR
|
|
}
|
|
|
|
# This function updates the Container OS by running apt-get update and upgrade
|
|
update_os() {
|
|
msg_info "Updating Container OS"
|
|
if [[ "$CACHER" == "yes" ]]; then
|
|
echo 'Acquire::http::Proxy-Auto-Detect "/usr/local/bin/apt-proxy-detect.sh";' >/etc/apt/apt.conf.d/00aptproxy
|
|
cat <<EOF >/usr/local/bin/apt-proxy-detect.sh
|
|
#!/bin/bash
|
|
if nc -w1 -z "${CACHER_IP}" 3142; then
|
|
echo -n "http://${CACHER_IP}:3142"
|
|
else
|
|
echo -n "DIRECT"
|
|
fi
|
|
EOF
|
|
chmod +x /usr/local/bin/apt-proxy-detect.sh
|
|
fi
|
|
$STD apt-get update
|
|
$STD apt-get -o Dpkg::Options::="--force-confold" -y dist-upgrade
|
|
rm -rf /usr/lib/python3.*/EXTERNALLY-MANAGED
|
|
msg_ok "Updated Container OS"
|
|
|
|
# tools.func is included in FUNCTIONS_FILE_PATH
|
|
}
|
|
|
|
# This function modifies the message of the day (motd) and SSH settings
|
|
motd_ssh() {
|
|
# Set terminal to 256-color mode
|
|
grep -qxF "export TERM='xterm-256color'" /root/.bashrc || echo "export TERM='xterm-256color'" >>/root/.bashrc
|
|
|
|
# Get OS information (Debian / Ubuntu)
|
|
if [ -f "/etc/os-release" ]; then
|
|
OS_NAME=$(grep ^NAME /etc/os-release | cut -d= -f2 | tr -d '"')
|
|
OS_VERSION=$(grep ^VERSION_ID /etc/os-release | cut -d= -f2 | tr -d '"')
|
|
elif [ -f "/etc/debian_version" ]; then
|
|
OS_NAME="Debian"
|
|
OS_VERSION=$(cat /etc/debian_version)
|
|
fi
|
|
|
|
PROFILE_FILE="/etc/profile.d/00_lxc-details.sh"
|
|
echo "echo -e \"\"" >"$PROFILE_FILE"
|
|
echo -e "echo -e \"${BOLD}${APPLICATION} LXC Container${CL}"\" >>"$PROFILE_FILE"
|
|
echo -e "echo -e \"${TAB}${GATEWAY}${YW} Provided by: ${GN}community-scripts ORG ${YW}| GitHub: ${GN}https://github.com/community-scripts/ProxmoxVE${CL}\"" >>"$PROFILE_FILE"
|
|
echo "echo \"\"" >>"$PROFILE_FILE"
|
|
echo -e "echo -e \"${TAB}${OS}${YW} OS: ${GN}${OS_NAME} - Version: ${OS_VERSION}${CL}\"" >>"$PROFILE_FILE"
|
|
echo -e "echo -e \"${TAB}${HOSTNAME}${YW} Hostname: ${GN}\$(hostname)${CL}\"" >>"$PROFILE_FILE"
|
|
echo -e "echo -e \"${TAB}${INFO}${YW} IP Address: ${GN}\$(hostname -I | awk '{print \$1}')${CL}\"" >>"$PROFILE_FILE"
|
|
|
|
# Disable default MOTD scripts
|
|
chmod -x /etc/update-motd.d/*
|
|
|
|
if [[ "${SSH_ROOT}" == "yes" ]]; then
|
|
sed -i "s/#PermitRootLogin prohibit-password/PermitRootLogin yes/g" /etc/ssh/sshd_config
|
|
systemctl restart sshd
|
|
fi
|
|
}
|
|
|
|
# This function customizes the container by modifying the getty service and enabling auto-login for the root user
|
|
customize() {
|
|
if [[ "$PASSWORD" == "" ]]; then
|
|
msg_info "Customizing Container"
|
|
GETTY_OVERRIDE="/etc/systemd/system/container-getty@1.service.d/override.conf"
|
|
mkdir -p $(dirname $GETTY_OVERRIDE)
|
|
cat <<EOF >$GETTY_OVERRIDE
|
|
[Service]
|
|
ExecStart=
|
|
ExecStart=-/sbin/agetty --autologin root --noclear --keep-baud tty%I 115200,38400,9600 \$TERM
|
|
EOF
|
|
systemctl daemon-reload
|
|
systemctl restart $(basename $(dirname $GETTY_OVERRIDE) | sed 's/\.d//')
|
|
msg_ok "Customized Container"
|
|
fi
|
|
echo "bash -c \"\$(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/ct/${app}.sh)\"" >/usr/bin/update
|
|
chmod +x /usr/bin/update
|
|
|
|
if [[ -n "${SSH_AUTHORIZED_KEY}" ]]; then
|
|
mkdir -p /root/.ssh
|
|
echo "${SSH_AUTHORIZED_KEY}" >/root/.ssh/authorized_keys
|
|
chmod 700 /root/.ssh
|
|
chmod 600 /root/.ssh/authorized_keys
|
|
fi
|
|
} |