Interactive Linux server automation toolkit — one launcher, 26 scripts across 8 categories: system setup, security hardening, cloud panels, databases, app runtimes, monitoring & observability, CI/CD, and network & Proxmox tooling.
Run scripts individually or use install.sh, an interactive grouped checkbox
launcher that fetches and runs the chosen scripts in order. 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.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.
curl -fsSL https://scripts.wanforge.asia/install.sh | bash
No curl? Use wget instead (present on many minimal images):
wget -qO- https://scripts.wanforge.asia/install.sh | bash
Menu controls:
| Key | Action |
|---|---|
| Up / Down | Move between rows |
| Space | Toggle a selection |
| A | Toggle all |
| Enter | Run the selected scripts |
| Q | Cancel and exit |
The menu is grouped by category and runs the selected scripts in menu order. If one fails, the rest still continue. No authentication is needed — this is a public repository.
Navigation: the launcher loops. After the chosen scripts finish you return to
this menu (press Enter), so you can keep picking more. Inside a sub-script’s own
menu (firewall / database / CloudPanel / Proxmox / net-tools managers) press Q
to go back to the launcher. Press Q at the launcher to quit entirely.
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
── Security ──
[✓] install-firewall Install & configure ufw firewall
[✓] firewall-manager Full ufw manager: allow/deny IP/port, multiple, rate-limit
[✓] install-fail2ban Install & enable Fail2Ban
[✓] secure-ssh Harden SSH: change port, disable root/password, pubkey
[✓] 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 (Debian/Ubuntu only)
[✓] clpctl-manager Manage CloudPanel via clpctl (sites, db, users, certs)
[✓] install-cockpit Install Cockpit web console + modules (Debian/Ubuntu)
── 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
── 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)
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-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
# 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
| 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 | 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 and enable the Fail2Ban service | Yes | Multi |
| Security | secure-ssh.sh |
Change SSH port, disable root/password login, enable pubkey | 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 | Debian/Ubuntu |
| 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, open port 9090 | Yes | Debian/Ubuntu |
| 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 |
Install Docker Engine + Docker Compose, run diagnostics, patch UFW bypass | Yes | Debian/Ubuntu |
| 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 |
| 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 (with alert rules & integrations) | Yes | Debian/Ubuntu |
| Observability | install-grafana.sh |
Grafana (official repo) + auto datasource & dashboard provisioning | Yes | Debian/Ubuntu |
| Observability | install-zabbix.sh |
Zabbix agent or full server (frontend + MySQL schema) | 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 |
apt, dnf, yum, pacman, zypper, apk.micro, curl, wget,
git. 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).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
22 — keep it or set a custom one), disables
root login, optionally disables password auth, enables pubkey auth.sshd_config.d/ when Include is active, otherwise
edits the main config. Backs up sshd_config first.ufw before restarting, validates with
sshd -t, and refuses to disable password auth when no authorized_keys exists.~/.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.EXPECTED_SHA from the CloudPanel docs for new
releases. Web console at 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.9090 in ufw (skip if proxied)./etc/cockpit/cockpit.conf with AllowOrigins (bare
domain, e.g. cockpit.domain.id — TLS terminated by CloudPanel),
ProtocolHeader, AllowUnencrypted. Add the domain in CloudPanel as a
reverse proxy to http://127.0.0.1:9090.yes confirmation, since it can drop SSH).networkmanager, storaged, sosreport, pcp, machines,
podman (each individually selectable).pmcd + pmlogger.http://127.0.0.1:9090.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./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.grafana-server (:3000), and opens the firewall.zabbix-agent2, set the server IP + hostname, open :10050.zabbix database, imports the schema, sets DBPassword, starts everything. Frontend at http://<ip>/zabbix, default login Admin/zabbix.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./etc/ufw/after.rules to force Docker traffic through UFW routing, ensuring standard UFW rules apply to all container ports..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.