Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e913a52
Nginx Fixes
mymanga Jul 2, 2025
d038ae6
Modify OVPN permissions
mymanga Jul 2, 2025
000a050
Added/Removed/Moved Settings
mymanga Jul 2, 2025
99998a2
Valkey fixes
mymanga Jul 4, 2025
7bceea0
Valkey fix
mymanga Aug 4, 2025
2316368
Fix bash scripts
mymanga Aug 13, 2025
5940b25
Update ubuntu_simplespot.sh
mymanga Sep 3, 2025
b81f2b5
Update ubuntu_simpleisp.sh
mymanga Sep 19, 2025
95b61f3
Update ubuntu_simplespot.sh
mymanga Oct 20, 2025
4634f1c
Modify composer install command for Laravel setup
mymanga Jan 6, 2026
b335cdf
Merge pull request #2 from simpleisp/main
mymanga Jan 6, 2026
8c59a81
Update composer install command to avoid security blocking
mymanga Jan 6, 2026
26f7586
DB Optimization
mymanga Jan 6, 2026
9df9aa6
Delete mmsqlconf.sh
mymanga Jan 6, 2026
76beb88
Add files via upload
mymanga May 27, 2026
cd20af8
optimzed versions of universal, simplespot and simpleisp
mymanga May 27, 2026
837e793
feat: add database cleanup script and enforce LF line endings across …
mymanga May 27, 2026
2813a20
fixed mojibake
mymanga Jun 17, 2026
96edae1
Integrate universal.sh v3, db_cleanup.sh and ovpn_fix.sh into the ins…
mymanga Jul 15, 2026
86416f5
Add README documenting installers, maintenance scripts, and cron sche…
mymanga Jul 15, 2026
f18f3ef
Remove db_cleanup.sh cron - install it for manual use only
mymanga Jul 15, 2026
d120755
Fix Valkey install on focal/jammy and MariaDB config on focal
mymanga Jul 17, 2026
6106401
Download helper scripts from mymanga/bash where they actually exist
mymanga Jul 17, 2026
655d59d
Fix Valkey startup on Percona 8.0 packages (focal/jammy)
mymanga Jul 17, 2026
9d75bdc
Update clean_server.sh for the current installers
mymanga Jul 17, 2026
0ce8164
Document the PHP 7.4 pin for SimpleISP
mymanga Jul 17, 2026
65272ea
Make Valkey startable before any apt operation on focal/jammy
mymanga Jul 17, 2026
403a5ae
Survive missing nginx/supervisor configs when reinstall marker was co…
mymanga Jul 17, 2026
b8eeeef
Make DB creation, cron installs and sudoers append idempotent on retries
mymanga Jul 17, 2026
e458046
Clone the panel repo's default branch instead of hardcoded master
mymanga Jul 17, 2026
386adcc
Reuse existing SSL certificates non-interactively
mymanga Jul 17, 2026
5ff29a2
Use Ubuntu archive FreeRADIUS on noble+, make buffered-sql accounting…
mymanga Jul 17, 2026
6297997
universal.sh: ensure buffered accounting wiring on existing servers (…
mymanga Jul 17, 2026
f875107
Keep sites-enabled/default a symlink; converge existing servers
mymanga Jul 17, 2026
a125954
Grant www-data the sudo commands the panel actually runs
mymanga Jul 17, 2026
5b180e3
universal.sh: ensure panel sudoers entries on existing servers (Step 6c)
mymanga Jul 17, 2026
f37deaf
removed all installers
mymanga Jul 22, 2026
009abf0
Harden buffered accounting against reader jams (v3.3)
mymanga Jul 23, 2026
309bc27
buffered-sql: fail = 1 so the Accounting-On/Off check actually runs
mymanga Jul 23, 2026
ca32a2d
radacct-watchdog: react in ~5 min, but only while MariaDB is up
mymanga Jul 23, 2026
fe5813a
Keep Accounting-On/Off out of the buffered queue (v3.4)
mymanga Jul 23, 2026
07be95f
Retire buffered accounting - direct sql in the default site (v3.5)
mymanga Jul 23, 2026
9f4deb5
Step 6e: radacct reconcile cron scaled to the 1-minute interim cadence
mymanga Jul 23, 2026
213d124
Never write backups into FreeRADIUS $INCLUDEd directories (v3.5.2)
mymanga Jul 23, 2026
cc1eb22
Recover a down FreeRADIUS at end of run, not only on config change
mymanga Jul 23, 2026
486dda8
Installers: sweep stray backups and retired buffered wiring before -XC
mymanga Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Enforce Unix line endings (LF) for shell scripts to prevent
# "cannot execute: required file not found" errors on Linux servers.
*.sh text eol=lf
87 changes: 87 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# SimpleISP / SimpleSpot Server Scripts

Bash scripts for installing and maintaining [SimpleISP](https://github.com/simpleisp/radius) and SimpleSpot hotspot/ISP billing servers on Ubuntu (focal / jammy / noble).

## Installers

| Script | Installs | PHP |
|---|---|---|
| `ubuntu_simpleisp.sh` | SimpleISP (ISP billing panel) | 7.4 |
| `ubuntu_simplespot.sh` | SimpleSpot (hotspot billing panel) | 8.2 |

The two installers are identical except for the application repository and PHP version. Run on a fresh Ubuntu server as root:

```bash
chmod +x ubuntu_simpleisp.sh
sudo ./ubuntu_simpleisp.sh
```

Each installer sets up the full stack:

- **nginx** + **PHP-FPM** serving the Laravel panel from `/var/www/html` (with Let's Encrypt via certbot). PHP is pinned per product — SimpleISP: **7.4** (the panel has code that breaks on newer PHP), SimpleSpot: **8.2** — and installs from the ondrej PPA on every supported Ubuntu release, so the pin holds on 24.04 too.
- **MariaDB** (unix_socket root auth; credentials written to a file reported at the end of the install)
- **FreeRADIUS 3.2** with buffered SQL accounting into the `radius` database — accounting goes to a local detail file and the `buffered-sql` virtual server replays it into SQL, so records survive DB stalls/restarts. Packages come from NetworkRADIUS on focal/jammy (config root `/etc/freeradius/`, their archives only have 3.0.x) and from the Ubuntu archive on noble+ (config root `/etc/freeradius/3.0/`, 3.2 in main with security updates). Existing noble servers installed with NetworkRADIUS packages keep them — apt won't downgrade; only fresh installs switch.
- **Valkey** (Redis-compatible cache) with systemd hardening overrides — installed from Percona's repo on focal/jammy (service `valkey`), from the Ubuntu archive on noble (service `valkey-server`)
- **OpenVPN** (via `openvpn.sh`) with systemd `ReadWritePaths` overrides so the panel can manage `/etc/openvpn`
- **supervisor** for Laravel queue workers, UFW rules, cron jobs, and sudoers entries for `www-data` service control

At the end, the installer places the maintenance scripts below into `/var/www/html/sh/`, schedules them, and runs the autotune once.

## Maintenance scripts

Installed to `/var/www/html/sh/` on the server; all three support `--dry-run`.

### `universal.sh` — capacity-model autotune

Sizes MariaDB, Valkey, PHP-FPM, and FreeRADIUS from one capacity model that scales from 2 vCPU / 2 GB to 16 vCPU / 16 GB (~5,000 concurrent hotspot users at the top tier). Copy it unchanged to any size server; it self-sizes.

- Backs up the database and all touched configs before changing anything; keeps the newest **3** runs (including the `.bak.*` copies written next to live configs)
- Applies MariaDB and Valkey settings **live** (`SET GLOBAL` / `valkey-cli`) — no restart, no cold cache
- Reloads PHP-FPM only if its pool config changed and `php-fpm -t` passes; restarts FreeRADIUS only if `radiusd.conf` changed **and** validates with `-XC` (rolls back otherwise)
- Ensures indexes on `radacct` and friends
- Removes the legacy `update_memory_config.sh` (file + cron) if a previous install left it behind
- Logs to `/var/log/universal_<timestamp>.log`; backups under `/var/backups/universal/`

### `db_cleanup.sh` — RADIUS database retention

Batched cleanup of closed `radacct` sessions, `radpostauth`, expired portal sessions and vouchers, payment ledgers, and Laravel `failed_jobs`; closes zombie sessions and runs `ANALYZE` / conditional `OPTIMIZE`.

```
db_cleanup.sh [--dry-run] [--auto] [--ask]
```

Run interactively it prompts per category for a retention age (`12h`, `2d`, `1w`, `3m`, `s` to skip) and confirms before deleting. Without a terminal (or with `--auto`) it silently uses the built-in defaults. **Not scheduled** — run it manually when the database needs trimming. Logs to `/var/log/radius_db_cleanup.log`.

### `ovpn_fix.sh` — PHP-FPM OpenVPN sandbox fix

Debian/Ubuntu php-fpm units ship with `ProtectSystem=full`, which makes `/etc` read-only inside the service and breaks panel writes to `/etc/openvpn/server.conf`. This script finds every installed `phpX.Y-fpm` unit (and any systemd Laravel queue-worker units), installs a `ReadWritePaths=/etc/openvpn` drop-in, restarts the affected units, and verifies writability from inside each service's mount namespace. Idempotent — safe to re-run any time.

```
ovpn_fix.sh [--dry-run] [--no-restart]
```

## Scheduled jobs (installed to root's crontab)

| Schedule | Job |
|---|---|
| `* * * * *` | Laravel scheduler (`artisan schedule:run`) |
| `*/5 * * * *` | Valkey health monitor (`valkey-debug.sh`) |
| `0 3 * * *` | `universal.sh` — daily autotune |
| `@reboot` (after 120 s) | `universal.sh` — re-tune after boot |

`db_cleanup.sh` is deliberately not scheduled; run it manually when needed.

## Utility scripts

| Script | Purpose |
|---|---|
| `openvpn.sh` | Standalone OpenVPN road-warrior installer (downloaded and run by the installers) |
| `clean_server.sh` | Uninstalls everything the installer set up and prepares the server for a clean reinstall (writes a marker the installer detects) |
| `ports.sh` | Configures firewall/port rules for a given subnet (`ports.sh -net <subnet>`) |
| `setup.sh` / `install.sh` | Minimal standalone MariaDB + app bootstrap (older path) |
| `transfer_tmpl.sh` | Proxmox: clones VM templates between nodes via the API |
| `template_generation.sh` | Proxmox: commands to build an Ubuntu cloud-image VM template |

## Legacy

`ubuntu_simpleisp_old.sh` and `ubuntu_simplespot_old.sh` are the previous generation of the installers, kept for reference. They embed the superseded `update_memory_config.sh` tuning approach — new installs should always use the current `ubuntu_simpleisp.sh` / `ubuntu_simplespot.sh`.
72 changes: 54 additions & 18 deletions clean_server.sh
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/bin/bash
#!/bin/bash

# Cleanup script for SimpleISP/SimpleSpot
# This script will uninstall all software installed by the SimpleISP/SimpleSpot installer
Expand Down Expand Up @@ -43,9 +43,14 @@ fi

echo "[$(date)] Detected PHP version: $PHP_VERSION"

# Stop services
# Stop services (valkey-server on noble, valkey + valkey-sentinel on focal/jammy Percona builds)
log_step "Stopping services"
systemctl stop nginx freeradius mariadb valkey-server php${PHP_VERSION}-fpm supervisor openvpn || echo "Could not stop all services"
systemctl stop nginx freeradius mariadb valkey-server valkey valkey-sentinel php${PHP_VERSION}-fpm supervisor openvpn openvpn@server || echo "Could not stop all services"

# Remove installer-added cron entries from root's crontab. The installers
# append these on every run, so leftovers would duplicate on reinstall.
log_step "Removing installer cron entries"
crontab -l 2>/dev/null | grep -vE 'artisan schedule:run|valkey-debug\.sh|universal\.sh|db_cleanup\.sh|update_memory_config\.sh' | crontab - 2>/dev/null || echo "No crontab entries to clean"

# Remove web files
log_step "Removing web files"
Expand All @@ -56,21 +61,51 @@ rm -rf /var/www/html/.* 2>/dev/null
log_step "Removing configuration directories"
rm -rf /etc/nginx/sites-available/default 2>/dev/null
rm -rf /etc/nginx/sites-enabled/default 2>/dev/null
# Preserve FreeRADIUS base configuration, only remove application-specific configs
if [ -d "/etc/freeradius" ]; then
# Remove application-specific FreeRADIUS configurations but preserve base system configs
rm -f /etc/freeradius/mods-enabled/sql 2>/dev/null
rm -f /etc/freeradius/mods-enabled/rest 2>/dev/null
# Preserve FreeRADIUS base configuration, only remove application-specific
# configs. Handle both packagings: NetworkRADIUS (/etc/freeradius) and the
# Ubuntu archive (/etc/freeradius/3.0). The 3.0 dir nests inside the other,
# so guard on mods-enabled existing rather than the root.
for frdir in /etc/freeradius /etc/freeradius/3.0; do
[ -d "$frdir/mods-enabled" ] || continue
rm -f "$frdir/mods-enabled/sql" 2>/dev/null
rm -f "$frdir/mods-enabled/rest" 2>/dev/null
# Remove any custom site configurations but preserve default
find /etc/freeradius/sites-enabled/ -name "*" ! -name "default" -delete 2>/dev/null
fi
find "$frdir/sites-enabled/" -name "*" ! -name "default" -delete 2>/dev/null
done
# Remove the buffered accounting queue file
rm -f /var/log/freeradius/radacct/detail* 2>/dev/null
rm -rf /etc/openvpn 2>/dev/null
rm -rf /etc/supervisor 2>/dev/null

# Remove valkey data
# log_step "Removing valkey data"
# rm -rf /var/lib/valkey/* 2>/dev/null
# rm -rf /var/lib/valkey/.* 2>/dev/null
# Remove valkey data, logs, debug script and systemd overrides
# (config in /etc/valkey is left in place - the installer rewrites it)
log_step "Removing valkey data and overrides"
rm -rf /var/lib/valkey/* 2>/dev/null
rm -f /var/log/valkey/*.log 2>/dev/null
rm -f /usr/local/bin/valkey-debug.sh 2>/dev/null
rm -rf /etc/systemd/system/valkey.service.d 2>/dev/null
rm -rf /etc/systemd/system/valkey-server.service.d 2>/dev/null

# Remove installer systemd sandbox overrides (php-fpm / supervisor ReadWritePaths)
log_step "Removing systemd sandbox overrides"
rm -rf /etc/systemd/system/php*-fpm.service.d 2>/dev/null
rm -rf /etc/systemd/system/supervisor.service.d 2>/dev/null
systemctl daemon-reload 2>/dev/null

# Remove installer-added www-data sudoers entries (appended on every install,
# so they would duplicate on reinstall). Validate before keeping the edit.
log_step "Removing www-data sudoers entries"
if grep -q '^www-data ALL=NOPASSWD:' /etc/sudoers; then
cp -a /etc/sudoers /etc/sudoers.cleanup.bak
sed -i '/^www-data ALL=NOPASSWD:/d' /etc/sudoers
if visudo -c >/dev/null 2>&1; then
rm -f /etc/sudoers.cleanup.bak
echo "[$(date)] www-data sudoers entries removed"
else
mv /etc/sudoers.cleanup.bak /etc/sudoers
echo "[$(date)] WARNING: sudoers validation failed, restored original"
fi
fi

# Remove MySQL/MariaDB data and users
log_step "Removing MySQL/MariaDB data and users"
Expand Down Expand Up @@ -115,12 +150,13 @@ log_step "Removing application-specific files"
# Preserve db.txt for credential reuse on reinstall
# rm -f /root/db.txt 2>/dev/null
rm -f /etc/cron.d/laravel-scheduler 2>/dev/null
rm -f /usr/local/bin/update_memory_config.sh 2>/dev/null

# Remove ionCube files
# Remove ionCube files (glob across all PHP versions in case detection missed one)
log_step "Removing ionCube files"
rm -f /etc/php/${PHP_VERSION}/mods-available/ioncube.ini 2>/dev/null
rm -f /etc/php/${PHP_VERSION}/cli/conf.d/00-ioncube.ini 2>/dev/null
rm -f /etc/php/${PHP_VERSION}/fpm/conf.d/00-ioncube.ini 2>/dev/null
rm -f /etc/php/*/mods-available/ioncube.ini 2>/dev/null
rm -f /etc/php/*/cli/conf.d/00-ioncube.ini 2>/dev/null
rm -f /etc/php/*/fpm/conf.d/00-ioncube.ini 2>/dev/null
# Preserve ionCube installation for reuse on reinstall
# rm -rf /usr/local/ioncube 2>/dev/null
find /usr/lib/php/ -name "*ioncube*" -delete 2>/dev/null
Expand Down
Loading