mirror of
https://github.com/lrnselfreliance/wrolpi.git
synced 2026-10-25 18:40:06 -04:00
Boxes installed from the Live USB run /usr/local/sbin/wrolpi-bootstrap.sh at every boot, but nothing ever updated it after image build — fixes to the bootstrap (e.g. Postgres bind-mounts on live boots only) could never reach installed systems. Copy the script (and its unit, if installed) from the repo during repair, which both upgrade.sh and install runs execute. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
207 lines
7.8 KiB
Bash
Executable file
207 lines
7.8 KiB
Bash
Executable file
#!/usr/bin/env bash
|
|
# This script will attempt to repair a WROLPi installation. It will not use internet.
|
|
|
|
cd /opt/wrolpi || (echo "Cannot repair. /opt/wrolpi does not exist" && exit 1)
|
|
|
|
# Re-execute this script if it wasn't called with sudo.
|
|
if [ $EUID != 0 ]; then
|
|
sudo "$0" "$@"
|
|
exit $?
|
|
fi
|
|
|
|
rpi=false
|
|
if (grep 'Raspberry Pi' /proc/cpuinfo >/dev/null); then
|
|
rpi=true
|
|
fi
|
|
|
|
set -e
|
|
set -x
|
|
|
|
# Stop services if they are running.
|
|
systemctl stop wrolpi-controller.service || :
|
|
systemctl stop wrolpi-api.service || :
|
|
systemctl stop wrolpi-app.service || :
|
|
systemctl stop wrolpi-kiwix.service || :
|
|
systemctl stop caddy || :
|
|
|
|
# Clear Python bytecode cache from virtual environments to fix potential corruption.
|
|
echo "Clearing Python bytecode cache..."
|
|
find /opt/wrolpi/venv -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || :
|
|
find /opt/wrolpi/venv -name "*.pyc" -delete 2>/dev/null || :
|
|
find /opt/wrolpi/controller/venv -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || :
|
|
find /opt/wrolpi/controller/venv -name "*.pyc" -delete 2>/dev/null || :
|
|
find /opt/wrolpi-help/venv -type d -name __pycache__ -exec rm -rf {} + 2>/dev/null || :
|
|
find /opt/wrolpi-help/venv -name "*.pyc" -delete 2>/dev/null || :
|
|
|
|
# Create the WROLPi user
|
|
grep wrolpi: /etc/passwd || useradd -md /home/wrolpi wrolpi -s "$(command -v bash)"
|
|
[ -f /home/wrolpi/.pgpass ] || cat >/home/wrolpi/.pgpass <<'EOF'
|
|
127.0.0.1:5432:wrolpi:wrolpi:wrolpi
|
|
EOF
|
|
chmod 0600 /home/wrolpi/.pgpass
|
|
|
|
# Reset any inadvertent changes to the WROLPi repo. Restore ownership in case this repair script fails.
|
|
git config --global --add safe.directory /opt/wrolpi
|
|
git reset HEAD --hard
|
|
chown -R wrolpi:wrolpi /opt/wrolpi
|
|
|
|
# Copy configs to system.
|
|
mkdir -p /etc/caddy
|
|
cp /opt/wrolpi/etc/raspberrypios/Caddyfile /etc/caddy/Caddyfile
|
|
mkdir -p /var/www
|
|
cp /opt/wrolpi/etc/raspberrypios/50x.html /var/www/50x.html
|
|
|
|
# Generate certificate for HTTPS.
|
|
/opt/wrolpi/scripts/generate_certificates.sh
|
|
|
|
# Install map fonts from blob (needed for MapLibre map labels).
|
|
MAP_FONTS_BLOB=/opt/wrolpi-blobs/map-fonts.tar.gz
|
|
if [ -f "${MAP_FONTS_BLOB}" ]; then
|
|
mkdir -p /opt/wrolpi/modules/map/static/fonts
|
|
tar -xzf "${MAP_FONTS_BLOB}" -C /opt/wrolpi/modules/map/static/
|
|
fi
|
|
|
|
# Start Caddy quickly so user can access Controller from React UI
|
|
systemctl start caddy || :
|
|
|
|
# WROLPi needs a few privileged commands.
|
|
cp /opt/wrolpi/etc/raspberrypios/90-wrolpi /etc/sudoers.d/90-wrolpi
|
|
chmod 0440 /etc/sudoers.d/90-wrolpi
|
|
# Verify this new file is valid.
|
|
visudo -c -f /etc/sudoers.d/90-wrolpi
|
|
|
|
# Update the Portable bootstrap on boxes installed from the Live USB; it is
|
|
# otherwise frozen at image-build time.
|
|
LIVE_INCLUDES=/opt/wrolpi/debian-live-config/config/includes.chroot
|
|
if [ -f /usr/local/sbin/wrolpi-bootstrap.sh ]; then
|
|
cp "${LIVE_INCLUDES}/usr/local/sbin/wrolpi-bootstrap.sh" /usr/local/sbin/wrolpi-bootstrap.sh
|
|
chmod 0755 /usr/local/sbin/wrolpi-bootstrap.sh
|
|
if [ -f /etc/systemd/system/wrolpi-bootstrap.service ]; then
|
|
cp "${LIVE_INCLUDES}/etc/systemd/system/wrolpi-bootstrap.service" /etc/systemd/system/wrolpi-bootstrap.service
|
|
fi
|
|
fi
|
|
|
|
# Install the systemd services
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi*.service /etc/systemd/system/
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi-*.timer /etc/systemd/system/
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi.target /etc/systemd/system/
|
|
systemctl enable wrolpi-controller.service
|
|
systemctl enable wrolpi-api.service
|
|
systemctl enable wrolpi-app.service
|
|
systemctl enable wrolpi-kiwix.service
|
|
systemctl enable wrolpi-help.service
|
|
systemctl enable wrolpi-mounts.service
|
|
systemctl enable wrolpi-cert-renew.timer
|
|
|
|
# Repair Controller (offline-safe - no pip install)
|
|
repair_controller() {
|
|
echo "Checking WROLPi Controller..."
|
|
|
|
# Check venv exists
|
|
if [ ! -f /opt/wrolpi/controller/venv/bin/python ]; then
|
|
echo "ERROR: Controller venv missing!"
|
|
echo "Run install.sh or upgrade.sh (requires internet) to reinstall."
|
|
return 1
|
|
fi
|
|
|
|
# Check venv is functional
|
|
if ! /opt/wrolpi/controller/venv/bin/python --version > /dev/null 2>&1; then
|
|
echo "ERROR: Controller venv is corrupted!"
|
|
echo "Run install.sh or upgrade.sh (requires internet) to reinstall."
|
|
return 1
|
|
fi
|
|
|
|
# Check systemd service is installed
|
|
if [ ! -f /etc/systemd/system/wrolpi-controller.service ]; then
|
|
echo "Controller systemd service not installed, copying..."
|
|
cp /opt/wrolpi/etc/raspberrypios/wrolpi-controller.service /etc/systemd/system/
|
|
systemctl daemon-reload
|
|
fi
|
|
|
|
# Ensure service is enabled
|
|
if ! systemctl is-enabled wrolpi-controller > /dev/null 2>&1; then
|
|
echo "Enabling Controller service..."
|
|
systemctl enable wrolpi-controller
|
|
fi
|
|
|
|
echo "Controller repair completed"
|
|
}
|
|
|
|
# Run Controller repair if venv exists (skip on fresh install)
|
|
if [ -d /opt/wrolpi/controller/venv ]; then
|
|
repair_controller || echo "Controller repair failed, continuing..."
|
|
fi
|
|
|
|
# Start Controller so user can monitor repair in UI.
|
|
systemctl start wrolpi-controller
|
|
|
|
/usr/bin/systemctl daemon-reload
|
|
|
|
# WROLPi needs a few privileged commands.
|
|
cp /opt/wrolpi/etc/raspberrypios/90-wrolpi /etc/sudoers.d/90-wrolpi
|
|
chmod 0440 /etc/sudoers.d/90-wrolpi
|
|
# Verify this new file is valid.
|
|
visudo -c -f /etc/sudoers.d/90-wrolpi
|
|
|
|
# Configure Postgresql. Do this after the API is stopped.
|
|
/opt/wrolpi/scripts/initialize_api_db.sh
|
|
# wrolpi user is superuser so they can import maps.
|
|
sudo -iu postgres psql -c "alter user wrolpi with superuser"
|
|
|
|
# Create the media directory. This should be mounted by the maintainer.
|
|
[ -d /media/wrolpi ] || mkdir /media/wrolpi
|
|
# Create config directory if external drive is mounted, and is empty.
|
|
if grep -qs /media/wrolpi /proc/mounts && [ -z "$(ls -A /media/wrolpi)" ] && [ ! -d /media/wrolpi/config ]; then
|
|
mkdir /media/wrolpi/config
|
|
fi
|
|
|
|
# Build the frontend app.
|
|
(cd /opt/wrolpi/app && npm run build)
|
|
|
|
# Change owner of the media directory, ignore any errors because the drive may be fat/exfat/etc.
|
|
chown wrolpi:wrolpi /media/wrolpi 2>/dev/null || echo "Ignoring failure to change media directory permissions."
|
|
# Ensure the config directory is owned by wrolpi so the API can write config files.
|
|
[ -d /media/wrolpi/config ] && chown -R wrolpi:wrolpi /media/wrolpi/config 2>/dev/null || :
|
|
# On bootstrapped systems the Postgres cluster lives under config/postgresql (bind-mounted to
|
|
# /var/lib/postgresql and /etc/postgresql). It must stay owned by postgres, or new backends
|
|
# die with: FATAL: could not open file "global/pg_filenode.map": Permission denied.
|
|
if [ -d /media/wrolpi/config/postgresql ] && id postgres >/dev/null 2>&1; then
|
|
chown -R postgres:postgres /media/wrolpi/config/postgresql 2>/dev/null || :
|
|
fi
|
|
|
|
# Remove immutable flag from blob files before chown (may not exist or may not be set).
|
|
chattr -i /opt/wrolpi-blobs/* 2>/dev/null || :
|
|
|
|
chown -R wrolpi:wrolpi /home/wrolpi /opt/wrolpi*
|
|
|
|
# Protect blob files from accidental modification or deletion.
|
|
# These files are critical for initializing WROLPi.
|
|
if [ -d /opt/wrolpi-blobs ] && ls /opt/wrolpi-blobs/* >/dev/null 2>&1; then
|
|
chown -R root:root /opt/wrolpi-blobs
|
|
chmod 444 /opt/wrolpi-blobs/*
|
|
chattr +i /opt/wrolpi-blobs/*
|
|
fi
|
|
|
|
# Copy MOTD once the repair has been successful.
|
|
cp /opt/wrolpi/etc/raspberrypios/motd/30-wrolpi.motd /etc/update-motd.d/30-wrolpi
|
|
chmod +x /etc/update-motd.d/*
|
|
|
|
# Copy desktop shortcuts to existing users (new users get them from /etc/skel).
|
|
if [[ ${rpi} == true ]]; then
|
|
for user_home in /home/wrolpi /home/pi; do
|
|
if [ -d "${user_home}/Desktop" ]; then
|
|
cp /opt/wrolpi/etc/raspberrypios/*.desktop "${user_home}/Desktop/"
|
|
chown -R "$(basename ${user_home})":"$(basename ${user_home})" "${user_home}/Desktop/"
|
|
fi
|
|
done
|
|
# Update skeleton for future users.
|
|
mkdir -p /etc/skel/Desktop
|
|
cp /opt/wrolpi/etc/raspberrypios/*.desktop /etc/skel/Desktop/
|
|
fi
|
|
|
|
systemctl restart wrolpi-help
|
|
systemctl start wrolpi.target
|
|
|
|
set +x
|
|
|
|
echo "Repair has completed. You may run /opt/wrolpi/help.sh to check system status."
|