2023-04-30 17:50:09 -06:00
#!/usr/bin/env bash
MEDIA_DIRECTORY = /media/wrolpi
# Source environment file after declaring globals.
[ -f /opt/wrolpi/.env ] && source /opt/wrolpi/.env
2023-10-09 13:25:13 -06:00
# Re-execute this script if it wasn't called with sudo.
if [ $EUID != 0 ] ; then
sudo " $0 " " $@ "
exit $?
fi
2023-04-30 17:50:09 -06:00
function check_directory( ) {
directory = $1
good_message = $2
bad_message = $3
if [ -d " ${ directory } " ] ; then
echo " OK: ${ good_message } "
else
echo " FAILED: ${ bad_message } "
fi
}
function check_file( ) {
file = $1
good_message = $2
bad_message = $3
if [ -f " ${ file } " ] ; then
echo " OK: ${ good_message } "
else
echo " FAILED: ${ bad_message } "
fi
}
echo
2024-06-12 16:38:46 -06:00
echo " WROLPi version: $( cat /opt/wrolpi/wrolpi/version.txt) "
echo
2023-04-30 17:50:09 -06:00
rpi = false
2025-01-10 11:31:41 -07:00
rpi4 = false
rpi5 = false
2023-09-24 20:10:09 -06:00
debian12 = false
2025-01-10 11:31:41 -07:00
grep -q 'Raspberry Pi' /proc/cpuinfo >/dev/null && rpi = true
grep -q 'Raspberry Pi 4' /proc/cpuinfo >/dev/null && rpi4 = true
grep -q 'Raspberry Pi 5' /proc/cpuinfo >/dev/null && rpi5 = true
grep -q 'PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"' /etc/os-release >/dev/null && debian12 = true
2023-04-30 17:50:09 -06:00
2025-01-10 11:31:41 -07:00
if [ [ ${ rpi4 } = = true ] ] ; then
echo 'OK: Running on Raspberry Pi 4'
elif [ [ ${ rpi5 } = = true ] ] ; then
echo 'OK: Running on Raspberry Pi 5'
elif [ [ ${ rpi } = = true ] ] ; then
echo 'OK: Running on unknown Raspberry Pi'
2023-09-24 20:10:09 -06:00
elif [ [ ${ debian12 } = = true ] ] ; then
echo 'OK: Running on Debian 12'
2023-04-30 17:50:09 -06:00
else
echo "FAILED: Running on unknown operating system"
fi
2025-01-10 11:31:41 -07:00
if dmesg | grep -q 'Undervoltage detected' >/dev/null 2>& 1; then
echo 'FAILED: Under voltage detected! Use a more powerful power supply.'
fi
if dmesg | grep -q 'over-current change' >/dev/null 2>& 1; then
echo 'FAILED: Over current detected! Your peripherals are using too much power!'
fi
2023-04-30 17:50:09 -06:00
if id -u wrolpi >/dev/null 2>& 1; then
echo "OK: Found wrolpi user"
else
echo "FAILED: No wrolpi user found"
fi
check_directory /opt/wrolpi "The WROLPi directory exists" "The WROLPi directory does not exist at /opt/wrolpi"
check_directory /opt/wrolpi-blobs "The WROLPi blobs directory exists" "The WROLPi blobs directory does not exist at /opt/wrolpi-blobs"
check_file /opt/wrolpi/main.py "The WROLPi main script exists" "The WROLPi main script does not exist at /opt/wrolpi/main.py"
2023-05-09 14:24:26 -06:00
check_file ${ MEDIA_DIRECTORY } /config/wrolpi.yaml "The WROLPi config file exists" "The WROLPi config file does not exist"
2023-04-30 17:50:09 -06:00
echo
# Postgresql
systemctl status postgresql.service >/dev/null &&
echo "OK: Postgres found" ||
echo "FAILED: Postgres service does not exist"
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
if netstat -ant | grep LISTEN | grep -E '[:\.]5432\b' >/dev/null; then
2023-04-30 17:50:09 -06:00
echo "OK: Port 5432 is occupied"
else
echo "FAILED: Port 5432 is not occupied"
fi
[ -S /var/run/postgresql/.s.PGSQL.5432 ] &&
echo "OK: Postgres is using file socket" ||
echo "FAILED: Postgres is not using file socket"
2026-07-06 20:06:21 -06:00
# Cluster-level checks. The umbrella postgresql.service reports active even
# when every cluster is down, so inspect the real clusters.
if command -v pg_lsclusters >/dev/null 2>& 1; then
cluster_line = $( pg_lsclusters -h 2>/dev/null | head -1)
if [ -z " ${ cluster_line } " ] ; then
echo "FAILED: No Postgres clusters exist (pg_lsclusters printed nothing)"
elif [ " $( echo " ${ cluster_line } " | awk '{print $4}' ) " = "online" ] ; then
echo " OK: Postgres cluster is online (port $( echo " ${ cluster_line } " | awk '{print $3}' ) ) "
else
echo " FAILED: Postgres cluster is not online: ${ cluster_line } "
fi
cluster_data_dir = $( echo " ${ cluster_line } " | awk '{print $6}' )
if [ -n " ${ cluster_data_dir } " ] ; then
case " ${ cluster_data_dir } " in
/var/lib/postgresql/*) echo " OK: Postgres data directory is at ${ cluster_data_dir } " ; ;
*) echo " FAILED: Postgres data directory is in an unexpected location: ${ cluster_data_dir } " ; ;
esac
fi
fi
# A mount over /var/lib/postgresql means the Portable bind layout (expected
# only on live boots). On an installed system this indicates the cluster is
# on the media drive — the wrong spot; see mount-issues.md Problem 8.
if findmnt -n /var/lib/postgresql >/dev/null 2>& 1; then
echo " Note: /var/lib/postgresql is a mount: $( findmnt -n -o SOURCE,FSTYPE /var/lib/postgresql) "
echo " (Portable/live-boot layout; on an installed system this is WRONG)"
else
echo "OK: /var/lib/postgresql is on the root filesystem (installed layout)"
fi
2026-07-09 15:48:48 -06:00
# Connect directly instead of `sudo -i -u wrolpi` so sudo/PAM do not spam the journal.
wrolpi_psql( ) {
PGPASSWORD = wrolpi psql -h 127.0.0.1 -p 5432 -U wrolpi wrolpi " $@ "
}
if wrolpi_psql -c 'select 1' >/dev/null 2>& 1; then
2023-04-30 17:50:09 -06:00
echo "OK: Found wrolpi database"
2026-07-09 15:48:48 -06:00
if wrolpi_psql -c '\d' 2>/dev/null | grep "file_group" >/dev/null; then
2023-04-30 17:50:09 -06:00
echo "OK: WROLPi database is initialized"
2026-07-09 15:48:48 -06:00
if [ " $( wrolpi_psql -c 'copy (select count(*) from file_group) to stdout' 2>/dev/null) " -gt 0 ] ; then
2023-04-30 17:50:09 -06:00
echo "OK: WROLPi database has files"
else
2025-01-11 11:06:43 -07:00
echo " FAILED: WROLPi database has no files. You need to refresh your files: https:// $( hostname) .local/files "
2023-04-30 17:50:09 -06:00
fi
else
echo "FAILED: WROLPi is not initialized"
fi
else
echo "FAILED: Unable to find wrolpi database"
fi
2025-12-11 18:32:55 -07:00
echo
# Controller
if [ -f /opt/wrolpi/controller/venv/bin/python3 ] ; then
echo "OK: Controller Python virtual environment exists"
if /opt/wrolpi/controller/venv/bin/python3 --version 2>/dev/null > /dev/null; then
echo 'OK: Controller Python can be run'
else
echo "FAILED: Controller Python could not be run"
fi
else
echo "FAILED: Controller Python virtual environment does not exist"
fi
if systemctl list-unit-files "*wrolpi-controller*" >/dev/null 2>& 1; then
echo "OK: WROLPi Controller systemd exists"
else
echo "FAILED: WROLPi Controller systemd does not exist"
fi
if [ -f /etc/systemd/system/wrolpi-controller.service ] ; then
if systemctl status wrolpi-controller.service >/dev/null 2>& 1; then
echo "OK: WROLPi Controller service is up"
else
echo "FAILED: WROLPi Controller service is not up"
fi
fi
2026-04-07 20:01:49 -06:00
if curl -s http://0.0.0.0:80/api/health --max-time 5 >/dev/null 2>& 1; then
2025-12-11 18:32:55 -07:00
echo "OK: WROLPi Controller health check passed"
else
echo "FAILED: WROLPi Controller health check failed"
fi
# WROL Mode status
if [ -f /media/wrolpi/config/.wrol_mode ] ; then
echo "Note: WROL Mode is ACTIVE"
else
echo "OK: WROL Mode is inactive"
fi
2023-04-30 17:50:09 -06:00
echo
# API
if [ -f /opt/wrolpi/venv/bin/python3 ] ; then
2023-05-09 14:24:26 -06:00
echo "OK: WROLPi Python virtual environment exists"
2023-04-30 17:50:09 -06:00
2023-11-23 17:02:03 -07:00
if /opt/wrolpi/venv/bin/python3 /opt/wrolpi/main.py -h 2>/dev/null > /dev/null; then
2023-04-30 17:50:09 -06:00
echo 'OK: WROLPi main can be run'
else
2026-07-09 15:48:48 -06:00
echo "FAILED: WROLPi main could not be run"
2023-04-30 17:50:09 -06:00
fi
2024-06-12 16:38:46 -06:00
if /opt/wrolpi/venv/bin/sanic --help 2>/dev/null > /dev/null; then
echo 'OK: Sanic can be run'
else
2026-07-09 15:48:48 -06:00
echo "FAILED: Sanic could not be run"
2024-06-12 16:38:46 -06:00
fi
2023-04-30 17:50:09 -06:00
else
2023-05-09 14:24:26 -06:00
echo "FAILED: WROLPi Python virtual environment does not exist"
2023-04-30 17:50:09 -06:00
fi
if systemctl list-unit-files "*wrolpi-api*" >/dev/null; then
echo "OK: WROLPi API systemd exists"
else
echo "FAILED: WROLPi API systemd does not exist"
fi
if [ -f /etc/systemd/system/wrolpi-api.service ] ; then
if systemctl status wrolpi-api.service >/dev/null; then
echo "OK: WROLPi API service is up"
else
echo "FAILED: WROLPi API service is not up"
fi
fi
2024-12-11 11:52:33 -07:00
if curl -s http://0.0.0.0:8081/api/echo --max-time 5 | grep -i '"method":"GET"' >/dev/null; then
2023-04-30 17:50:09 -06:00
echo "OK: WROLPi API echoed correctly"
else
echo "FAILED: WROLPi API did not echo correctly"
fi
echo
# Webapp
if [ -d /opt/wrolpi/app ] ; then
echo "OK: WROLPi app directory exists"
2026-07-09 15:48:48 -06:00
if ( cd /opt/wrolpi/app && npm ls >/dev/null 2>& 1) ; then
2023-04-30 17:50:09 -06:00
echo "OK: WROLPi app exists"
else
echo "FAILED: WROLPi app does not exist"
fi
else
echo "FAILED: WROLPi app directory does not exist"
fi
if systemctl list-unit-files "*wrolpi-app*" >/dev/null; then
echo "OK: WROLPi app systemd exists"
else
echo "FAILED: WROLPi app systemd does not exist"
fi
if [ -f /etc/systemd/system/wrolpi-app.service ] ; then
if systemctl status wrolpi-app.service >/dev/null; then
echo "OK: WROLPi app service is up"
else
echo "FAILED: WROLPi app service is not up"
fi
fi
2024-12-11 11:52:33 -07:00
if curl -s http://0.0.0.0:3000 --max-time 5 | grep -i wrolpi >/dev/null; then
2024-10-01 11:29:57 -06:00
echo "OK: WROLPi app responded with UI"
2023-04-30 17:50:09 -06:00
else
2024-10-01 11:29:57 -06:00
echo "FAILED: WROLPi app did not respond with UI"
fi
2024-12-11 11:52:33 -07:00
if curl -s http://0.0.0.0:3000/epub/epub.html --max-time 5 | grep -i epub.js >/dev/null; then
2024-10-01 11:29:57 -06:00
echo "OK: WROLPi app responded with ebook interface"
else
echo "FAILED: WROLPi app did not respond with ebook interface"
2023-04-30 17:50:09 -06:00
fi
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
echo
# Caddy
if command -v caddy & >/dev/null; then
echo " OK: Caddy is installed ( $( caddy version 2>/dev/null | head -1) ) "
else
echo "FAILED: Caddy is not installed"
fi
if systemctl list-unit-files "*caddy*" >/dev/null 2>& 1; then
echo "OK: Caddy systemd exists"
if systemctl status caddy >/dev/null 2>& 1; then
echo "OK: Caddy service is running"
else
echo "FAILED: Caddy service is not running"
fi
2023-04-30 17:50:09 -06:00
else
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
echo "FAILED: Caddy systemd does not exist"
2023-04-30 17:50:09 -06:00
fi
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
check_file /etc/caddy/Caddyfile "Caddyfile exists" "Caddyfile does not exist at /etc/caddy/Caddyfile"
check_file /etc/ssl/wrolpi/cert.crt "TLS certificate exists" "TLS certificate does not exist at /etc/ssl/wrolpi/cert.crt"
check_file /etc/ssl/wrolpi/cert.key "TLS key exists" "TLS key does not exist at /etc/ssl/wrolpi/cert.key"
check_file ${ MEDIA_DIRECTORY } /config/ssl/ca.crt "Root CA certificate exists" " Root CA certificate does not exist at ${ MEDIA_DIRECTORY } /config/ssl/ca.crt "
check_file ${ MEDIA_DIRECTORY } /config/ssl/ca.key "Root CA key exists" " Root CA key does not exist at ${ MEDIA_DIRECTORY } /config/ssl/ca.key "
if [ -f ${ MEDIA_DIRECTORY } /config/ssl/ca.crt ] && [ -f /etc/ssl/wrolpi/cert.crt ] ; then
if openssl verify -CAfile ${ MEDIA_DIRECTORY } /config/ssl/ca.crt /etc/ssl/wrolpi/cert.crt >/dev/null 2>& 1; then
echo "OK: Leaf certificate is signed by root CA"
else
echo "FAILED: Leaf certificate is NOT signed by root CA (regenerate with /opt/wrolpi/scripts/generate_certificates.sh)"
fi
fi
2026-07-09 15:28:54 -06:00
if [ -f ${ MEDIA_DIRECTORY } /config/ssl/ca.crt ] ; then
if ! openssl x509 -noout -in ${ MEDIA_DIRECTORY } /config/ssl/ca.crt >/dev/null 2>& 1; then
echo "FAILED: Root CA certificate cannot be parsed (regenerate with /opt/wrolpi/scripts/generate_certificates.sh)"
elif ! openssl x509 -checkend 0 -noout -in ${ MEDIA_DIRECTORY } /config/ssl/ca.crt >/dev/null 2>& 1; then
echo " FAILED: Root CA certificate is expired (delete ${ MEDIA_DIRECTORY } /config/ssl and regenerate with /opt/wrolpi/scripts/generate_certificates.sh) "
else
echo " OK: Root CA certificate is valid (expires $( openssl x509 -enddate -noout -in ${ MEDIA_DIRECTORY } /config/ssl/ca.crt | cut -d= -f2) ) "
fi
fi
if [ -f /etc/ssl/wrolpi/cert.crt ] ; then
if ! openssl x509 -noout -in /etc/ssl/wrolpi/cert.crt >/dev/null 2>& 1; then
echo "FAILED: TLS certificate cannot be parsed (regenerate with /opt/wrolpi/scripts/generate_certificates.sh)"
elif ! openssl x509 -checkend 0 -noout -in /etc/ssl/wrolpi/cert.crt >/dev/null 2>& 1; then
echo "FAILED: TLS certificate is expired (regenerate with /opt/wrolpi/scripts/generate_certificates.sh)"
elif ! openssl x509 -checkend 2592000 -noout -in /etc/ssl/wrolpi/cert.crt >/dev/null 2>& 1; then
echo " Note: TLS certificate expires within 30 days ( $( openssl x509 -enddate -noout -in /etc/ssl/wrolpi/cert.crt | cut -d= -f2) ) "
else
echo " OK: TLS certificate is valid (expires $( openssl x509 -enddate -noout -in /etc/ssl/wrolpi/cert.crt | cut -d= -f2) ) "
fi
2026-07-09 15:48:48 -06:00
if openssl x509 -in /etc/ssl/wrolpi/cert.crt -noout -checkhost " $( hostname) .local " 2>/dev/null | grep -q "does match certificate" ; then
2026-07-09 15:28:54 -06:00
echo " OK: TLS certificate covers $( hostname) .local "
else
echo " FAILED: TLS certificate does not cover $( hostname) .local (was the hostname changed? regenerate with /opt/wrolpi/scripts/generate_certificates.sh) "
fi
fi
if [ -f /etc/ssl/wrolpi/cert.crt ] && [ -f /etc/ssl/wrolpi/cert.key ] ; then
cert_pubkey = $( openssl x509 -in /etc/ssl/wrolpi/cert.crt -noout -pubkey 2>/dev/null)
key_pubkey = $( openssl pkey -in /etc/ssl/wrolpi/cert.key -pubout 2>/dev/null)
if [ -n " ${ cert_pubkey } " ] && [ " ${ cert_pubkey } " = " ${ key_pubkey } " ] ; then
echo "OK: TLS certificate matches its private key"
else
echo "FAILED: TLS certificate does not match its private key (regenerate with /opt/wrolpi/scripts/generate_certificates.sh)"
fi
fi
# Compare the certificate Caddy is actually serving to the one on disk. A mismatch means
# Caddy was not reloaded after the certificate was regenerated.
if [ -f /etc/ssl/wrolpi/cert.crt ] ; then
served_fingerprint = $( echo | timeout 5 openssl s_client -connect 127.0.0.1:443 2>/dev/null | openssl x509 -noout -fingerprint -sha256 2>/dev/null)
disk_fingerprint = $( openssl x509 -in /etc/ssl/wrolpi/cert.crt -noout -fingerprint -sha256 2>/dev/null)
if [ -z " ${ served_fingerprint } " ] ; then
echo "FAILED: Could not fetch the TLS certificate being served on port 443"
elif [ " ${ served_fingerprint } " = " ${ disk_fingerprint } " ] ; then
echo "OK: Caddy is serving the TLS certificate on disk"
else
echo "FAILED: Caddy is serving a different TLS certificate than the one on disk (reload with: systemctl reload caddy)"
fi
fi
if [ -x /opt/wrolpi/scripts/renew_certificates.sh ] ; then
echo "OK: Certificate renewal script is executable"
else
echo "FAILED: Certificate renewal script is not executable (fix with: chmod +x /opt/wrolpi/scripts/renew_certificates.sh)"
fi
if systemctl is-enabled wrolpi-cert-renew.timer >/dev/null 2>& 1; then
echo "OK: Certificate renewal timer is enabled"
else
echo "FAILED: Certificate renewal timer is not enabled (fix with: systemctl enable --now wrolpi-cert-renew.timer)"
fi
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
for port in 80 443 8084 8085 8086; do
if netstat -ant | grep LISTEN | grep -E " (0\.0\.0\.0|:::) ${ port } \b " >/dev/null; then
echo " OK: Caddy port ${ port } is occupied "
else
echo " FAILED: Caddy port ${ port } is not occupied "
fi
done
if curl -k -s https://0.0.0.0/ --max-time 5 | grep -i wrolpi >/dev/null; then
echo "OK: Caddy HTTPS proxy responded on :443"
2023-04-30 17:50:09 -06:00
else
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
echo "FAILED: Caddy HTTPS proxy did not respond on :443"
2023-04-30 17:50:09 -06:00
fi
echo
# Map
2026-03-29 18:58:31 -06:00
if curl -k -s https://0.0.0.0:8084 --max-time 5 2>/dev/null | grep -i "WROLPi Map" >/dev/null; then
echo "OK: Map viewer responded"
2025-01-01 10:59:28 -07:00
else
2026-03-29 18:58:31 -06:00
echo "FAILED: Map viewer did not respond on port 8084"
2025-01-01 10:59:28 -07:00
fi
2026-03-29 18:58:31 -06:00
check_directory /opt/wrolpi/modules/map/static "Map static assets exist" "Map static assets missing at /opt/wrolpi/modules/map/static"
2023-04-30 17:50:09 -06:00
2026-03-29 18:58:31 -06:00
if ls /media/wrolpi/map/*.pmtiles >/dev/null 2>& 1; then
2026-07-09 15:48:48 -06:00
echo " OK: Found $( ls /media/wrolpi/map/*.pmtiles 2>/dev/null | wc -l | tr -d ' ' ) PMTiles map files "
2023-04-30 17:50:09 -06:00
else
2026-03-29 18:58:31 -06:00
echo "Note: No PMTiles map files found in /media/wrolpi/map/"
2023-04-30 17:50:09 -06:00
fi
2026-03-29 18:58:31 -06:00
if [ -f /opt/wrolpi/.protomaps_installed ] ; then
echo "OK: Protomaps migration completed"
2023-04-30 17:50:09 -06:00
else
2026-03-29 18:58:31 -06:00
echo "Note: Protomaps migration has not been run (old map stack may still be active)"
2023-04-30 17:50:09 -06:00
fi
2023-07-11 08:29:17 -06:00
echo
# Kiwix
check_file /media/wrolpi/zims/library.xml "The kiwix library file exists" "The kiwix library file does not exist at /media/wrolpi/zims/library.xml"
2024-12-11 11:52:33 -07:00
if curl -k -s https://0.0.0.0:8085 --max-time 5 2>/dev/null | grep -i kiwix >/dev/null; then
2023-07-11 08:29:17 -06:00
echo "OK: Kiwix app responded"
else
echo "FAILED: Kiwix app did not respond"
fi
2023-04-30 17:50:09 -06:00
echo
# Media Directory
check_directory " ${ MEDIA_DIRECTORY } " "The media directory exists" " The media directory does not exist at ${ MEDIA_DIRECTORY } "
if [ -d " ${ MEDIA_DIRECTORY } " ] && [ -d ${ MEDIA_DIRECTORY } /config ] ; then
if touch ${ MEDIA_DIRECTORY } /config; then
echo "OK: Can modify media directory"
else
echo "FAILED: Cannot modify media directory"
fi
fi
2024-03-16 19:57:13 -06:00
if grep -qs " ${ MEDIA_DIRECTORY } " /proc/mounts >/dev/null 2>& 1 ; then
echo "OK: Media directory is a mounted drive"
else
echo "FAILED: Media directory is not a mounted drive. (This is fine if you don't have an external drive.)"
fi
2023-04-30 17:50:09 -06:00
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
if curl -k -s https://0.0.0.0/media/ --max-time 5 | grep -i "media" >/dev/null; then
echo "OK: Media directory files are served by caddy"
if curl -k -s -I https://0.0.0.0/media/config/wrolpi.yaml --max-time 5 | grep -E '200( OK)?' >/dev/null; then
echo "OK: Config can be fetched from caddy"
2023-05-09 14:24:26 -06:00
else
echo "FAILED: Media directory files are not being served"
fi
2023-04-30 17:50:09 -06:00
else
echo "FAILED: Media directory files are not being served"
fi
Replace nginx with Caddy for TLS termination and reverse proxying.
- Replace nginx with Caddy as the web server for both Docker and native
(RPi/Debian) deployments. Caddy handles HTTPS termination, reverse
proxying to all services (API, React app, Controller, Kiwix, Help, Map),
and serves the media/download file browsers.
- Generate a Root CA and signed leaf certificates for HTTPS. The Root CA
uses Name Constraints to restrict signing to local addresses only
(.local, localhost, and RFC 1918 private IP ranges), mitigating MITM
risk if the CA key is compromised.
- Add an HTTP landing page that guides users through one-time CA
certificate installation on iOS, Android, macOS, Windows, Linux, and
Firefox, with auto-redirect when the cert is already trusted.
- Add trailing-slash redirects for /controller, /docs, /media, and
/download so bare paths don't fall through to the React catch-all.
- Add a Root CA download link on the Settings page under Configs.
- Update help.sh diagnostics for IPv6 listener detection and HTTP/2
status codes.
- Remove all nginx config files and the https_proxy Docker container.
- Bump wrolpi-help submodule with certificate documentation.
2026-03-07 12:08:27 -07:00
if curl -k -s -I https://0.0.0.0/download/ --max-time 5 | grep -E '200( OK)?' >/dev/null; then
echo "OK: Media download directory files are served by caddy"
if curl -k -s -I https://0.0.0.0/download/config/wrolpi.yaml --max-time 5 | grep -E '200( OK)?' >/dev/null; then
echo "OK: Config can be downloaded from caddy"
2024-10-01 11:29:57 -06:00
else
echo "FAILED: Media download directory files are not being served"
fi
else
echo "FAILED: Media download directory files are not being served"
fi
2023-09-24 20:10:09 -06:00
if [ " $( stat -c '%U' /media/wrolpi/) " = = 'wrolpi' ] ; then
echo "OK: Media directory is owned by wrolpi user"
else
echo "FAILED: Media directory is not owned by wrolpi user"
fi
2023-04-30 17:50:09 -06:00
echo
# 3rd party commands
if single-file -h >/dev/null 2>& 1; then
echo "OK: Singlefile can be run"
else
echo "FAILED: Singlefile cannot be run"
fi
2023-09-24 20:10:09 -06:00
if [ -f /usr/bin/readability-extractor ] ; then
echo "OK: readability exists"
else
if [ -f /usr/local/bin/readability-extractor ] ; then
echo "OK: readability exists"
else
echo "FAILED: readability does not exist"
fi
fi
2023-04-30 17:50:09 -06:00
if wget -h >/dev/null 2>& 1; then
echo "OK: wget can be run"
else
echo "FAILED: wget cannot be run"
fi
2025-04-17 17:02:39 -06:00
if aria2c -h >/dev/null 2>& 1; then
echo "OK: aria2c can be run"
else
echo "FAILED: aria2c cannot be run"
fi
2023-04-30 17:50:09 -06:00
if /opt/wrolpi/venv/bin/yt-dlp -h >/dev/null 2>& 1; then
echo "OK: yt-dlp can be run"
else
echo "FAILED: yt-dlp cannot be run"
fi
if chromium-browser -h >/dev/null 2>& 1; then
echo "OK: Chromium can be run"
else
2023-09-24 20:10:09 -06:00
if chromium -h >/dev/null 2>& 1; then
echo "OK: Chromium can be run"
else
echo "FAILED: Chromium cannot be run"
fi
2023-04-30 17:50:09 -06:00
fi
if ffmpeg -h >/dev/null 2>& 1; then
echo "OK: ffmpeg can be run"
else
echo "FAILED: ffmpeg cannot be run"
fi
2023-11-23 17:02:03 -07:00
echo
# Help Service
2024-06-12 16:38:46 -06:00
if /opt/wrolpi-help/venv/bin/mkdocs --help & >/dev/null; then
echo "OK: Help mkdocs can be run"
else
echo "FAILED: Help mkdocs cannot be run"
fi
2024-12-11 11:52:33 -07:00
if curl -k -s https://0.0.0.0:8086/ --max-time 5 | grep MkDocs 2>/dev/null >/dev/null; then
2023-11-23 17:02:03 -07:00
echo "OK: Help service is running"
else
echo "FAILED: Help service is not running"
2024-07-22 16:36:57 -06:00
fi
echo
# Internet
if ping -c1 1.1.1.1 -W 5 & >/dev/null; then
echo "OK: Can ping 1.1.1.1"
else
echo "FAILED: Cannot ping 1.1.1.1. Is internet working?"
fi
2024-07-22 22:27:58 -06:00
if ping -c1 one.one.one.one -W 5 & >/dev/null; then
echo "OK: Can ping one.one.one.one"
2024-07-22 16:36:57 -06:00
else
2024-07-22 22:27:58 -06:00
echo "FAILED: Cannot ping one.one.one.one Is internet working?"
2024-07-22 16:36:57 -06:00
fi