Opus/setperms.sh
2026-07-04 09:09:13 -07:00

156 lines
5.7 KiB
Bash
Executable File

#!/usr/bin/env bash
# setperms.sh
# Run from anywhere — WEB_ROOT is absolute
# Handles both WordPress sites and custom PHP apps
set -euo pipefail
# ====== EDIT THESE ======
WEB_ROOT="/mnt/data/www"
ADMIN_USER="ubuntu"
ADMIN_GROUP="ubuntu"
WEB_USER="www-data"
WEB_GROUP="www-data"
DRY_RUN=false # set true to preview without changes
# ========================
run() { $DRY_RUN && echo "[DRY] $*" || eval "$*"; }
# ─────────────────────────────────────────────
# Custom PHP apps and their writable dirs
# Each value is a space-separated list of dirs
# relative to the app root
# ─────────────────────────────────────────────
declare -A CUSTOM_APP_WRITABLE
CUSTOM_APP_WRITABLE["grailheart.com"]="CA IM __ de en es fr la pt public/uploads public/cache"
CUSTOM_APP_WRITABLE["xyzzy31416.com"]="public/uploads public/cache storage tmp"
# ─────────────────────────────────────────────
# SECTION 1: WordPress sites
# ─────────────────────────────────────────────
echo "========================================"
echo "Processing WordPress sites..."
echo "========================================"
mapfile -t WP_SITES < <(find "$WEB_ROOT" -maxdepth 3 -type f -name wp-config.php -printf '%h\n' | sort -u)
if [[ ${#WP_SITES[@]} -eq 0 ]]; then
echo "No WordPress sites found."
else
for WP in "${WP_SITES[@]}"; do
echo "----"
echo "WordPress: $WP"
CONTENT="$WP/wp-content"
UPLOADS="$CONTENT/uploads"
CACHE="$CONTENT/cache"
UPGRADE="$CONTENT/upgrade"
PLUGINS="$CONTENT/plugins"
THEMES="$CONTENT/themes"
WC_LOGS="$UPLOADS/wc-logs"
WC_DOWNLOADS="$UPLOADS/wc-downloads"
WC_UPLOADS="$UPLOADS/woocommerce_uploads"
run "mkdir -p '$UPLOADS' '$CACHE' '$UPGRADE' '$PLUGINS' '$THEMES' '$WC_LOGS' '$WC_DOWNLOADS' '$WC_UPLOADS'"
# Baseline: ubuntu owns code, dirs 755, files 644
run "chown -R '$ADMIN_USER:$ADMIN_GROUP' '$WP'"
run "find '$WP' -type d -exec chmod 755 {} +"
run "find '$WP' -type f -exec chmod 644 {} +"
# Sensitive files
[[ -f "$WP/wp-config.php" ]] && run "chmod 640 '$WP/wp-config.php'"
[[ -f "$WP/.htaccess" ]] && run "chmod 644 '$WP/.htaccess'"
# wp-content: web-owned, writable
run "chown '$WEB_USER:$WEB_GROUP' '$CONTENT' || true"
run "chmod 775 '$CONTENT' || true"
# Core code dirs
for CODE in "$WP/wp-admin" "$WP/wp-includes"; do
[[ -d "$CODE" ]] && run "chown -R '$WEB_USER:$WEB_GROUP' '$CODE'"
done
# Writable runtime areas
for WDIR in "$UPLOADS" "$CACHE" "$UPGRADE" "$PLUGINS" "$THEMES" \
"$WC_LOGS" "$WC_DOWNLOADS" "$WC_UPLOADS"; do
run "chown -R '$WEB_USER:$WEB_GROUP' '$WDIR'"
run "find '$WDIR' -type d -exec chmod 775 {} +"
run "find '$WDIR' -type f -exec chmod 664 {} +"
done
# Setgid on writable dirs
run "chmod g+s '$CONTENT' '$UPLOADS' '$CACHE' '$UPGRADE' '$PLUGINS' '$THEMES' || true"
# PHP files never executable
run "find '$WP' -type f -name '*.php' -exec chmod 644 {} +"
echo "Done: $WP"
done
fi
# ─────────────────────────────────────────────
# SECTION 2: Custom PHP apps
# ─────────────────────────────────────────────
echo ""
echo "========================================"
echo "Processing custom PHP apps..."
echo "========================================"
for APP in "${!CUSTOM_APP_WRITABLE[@]}"; do
APP_PATH="$WEB_ROOT/$APP"
if [[ ! -d "$APP_PATH" ]]; then
echo "Skipping $APP — directory not found"
continue
fi
echo "----"
echo "Custom app: $APP_PATH"
# Baseline: ubuntu owns everything, dirs 755, files 644
run "chown -R '$ADMIN_USER:$ADMIN_GROUP' '$APP_PATH'"
run "find '$APP_PATH' -type d -exec chmod 755 {} +"
run "find '$APP_PATH' -type f -exec chmod 644 {} +"
# PHP files never executable
run "find '$APP_PATH' -type f -name '*.php' -exec chmod 644 {} +"
# Writable dirs for www-data (only if they exist)
for WDIR in ${CUSTOM_APP_WRITABLE[$APP]}; do
FULL="$APP_PATH/$WDIR"
if [[ -d "$FULL" ]]; then
run "chown -R '$WEB_USER:$WEB_GROUP' '$FULL'"
run "find '$FULL' -type d -exec chmod 775 {} +"
run "find '$FULL' -type f -exec chmod 664 {} +"
run "chmod g+s '$FULL'"
echo " Writable: $WDIR"
fi
done
echo "Done: $APP"
done
# ─────────────────────────────────────────────
# SECTION 3: Shared .env
# ─────────────────────────────────────────────
echo ""
echo "========================================"
echo "Securing shared .env..."
echo "========================================"
SHARED_ENV="$WEB_ROOT/.env"
if [[ -f "$SHARED_ENV" ]]; then
run "chown '$ADMIN_USER:$WEB_GROUP' '$SHARED_ENV'"
run "chmod 640 '$SHARED_ENV'"
echo "Done: $SHARED_ENV"
else
echo "No shared .env found at $SHARED_ENV — skipping"
fi
echo ""
echo "========================================"
echo "setperms complete."
echo "========================================"