Fresh install on Oracle Linux 9 / 10

Step-by-step for installing customsso-manager on a brand-new Oracle Linux 9 or 10 minimal VPS + pairing it with one PBX.

RHEL / Rocky / AlmaLinux 9 / 10 also ride this branch (share the dnf + httpd + firewalld + SELinux paths) but are less formally tested; anything you learn on OL applies verbatim.

Requirements before you start

Step 1 — Prep the VPS

# On the fresh VPS as root
hostnamectl set-hostname manager-test.lan          # or whatever
timedatectl set-timezone America/Chicago           # set BEFORE install

About the timezone: set it BEFORE running the installer. The installer reads your OS timezone and pins PHP + MariaDB to match — all three components (OS, PHP, MariaDB) must agree, or "X ago" calculations drift and short-TTL rows (2FA codes, password-reset links) mis-expire. If the OS is still on UTC when you install and you change it later, PHP will remain on UTC and you'll see a 5+ hour skew in the audit log. See TIMEZONE.md for the retune ritual if you need to change it after install.

The installer runs dnf -y update itself (step 2 of 16); no need to do it here. If you'd rather reboot on your schedule than let one land mid-install, run dnf -y update && reboot now and pick up at Step 2 after the box comes back.

Step 2 — Run the install one-liner

curl -sSfL https://git.voip-stuff.net/customsso-manager/install.sh -o /tmp/setup.sh && sudo bash /tmp/setup.sh

The bootstrap script downloads the latest release tarball, verifies its SHA256, extracts, and execs install.sh. The 16 steps then run:

  1. Detect Oracle Linux + populate RHEL-family variables
  2. dnf -y update
  3. Install EPEL
  4. Install runtime deps: httpd, mod_ssl, php-fpm + extensions, mariadb-server, python3, msmtp, fail2ban, firewalld, certbot, ...
  5. Create Python sidecar venv (paramiko, cryptography, mysql-connector-python, ...) 5b. Create output spool dir at /var/spool/customsso/ with SELinux label httpd_sys_rw_content_t 5c. Sync system + PHP + MariaDB timezones
  6. Initialize MariaDB, create app DB + user
  7. Generate 32-byte master key at /etc/customsso-manager/master.key
  8. Copy web files → /var/www/customsso-manager/; sidecar → /opt/customsso-manager/
  9. Apply migrations from src/schema/*.sql
  10. Neutralize stock ssl.conf (OL9's default <VirtualHost _default_:443> hijacks the HTTPS handshake and serves localhost.localdomain's snake-oil cert on every LAN-IP hit — install.sh comments out the offending vhost block and backs it up as .pre-customsso) + write our vhost + generate self-signed cert with SAN entries for the primary IP + hostname + localhost
  11. Configure firewalld: --add-service=https/http/ssh
  12. Apply SELinux fcontext labels + setsebool -P httpd_can_network_connect 1
  13. Configure fail2ban jail for the manager's audit log
  14. systemctl enable + restart mariadb, httpd, php-fpm, customsso-sidecar
  15. Generate first-run boot token; print the URL
  16. Print final summary

Optional flags

sudo bash /tmp/setup.sh -- --listen-host sso.example.com
sudo bash /tmp/setup.sh -- --update                  # refresh app files, preserve DB + master key
sudo bash /tmp/setup.sh -- --admin-user alice --admin-pass 's3cret!' --listen-host sso.example.com
sudo bash /tmp/setup.sh -- --require-luks            # refuse if / is not LUKS-encrypted

Expected output near the end:

[10/16] Apache vhost (rhel: /etc/httpd/conf.d/customsso-manager.conf)
  neutralized stock ssl.conf VirtualHost block (backup at ssl.conf.pre-customsso)
[11/16] firewalld
[12/16] SELinux
[13/16] fail2ban
[14/16] sidecar service
[15/16] first admin

  ================================================================
   First-admin boot token generated. To finish setup, open:

     https://<your-host>/setup?token=<64-hex>
  ================================================================

  =============================================
    customsso-manager v0.6.x installed
  =============================================

Step 3 — Claim the boot token from a browser

Sanity check: sudo cat /etc/customsso-manager/first-run.token should now be empty (truncated on successful setup). Retrying the URL shows "setup already complete."

Step 4 — First smoke tests (before pairing)

Step 5 — Pair with a test PBX

Sidebar → + Add PBX. Enter host + root password + label. Click Pair. Watch the transcript at /pair/progress/{job}.

Behind the scenes the sidecar SSHes in as root, installs the customsso agent module, drops the SSO landing endpoint + Apache alias, writes a manifest of everything it created, installs its own SSH pubkey with from=<manager-ip>, then wipes the root SSH password. The root password never touches manager disk.

The dashboard flips the PBX from unknownok within ~60 s.

Step 6 — End-to-end smoke test on the paired PBX

Step 7 — Test the --update path

To refresh to a newer release without touching DB or master key:

curl -sSfL https://git.voip-stuff.net/customsso-manager/install.sh -o /tmp/setup.sh
sudo bash /tmp/setup.sh -- --update

Expected: app files refresh, DB + master key + admins + paired PBXes preserved, vhost backed up before rewrite (.pre-<timestamp>), migrations run any new NNN_*.sql, sidecar restarts.

OL9-specific gotchas

Rollback

/etc/customsso-manager/, /var/www/customsso-manager/, /opt/customsso-manager/, the DB, and the fail2ban / vhost / spool paths listed at install time are the only things touched. Wiping those + dnf remove on the packages returns the box to baseline. On a VPS the cheapest recovery is destroy + re-provision.