diff --git a/ct/headers/pangolin b/ct/headers/pangolin new file mode 100644 index 000000000..0a2d42304 --- /dev/null +++ b/ct/headers/pangolin @@ -0,0 +1,6 @@ + ____ ___ + / __ \____ _____ ____ _____ / (_)___ + / /_/ / __ `/ __ \/ __ `/ __ \/ / / __ \ + / ____/ /_/ / / / / /_/ / /_/ / / / / / / +/_/ \__,_/_/ /_/\__, /\____/_/_/_/ /_/ + /____/ diff --git a/ct/pangolin.sh b/ct/pangolin.sh new file mode 100644 index 000000000..704299ff2 --- /dev/null +++ b/ct/pangolin.sh @@ -0,0 +1,83 @@ +#!/usr/bin/env bash +source <(curl -fsSL https://raw.githubusercontent.com/community-scripts/ProxmoxVE/main/misc/build.func) +# Copyright (c) 2021-2025 community-scripts ORG +# Author: Slaviša Arežina (tremor021) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://pangolin.net/ + +APP="Pangolin" +var_tags="${var_tags:-proxy}" +var_cpu="${var_cpu:-2}" +var_ram="${var_ram:-4096}" +var_disk="${var_disk:-5}" +var_os="${var_os:-debian}" +var_version="${var_version:-13}" +var_unprivileged="${var_unprivileged:-1}" +var_tun="${var_tun:-1}" + +header_info "$APP" +variables +color +catch_errors + +function update_script() { + header_info + check_container_storage + check_container_resources + if [[ ! -d /opt/pangolin ]]; then + msg_error "No ${APP} Installation Found!" + exit + fi + + if check_for_gh_release "pangolin" "fosrl/pangolin"; then + msg_info "Stopping Service" + systemctl stop pangolin + msg_info "Service stopped" + + msg_info "Creating backup" + tar -czf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin config + msg_ok "Created backup" + + fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" + fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64" + + msg_info "Updating Pangolin" + export BUILD=oss + export DATABASE=sqlite + cd /opt/pangolin + $STD npm ci + echo "export * from \"./$DATABASE\";" > server/db/index.ts + echo "export const build = \"$BUILD\" as any;" > server/build.ts + cp tsconfig.oss.json tsconfig.json + $STD npm run next:build + $STD node esbuild.mjs -e server/index.ts -o dist/server.mjs -b $BUILD + $STD node esbuild.mjs -e server/setup/migrationsSqlite.ts -o dist/migrations.mjs + $STD npm run build:cli + cp -R .next/standalone ./ + + cat </usr/local/bin/pangctl +#!/bin/sh +cd /opt/pangolin +./dist/cli.mjs "$@" +EOF + chmod +x /usr/local/bin/pangctl ./dist/cli.mjs + cp server/db/names.json ./dist/names.json + msg_ok "Updated Pangolin" + + msg_info "Restoring config" + tar -xzf /opt/pangolin_config_backup.tar.gz -C /opt/pangolin --overwrite + rm -f /opt/pangolin_config_backup.tar.gz + msg_ok "Restored config" + 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}:3002${CL}" diff --git a/frontend/public/json/pangolin.json b/frontend/public/json/pangolin.json new file mode 100644 index 000000000..8cd3c13b2 --- /dev/null +++ b/frontend/public/json/pangolin.json @@ -0,0 +1,48 @@ +{ + "name": "Pangolin", + "slug": "pangolin", + "categories": [ + 21 + ], + "date_created": "2025-11-01", + "type": "ct", + "updateable": true, + "privileged": false, + "interface_port": 3002, + "documentation": "https://docs.pangolin.net/", + "config_path": "/opt/pangolin/config/config.yml", + "website": "https://pangolin.net/", + "logo": "https://cdn.jsdelivr.net/gh/selfhst/icons/webp/pangolin.webp", + "description": "Pangolin securely routes traffic over WireGuard tunnels to any private network. It works like a reverse proxy that spans multiple networks — no public IPs, DNS setup, or certificates required.", + "install_methods": [ + { + "type": "default", + "script": "ct/pangolin.sh", + "resources": { + "cpu": 2, + "ram": 4096, + "hdd": 5, + "os": "Debian", + "version": "13" + } + } + ], + "default_credentials": { + "username": null, + "password": null + }, + "notes": [ + { + "text": "Type `journalctl -u pangolin | grep -oP 'Token:\\s*\\K\\w+'` into LXC console to get admin token which you will use to create admin account.", + "type": "info" + }, + { + "text": "LXC has 4GB of RAM set initially for the build stage. After installation finishes, you can decrease the RAM allocated to 1024MB or 512MB even.", + "type": "info" + }, + { + "text": "Make sure you edit `/opt/pangolin/config/config.yml` and change it to match your needs", + "type": "warning" + } + ] +} diff --git a/install/pangolin-install.sh b/install/pangolin-install.sh new file mode 100644 index 000000000..9e2cdb09d --- /dev/null +++ b/install/pangolin-install.sh @@ -0,0 +1,137 @@ +#!/usr/bin/env bash + +# Copyright (c) 2021-2025 community-scripts ORG +# Author: Slaviša Arežina (tremor021) +# License: MIT | https://github.com/community-scripts/ProxmoxVE/raw/main/LICENSE +# Source: https://pangolin.net/ + +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 \ + sqlite3 \ + iptables +msg_ok "Installed Dependencies" + +NODE_VERSION="22" setup_nodejs +fetch_and_deploy_gh_release "pangolin" "fosrl/pangolin" "tarball" +fetch_and_deploy_gh_release "gerbil" "fosrl/gerbil" "singlefile" "latest" "/usr/bin" "gerbil_linux_amd64" + +msg_info "Setup Pangolin" +IP_ADDR=$(hostname -I | awk '{print $1}') +SECRET_KEY=$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | head -c 32) +export BUILD=oss +export DATABASE=sqlite +cd /opt/pangolin +$STD npm ci +echo "export * from \"./$DATABASE\";" > server/db/index.ts +echo "export const build = \"$BUILD\" as any;" > server/build.ts +cp tsconfig.oss.json tsconfig.json +mkdir -p dist +$STD npm run next:build +$STD node esbuild.mjs -e server/index.ts -o dist/server.mjs -b $BUILD +$STD node esbuild.mjs -e server/setup/migrationsSqlite.ts -o dist/migrations.mjs +$STD npm run build:cli +cp -R .next/standalone ./ + +cat </usr/local/bin/pangctl +#!/bin/sh +cd /opt/pangolin +./dist/cli.mjs "$@" +EOF +chmod +x /usr/local/bin/pangctl ./dist/cli.mjs +cp server/db/names.json ./dist/names.json +mkdir -p /var/config + +cat </opt/pangolin/config/config.yml +app: + dashboard_url: http://$IP_ADDR:3002 + log_level: debug + +domains: + domain1: + base_domain: example.com + +server: + secret: $SECRET_KEY + +gerbil: + base_endpoint: example.com + +orgs: + block_size: 24 + subnet_group: 100.90.137.0/20 + +flags: + require_email_verification: false + disable_signup_without_invite: true + disable_user_create_org: true + allow_raw_resources: true + enable_integration_api: true + enable_clients: true +EOF +$STD npm run db:sqlite:generate +$STD npm run db:sqlite:push + +. /etc/os-release +if [ "$VERSION_CODENAME" = "trixie" ]; then + echo "net.ipv4.ip_forward=1" >>/etc/sysctl.d/sysctl.conf + $STD sysctl -p /etc/sysctl.d/sysctl.conf +else + echo "net.ipv4.ip_forward=1" >>/etc/sysctl.conf + $STD sysctl -p /etc/sysctl.conf +fi +msg_ok "Setup Pangolin" + +msg_info "Creating Services" +cat </etc/systemd/system/pangolin.service +[Unit] +Description=Pangolin Service +After=network.target + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/pangolin +ExecStart=/usr/bin/npm start +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now pangolin + +cat </etc/systemd/system/gerbil.service +[Unit] +Description=Gerbil Service +After=network.target +Requires=pangolin.service + +[Service] +Type=simple +User=root +ExecStart=/usr/bin/gerbil --reachableAt=http://$IP_ADDR:3004 --generateAndSaveKeyTo=/var/config/key --remoteConfig=http://$IP_ADDR:3001/api/v1/ +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +EOF +systemctl enable -q --now gerbil +msg_ok "Created Services" + +motd_ssh +customize + +msg_info "Cleaning up" +$STD apt -y autoremove +$STD apt -y autoclean +$STD apt -y clean +msg_ok "Cleaned"