Interactive Linux server automation toolkit — one unified launcher, 39 scripts across 10 categories: system setup, security hardening, databases, app runtimes, cloud panels, network & tunneling, monitoring, observability, CI/CD runners, and AI & agents.
Run scripts individually, use install.sh, or use ./wf, a zero-dependency
portable keyboard-driven dual-pane TUI dashboard. It features live search,
category sidebars, code inspector (v), batch multi-select (b), and runs 100%
portably in-place without polluting system directories or requiring root.
No authentication required — public repo, served via GitHub Pages at scripts.wanforge.asia.
Scripts are organized under script/linux/<category>/, structured so future
macOS or Windows scripts can be added alongside without changing the layout.
script/linux/; macOS/Windows
variants would go in script/macos/ / script/windows/ when added.~/.cache/wanforge-scripts). No dependencies to install the TUI.apt, dnf, yum, pacman, zypper, or apk.
Some scripts are Debian/Ubuntu only (noted in the table below).curl and sudo (or root). Node.js, Composer, and PM2 install
user-local — no sudo needed for those./dev/tty).curl first (fresh systems)A minimal install may not ship curl. Install it for your distro:
# Debian / Ubuntu
sudo apt update && sudo apt install -y curl
# Fedora / RHEL / CentOS / Rocky / Alma
sudo dnf install -y curl # or: sudo yum install -y curl
# Arch / Manjaro
sudo pacman -Sy --noconfirm curl
# openSUSE
sudo zypper install -y curl
# Alpine
sudo apk add curl
If you are root (e.g. a fresh container/VM), drop the sudo. No package
manager handy? curl usually rides along with wget — see the wget alternative
below.
# Remote one-liner (Zero installation, runs in memory/user-space cache)
curl -fsSL https://scripts.wanforge.asia/install.sh | bash
# Or via cloned repository
./wf # or: ./install.sh
No curl? Use wget instead (present on many minimal images):
wget -qO- https://scripts.wanforge.asia/install.sh | bash
The new keyboard-driven TUI provides a dual-pane interface with alternate screen buffering (leaves your terminal prompt 100% clean upon exit):
| Key / Shortcut | Action |
|---|---|
↑ / ↓ / k/j |
Move selection in the active pane |
Tab / ← / → |
Switch focus between Category pane and Tools pane |
Enter |
Run selected script (or focus tools pane from category) |
v |
View Code: Inspect script source in pager without running |
/ or s |
Live Search: Instant real-time filter across all 39 tools |
b |
Batch Mode: Multi-select and run several tools in order |
i |
System Snapshot: Instant audit popup (OS, RAM, CPU, IP) |
1 – 9, 0 |
Direct jump to category index 1 to 10 |
q / Esc |
Cleanly exit back to original shell prompt |
All scripts can also be invoked non-interactively without the TUI:
# List all 39 tools with indices and descriptions
./wf list
# Run a specific script directly by name or global number
./wf setup-motd
./wf docker
./wf 6 # Global #6 (setup-motd)
# Open a category submenu directly (1-10)
./wf 1 # System category
./wf 2 # Security category
# Run a specific script by category & tool number
./wf 1 6 # Category 1 (System), Tool 6 (setup-motd)
# Search tools by keyword non-interactively
./wf search docker
# Server quick status audit
./wf info
# Classic prompt menu fallback (if running on primitive terminal)
./wf --classic
Select scripts to run:
↑/↓ move · SPACE toggle · A all · ENTER confirm · Q quit
── System ──
❯ [✓] install-packages Update system + base essentials (micro, curl, wget, git)
[✓] set-timezone Set timezone (UTC recommended for servers)
[✓] backup-tools Backup manager: S3 / FTP / SFTP — named profiles, cron, dry-run
[✓] sys-troubleshoot Diagnostics & troubleshooting: CPU, RAM, services, OOM, logs, firewall, network
[✓] hardware-info Hardware audit: CPU, RAM, disks, GPU, firmware, NIC, sensors, virt
[✓] setup-motd Custom dynamic SSH login banner (MOTD) with live system KPIs
── Security ──
[✓] install-firewall Install & configure ufw firewall
[✓] firewall-manager Full ufw manager: allow/deny IP/port, multiple, rate-limit
[✓] install-fail2ban Install, optimize & manage Fail2Ban (progressive ban, recidive)
[✓] secure-ssh Harden SSH: audit, port change, root/pw lockdown, SELinux & firewall
[✓] generate-ssh-key Generate an ed25519 SSH key (user-local)
[✓] manage-users Manage Linux users, sudo access & SSH keys
[✓] ssl-toolkit SSL/TLS diagnostics & management: remote/local audit, self-signed SAN, TLS handshake debug, Certbot
── Panel & Console ──
[✓] install-cloudpanel Install CloudPanel CE v2 (Ubuntu 24 only)
[✓] clpctl-manager Manage CloudPanel via clpctl (sites, db, users, certs)
[✓] install-cockpit Install Cockpit web console, plugins, proxy & optimized PCP logger
── Database ──
[✓] install-postgresql Install PostgreSQL + create roles + remote access
[✓] enable-mysql-remote Allow remote MySQL/MariaDB access (sensitive)
[✓] database-toolkit Monitor, optimize, config, datetime (MySQL/PostgreSQL)
── App Runtime ──
[✓] install-nodejs Install Node.js via nvm (user-local) + PM2
[✓] install-python Install Python 3 + pip, venv, dev, pipx
[✓] install-composer Install Composer (user-local, signature-verified)
[✓] setup-pm2-app Configure pm2-logrotate + register an app (ecosystem)
[✓] install-docker Docker Engine & Docker Compose (with UFW security patch & container diagnostics)
── Monitoring ──
[✓] monitor-system CPU, RAM, storage, processes, network (snapshot or realtime)
── Network ──
[✓] net-tools Local/public IP, ports, speedtest, ping, dig, scan
[✓] install-cloudflared Install and configure Cloudflare Tunnel daemon
── Proxmox ──
[✓] proxmox-toolkit PVE: node/VM/CT resources, storage, realtime dashboard
── CI/CD ──
[✓] install-github-runner GitHub Actions self-hosted runner (avoid billed minutes)
[✓] install-gitlab-runner GitLab CI/CD self-hosted runner
── Observability ──
[✓] install-prometheus Prometheus + node_exporter (+ Alertmanager)
[✓] install-grafana Grafana + Prometheus data source
[✓] install-zabbix Zabbix agent or server (official repo)
[✓] install-uptime-kuma Uptime Kuma beautiful self-hosted status page
[✓] install-loki Loki + Promtail log aggregator & forwarding agent
[✓] install-goaccess GoAccess real-time web log analyzer (terminal & HTML daemon)
── AI & Agents ──
[✓] install-ai-agents Modular AI stack: Hermes, Claude Code, AGY, 9Router
[✓] setup-hermes-telegram Setup Telegram bot, user/group whitelist, optimizations
[✓] setup-9router-tunnel Cloudflare Tunnel & custom domain reverse proxy for 9Router
flowchart TD
A(["curl | bash install.sh"])
B["TUI Checkbox Menu\n↑/↓ Space A Enter Q\n─ grouped by category ─"]
C(["bash script.sh"])
D["Management Menu\ninstall · stop · start · restart\nenable · disable · status\nremove-cron · uninstall"]
E(["bash script.sh --flag"])
IW["Install / Configure Wizard\n(interactive prompts)"]
SVC["systemctl action\n(stop / start / restart /\nenable / disable / status)"]
CRON["crontab cleanup\n(user + root)"]
RM["Removal Wizard\n(purge packages,\nrepo, firewall rules)"]
A --> B
B -->|"bash script.sh --install\n(skips management menu)"| IW
C -->|no args| D
D -->|install| IW
D -->|stop · start · restart\nenable · disable · status| SVC
D -->|remove-cron| CRON
D -->|uninstall| RM
E -->|"--stop / --start\n--restart / --enable\n--disable / --status"| SVC
E -->|--remove-cron| CRON
E -->|--uninstall| RM
E -->|"--install (or unknown flag)"| IW
style A fill:#1e3a5f,color:#fff,stroke:#4a9eff
style C fill:#1e3a5f,color:#fff,stroke:#4a9eff
style E fill:#1e3a5f,color:#fff,stroke:#4a9eff
style B fill:#2d4a1e,color:#fff,stroke:#6abf40
style D fill:#2d4a1e,color:#fff,stroke:#6abf40
style IW fill:#3a2d1e,color:#fff,stroke:#bf8c40
style SVC fill:#1e2d3a,color:#fff,stroke:#40a0bf
style CRON fill:#1e2d3a,color:#fff,stroke:#40a0bf
style RM fill:#3a1e1e,color:#fff,stroke:#bf4040
Service scripts (fail2ban, grafana, prometheus, zabbix, cockpit, postgresql) use
systemctlfor stop/start/restart/enable/disable/status. backup-tools and setup-pm2-app have their own action sets (backup engine / pm2 commands). Non-service scripts (nodejs, composer, python, ssh-key) only expose install + uninstall.
Every script shares one verbosity control (defined in lib.sh). Set it with an
environment variable (recommended — it also propagates through the launcher) or
a flag:
| Mode | Shows | How |
|---|---|---|
silent |
Errors and final result only, no banner | MODE=silent · QUIET=1 · -q |
normal |
Banner + info/ok/warn/err (default) | MODE=normal (default) |
verbose |
Normal + extra dbg detail |
MODE=verbose · VERBOSE=1 · -v |
debug |
Verbose + shell trace (set -x) |
MODE=debug · DEBUG=1 · --debug |
# silent (good for automation / cron)
curl -fsSL https://scripts.wanforge.asia/install.sh | MODE=silent bash
# verbose
curl -fsSL .../script/linux/monitoring/monitor-system.sh | VERBOSE=1 bash
DRY_RUN=1 (or --dry-run / -n) makes every script print the
state-changing commands instead of running them — defined once in lib.sh, so
it works the same everywhere:
curl -fsSL .../script/linux/security/install-fail2ban.sh | DRY_RUN=1 bash
# → [dry-run] sudo apt-get install -y fail2ban
# [dry-run] sudo systemctl start fail2ban
Dry-run covers system mutations: package managers (install/upgrade/remove),
services (systemctl/rc-service), ufw, sed -i, tee config writes,
timedatectl, file ops, and PostgreSQL VACUUM/REINDEX. Read-only commands
still run so you see real state. A few user-local installs (nvm/Node, Composer,
PM2) and MySQL client mutations execute as normal.
| Variable / flag | Effect |
|---|---|
ASSUME_YES=1 · YES=1 · -y |
ask returns the default answer without prompting (non-interactive) |
LOG_FILE=/path |
Appends a plain-text (no-color) copy of every log line |
NO_COLOR=1 |
Disables colors in any mode |
# fully unattended, dry-run, logged
curl -fsSL .../script/linux/security/install-fail2ban.sh | ASSUME_YES=1 DRY_RUN=1 LOG_FILE=/var/log/wf.log bash
Note: ASSUME_YES only fills prompts that have a safe default; password prompts
and free-text inputs (e.g. role names) still need real input or are skipped.
The user-local scripts (install-nodejs, install-composer, setup-pm2-app)
install into a user’s home — not the system. When you run them as root, they
ask which user to install for (or set TARGET_USER=<name> / --user=<name>) and
re-run themselves as that user via sudo -u, so Node/Composer/PM2 land in that
user’s home. Perfect for CloudPanel site users:
# install Node + PM2 into the CloudPanel site user 'john'
curl -fsSL .../script/linux/runtime/install-nodejs.sh | TARGET_USER=john bash
All menus (launcher and the clpctl / database / firewall managers) are
arrow-key TUIs — ↑/↓ to move, ENTER to select, Q to go back.
Install scripts support sub-commands for granular lifecycle control.
Download the script first (pipe discards $1), then run with a flag:
curl -fsSL .../install-grafana.sh -o install-grafana.sh
bash install-grafana.sh --stop # stop service only
bash install-grafana.sh --disable # stop + disable autostart
bash install-grafana.sh --enable # enable + start
bash install-grafana.sh --restart # restart
bash install-grafana.sh --status # systemctl status (no-pager)
bash install-grafana.sh --remove-cron # remove related cron entries
bash install-grafana.sh --uninstall # full removal (packages, repo, firewall rules)
Available flags per script:
| Script | stop | start | restart | enable | disable | status | remove-cron | uninstall |
|---|---|---|---|---|---|---|---|---|
install-fail2ban.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
install-grafana.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
install-prometheus.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
install-zabbix.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
install-uptime-kuma.sh |
✓ | ✓ | ✓ | — | — | ✓ | — | ✓ |
install-loki.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ |
install-goaccess.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ |
install-cockpit.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
install-postgresql.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ ⚠ |
install-firewall.sh |
--disable |
--enable |
— | --enable |
--disable |
✓ | ✓ | ✓ |
install-firewall.sh (extra) |
--reload · --reset (wipes all rules) |
|||||||
setup-pm2-app.sh |
✓ | ✓ | ✓ | — | — | ✓ | ✓ | ✓ |
setup-pm2-app.sh (extra) |
--logs (tail app logs) |
|||||||
install-nodejs.sh |
— | — | — | — | — | — | ✓ | ✓ |
install-composer.sh |
— | — | — | — | — | — | — | ✓ |
install-python.sh |
— | — | — | — | — | — | — | ✓ |
enable-mysql-remote.sh |
— | — | — | — | — | — | — | ✓ (rollback) |
secure-ssh.sh |
— | — | — | — | — | — | — | ✓ (restore backup) |
generate-ssh-key.sh |
— | — | — | — | — | — | — | ✓ |
install-cloudpanel.sh |
— | — | — | — | — | — | — | ✓ (manual steps) |
install-docker.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ |
install-cloudflared.sh |
✓ | ✓ | ✓ | ✓ | ✓ | ✓ | — | ✓ |
install-github-runner.sh |
✓ | ✓ | ✓ | — | — | ✓ | — | ✓ |
install-gitlab-runner.sh |
✓ | ✓ | ✓ | — | — | ✓ | — | ✓ |
Service scripts (--stop/start/restart/enable/disable/status) use systemctl and
operate on all services the script manages (e.g. prometheus also controls
prometheus-node-exporter and prometheus-alertmanager).
--remove-cron scans both the current user’s and root’s crontab for entries
matching the service name and removes them.
PostgreSQL
--uninstall: prompts twice — once for package removal, once for/var/lib/postgresqldata deletion. Answer carefully.
Each script can also be run directly without the launcher.
# System
curl -fsSL https://scripts.wanforge.asia/script/linux/system/install-packages.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/system/set-timezone.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/system/install-firewall.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/system/backup-tools.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/system/sys-troubleshoot.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/system/hardware-info.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/system/hardware-info.sh | bash -s -- --summary
curl -fsSL https://scripts.wanforge.asia/script/linux/system/hardware-info.sh | bash -s -- --json
curl -fsSL https://scripts.wanforge.asia/script/linux/system/hardware-info.sh | bash -s -- --markdown
# Security
curl -fsSL https://scripts.wanforge.asia/script/linux/security/firewall-manager.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/security/install-fail2ban.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/security/secure-ssh.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/security/generate-ssh-key.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/security/manage-users.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/security/ssl-toolkit.sh | bash
# Panels & consoles
curl -fsSL https://scripts.wanforge.asia/script/linux/cloud/install-cloudpanel.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/cloud/clpctl-manager.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/cloud/install-cockpit.sh | bash
# Databases
curl -fsSL https://scripts.wanforge.asia/script/linux/database/install-postgresql.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/database/enable-mysql-remote.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/database/database-toolkit.sh | bash
# Monitoring & network
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/monitor-system.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/network/net-tools.sh | bash
# Proxmox (run on a PVE node)
curl -fsSL https://scripts.wanforge.asia/script/linux/network/proxmox-toolkit.sh | bash
# CI/CD
curl -fsSL https://scripts.wanforge.asia/script/linux/cicd/install-github-runner.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/cicd/install-gitlab-runner.sh | bash
# Observability stack
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-prometheus.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-grafana.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-zabbix.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-uptime-kuma.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-loki.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-goaccess.sh | bash
# App runtime
curl -fsSL https://scripts.wanforge.asia/script/linux/runtime/install-nodejs.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/runtime/install-python.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/runtime/install-composer.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/runtime/setup-pm2-app.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/runtime/install-docker.sh | bash
# Network & Tunnel
curl -fsSL https://scripts.wanforge.asia/script/linux/network/net-tools.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/network/install-cloudflared.sh | bash
# AI & Agents
curl -fsSL https://scripts.wanforge.asia/script/linux/ai/install-ai-agents.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/ai/setup-hermes-telegram.sh | bash
curl -fsSL https://scripts.wanforge.asia/script/linux/ai/setup-9router-tunnel.sh | bash
| Group | Script | Purpose | Sudo | Distro |
|---|---|---|---|---|
| — | install.sh |
Grouped checkbox launcher that runs the other scripts | — | Any |
| System | install-packages.sh |
Update/upgrade system, install base essentials (micro/curl/wget/git) | Yes | Multi |
| System | set-timezone.sh |
Set timezone via timedatectl (default Asia/Jakarta) |
Yes | Any (systemd) |
| System | backup-tools.sh |
Backup manager: S3 / FTP / SFTP — named profiles, cron, dry-run | No | Any |
| System | sys-troubleshoot.sh |
Diagnostics & troubleshooting: CPU, RAM, services, OOM, logs, firewall, net | Yes | Any |
| System | hardware-info.sh |
Hardware audit: CPU, RAM, disks, GPU, firmware, NIC, sensors, virt | Some | Any |
| System | setup-motd.sh |
Custom dynamic SSH login banner (MOTD) with live system KPIs | Yes | Any |
| Security | install-firewall.sh |
Install ufw, open SSH/http/https, add custom ports, enable |
Yes | Mainly Deb/Ubu |
| Security | firewall-manager.sh |
Full ufw manager: allow/deny IP & port, multi-IP, rate-limit | Yes | Any (ufw) |
| Security | install-fail2ban.sh |
Install, optimize & manage Fail2Ban (progressive ban, recidive) | Yes | Multi |
| Security | secure-ssh.sh |
Audit, port change, root/pw lockdown, passwordless sudo, CIS, SELinux/fw | Yes | Any (OpenSSH) |
| Security | manage-users.sh |
Manage Linux users, sudo access, passwords, shells, and SSH keys | Yes | Any |
| Security | generate-ssh-key.sh |
Generate an ed25519 SSH key, fix perms, print public key | No | Any |
| Security | ssl-toolkit.sh |
SSL/TLS diagnostics: remote/local audit, self-signed SAN, handshake, Certbot | Yes | Any |
| Panel & Console | install-cloudpanel.sh |
Install CloudPanel CE v2, choose DB engine, verify checksum | Yes | Ubuntu 24 |
| Panel & Console | clpctl-manager.sh |
Manage CloudPanel via clpctl: sites, db, users, certs, vhosts |
Yes | CloudPanel |
| Panel & Console | install-cockpit.sh |
Install Cockpit + modules, reverse-proxy config, optimized PCP logger, port 9090 | Yes | Debian/Ubuntu/RHEL |
| Database | install-postgresql.sh |
Install latest PostgreSQL (PGDG), create roles, remote access | Yes | Debian/Ubuntu |
| Database | enable-mysql-remote.sh |
Remote MySQL/MariaDB: bind-address, firewall, create users | Yes | Debian/Ubuntu |
| Database | database-toolkit.sh |
Monitor / optimize / config / datetime — MySQL & PostgreSQL | Yes | Any (DB client) |
| App Runtime | install-nodejs.sh |
Install Node.js via nvm (user-local), choose version, PM2 | No | Any |
| App Runtime | install-python.sh |
Python 3 + pip, venv/virtualenv, dev headers, pipx (multi-distro) | Yes | Multi |
| App Runtime | install-composer.sh |
Install Composer to ~/.local/bin, verify signature |
No | Any (needs PHP) |
| App Runtime | setup-pm2-app.sh |
Configure pm2-logrotate + register an app (ecosystem.config.js) | No | Any |
| App Runtime | install-docker.sh |
Container runtimes: Docker & Podman, docker CLI alias/socket, diagnostics, UFW | Yes | Multi |
| Monitoring | monitor-system.sh |
CPU/RAM/storage/processes/network — snapshot or realtime watch | Some | Any |
| Network | net-tools.sh |
Local/public IP, ports, speedtest, ping/traceroute/dig/whois/scan | Some | Any |
| Network | install-cloudflared.sh |
Install & configure Cloudflare Tunnel daemon (named / quick / token) | Yes | Multi |
| Proxmox | proxmox-toolkit.sh |
PVE node/VM/CT resources, storage, cluster, realtime dashboard | Yes | Proxmox VE |
| CI/CD | install-github-runner.sh |
GitHub Actions self-hosted runner as a systemd service (avoid billed minutes) | Yes | Linux |
| CI/CD | install-gitlab-runner.sh |
GitLab CI/CD self-hosted runner manager | Yes | Linux |
| Observability | install-prometheus.sh |
Prometheus + node_exporter + Alertmanager (alerts, notification wizard, audit) | Yes | Debian/Ubuntu |
| Observability | install-grafana.sh |
Grafana (official repo) + datasource/dashboard provisioning, proxy & audit | Yes | Debian/Ubuntu |
| Observability | install-zabbix.sh |
Zabbix 7.0 LTS Server or Agent 2 (official repo, MySQL schema, multi-fw) | Yes | Debian/Ubuntu |
| Observability | install-uptime-kuma.sh |
Uptime Kuma status page & endpoint monitor (Node.js + PM2) | No | Linux |
| Observability | install-loki.sh |
Loki + Promtail log aggregator & forwarding agent | Yes | Debian/Ubuntu |
| Observability | install-goaccess.sh |
GoAccess real-time web log analyzer (terminal & HTML daemon) | Yes | Debian/Ubuntu |
| AI & Agents | install-ai-agents.sh |
Modular AI stack: Hermes, Claude Code, AGY, 9Router, token optimization | Some | Linux |
| AI & Agents | setup-hermes-telegram.sh |
Configure Hermes Telegram Bot: token, whitelist, group policy, 9Router backend | No | Linux |
| AI & Agents | setup-9router-tunnel.sh |
Cloudflare Tunnel & custom domain reverse proxy for 9Router & AI agents | Some | Linux |
apt, dnf, yum, pacman, zypper, apk.micro, curl, wget,
git, tmux (with tuned ~/.tmux.conf). Package names are resolved per distro.install-python.sh; speedtest-cli is in net-tools.sh.pip, venv/virtualenv, dev
headers (build C extensions), and pipx (install Python CLI apps isolated).pipx falls back to pip --user where the
repo has no package, then runs pipx ensurepath.timedatectl via an arrow-key menu: UTC (recommended
for servers & databases — no DST, consistent logs), Asia/Jakarta, a custom
zone, or skip. Best practice: keep the OS and DB in UTC and format to local
time in the application.database-toolkit.sh’s date/time action
reminds you to run MySQL/PostgreSQL in UTC.~/.config/wanforge-scripts/backup-profiles/<name>.conf, chmod 600). No global config, no cron clutter.Database — dumps the DB then uploads the dump file; supported engines:
| Engine | Tool | Default port | Notes |
|---|---|---|---|
| MySQL/MariaDB | mysqldump |
3306 | --all-databases or single DB, gzip-compressed |
| PostgreSQL | pg_dump / pg_dumpall |
5432 | single DB or all, gzip-compressed |
| SQLite | sqlite3 |
(file path) | .dump piped through gzip |
| MongoDB | mongodump |
27017 | per-DB or all, tar.gz archive |
| Redis | redis-cli |
6379 | BGSAVE → copies RDB, gzip-compressed |
openssl enc -pbkdf2). Enabled in the wizard; passphrase stored in profile (chmod 600). Encrypted files get .enc suffix. Applied automatically on every run/cron.Destination types — same for both directory and DB profiles:
| Type | Tool | Notes |
|---|---|---|
s3 |
aws CLI (pip3 install awscli) |
Custom --endpoint-url → AWS, IDCloudHost, MinIO, Backblaze B2, etc. |
ftp |
lftp (apt install lftp) |
lftp mirror -R (dir) or put (DB dump); SSL: off / explicit / implicit |
sftp |
rsync (apt install rsync) |
rsync -avz -e ssh; SSH key path or agent; --delete for dir profiles |
source → target summary.crontab entry for a profile; runs via --run non-interactively.Non-interactive / cron / scripted flags:
# Directory backup
bash backup-tools.sh --run web-daily # sync dir → S3/FTP/SFTP
bash backup-tools.sh --run-all # run all profiles
bash backup-tools.sh --test web-daily # dry-run
# DB backup (dump + optional encrypt + upload)
bash backup-tools.sh --run mysql-daily # dump MySQL → upload
bash backup-tools.sh --run-all # all profiles incl. DB
# Dump to local file only (no upload)
bash backup-tools.sh --dump mysql-daily # → ~/mysql-daily_20260623_020000.sql.gz
bash backup-tools.sh --dump mysql-daily /tmp # custom output dir
bash backup-tools.sh --dump-all /backups/local # dump all DB profiles locally
# Schedule
bash backup-tools.sh --cron mysql-daily 2 # daily at 02:00
bash backup-tools.sh --remove-cron mysql-daily # remove its cron entry
# Profile management
bash backup-tools.sh --list
bash backup-tools.sh --delete old-profile another-profile
# run manually (TUI)
curl -fsSL https://scripts.wanforge.asia/script/linux/system/backup-tools.sh | bash
<profile>_YYYYMMDD_HHMMSS.sql.gz (or .tar.gz, .rdb.gz, .sql.gz.enc for encrypted).systemctl --failed)./var/log/nginx/ for 502/504 gateways, timeouts, connection refused, or permissions issues and displays recent logs)./sys/devices/system/cpu/vulnerabilities).dmidecode -t 17 when root/sudo).lsblk), transport type (NVMe, SATA, USB, SCSI), SSD/NVMe vs HDD (rotational check), filesystem types, mount points, capacity, I/O schedulers, and SMART health/temperature status via smartctl.lspci, active kernel drivers (nvidia, amdgpu, i915, xe, nouveau), and integration with nvidia-smi / rocm-smi if present.ethtool, and Wi-Fi chipset details.lsusb -t).systemd-detect-virt), OS release, Linux kernel, uptime, and load averages.(no flag): Full-color interactive CLI display styled with lib.sh.--summary or -s: Compact 1-page overview of key hardware specifications.--json or -j: Valid, machine-parseable JSON object for automation or API integration.--markdown or -m: Clean Markdown report ready for documentation or GitHub issues.sudo -n for privileged tools (dmidecode, smartctl) without prompting for passwords or blocking execution./), private LAN IP, public IP (fast 1-hr cached lookup), SSH listening port, active firewall status (firewalld, ufw, nftables, iptables), active user sessions, and service status badges (sshd, firewall, fail2ban, docker, podman, 9router)./proc inspection executing in under 0.05 seconds with zero external network bloat or login lag.10-help-text, 50-motd-news, 88-esm-announce, 91-release-upgrade)./etc/update-motd.d/ (Debian/Ubuntu) or /etc/profile.d/ (Fedora/RHEL/CentOS/Arch).preview (instant test render), install (set up system-wide), clean (silence Ubuntu ads only), uninstall (restore stock distro MOTD).ufw if missing, allows OpenSSH, http, https.8443/tcp 3000/tcp).ufw manager (installs ufw if missing). Looping menu:
Dry-run: set DRY_RUN=1 to print every ufw command without executing —
safe to try the menus and inputs first:
curl -fsSL https://scripts.wanforge.asia/script/linux/security/firewall-manager.sh | DRY_RUN=1 bash
bantime.increment = true: Applies exponential progressive bans for recidivists (1h → 2h → 4h up to 4 weeks).bantime = 1h, findtime = 15m, maxretry = 4.[recidive]): Traps and bans persistent attackers across all services for 2 weeks.ss and sshd_config.backend = systemd): provides zero-lag log parsing immune to log rotation.ufw, firewallcmd-richrules, nftables-multiport, or iptables-multiport.SSH_CLIENT) and RFC 1918 subnets into ignoreip.[nginx-http-auth], [nginx-botsearch], and [nginx-bad-request] if Nginx or CloudPanel is detected.status: Real-time audit of service state, active jails, and currently banned IPs.optimize: Applies production hardening presets with automatic config backup.unban <ip>: Unbans an IP address across all jails or selected jail.ban <ip> [jail]: Manually bans an IP address in a specific jail.logs: Inspects the last 35 Ban/Unban events from /var/log/fail2ban.log or journalctl.status): Inspects active daemon status, listening ports, effective directives (PermitRootLogin, PubkeyAuthentication, PasswordAuthentication, X11Forwarding, MaxAuthTries), registered keys in authorized_keys, firewall state, and SELinux enforcement.22 — keep it or set custom 1-65535)./etc/sudoers.d/99-wanforge-nopasswd with NOPASSWD: ALL (validated with visudo), allowing sudo su and root commands without password prompts (default cloud VPS behavior).ufw (Ubuntu/Debian) or firewalld (RHEL/Fedora/Rocky/AlmaLinux) before restarting sshd.semanage port -a -t ssh_port_t -p tcp <port>) to prevent permission denied bind errors.ssh.socket migration to ssh.service so custom ports take effect immediately.~/.ssh/authorized_keys and /root/.ssh/authorized_keys before allowing password authentication to be disabled; offers on-the-spot key paste or ed25519 key generation if missing.no / prohibit-password), enforces PubkeyAuthentication yes, disables password auth, disables PAM keyboard-interactive fallback, disables X11Forwarding, sets MaxAuthTries 3, LoginGraceTime 30, and keeps sessions alive (ClientAliveInterval 300, ClientAliveCountMax 2)./etc/ssh/sshd_config.d/99-wanforge-hardening.conf, automatically backs up configurations, tests syntax with sshd -t, and offers rollback (--uninstall / rollback).~/.ssh/authorized_keys and can show per-user
status (sudo, locked, SSH keys).ed25519 key in ~/.ssh (no sudo). Prompts for the file path,
comment (default wanforge-asia@<hostname>), and an optional passphrase.~/.ssh to
700, the private key to 600, the public key to 644..crt or .pem files and parses their metadata.certbot python3-certbot-nginx) to auto-provision SSL certificates./etc/os-release and aborts immediately if the host is not Ubuntu 24.MARIADB_12.3, with support for MARIADB_11.8,
MARIADB_11.4, MARIADB_10.11, MYSQL_8.4, and MYSQL_8.0.https://installer.cloudpanel.io/ce/v2/install.sh,
pipes checksum verification against 8146dbe0a488e7088b04071b0c34d59aa0ab1fe9dcec382d395fd155c9e6c476,
and executes via sudo DB_ENGINE=MARIADB_12.3 bash install.sh.https://<server-ip>:8443.clpctl). Interactive menu over the documented v2 CLI
(reference). Loops until you quit.clpctl as flags, so they may briefly appear in the process list.cockpit.socket) on port 9090.cockpit-networkmanager: Network interfaces, IP/DNS, bridges, VLANs, bonds.cockpit-storaged: Disks, partitions, LVM volume groups, RAID, NFS mounts, SMART drive health.cockpit-sosreport: Diagnostic system state and support reports.cockpit-pcp: Performance Co-Pilot integration for live & historical metrics graphing.cockpit-machines: KVM / QEMU virtual machines management via libvirt.cockpit-podman: Podman container images and container lifecycle management.pmcd and pmlogger daemons.pmlogconf -r (CPU, memory, disk I/O, network, filesystems).pmlogger_daily.timer and pmlogger_check.timer for automatic archive rotation./etc/cockpit/cockpit.conf (Origins, AllowOrigins, ProtocolHeader = X-Forwarded-Proto, AllowUnencrypted = true).9090/tcp in UFW or Firewalld with an explicit note that it can remain closed if accessed exclusively via reverse proxy.status):
/usr/share/cockpit/, PCP logger status, archive disk footprint, and reverse proxy rules.postgresql-contrib.SUPERUSER (default off).pg_hba.conf + listen_addresses (paths
resolved via SHOW hba_file/config_file), restarts, and opens 5432 for a
chosen source CIDR.bind-address = 0.0.0.0, restarts the service, and opens 3306 for a
chosen source CIDR.sudo,
or a root password), then loops to create user@host with a password and a
grant on a chosen database (or all). Host defaults to % (any client).
Passwords are entered interactively and never stored.mysqlcheck), MySQLTuner.pg_stat_activity, date/time + timezone check, key settings, cache hit ratio,
VACUUM ANALYZE + optional REINDEX.sudo) or a prompted password (MySQL) / the
postgres system user (PostgreSQL). Read-only actions are safe; optimize
actions modify tables.lm-sensors).Realtime / watch mode: refreshes the selected sections on an interval until
Ctrl-C. Enable with the prompt, WATCH=1, or -w/--watch; set the cadence
with INTERVAL=<seconds> (default 2). bigdirs is skipped while watching.
Updates happen in place — the cursor homes and overwrites each line (no
full-screen clear), so the values refresh without flicker or a “page reload”.
curl -fsSL .../script/linux/monitoring/monitor-system.sh | WATCH=1 INTERVAL=2 bash
htop, btop, ncdu, glances, iotop
— full-screen realtime monitors if you prefer a TUI.host:port, scan ports (nmap or /dev/tcp).mtr, DNS lookup (dig), whois, HTTP
headers (curl -I), interface traffic stats.speedtest/speedtest-cli).pvesh/qm//etc/pve). Arrow-key TUI:
pvecm), recent tasks, HA.pvesm storage,
top processes, disk I/O.qm) and containers (pct); manage one VM/CT
(status / start / shutdown / stop / reboot / config / vzdump backup).DRY_RUN.A single-select TUI manager for GitHub Actions self-hosted runners.
Jobs with runs-on: self-hosted execute on your machine, so GitHub-hosted
runner minutes are not consumed — self-hosted runners are
free of per-minute billing.
Menu actions:
| Action | What it does |
|---|---|
| Install | Register a new runner and install it as a systemd service |
| List | Show every runner on this host (name, service state, user, target URL, dir) |
| Status | systemctl status of a chosen runner service |
| Logs | journalctl -u <svc> (last 100 lines) for a chosen runner |
| Start / Stop / Restart | Control a chosen runner service via svc.sh |
| Remove | Stop + uninstall the service, unregister from GitHub, optionally delete the dir |
owner/name) or a whole org. Fetches the
latest actions/runner release
for your arch (x64 / arm64 / arm), or prompts for a version if the
GitHub API is unreachable.--system user (default github-runner);
GitHub forbids running the service as root.
Override the user at the prompt.${RUNNER_ROOT}/<name> (default
RUNNER_ROOT=/opt/actions-runner), so multiple runners coexist. Install runs
bin/installdependencies.sh (libicu etc.), config.sh --unattended --replace
(with optional --ephemeral, --labels, --runnergroup, --work), then
svc.sh install <user> + svc.sh start.Use in a workflow:
jobs:
build:
runs-on: [self-hosted, linux, x64] # or a custom label you set at install
A single-select TUI manager for GitLab CI/CD self-hosted runners. Allows registering runners to execute CI/CD jobs on your own machine.
Menu actions:
gitlab-runner, and register a new runner with the GitLab instance (supports shell and docker executors, tags, and description).:9090), node_exporter (:9100, host CPU/RAM/disk metrics), Alertmanager (:9093), and firewall (UFW & Firewalld)./etc/prometheus/prometheus.yml./etc/prometheus/alert.rules.yml containing pre-configured rules (Host down, high CPU/RAM, low disk space) and links them to Prometheus.status): Audits running services, open ports (9090, 9100, 9093), configured scrape jobs, and active alert rules.grafana-server (:3000), and opens the firewall (UFW & Firewalld).http://localhost:9090).proxy): Configures domain and root_url in /etc/grafana/grafana.ini for SSL reverse proxies (CloudPanel / Nginx / Caddy).reset-pass): Resets the Grafana admin user password directly from CLI using grafana-cli.status): Audits grafana-server state, listening port 3000, provisioned datasources, and dashboards.zabbix-agent2 with plugins, sets server polling IP + hostname, opens port :10050 in UFW / Firewalld.zabbix database, imports schema, configures DBPassword, starts everything. Frontend at http://<ip>/zabbix, default login Admin/zabbix.status): Audits Zabbix server, agent, database connectivity, and listening ports (10051, 10050, 80).install-nodejs.sh first to set up the Node environment).3100, storing indices and chunks persistently at /var/lib/loki. Optionally registers as a Grafana datasource./var/log/*log and systemd-journal (system unit logs), then forwards them to a central Loki URL. Allows setting up distributed logging (pushing to a remote Loki server).goaccess.service) that runs in the background, reading access logs and generating a real-time HTML report on a selected web directory (e.g. /var/www/html/report.html), utilizing WebSockets on port 7890 for live browser updates.# 1) On each host to monitor (metrics + log agents):
# Installs node_exporter to export metrics and Promtail to forward logs
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-prometheus.sh | bash # pick node_exporter
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-loki.sh | bash # pick promtail, point to Loki server URL
# 2) On the central monitoring host (Prometheus server, Loki server, Grafana):
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-prometheus.sh | bash # pick prometheus + Alertmanager
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-loki.sh | bash # pick loki (server)
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-grafana.sh | bash # installs Grafana, auto-adds Prometheus datasource, auto-imports Dashboard 1860
# 3) Open Grafana (http://host:3000)
# - Dashboards -> Node Exporter Full dashboard is ready.
# - Explore -> Select 'Loki' data source -> Browse and query your system and journal logs in real-time.
# Alternative standalone status page:
curl -fsSL https://scripts.wanforge.asia/script/linux/monitoring/install-uptime-kuma.sh | bash # install Uptime Kuma on port 3001
nvm into $HOME/.nvm (no sudo) and the chosen Node version
(18, 20, lts, latest). Sets it as the default + stable alias.pm2-logrotate, runs pm2 save, and (optionally)
sets up boot startup via systemd (this single step needs sudo).~/.local/bin/composer (no sudo),
verifying the installer SHA-384 signature before running it.~/.local/bin to PATH in ~/.bashrc and runs composer self-update.install-nodejs.sh first). Sources nvm to find PM2.pm2-logrotate (max size, retention, compression, daily
rotation).ecosystem.config.js (name, cwd, script,
args, instances/cluster, NODE_ENV, memory restart limit), then runs
pm2 start + pm2 save.podman-docker package or symlinks /usr/local/bin/docker -> podman, installs global shell aliases (alias docker=podman), silences emulation notice (/etc/containers/nodocker), configures default registries (docker.io, quay.io), and enables Podman API socket (systemctl enable --now podman.socket) linked to /var/run/docker.sock for seamless compatibility with Docker-dependent tools and SDKs.stats --no-stream), and detects containers caught in restart loops or exited with non-zero error codes.system prune -a --volumes)./etc/ufw/after.rules.cloudflared) on Debian/Ubuntu/RHEL/Arch.trycloudflare.com tunnel for instant testing without an account.--start, --stop, --restart, --status, --uninstall).9router AI gateway, creates 9router.service systemd daemon on port 20128, configures multi-provider models (Anthropic, OpenAI, DeepSeek, Google Gemini) with automated fallback combos.curl -fsSL https://claude.ai/install.sh | bash with npm fallback), configures ~/.claude/settings.json with 9Router base URL, 998k context window, and permission whitelist for automated execution.curl -fsSL https://antigravity.google/cli/install.sh | bash), wires binary to PATH, and configures RTK hooks in ~/.gemini/settings.json.curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash), bootstraps Python environment, and provisions user systemd service.@caveman-ai/cli) and prompt compression tools.chmod 600) in ~/.hermes/.env.allowed_users) to prevent unauthorized command execution.allowed_chats) and optional mention enforcement (require_mention: true) to prevent agent runaway in active groups.model.base_url to local or remote 9Router endpoints.hermes-gateway.service and enables persistent linger via loginctl.ai.wanforge.asia) to local 9Router port 20128..gitignore for the blocked patterns.install-postgresql.sh asks for role names and
passwords interactively. No passwords are stored in these scripts.install-postgresql.sh and enable-mysql-remote.sh
expose the database to the network. Prefer a restricted source CIDR over
0.0.0.0/0, and place the server behind a firewall or private network.secure-ssh.sh can lock you out. It opens the new port in
ufw before restarting, validates with sshd -t, backs up the config, and
refuses to disable password auth without an authorized_keys present. Keep
your current session open and test the new port before closing it.AllowUnencrypted = true is only safe when TLS is terminated by
the proxy (e.g. CloudPanel) in front of Cockpit.sudo. PM2
boot startup (pm2 startup) is optional and needs sudo for systemd.The banner, colors, logging helpers, prompts, and TUI menus live once in
script/linux/lib.sh. Every script sources it.
| Helper | Purpose |
|---|---|
hd "Title" |
Centered fill-line section header (───── Title ─────) |
info "…" |
• info line |
ok "…" |
✓ success line |
warn "…" |
⚠ warning line |
err "…" |
✖ error line (always prints, ignores LOG_LEVEL) |
step N "…" |
[N] task name numbered step indicator |
hr |
────────── horizontal rule separator |
pause |
Press Enter to continue (reads from /dev/tty) |
dbg "…" |
Debug line (only at LOG_LEVEL ≥ 2) |
ask "prompt" "default" |
› interactive prompt; auto-fills default in ASSUME_YES mode |
asks "prompt" |
Same but masked input (for secrets) |
checkbox "title" |
Arrow-key grouped checkbox with [✓] toggles |
menu_select "title" |
Arrow-key single-select menu |
TASK="my-script"
__LIB="https://scripts.wanforge.asia/script/linux/lib.sh"
__d="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" 2>/dev/null && pwd || true)"
if [ -r "${__d}/../lib.sh" ]; then . "${__d}/../lib.sh"
else . <(curl -fsSL "${__LIB}"); fi
Looks for lib.sh one directory up (cloned repo: script/linux/<category>/),
otherwise fetches from the public repo over HTTPS. Set TASK before sourcing —
the banner subtitle uses it. To add a script: copy the header, fill in TASK,
place under script/linux/<os>/<category>/, register in install.sh.
GNU General Public License v3.0 (GPL-3.0). Copyright (c) 2026 Sugeng Sulistiyawan.
See LICENSE.