156 lines
5.7 KiB
Bash
Executable File
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 "========================================"
|