P2P App Store Emancipation: - secubox-p2p: Package distribution via mesh peers (CGI API, RPCD, CLI) - packages.js: LuCI view with LOCAL/PEER badges, fetch/install actions - devstatus.js: Dev Status widget with Gitea commits, v1.0 progress tracking - secubox-feed: sync-content command for auto-installing content packages - ACL fix for P2P feed RPCD methods Remote Access: - secubox-app-rustdesk: Native hbbs/hbbr relay server from GitHub releases - secubox-app-guacamole: LXC Debian container with guacd + Tomcat (partial) Content Distribution: - secubox-content-pkg: Auto-package Metablogizer/Streamlit as IPKs - Auto-publish hooks in metablogizerctl and streamlitctl Mesh Media: - secubox-app-ksmbd: In-kernel SMB3 server with ksmbdctl CLI - Pre-configured shares for Jellyfin, Lyrion, Backup UI Consistency: - client-guardian: Ported to sh-page-header chip layout - auth-guardian: Ported to sh-page-header chip layout Fixes: - services.js: RPC expect unwrapping bug fix - metablogizer: Chunked upload for uhttpd 64KB limit Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
683 lines
18 KiB
Bash
683 lines
18 KiB
Bash
#!/bin/sh
|
|
# SecuBox Apache Guacamole Manager — LXC Debian container
|
|
|
|
CONFIG="guacamole"
|
|
LXC_NAME="guacamole"
|
|
LXC_PATH="/srv/lxc"
|
|
LXC_ROOTFS="$LXC_PATH/$LXC_NAME/rootfs"
|
|
LXC_CONF="$LXC_PATH/$LXC_NAME/config"
|
|
DATA_PATH_DEFAULT="/srv/guacamole"
|
|
GUAC_VERSION="1.5.5"
|
|
OPKG_UPDATED=0
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: guacamolectl <command>
|
|
|
|
Commands:
|
|
install Create LXC container with Guacamole
|
|
uninstall Remove container (preserves config)
|
|
update Update Guacamole to latest version
|
|
check Run prerequisite checks
|
|
status Show container and service status
|
|
logs [N] Show last N lines of logs (default: 50)
|
|
shell Open interactive shell in container
|
|
add-ssh <name> <host> [port] [user] Add SSH connection
|
|
add-vnc <name> <host> [port] Add VNC connection
|
|
add-rdp <name> <host> [port] [user] Add RDP connection
|
|
list-connections List configured connections
|
|
configure-haproxy Register as HAProxy vhost
|
|
mesh-register Register in P2P mesh
|
|
service-run Internal: run container via procd
|
|
service-stop Stop container
|
|
USAGE
|
|
}
|
|
|
|
# ---------- helpers ----------
|
|
|
|
require_root() { [ "$(id -u)" -eq 0 ]; }
|
|
|
|
uci_get() {
|
|
local key="$1"
|
|
local section="${2:-main}"
|
|
uci -q get ${CONFIG}.${section}.$key
|
|
}
|
|
|
|
uci_set() {
|
|
local key="$1"
|
|
local value="$2"
|
|
local section="${3:-main}"
|
|
uci set ${CONFIG}.${section}.$key="$value"
|
|
}
|
|
|
|
log_info() { echo "[INFO] $*"; logger -t guacamolectl "$*"; }
|
|
log_error() { echo "[ERROR] $*" >&2; logger -t guacamolectl -p err "$*"; }
|
|
|
|
ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }
|
|
|
|
ensure_packages() {
|
|
for pkg in "$@"; do
|
|
if ! opkg status "$pkg" 2>/dev/null | grep -q "Status:.*installed"; then
|
|
if [ "$OPKG_UPDATED" -eq 0 ]; then
|
|
opkg update || return 1
|
|
OPKG_UPDATED=1
|
|
fi
|
|
opkg install "$pkg" || return 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
defaults() {
|
|
data_path="$(uci_get data_path || echo $DATA_PATH_DEFAULT)"
|
|
web_port="$(uci_get web_port || echo 8080)"
|
|
memory="$(uci_get memory || echo 512)"
|
|
}
|
|
|
|
detect_arch() {
|
|
case "$(uname -m)" in
|
|
aarch64) echo "aarch64" ;;
|
|
armv7l) echo "armv7" ;;
|
|
x86_64) echo "x86_64" ;;
|
|
*) echo "x86_64" ;;
|
|
esac
|
|
}
|
|
|
|
# ---------- LXC helpers ----------
|
|
|
|
lxc_running() {
|
|
lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"
|
|
}
|
|
|
|
lxc_exists() {
|
|
[ -f "$LXC_CONF" ] && [ -d "$LXC_ROOTFS" ]
|
|
}
|
|
|
|
lxc_exec() {
|
|
lxc-attach -n "$LXC_NAME" -- "$@"
|
|
}
|
|
|
|
lxc_stop() {
|
|
if lxc_running; then
|
|
lxc-stop -n "$LXC_NAME" -k 2>/dev/null || true
|
|
sleep 1
|
|
fi
|
|
}
|
|
|
|
# ---------- rootfs creation ----------
|
|
|
|
lxc_create_rootfs() {
|
|
local arch=$(detect_arch)
|
|
|
|
# Map to Debian architecture names
|
|
local debian_arch
|
|
case "$arch" in
|
|
aarch64) debian_arch="arm64" ;;
|
|
armv7) debian_arch="armhf" ;;
|
|
x86_64) debian_arch="amd64" ;;
|
|
*) debian_arch="amd64" ;;
|
|
esac
|
|
|
|
ensure_dir "$LXC_ROOTFS"
|
|
|
|
# Minimal Debian rootfs via tarball from LXC image server
|
|
local rootfs_url="https://images.linuxcontainers.org/images/debian/bookworm/${debian_arch}/default/"
|
|
log_info "Downloading Debian bookworm rootfs for ${debian_arch}..."
|
|
|
|
# Get latest build directory
|
|
local latest_path
|
|
latest_path=$(wget -q -O - "$rootfs_url" 2>/dev/null | grep -oE '[0-9]{8}_[0-9]{2}:[0-9]{2}' | tail -1)
|
|
if [ -z "$latest_path" ]; then
|
|
log_error "Failed to find latest Debian rootfs build"
|
|
return 1
|
|
fi
|
|
|
|
local tarball="/tmp/debian-guacamole.tar.xz"
|
|
local tarball_url="${rootfs_url}${latest_path}/rootfs.tar.xz"
|
|
wget -q -O "$tarball" "$tarball_url" || {
|
|
log_error "Failed to download Debian rootfs from $tarball_url"
|
|
return 1
|
|
}
|
|
|
|
tar -xJf "$tarball" -C "$LXC_ROOTFS" || {
|
|
log_error "Failed to extract Debian rootfs"
|
|
return 1
|
|
}
|
|
rm -f "$tarball"
|
|
|
|
# DNS
|
|
cp /etc/resolv.conf "$LXC_ROOTFS/etc/resolv.conf" 2>/dev/null || \
|
|
echo "nameserver 8.8.8.8" > "$LXC_ROOTFS/etc/resolv.conf"
|
|
|
|
# Create minimal /dev for chroot operations
|
|
mkdir -p "$LXC_ROOTFS/dev"
|
|
[ -c "$LXC_ROOTFS/dev/null" ] || mknod -m 666 "$LXC_ROOTFS/dev/null" c 1 3 2>/dev/null
|
|
[ -c "$LXC_ROOTFS/dev/zero" ] || mknod -m 666 "$LXC_ROOTFS/dev/zero" c 1 5 2>/dev/null
|
|
[ -c "$LXC_ROOTFS/dev/random" ] || mknod -m 666 "$LXC_ROOTFS/dev/random" c 1 8 2>/dev/null
|
|
[ -c "$LXC_ROOTFS/dev/urandom" ] || mknod -m 666 "$LXC_ROOTFS/dev/urandom" c 1 9 2>/dev/null
|
|
|
|
# Configure apt sources explicitly
|
|
cat > "$LXC_ROOTFS/etc/apt/sources.list" <<'SOURCES'
|
|
deb http://deb.debian.org/debian bookworm main contrib non-free non-free-firmware
|
|
deb http://deb.debian.org/debian bookworm-updates main contrib non-free non-free-firmware
|
|
deb http://security.debian.org/debian-security bookworm-security main contrib non-free non-free-firmware
|
|
SOURCES
|
|
|
|
# Install Guacamole dependencies
|
|
log_info "Installing Guacamole dependencies (this takes a while)..."
|
|
chroot "$LXC_ROOTFS" /bin/sh -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get update && \
|
|
apt-get install -y --no-install-recommends \
|
|
openjdk-17-jre-headless \
|
|
tomcat10 \
|
|
wget \
|
|
ca-certificates \
|
|
libcairo2 libpng-dev libjpeg62-turbo-dev libpango1.0-dev \
|
|
libssh2-1 libvncserver1 freerdp2-dev libfreerdp-client2-2 \
|
|
libssl-dev libavutil-dev libswscale-dev libvorbis-dev \
|
|
libpulse-dev uuid-dev libtelnet-dev libwebsockets-dev
|
|
" || {
|
|
log_error "Failed to install base dependencies"
|
|
return 1
|
|
}
|
|
|
|
# Build guacd from source (not in Debian repos)
|
|
log_info "Building guacd from source..."
|
|
chroot "$LXC_ROOTFS" /bin/sh -c "
|
|
export DEBIAN_FRONTEND=noninteractive
|
|
apt-get install -y --no-install-recommends build-essential autoconf automake libtool pkg-config && \
|
|
cd /tmp && \
|
|
wget -q https://apache.org/dyn/closer.lua/guacamole/${GUAC_VERSION}/source/guacamole-server-${GUAC_VERSION}.tar.gz?action=download -O guacamole-server.tar.gz || \
|
|
wget -q https://dlcdn.apache.org/guacamole/${GUAC_VERSION}/source/guacamole-server-${GUAC_VERSION}.tar.gz -O guacamole-server.tar.gz && \
|
|
tar xzf guacamole-server.tar.gz && \
|
|
cd guacamole-server-${GUAC_VERSION} && \
|
|
autoreconf -fi && \
|
|
./configure --with-init-dir=/etc/init.d && \
|
|
make -j\$(nproc) && \
|
|
make install && \
|
|
ldconfig && \
|
|
cd / && rm -rf /tmp/guacamole-server*
|
|
" || {
|
|
log_error "Failed to build guacd"
|
|
return 1
|
|
}
|
|
|
|
# Download Guacamole client WAR
|
|
log_info "Downloading Guacamole client v${GUAC_VERSION}..."
|
|
local war_url="https://apache.org/dyn/closer.lua/guacamole/${GUAC_VERSION}/binary/guacamole-${GUAC_VERSION}.war?action=download"
|
|
wget -q -O "$LXC_ROOTFS/var/lib/tomcat10/webapps/guacamole.war" "$war_url" || {
|
|
# Try mirror
|
|
war_url="https://dlcdn.apache.org/guacamole/${GUAC_VERSION}/binary/guacamole-${GUAC_VERSION}.war"
|
|
wget -q -O "$LXC_ROOTFS/var/lib/tomcat10/webapps/guacamole.war" "$war_url" || {
|
|
log_error "Failed to download Guacamole WAR"
|
|
return 1
|
|
}
|
|
}
|
|
|
|
# Create Guacamole config directory
|
|
mkdir -p "$LXC_ROOTFS/etc/guacamole"
|
|
|
|
# Create guacamole.properties
|
|
cat > "$LXC_ROOTFS/etc/guacamole/guacamole.properties" <<'EOF'
|
|
guacd-hostname: localhost
|
|
guacd-port: 4822
|
|
user-mapping: /etc/guacamole/user-mapping.xml
|
|
EOF
|
|
|
|
# Create startup script
|
|
cat > "$LXC_ROOTFS/opt/start-guacamole.sh" <<'STARTUP'
|
|
#!/bin/sh
|
|
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
|
|
|
# Start guacd
|
|
/usr/sbin/guacd -b 127.0.0.1 -l 4822 &
|
|
GUACD_PID=$!
|
|
|
|
# Wait for guacd
|
|
sleep 2
|
|
|
|
# Set GUACAMOLE_HOME
|
|
export GUACAMOLE_HOME=/etc/guacamole
|
|
|
|
# Start Tomcat in foreground
|
|
cd /var/lib/tomcat10
|
|
exec /usr/share/tomcat10/bin/catalina.sh run
|
|
STARTUP
|
|
chmod +x "$LXC_ROOTFS/opt/start-guacamole.sh"
|
|
|
|
log_info "Rootfs created successfully"
|
|
}
|
|
|
|
lxc_create_config() {
|
|
defaults
|
|
local mem_bytes=$((memory * 1024 * 1024))
|
|
|
|
ensure_dir "$LXC_PATH/$LXC_NAME"
|
|
ensure_dir "$data_path"
|
|
|
|
cat > "$LXC_CONF" <<EOF
|
|
# Guacamole LXC Container
|
|
lxc.uts.name = $LXC_NAME
|
|
lxc.rootfs.path = dir:$LXC_ROOTFS
|
|
lxc.arch = $(detect_arch)
|
|
|
|
# Network: share host network
|
|
lxc.net.0.type = none
|
|
|
|
# Auto-mounts
|
|
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
|
|
|
|
# Bind mount for persistent config
|
|
lxc.mount.entry = $data_path etc/guacamole none bind,create=dir 0 0
|
|
|
|
# Resource limits
|
|
lxc.cgroup2.memory.max = $mem_bytes
|
|
|
|
# Security
|
|
lxc.cap.drop = sys_module mac_admin mac_override sys_time
|
|
|
|
# TTY/PTY for cgroup2
|
|
lxc.tty.max = 4
|
|
lxc.pty.max = 16
|
|
lxc.cgroup2.devices.allow = c 1:3 rwm
|
|
lxc.cgroup2.devices.allow = c 1:5 rwm
|
|
lxc.cgroup2.devices.allow = c 1:7 rwm
|
|
lxc.cgroup2.devices.allow = c 1:8 rwm
|
|
lxc.cgroup2.devices.allow = c 1:9 rwm
|
|
lxc.cgroup2.devices.allow = c 5:0 rwm
|
|
lxc.cgroup2.devices.allow = c 5:1 rwm
|
|
lxc.cgroup2.devices.allow = c 5:2 rwm
|
|
lxc.cgroup2.devices.allow = c 136:* rwm
|
|
|
|
# Startup command
|
|
lxc.init.cmd = /opt/start-guacamole.sh
|
|
EOF
|
|
|
|
log_info "LXC config created"
|
|
}
|
|
|
|
# ---------- user mapping ----------
|
|
|
|
generate_user_mapping() {
|
|
defaults
|
|
|
|
local mapping_file="$data_path/user-mapping.xml"
|
|
|
|
cat > "$mapping_file" <<'HEADER'
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<user-mapping>
|
|
<authorize username="admin" password="admin">
|
|
HEADER
|
|
|
|
# Add connections from UCI
|
|
config_load "$CONFIG"
|
|
config_foreach _add_connection_xml connection
|
|
|
|
cat >> "$mapping_file" <<'FOOTER'
|
|
</authorize>
|
|
</user-mapping>
|
|
FOOTER
|
|
|
|
log_info "Generated user-mapping.xml with connections"
|
|
}
|
|
|
|
_add_connection_xml() {
|
|
local section="$1"
|
|
local enabled name protocol hostname port username password
|
|
|
|
config_get enabled "$section" enabled 1
|
|
[ "$enabled" = "1" ] || return 0
|
|
|
|
config_get name "$section" name "$section"
|
|
config_get protocol "$section" protocol "ssh"
|
|
config_get hostname "$section" hostname "127.0.0.1"
|
|
config_get port "$section" port ""
|
|
config_get username "$section" username ""
|
|
config_get password "$section" _password ""
|
|
|
|
defaults
|
|
local mapping_file="$data_path/user-mapping.xml"
|
|
|
|
# Default ports
|
|
[ -z "$port" ] && case "$protocol" in
|
|
ssh) port=22 ;;
|
|
vnc) port=5900 ;;
|
|
rdp) port=3389 ;;
|
|
esac
|
|
|
|
cat >> "$mapping_file" <<EOF
|
|
<connection name="$name">
|
|
<protocol>$protocol</protocol>
|
|
<param name="hostname">$hostname</param>
|
|
<param name="port">$port</param>
|
|
EOF
|
|
|
|
[ -n "$username" ] && echo " <param name=\"username\">$username</param>" >> "$mapping_file"
|
|
[ -n "$password" ] && echo " <param name=\"password\">$password</param>" >> "$mapping_file"
|
|
|
|
echo " </connection>" >> "$mapping_file"
|
|
}
|
|
|
|
# ---------- commands ----------
|
|
|
|
cmd_install() {
|
|
require_root || { log_error "Must run as root"; return 1; }
|
|
|
|
log_info "Installing Apache Guacamole..."
|
|
|
|
# Check prerequisites
|
|
ensure_packages lxc lxc-common wget || return 1
|
|
|
|
# Create LXC rootfs
|
|
if ! lxc_exists; then
|
|
lxc_create_rootfs || return 1
|
|
fi
|
|
|
|
# Create LXC config
|
|
lxc_create_config
|
|
|
|
# Generate user mapping
|
|
generate_user_mapping
|
|
|
|
# Enable and start
|
|
uci_set enabled '1'
|
|
uci commit "$CONFIG"
|
|
/etc/init.d/guacamole enable
|
|
/etc/init.d/guacamole start
|
|
|
|
defaults
|
|
log_info "Guacamole installed successfully"
|
|
log_info "Access at: http://$(uci -q get network.lan.ipaddr || echo '192.168.255.1'):${web_port}/guacamole/"
|
|
log_info "Default credentials: admin / admin"
|
|
}
|
|
|
|
cmd_uninstall() {
|
|
require_root || { log_error "Must run as root"; return 1; }
|
|
|
|
log_info "Uninstalling Guacamole..."
|
|
|
|
# Stop and disable
|
|
/etc/init.d/guacamole stop 2>/dev/null
|
|
/etc/init.d/guacamole disable 2>/dev/null
|
|
lxc_stop
|
|
|
|
# Remove container but keep config
|
|
rm -rf "$LXC_ROOTFS" "$LXC_CONF"
|
|
|
|
uci_set enabled '0'
|
|
uci commit "$CONFIG"
|
|
|
|
defaults
|
|
log_info "Container removed. Config preserved in $data_path"
|
|
}
|
|
|
|
cmd_update() {
|
|
require_root || { log_error "Must run as root"; return 1; }
|
|
|
|
log_info "Updating Guacamole..."
|
|
lxc_stop
|
|
|
|
# Re-download WAR
|
|
local war_url="https://dlcdn.apache.org/guacamole/${GUAC_VERSION}/binary/guacamole-${GUAC_VERSION}.war"
|
|
wget -q -O "$LXC_ROOTFS/var/lib/tomcat10/webapps/guacamole.war" "$war_url" || {
|
|
log_error "Failed to download new version"
|
|
return 1
|
|
}
|
|
|
|
# Remove expanded webapp
|
|
rm -rf "$LXC_ROOTFS/var/lib/tomcat10/webapps/guacamole"
|
|
|
|
/etc/init.d/guacamole start
|
|
log_info "Update complete"
|
|
}
|
|
|
|
cmd_check() {
|
|
echo "Guacamole Prerequisites Check"
|
|
echo "=============================="
|
|
|
|
# LXC
|
|
if command -v lxc-start >/dev/null 2>&1; then
|
|
echo "[OK] LXC installed"
|
|
else
|
|
echo "[FAIL] LXC not installed"
|
|
fi
|
|
|
|
# Container exists
|
|
if lxc_exists; then
|
|
echo "[OK] Container exists"
|
|
else
|
|
echo "[--] Container not created"
|
|
fi
|
|
|
|
# Container running
|
|
if lxc_running; then
|
|
echo "[OK] Container running"
|
|
else
|
|
echo "[--] Container not running"
|
|
fi
|
|
|
|
# Tomcat port
|
|
defaults
|
|
if netstat -tln 2>/dev/null | grep -q ":${web_port} " || \
|
|
grep -q ":$(printf '%04X' $web_port) " /proc/net/tcp 2>/dev/null; then
|
|
echo "[OK] Tomcat listening on port $web_port"
|
|
else
|
|
echo "[--] Tomcat not listening"
|
|
fi
|
|
}
|
|
|
|
cmd_status() {
|
|
defaults
|
|
|
|
echo "Guacamole Status"
|
|
echo "================"
|
|
echo ""
|
|
echo "Configuration:"
|
|
echo " Enabled: $(uci_get enabled || echo '0')"
|
|
echo " Web Port: $web_port"
|
|
echo " Memory: ${memory}M"
|
|
echo " Data Path: $data_path"
|
|
echo ""
|
|
|
|
if lxc_exists; then
|
|
echo "Container: EXISTS"
|
|
else
|
|
echo "Container: NOT CREATED (run: guacamolectl install)"
|
|
return 0
|
|
fi
|
|
|
|
if lxc_running; then
|
|
echo "State: RUNNING"
|
|
lxc-info -n "$LXC_NAME" | grep -E "PID|Memory" | sed 's/^/ /'
|
|
else
|
|
echo "State: STOPPED"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Access URL: http://$(uci -q get network.lan.ipaddr || echo '192.168.255.1'):${web_port}/guacamole/"
|
|
echo "Credentials: admin / admin (change after first login)"
|
|
}
|
|
|
|
cmd_logs() {
|
|
local lines="${1:-50}"
|
|
|
|
if lxc_running; then
|
|
echo "=== Tomcat logs ==="
|
|
lxc_exec tail -n "$lines" /var/log/tomcat10/catalina.out 2>/dev/null || \
|
|
echo "No Tomcat logs"
|
|
|
|
echo ""
|
|
echo "=== guacd logs ==="
|
|
lxc_exec tail -n "$lines" /var/log/syslog 2>/dev/null | grep guacd || \
|
|
echo "No guacd logs"
|
|
else
|
|
echo "Container not running"
|
|
fi
|
|
}
|
|
|
|
cmd_shell() {
|
|
if lxc_running; then
|
|
lxc_exec /bin/bash || lxc_exec /bin/sh
|
|
else
|
|
log_error "Container not running"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
cmd_add_ssh() {
|
|
local name="$1"
|
|
local host="$2"
|
|
local port="${3:-22}"
|
|
local user="${4:-root}"
|
|
|
|
[ -z "$name" ] || [ -z "$host" ] && { echo "Usage: guacamolectl add-ssh <name> <host> [port] [user]"; return 1; }
|
|
|
|
uci set ${CONFIG}.${name}=connection
|
|
uci set ${CONFIG}.${name}.enabled='1'
|
|
uci set ${CONFIG}.${name}.name="$name"
|
|
uci set ${CONFIG}.${name}.protocol='ssh'
|
|
uci set ${CONFIG}.${name}.hostname="$host"
|
|
uci set ${CONFIG}.${name}.port="$port"
|
|
uci set ${CONFIG}.${name}.username="$user"
|
|
uci commit "$CONFIG"
|
|
|
|
generate_user_mapping
|
|
log_info "Added SSH connection: $name -> $host:$port"
|
|
}
|
|
|
|
cmd_add_vnc() {
|
|
local name="$1"
|
|
local host="$2"
|
|
local port="${3:-5900}"
|
|
|
|
[ -z "$name" ] || [ -z "$host" ] && { echo "Usage: guacamolectl add-vnc <name> <host> [port]"; return 1; }
|
|
|
|
uci set ${CONFIG}.${name}=connection
|
|
uci set ${CONFIG}.${name}.enabled='1'
|
|
uci set ${CONFIG}.${name}.name="$name"
|
|
uci set ${CONFIG}.${name}.protocol='vnc'
|
|
uci set ${CONFIG}.${name}.hostname="$host"
|
|
uci set ${CONFIG}.${name}.port="$port"
|
|
uci commit "$CONFIG"
|
|
|
|
generate_user_mapping
|
|
log_info "Added VNC connection: $name -> $host:$port"
|
|
}
|
|
|
|
cmd_add_rdp() {
|
|
local name="$1"
|
|
local host="$2"
|
|
local port="${3:-3389}"
|
|
local user="$4"
|
|
|
|
[ -z "$name" ] || [ -z "$host" ] && { echo "Usage: guacamolectl add-rdp <name> <host> [port] [user]"; return 1; }
|
|
|
|
uci set ${CONFIG}.${name}=connection
|
|
uci set ${CONFIG}.${name}.enabled='1'
|
|
uci set ${CONFIG}.${name}.name="$name"
|
|
uci set ${CONFIG}.${name}.protocol='rdp'
|
|
uci set ${CONFIG}.${name}.hostname="$host"
|
|
uci set ${CONFIG}.${name}.port="$port"
|
|
[ -n "$user" ] && uci set ${CONFIG}.${name}.username="$user"
|
|
uci commit "$CONFIG"
|
|
|
|
generate_user_mapping
|
|
log_info "Added RDP connection: $name -> $host:$port"
|
|
}
|
|
|
|
cmd_list_connections() {
|
|
echo "Configured Connections:"
|
|
echo "======================="
|
|
config_load "$CONFIG"
|
|
config_foreach _list_connection connection
|
|
}
|
|
|
|
_list_connection() {
|
|
local section="$1"
|
|
local enabled name protocol hostname port
|
|
|
|
config_get enabled "$section" enabled 1
|
|
config_get name "$section" name "$section"
|
|
config_get protocol "$section" protocol "?"
|
|
config_get hostname "$section" hostname "?"
|
|
config_get port "$section" port ""
|
|
|
|
local status="enabled"
|
|
[ "$enabled" != "1" ] && status="disabled"
|
|
|
|
printf " %-15s %-5s %s:%s [%s]\n" "$name" "$protocol" "$hostname" "$port" "$status"
|
|
}
|
|
|
|
cmd_configure_haproxy() {
|
|
require_root || { log_error "Must run as root"; return 1; }
|
|
defaults
|
|
|
|
local domain=$(uci_get domain network)
|
|
|
|
if command -v haproxyctl >/dev/null 2>&1; then
|
|
haproxyctl add-vhost "$domain" "127.0.0.1:${web_port}" 2>&1
|
|
uci_set haproxy '1' network
|
|
uci commit "$CONFIG"
|
|
log_info "HAProxy vhost configured for $domain"
|
|
else
|
|
log_error "haproxyctl not available"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
cmd_mesh_register() {
|
|
defaults
|
|
|
|
if [ -x /usr/sbin/secubox-p2p ]; then
|
|
/usr/sbin/secubox-p2p register-service guacamole "$web_port" 2>/dev/null
|
|
log_info "Registered Guacamole with mesh"
|
|
else
|
|
log_error "secubox-p2p not available"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# ---------- service management ----------
|
|
|
|
cmd_service_run() {
|
|
require_root || exit 1
|
|
defaults
|
|
|
|
# Verify container exists
|
|
lxc_exists || { log_error "Container not found. Run: guacamolectl install"; exit 1; }
|
|
|
|
# Regenerate user mapping in case config changed
|
|
generate_user_mapping
|
|
|
|
log_info "Starting Guacamole container..."
|
|
|
|
# Start container in foreground
|
|
exec lxc-start -n "$LXC_NAME" -F -f "$LXC_CONF"
|
|
}
|
|
|
|
cmd_service_stop() {
|
|
log_info "Stopping Guacamole container..."
|
|
lxc_stop
|
|
}
|
|
|
|
# ---------- main ----------
|
|
|
|
case "$1" in
|
|
install) cmd_install ;;
|
|
uninstall) cmd_uninstall ;;
|
|
update) cmd_update ;;
|
|
check) cmd_check ;;
|
|
status) cmd_status ;;
|
|
logs) shift; cmd_logs "$@" ;;
|
|
shell) cmd_shell ;;
|
|
add-ssh) shift; cmd_add_ssh "$@" ;;
|
|
add-vnc) shift; cmd_add_vnc "$@" ;;
|
|
add-rdp) shift; cmd_add_rdp "$@" ;;
|
|
list-connections) cmd_list_connections ;;
|
|
configure-haproxy) cmd_configure_haproxy ;;
|
|
mesh-register) cmd_mesh_register ;;
|
|
service-run) cmd_service_run ;;
|
|
service-stop) cmd_service_stop ;;
|
|
*) usage; exit 1 ;;
|
|
esac
|