Troubleshooting
A collection of real things that have gone wrong, and how to fix them. Each section follows the same shape: Symptom, Cause, Fix. If you hit something that isn’t here, open an issue at codetot-web/litesoup — most entries on this page started life as a bug report.
1. Unable to locate package php8.2-fpm during install
Symptom. install/install-stack.sh aborts in stage 2 (PHP install) with:
E: Unable to locate package php8.2-fpm
Cause. Your VPS can’t reach ppa.launchpadcontent.net. This bites
DigitalOcean Singapore droplets and a handful of other regions where the
launchpad CDN is firewalled or routes badly. The PPA appears to register
cleanly (apt-get update returns 0 with warnings) but the package index never
makes it into the cache, so the next apt-get install can’t find anything.
Fix. Force the CloudPanel mirror, which serves byte-equivalent Sury PHP builds from CloudFront:
LITESOUP_PPA_FORCE_MIRROR=cloudpanel sudo bash install/install-stack.sh
Same package names, same versions (suffix +clp-noble instead of upstream),
GPG key pinned. This was added in v0.5.1 specifically to unblock these
networks. As of v0.5.1+ the installer will also auto-fall-back if it detects
the launchpad URL is unreachable — but forcing it skips the timeout entirely
(useful in CI).
2. php8.2-imagick or php8.2-redis skipped with a warning
Symptom. Toward the end of the PHP stage you see something like:
WARN: apt: php8.2-imagick has no Candidate -- skipping (optional)
WARN: apt: php8.2-redis has no Candidate -- skipping (optional)
Cause. You’re installing through the CloudPanel mirror (either via
LITESOUP_PPA_FORCE_MIRROR=cloudpanel or the auto-fallback). CloudPanel
mirrors core PHP and the standard extension set, but not PECL extensions
like imagick or redis. The launchpad PPA has them; CloudPanel doesn’t.
Fix. This is expected and the stack handles it for you:
- Redis Object Cache plugin automatically falls back to the bundled Predis pure-PHP client. Slower than the C extension, but functional.
- Image processing falls back to GD (already installed as a CORE extension). Plenty of WP themes never touch ImageMagick.
If you genuinely need the C extensions (e.g. you’re processing thousands of images per hour and Predis is too slow), use the launchpad PPA directly by re-running install on a network where launchpad is reachable, or install the extensions by hand from a different repo.
3. Locked out of SSH after running install-stack
Symptom. Your SSH session disconnects after running install, and you can’t
reconnect. ssh user@host hangs or rejects you with Permission denied
(publickey).
Cause. This only happens if you ran harden/harden-ssh.sh with
--no-password-auth or --no-root-login and didn’t have a working SSH key
installed first. (As of v0.7.1 the defaults are gentler — both flags are
opt-in. If you hit this on a fresh v0.7.0 install, it’s the v0.7.0 default
that bit you; see the v0.7.1 release notes.)
Fix. Use your VPS provider’s web console (DigitalOcean → Console, Vultr → View Console, etc.) to log in, then either remove the offending directives or override them:
sudo nano /etc/ssh/sshd_config.d/52-litesoup-harden.conf
# Delete or comment out:
# PasswordAuthentication no
# PermitRootLogin no
sudo sshd -t # validate syntax first
sudo systemctl reload ssh
Or write a higher-numbered file that overrides litesoup’s:
echo 'PasswordAuthentication yes' | sudo tee /etc/ssh/sshd_config.d/99-local.conf
sudo systemctl reload ssh
4. bash site-create.sh errors with “WordPress files seem to already be present”
Symptom. Re-running site/site-create.sh --domain=example.com against a
domain that already exists fails partway through with a wp-cli message about
WordPress files already being present in the docroot.
Cause. This is the desired guard. site-create.sh is for creating brand
new sites. Running it against an existing site would risk clobbering the
docroot or rotating live secrets.
Fix. Pick the operation that matches what you actually want:
- To re-render the vhost (e.g. add or change TLS) — run
site/site-set-tls.sh --domain=example.com --tls=letsencrypt --email=you@example.com. - To change the PHP version — run
site/site-set-php.sh --domain=example.com --php=8.3. - To retune the FPM pool tier — run
site/site-set-tier.sh .... - To delete and start over — run
site/site-delete.sh --domain=example.com --purge-db, then re-run site-create.
5. Error establishing a database connection after a failed site-create
Symptom. A previous site-create.sh aborted partway through (network
glitch on certbot, apache configtest failed, you ctrl-c’d it). You re-ran it,
it reported success, but visiting the site shows WordPress’s white screen with
“Error establishing a database connection”.
Cause. Pre-v0.4.1, create_database used CREATE USER IF NOT EXISTS,
which silently kept the old password if the user already existed — but
generated a new password and wrote it to wp-config.php. Mismatch =
500.
Fix. Make sure you’re on v0.4.1 or newer (cat VERSION in the repo
root). Re-run site-create.sh for the affected domain:
sudo bash site/site-create.sh --domain=example.com
v0.4.1+ both reuses the existing wp-config password AND emits an ALTER USER
to force MySQL into sync. Self-healing on retry.
6. apache2ctl configtest fails after install
Symptom. Running sudo apache2ctl configtest reports something like:
AH00526: Syntax error
... </VirtualHost> without matching <VirtualHost>
…and Apache won’t reload.
Cause. Almost always the v0.3.0–v0.4.0 vhost template substitution bug.
The template’s head comment block contained the literal placeholders
__HTTP_REDIRECT__ and __HTTPS_BLOCK__, and Python’s str.replace()
substitutes inside # comments — so with TLS active, the multi-line HTTPS
block was injected into a comment, breaking the comment boundary.
Fix. Make sure you’re on v0.4.1 or newer, then re-render the affected vhost by re-running site-create’s TLS step:
sudo bash site/site-set-tls.sh --domain=example.com --tls=letsencrypt --email=you@example.com
sudo apache2ctl configtest && sudo systemctl reload apache2
7. fail2ban-client status sshd shows port 22 but my sshd runs on a different port
Symptom. You moved sshd to a non-default port (say, 2222) but
fail2ban-client status sshd still reports it watching port 22 — meaning
brute-force attacks against your real port are unprotected.
Cause. Pre-v0.7.0, harden-fail2ban.sh wrote port = ssh into the jail
config, which /etc/services resolves to 22. Fixed in v0.7.0 by parsing
the actual Port directive out of /etc/ssh/sshd_config (same parser used by
harden-firewall.sh).
Fix. Make sure you’re on v0.7.0+, then refresh fail2ban:
sudo bash harden/harden-fail2ban.sh
sudo fail2ban-client status sshd # confirm port matches sshd_config
8. CI integration test takes 5+ minutes on every PR
Symptom. Your fork’s GitHub Actions run sits in
integration-install-stack for ages, eventually times out or finishes after
~5 minutes mostly waiting on apt.
Cause. GitHub’s ubuntu-24.04 runners can’t reach
ppa.launchpadcontent.net reliably from every region. Each install attempt
burns the launchpad TLS-handshake timeout before falling back to the
CloudPanel mirror.
Fix. Skip the launchpad probe entirely by setting the env var at the job
level. See .github/workflows/ci.yml for the exact wiring — it’s a one-liner:
jobs:
integration:
env:
LITESOUP_PPA_FORCE_MIRROR: cloudpanel
This is what litesoup’s own CI uses.
9. How to verify the install actually worked
Two scripts in audit/ give you a quick read on whether the stack is healthy:
# Read-only system + service metrics: CPU, RAM, disk, Apache, PHP-FPM,
# MariaDB, Redis. Flags >85% disk usage, slow queries, etc.
sudo bash audit/audit-system-metrics.sh
# Per-site WordPress health: core version, plugin count, DB connection,
# wp-config.php permissions, TLS cert expiry, error log size.
sudo bash audit/audit-wp-health.sh
Both are pure read scripts — they touch nothing. Exit codes follow the
nagios convention: 0 healthy, 1 warning, 2 critical, so they slot into
cron cleanly. Add --format=json to either script for machine-readable
output.
For a deeper performance audit (Apache mpm_event, FPM pool sizing, OPcache, MariaDB, Redis vs recommended values for your RAM tier):
sudo bash audit/audit-performance.sh --service=all
Still stuck?
- Check the CHANGELOG — most issues here started as release notes, so a search for your error message often turns up the version that fixed it.
- Open a bug at
codetot-web/litesoup/issues
with: your
cat VERSION, distro (lsb_release -a), and the last ~50 lines ofinstall-stack.shoutput.