diff --git a/ct/termix.sh b/ct/termix.sh new file mode 100644 index 000000000..b78d38009 --- /dev/null +++ b/ct/termix.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2026 community-scripts ORG +# Author: MickLesk (CanbiZ) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/Termix-SSH/Termix + +APP="Termix" +var_tags="${var_tags:-ssh;terminal;management}" +var_cpu="${var_cpu:-4}" +var_ram="${var_ram:-4096}" +var_disk="${var_disk:-10}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + + if [[ ! -d /opt/termix ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "termix" "Termix-SSH/Termix"; then + msg_info "Stopping Service" + systemctl stop termix + msg_ok "Stopped Service" + + msg_info "Backing up Data" + cp -r /opt/termix/data /opt/termix_data_backup + msg_ok "Backed up Data" + + CLEAN_INSTALL=1 fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix" + + msg_info "Building Frontend" + cd /opt/termix + export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 + find public/fonts -name "*.ttf" ! -name "*Regular.ttf" ! -name "*Bold.ttf" ! -name "*Italic.ttf" -delete 2>/dev/null || true + $STD npm install --ignore-scripts --force + $STD npm run build + msg_ok "Built Frontend" + + msg_info "Building Backend" + $STD npm rebuild better-sqlite3 --force + $STD npm run build:backend + msg_ok "Built Backend" + + msg_info "Setting up Production Dependencies" + $STD npm ci --only=production --ignore-scripts --force + $STD npm rebuild better-sqlite3 bcryptjs --force + $STD npm cache clean --force + msg_ok "Set up Production Dependencies" + + msg_info "Restoring Data" + mkdir -p /opt/termix/data + cp -r /opt/termix_data_backup/. /opt/termix/data + rm -rf /opt/termix_data_backup + msg_ok "Restored Data" + + msg_info "Updating Frontend Files" + rm -rf /opt/termix/html/* + cp -r /opt/termix/dist/* /opt/termix/html/ 2>/dev/null || true + cp -r /opt/termix/src/locales /opt/termix/html/locales 2>/dev/null || true + cp -r /opt/termix/public/fonts /opt/termix/html/fonts 2>/dev/null || true + msg_ok "Updated Frontend Files" + + msg_info "Starting Service" + systemctl start termix + msg_ok "Started Service" + msg_ok "Updated successfully!" + fi + exit +} + +start +build_container +description + +msg_ok "Completed Successfully!\n" +echo -e "${CREATING}${GN}${APP} setup has been successfully initialized!${CL}" +echo -e "${INFO}${YW} Access it using the following URL:${CL}" +echo -e "${TAB}${GATEWAY}${BGN}http://${IP}${CL}" diff --git a/frontend/public/json/termix.json b/frontend/public/json/termix.json new file mode 100644 index 000000000..21e590170 --- /dev/null +++ b/frontend/public/json/termix.json @@ -0,0 +1,35 @@ +{ + "name": "Termix", + "slug": "termix", + "categories": [ + 6 + ], + "date_created": "2026-01-16", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 80, + "documentation": "https://docs.termix.site/", + "website": "https://termix.site/", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons@main/webp/termix.webp", + "config_path": "", + "description": "Termix is an open-source, self-hosted server management platform with SSH terminal access, SSH tunneling, remote file management, Docker management, and multi-platform support.", + "install_methods": [ + { + "type": "default", + "script": "ct/termix.sh", + "resources": { + "cpu": 4, + "ram": 4096, + "hdd": 10, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [] +} diff --git a/install/termix-install.sh b/install/termix-install.sh new file mode 100644 index 000000000..c125945fd --- /dev/null +++ b/install/termix-install.sh @@ -0,0 +1,258 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2026 community-scripts ORG +# Author: MickLesk (CanbiZ) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://github.com/Termix-SSH/Termix + +source /dev/stdin <<<"$FUNCTIONS_FILE_PATH" +color +verb_ip6 +catch_errors +setting_up_container +network_check +update_os + +msg_info "Installing Dependencies" +$STD apt install -y \ + build-essential \ + python3 \ + nginx \ + openssl \ + gettext-base +msg_ok "Installed Dependencies" + +NODE_VERSION="22" setup_nodejs +fetch_and_deploy_gh_release "termix" "Termix-SSH/Termix" + +msg_info "Building Frontend" +cd /opt/termix +export COREPACK_ENABLE_DOWNLOAD_PROMPT=0 +find public/fonts -name "*.ttf" ! -name "*Regular.ttf" ! -name "*Bold.ttf" ! -name "*Italic.ttf" -delete 2>/dev/null || true +$STD npm install --ignore-scripts --force +$STD npm cache clean --force +$STD npm run build +msg_ok "Built Frontend" + +msg_info "Building Backend" +$STD npm rebuild better-sqlite3 --force +$STD npm run build:backend +msg_ok "Built Backend" + +msg_info "Setting up Node Dependencies" +cd /opt/termix +$STD npm ci --only=production --ignore-scripts --force +$STD npm rebuild better-sqlite3 bcryptjs --force +$STD npm cache clean --force +msg_ok "Set up Node Dependencies" + +msg_info "Setting up Directories" +mkdir -p /opt/termix/data \ + /opt/termix/uploads \ + /opt/termix/html \ + /opt/termix/nginx \ + /opt/termix/nginx/logs \ + /opt/termix/nginx/cache \ + /opt/termix/nginx/client_body + +cp -r /opt/termix/dist/* /opt/termix/html/ 2>/dev/null || true +cp -r /opt/termix/src/locales /opt/termix/html/locales 2>/dev/null || true +cp -r /opt/termix/public/fonts /opt/termix/html/fonts 2>/dev/null || true +msg_ok "Set up Directories" + +msg_info "Configuring Nginx" +cat <<'EOF' >/etc/nginx/sites-available/termix.conf +error_log /opt/termix/nginx/logs/error.log warn; + +events { + worker_connections 1024; +} + +http { + include /etc/nginx/mime.types; + default_type application/octet-stream; + access_log /opt/termix/nginx/logs/access.log; + + client_body_temp_path /opt/termix/nginx/client_body; + proxy_temp_path /opt/termix/nginx/proxy_temp; + + sendfile on; + keepalive_timeout 65; + client_header_timeout 300s; + + server { + listen 80; + server_name _; + + add_header X-Content-Type-Options nosniff always; + add_header X-XSS-Protection "1; mode=block" always; + + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + root /opt/termix/html; + expires 1y; + add_header Cache-Control "public, immutable"; + try_files $uri =404; + } + + location / { + root /opt/termix/html; + index index.html; + try_files $uri $uri/ /index.html; + } + + location ~ ^/users(/.*)?$ { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~ ^/(version|releases|alerts|rbac|credentials|snippets|terminal|encryption)(/.*)?$ { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + } + + location ~ ^/(database|db)(/.*)?$ { + client_max_body_size 5G; + client_body_timeout 300s; + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_connect_timeout 60s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; + proxy_request_buffering off; + proxy_buffering off; + } + + location /ssh/ { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location /ssh/websocket/ { + proxy_pass http://127.0.0.1:30002/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_set_header X-Real-IP $remote_addr; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + proxy_buffering off; + proxy_request_buffering off; + } + + location /ssh/tunnel/ { + proxy_pass http://127.0.0.1:30003; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location /ssh/file_manager/ssh/ { + client_max_body_size 5G; + client_body_timeout 300s; + proxy_pass http://127.0.0.1:30004; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_connect_timeout 60s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; + proxy_request_buffering off; + proxy_buffering off; + } + + location ~ ^/ssh/file_manager/(recent|pinned|shortcuts)$ { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location /health { + proxy_pass http://127.0.0.1:30001; + proxy_http_version 1.1; + proxy_set_header Host $host; + } + + location ~ ^/(status|metrics)(/.*)?$ { + proxy_pass http://127.0.0.1:30005; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location ~ ^/(uptime|activity)(/.*)?$ { + proxy_pass http://127.0.0.1:30006; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + } + + location ^~ /docker/console/ { + proxy_pass http://127.0.0.1:30008/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + proxy_buffering off; + proxy_request_buffering off; + } + + location ~ ^/docker(/.*)?$ { + proxy_pass http://127.0.0.1:30007; + proxy_http_version 1.1; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_connect_timeout 60s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; + } + } +} +EOF +rm -f /etc/nginx/sites-enabled/default +rm -f /etc/nginx/nginx.conf +ln -sf /etc/nginx/sites-available/termix.conf /etc/nginx/nginx.conf +systemctl reload nginx +msg_ok "Configured Nginx" + +msg_info "Creating Service" +cat </etc/systemd/system/termix.service +[Unit] +Description=Termix Backend +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/termix +Environment=NODE_ENV=production +Environment=DATA_DIR=/opt/termix/data +ExecStart=/usr/bin/node /opt/termix/dist/backend/backend/starter.js +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now termix +msg_ok "Created Service" + +motd_ssh +customize +cleanup_lxc