#!/usr/bin/env bash set -euo pipefail # Increase PHP memory for WP-CLI tasks export WP_CLI_PHP_ARGS="-d memory_limit=256M" # === Config === PORT="${PORT:-7860}" WP_PATH="/var/www/html" DB_DIR="$WP_PATH/wp-content/database" export DB_FILE="$DB_DIR/.ht.sqlite" UPLOADS_DIR="$WP_PATH/wp-content/uploads" # LOG log() { echo "[space] $(date -Iseconds) $*"; } lognew() { echo "$1 $(date -Iseconds) $2"; } export -f lognew # Load .public PUBLIC_FILE_PATH=/root/.public if [ -f "$PUBLIC_FILE_PATH" ]; then log "source ${PUBLIC_FILE_PATH}" eval "source $PUBLIC_FILE_PATH" else echo "File '$PUBLIC_FILE_PATH' not present!" export SITE_TITLE="WordPress SQLite" export ARCHIVE_ITEM_ID="wp-sqlite-backup-enc" fi # Configure Wordpress ADMIN_USER="${ADMIN_USER:-codersall}" ADMIN_PASS="${ADMIN_PASS:-codersAll.com}" ADMIN_EMAIL="${ADMIN_EMAIL:-admin@codersAll.com}" log "ADMIN_USER: $ADMIN_USER" # Configure Internet Archive if [[ -v IA_EMAIL ]] && [[ -v IA_PASSWORD ]]; then log "Configuring Internet Archive" ia configure -u $IA_EMAIL -p $IA_PASSWORD history -c export IA="exist" else log "Skipped Configuring Internet Archive!" export IA="" fi # Configure Dropbox (via RClone) if [[ -n "$RCLONE_DROPBOX_TOKEN" ]]; then log "Configuring Dropbox (via RClone)" mkdir -p .config/rclone/ cat <.config/rclone/rclone.conf [my-dropbox] type = dropbox token = ${RCLONE_DROPBOX_TOKEN} EOF chmod 600 .config/rclone/rclone.conf export DBRC="exist" else log "Skipped Configuring Dropbox (via RClone)" export DBRC="" fi # Configure HuggingFace Repo (to persist themes & plugins) REPO_NAME="wp-persist" export SITE_URL="${SITE_URL:-}" export HF_USER=$(echo "$SITE_URL" | cut -d'/' -f3 | cut -d'-' -f1) HF_TOKEN="${HF_TOKEN:-}" if [[ -n "$HF_USER" ]] && [[ -n "$HF_TOKEN" ]]; then log "creating Repo: $REPO_NAME (if doesn't exists)" hf repo create $HF_USER/$REPO_NAME --repo-type space --space-sdk static --private --token $HF_TOKEN --exist-ok git lfs install git clone https://$HF_USER:$HF_TOKEN@huggingface.co/spaces/$HF_USER/$REPO_NAME /tmp/wp-store || { log "ERROR: Failed to clone repo. Make sure the space exists and HF_TOKEN has write access." exit 1 } cd /tmp/wp-store # Configure git identity git config user.email "$HF_USER@users.noreply.huggingface.co" git config user.name "$HF_USER" # Configure git auth persistence git config credential.helper store echo "https://$HF_USER:$HF_TOKEN@huggingface.co" > ~/.git-credentials #echo "https://$HF_USER:$HF_TOKEN@huggingface.co" >> ~/.git-credentials # Initialize folder structure if missing if [[ ! -d wp-content ]]; then log "Initializing wp-content directory in repo" mkdir -p wp-content/themes mkdir -p wp-content/plugins touch wp-content/themes/.empty touch wp-content/plugins/.empty echo -en "*.woff2 filter=lfs diff=lfs merge=lfs -text\n*.webp filter=lfs diff=lfs merge=lfs -text\n*.png filter=lfs diff=lfs merge=lfs -text\n*.ttf filter=lfs diff=lfs merge=lfs -text\n*.gif filter=lfs diff=lfs merge=lfs -text\n*.jpg filter=lfs diff=lfs merge=lfs -text" >> .gitattributes git add . git commit -m "Initialize empty wp-content" git push log "Initial push completed" cd - else log "HF repo already contains wp-content" cd - rsync -aq --delete /tmp/wp-store/wp-content/themes/ /var/www/html/wp-content/themes/ rsync -aq --delete /tmp/wp-store/wp-content/plugins/ /var/www/html/wp-content/plugins/ log "Sync completed" fi else log "Skipping HF sync: HF_USER or HF_TOKEN missing" fi # export ARCHIVE_ITEM_ID="$ARCHIVE_ITEM_ID-$HF_USER" log "SITE_URL: $SITE_URL" log "ARCHIVE_ITEM_ID: $ARCHIVE_ITEM_ID" if [[ -n "$SITE_URL" ]]; then export HTTP_HOST=$(echo "$SITE_URL" | sed -E 's~https?://([^/]+).*~\1~') export HTTPS=on export SERVER_PORT=443 log "Running in HTTPS mode for proxied environment. SITE_URL: $SITE_URL, HTTP_HOST: $HTTP_HOST" else export HTTP_HOST="127.0.0.1" export SITE_URL="http://127.0.0.1" export HTTPS=off export SERVER_PORT=80 log "Running in local HTTP mode (no proxy detected)" fi # === 1) Make Apache listen on $PORT === log "Configuring Apache to listen on port ${PORT}" # --- EARLY FIX: force HTTPS perception before mod_dir runs --- if [[ "$SITE_URL" != "http://127.0.0.1" && "$HTTP_HOST" != "127.0.0.1" ]]; then cat </etc/apache2/conf-enabled/00-early-https.conf SetEnvIf X-Forwarded-Proto https HTTPS=on SetEnvIf X-Forwarded-Proto https SERVER_PORT=443 RequestHeader set X-Forwarded-Proto "https" RequestHeader set X-Forwarded-Port "443" UseCanonicalName Off UseCanonicalPhysicalPort Off EOF else log "Skipping early HTTPS header config (local mode)" fi VHOST_7860=/etc/apache2/sites-available/000-default-${PORT}.conf # ensure 7860 is listened on if [[ "${PORT}" != "80" ]]; then sed -ri "s/^Listen 80$/Listen 80\nListen ${PORT}/" /etc/apache2/ports.conf || true # create a copy of the default vhost for the runtime port (if not already present) if [[ ! -f "${VHOST_7860}" ]]; then cp /etc/apache2/sites-available/000-default.conf "${VHOST_7860}" sed -ri "s///g" "${VHOST_7860}" # Inject manual /wp-admin → /wp-admin/ redirect near top of VirtualHost (before DirectoryIndex) if ! grep -q "RewriteCond %{REQUEST_URI} ^/wp-admin$" "${VHOST_7860}"; then log "Injecting early wp-admin redirect inside VirtualHost" sed -i "/\\n\ RewriteEngine On\\n\ RewriteCond %{REQUEST_URI} ^/wp-admin$\\n\ RewriteRule ^/wp-admin$ /wp-admin/ [R=301,L]\\n\ \\n" "${VHOST_7860}" fi a2ensite "000-default-${PORT}.conf" >/dev/null 2>&1 || true fi fi # --- 🔧 Inject canonical ServerName/Port inside VirtualHost to remove :7860 redirects --- if [[ -f "${VHOST_7860}" ]]; then log "Injecting canonical ServerName/Port into ${VHOST_7860}" sed -i "/<\/VirtualHost>/i \\ ServerName ${HTTP_HOST}\\n\ UseCanonicalName Off\\n\ UseCanonicalPhysicalPort Off\\n\ RequestHeader set X-Forwarded-Proto https\\n\ RequestHeader set X-Forwarded-Port 443\\n\ SetEnv HTTPS on\\n\ SetEnv SERVER_PORT 443\\n" "${VHOST_7860}" fi # --- Skip HTTPS enforcement if running locally --- if [[ "$SITE_URL" == "http://127.0.0.1" || "$HTTP_HOST" == "127.0.0.1" ]]; then log "Detected local environment — disabling all HTTPS and proxy forcing." echo "SetEnv HTTPS off" >> /etc/apache2/apache2.conf echo "SetEnv SERVER_PORT 80" >> /etc/apache2/apache2.conf export HTTPS=off export SERVER_PORT=80 else # --- Force Apache to believe it runs on HTTPS:443 globally (fixes :7860 + http redirects) --- log "Enforcing global HTTPS canonical scheme and port" cat </etc/apache2/conf-enabled/force-canonical-https.conf # Global canonicalization fix for HuggingFace reverse proxy UseCanonicalName Off UseCanonicalPhysicalPort Off ServerTokens Prod ServerSignature Off ServerName ${HTTP_HOST} ServerAdmin webmaster@localhost # Pretend Apache runs on 443 by overriding canonical name/port behavior DirectorySlash On UseCanonicalPhysicalPort Off SetEnv HTTPS on SetEnv SERVER_PORT 443 RequestHeader set X-Forwarded-Proto https RequestHeader set X-Forwarded-Port 443 RewriteEngine On # Ensure all self-generated redirects use https:// RewriteCond %{HTTPS} !=on [OR] RewriteCond %{REQUEST_SCHEME} =http RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] EOF # --- Reverse proxy environment --- cat </etc/apache2/conf-enabled/remoteip-proxy.conf RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 10.0.0.0/8 RemoteIPTrustedProxy 172.16.0.0/12 RemoteIPTrustedProxy 192.168.0.0/16 # Force Apache to believe it's HTTPS and on port 443 for generated redirects SetEnv HTTPS on SetEnv SERVER_PORT 443 UseCanonicalName Off UseCanonicalPhysicalPort Off EOF # --- HTTPS rewrite logic --- cat <<'EOF' >/etc/apache2/conf-enabled/global-https-rewrite.conf RewriteEngine On # Force HTTPS canonical scheme and trailing slash if directory RewriteCond %{HTTPS} !=on [OR] RewriteCond %{REQUEST_SCHEME} =http [OR] RewriteCond %{SERVER_PORT} !^443$ RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # Ensure trailing slash for directories (manual replacement of DirectorySlash) RewriteCond %{REQUEST_FILENAME} -d RewriteCond %{REQUEST_URI} !/$ RewriteRule (.*[^/])$ https://%{HTTP_HOST}/$1/ [R=301,L] EOF fi # --- Force HTTPS early (preempt DirectorySlash before rewrite phase) --- if [[ "$SITE_URL" == "http://127.0.0.1" || "$HTTP_HOST" == "127.0.0.1" ]]; then log "Skipping HTTPS envvar patch (local HTTP mode)" sed -i '/export HTTPS=on/d' /etc/apache2/envvars 2>/dev/null || true sed -i '/export SERVER_PORT=443/d' /etc/apache2/envvars 2>/dev/null || true echo "export HTTPS=off" >> /etc/apache2/envvars echo "export SERVER_PORT=80" >> /etc/apache2/envvars else log "Hard-setting HTTPS environment defaults inside Apache envvars" if ! grep -q "export HTTPS=on" /etc/apache2/envvars 2>/dev/null; then cat <<'EOF' >> /etc/apache2/envvars # Added by space-entrypoint for HuggingFace proxy export HTTPS=on export SERVER_PORT=443 EOF fi fi # --- Globally force Apache to treat all VirtualHosts as HTTPS:443 for canonical redirects --- # log "Forcing Apache global canonical port to 443" # cat </etc/apache2/conf-enabled/force-global-canonical-port.conf # UseCanonicalName Off # UseCanonicalPhysicalPort Off # # Tell Apache its canonical scheme and port # ServerTokens Prod # ServerSignature Off # ServerName ${HTTP_HOST} # ServerAdmin webmaster@localhost # # UseCanonicalPhysicalPort Off # RequestHeader set X-Forwarded-Proto https # RequestHeader set X-Forwarded-Port 443 # # EOF # --- Manually redirect /wp-admin → /wp-admin/ to replace disabled DirectorySlash --- # cat </etc/apache2/conf-enabled/fix-wp-admin-noslash.conf # # RewriteEngine On # RewriteCond %{REQUEST_URI} ^/wp-admin$ # RewriteRule ^/wp-admin$ /wp-admin/ [R=301,L] # # EOF # --- Enable Apache modules needed for HTTPS proxy logic --- a2enmod rewrite headers >/dev/null 2>&1 || true # --- Globally enable rewrite engine early --- cat <<'EOF' >/etc/apache2/conf-enabled/00-global-rewrite.conf RewriteEngine On EOF # --- Fix Apache self-redirects under reverse proxy (HuggingFace) --- a2enmod remoteip >/dev/null 2>&1 || true # --- Disable global DirectorySlash to prevent early HTTP redirects --- cat <<'EOF' >/etc/apache2/conf-enabled/disable-global-dirslash.conf DirectorySlash Off AllowOverride All EOF # --- Override Apache's mod_dir default to disable global DirectorySlash early --- cat <<'EOF' >/etc/apache2/conf-enabled/00-global-noslash.conf DirectorySlash Off EOF # --- Inject canonical rewrite directly into vhost for /wp-admin --- VHOST_CONF="/etc/apache2/sites-available/000-default-${PORT}.conf" if ! grep -q "RewriteCond %{REQUEST_URI} ^/wp-admin$" "$VHOST_CONF"; then log "Patching default vhost with wp-admin rewrite rule" sed -i '/<\/VirtualHost>/i \ \n\ RewriteEngine On\n\ RewriteCond %{REQUEST_URI} ^/wp-admin$\n\ RewriteRule ^/wp-admin$ /wp-admin/ [R=301,L]\n\ \n' "$VHOST_CONF" fi # --- Enforce canonical HTTPS and hide internal port --- # cat </etc/apache2/conf-enabled/force-https-proxy.conf # # RewriteEngine On # # Redirect plain HTTP requests to HTTPS # RewriteCond %{HTTPS} !=on # RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # # # Treat the canonical port as 443 even if Apache listens on ${PORT} # UseCanonicalName Off # UseCanonicalPhysicalPort Off # # Force Apache to always assume HTTPS and canonical host # ServerName ${HTTP_HOST} # RequestHeader set X-Forwarded-Proto "https" # RequestHeader set X-Forwarded-Port "443" # EOF echo "UseCanonicalName Off" >> /etc/apache2/apache2.conf #echo "ServerName localhost" >> /etc/apache2/apache2.conf echo "ServerName ${HTTP_HOST:-localhost}" >> /etc/apache2/apache2.conf # cat <<'EOF' >/etc/apache2/conf-enabled/override-canonical-port.conf # # DirectorySlash On # # UseCanonicalPhysicalPort Off # EOF # Disable DirectorySlash for wp-admin and rewrite cleanly to /wp-admin/ # cat <<'EOF' >/etc/apache2/conf-enabled/no-dirslash.conf # # DirectorySlash Off # Options -Indexes # AllowOverride All # # # Force /wp-admin to redirect with HTTPS and trailing slash # # RewriteEngine On # RewriteCond %{REQUEST_URI} ^/wp-admin$ # RewriteRule ^/wp-admin$ https://%{HTTP_HOST}/wp-admin/ [R=301,L] # # EOF # --- Fix /wp-admin directory handling (index + trailing slash) --- cat <<'EOF' >/etc/apache2/conf-enabled/wp-admin-fix.conf # Ensure WordPress admin directory resolves correctly DirectoryIndex index.php Options -Indexes AllowOverride All # Re-enable DirectorySlash *only* here DirectorySlash On # Explicit rewrite to /wp-admin/ if missing slash (final fallback) RewriteEngine On RewriteCond %{REQUEST_URI} ^/wp-admin$ RewriteRule ^/wp-admin$ /wp-admin/ [R=301,L] EOF # --- Ensure Apache knows the index for wp-admin to avoid autoindex 403 --- # cat <<'EOF' >/etc/apache2/conf-enabled/wp-admin-dirindex.conf # # DirectoryIndex index.php # Options -Indexes # AllowOverride All # # EOF # export HTTPS=${HTTPS:-on} # export SERVER_PORT=${SERVER_PORT:-443} export HTTPS=$HTTPS export SERVER_PORT=$SERVER_PORT # add hf proxy conf that only sets env values (no syntax issues) if [[ "$SITE_URL" != "http://127.0.0.1" && "$HTTP_HOST" != "127.0.0.1" ]]; then cat <<'EOF' > /etc/apache2/conf-enabled/hf-proxy.conf # Proxy environment (trusted front proxy will serve TLS) SetEnvIf X-Forwarded-Proto https HTTPS=on SetEnvIf X-Forwarded-Proto https SERVER_PORT=443 PassEnv HTTPS PassEnv SERVER_PORT EOF else log "Skipping hf-proxy.conf (local HTTP mode)" fi # === 2) Prepare WordPress paths === mkdir -p "$DB_DIR" "$UPLOADS_DIR" chown -R www-data:www-data "$WP_PATH/wp-content" || true chmod -R 775 "$WP_PATH/wp-content" || true # === 3) export SQLITE_ENC_PASSWORD=${SQLITE_ENC_PASSWORD:-"pzTDUd7iBJygH8zldBDw3ZzkNpe8kQ/+epSNFoaFck0l6aUjNUO5zgzi+O5EiKdq9eVjUBxhHayQ8pvd9xXd51JGK8X4LbP5zfxSIfvW3I5MazPYVwTHySV1scXcvcii"} #SQLITE_ZIP_PASSWORD=iPgXNCzSxoSrFG41IAoNRY5/4znAJp5DUeHCV77qolyAh8EhiGsHoq/stq19R4kX restore_sqlite_backup() { log "Checking for existing SQLite backup on Archive.org..." if ia metadata "${ARCHIVE_ITEM_ID}" >/dev/null 2>&1; then log "Backup found — downloading .ht.sqlite..." mkdir -p "$(dirname "$DB_FILE")" ia download "${ARCHIVE_ITEM_ID}" --destdir "$(dirname "$DB_FILE")" --glob "*.zip" --no-directories || { log "Download failed, skipping restore." #return exit 1 } if [[ -f "$(dirname "$DB_FILE")/sqlite_backup.zip" ]]; then log "Extracting SQLite backup..." unzip -j -qo "$(dirname "$DB_FILE")/sqlite_backup.zip" -d "/tmp" log "Decrypting SQLite Content..." openssl enc -d -aes-256-cbc -pbkdf2 \ -in /tmp/.ht.sqlite.enc \ -out "$DB_FILE" \ -pass pass:"$SQLITE_ENC_PASSWORD" chown www-data:www-data "$DB_FILE" || true chmod 660 "$DB_FILE" || true log "SQLite DB restored successfully ✅" else log "No valid sqlite_backup.zip found, skipping restore." fi else log "No previous backup found — fresh install will proceed." fi } # === 4) First-boot WP setup + SQLite plugin === setup_wp_sqlite() { ( cd "$WP_PATH" || exit # SITE_URL may be provided by HF Space secret (https://-.hf.space) export SITE_URL="${SITE_URL:-}" # If SITE_URL provided use it; otherwise default to http://127.0.0.1 if [[ -n "$SITE_URL" ]]; then INSTALL_URL="$SITE_URL" else INSTALL_URL="http://127.0.0.1" fi # Ensure WordPress core is present if [[ ! -f "$WP_PATH/wp-settings.php" ]]; then if [[ -d /usr/src/wordpress && -f /usr/src/wordpress/wp-settings.php ]]; then log "Populating WordPress core from /usr/src/wordpress" cp -a /usr/src/wordpress/. "$WP_PATH"/ chown -R www-data:www-data "$WP_PATH" else log "WARNING: /usr/src/wordpress not found — falling back to wp core download" export WP_CLI_PHP_ARGS="-d memory_limit=256M" wp core download --allow-root --path="$WP_PATH" fi fi log "WordPress core present ✅" # Create wp-config.php if it does not exist if [[ ! -f "$WP_PATH/wp-config.php" ]]; then log "Generating wp-config.php" wp config create \ --dbname="sqlite" \ --dbuser="dummy" \ --dbpass="dummy" \ --dbhost="localhost" \ --dbprefix="wp_" \ --skip-check \ --allow-root fi # Apply persistent SQLite wp-config patch if present if [[ -x /usr/local/bin/wp-config-patch.sh ]]; then log "Applying SQLite wp-config patch..." /usr/local/bin/wp-config-patch.sh || log "Warning: wp-config patch failed (continuing)..." fi # Patch wp-config.php once only (legacy helper file) # if ! grep -q "AUTOMATIC_UPDATER_DISABLED" "$WP_PATH/wp-config.php"; then # log "Appending hardening defaults to wp-config.php" # cat /tmp/wp-config-patches.php >> "$WP_PATH/wp-config.php" || true # fi # Download plugin zip directly (we need files to copy db.php drop-in) log "Downloading SQLite plugin package" curl -sSL https://downloads.wordpress.org/plugin/sqlite-database-integration.latest-stable.zip -o /tmp/sqlite.zip unzip -qo /tmp/sqlite.zip -d /tmp/ rm -f /tmp/sqlite.zip # Ensure DB exists early if [[ ! -f "$DB_FILE" ]]; then log "Creating SQLite DB file" mkdir -p "$DB_DIR" touch "$DB_FILE" chown -R www-data:www-data "$DB_DIR" fi # Copy REAL db.php drop-in + helper files DBPLUGINSRC="/tmp/sqlite-database-integration/wp-includes/sqlite" DBPLUGINDEST="$WP_PATH/wp-content" if [[ -f "$DBPLUGINSRC/db.php" ]]; then log "Installing REAL SQLite drop-in and dependencies" cp "$DBPLUGINSRC"/*.php "$DBPLUGINDEST"/ cp "$DBPLUGINSRC/db.php" "$DBPLUGINDEST/db.php" # patch absolute path quirks (safe) sed -i \ -e "s|dirname( __DIR__, 2 ) . '/version.php'|'/var/www/html/wp-includes/version.php'|" \ -e "s|dirname( __DIR__, 2 ) . '/constants.php'|'/tmp/sqlite-database-integration/constants.php'|" \ -e "s|require_once dirname( __DIR__, 2 ) . '/integrations/query-monitor/boot.php';|// require_once '/tmp/sqlite-database-integration/integrations/query-monitor/boot.php';|" \ "$DBPLUGINDEST/db.php" chown -R www-data:www-data "$DBPLUGINDEST" else log "ERROR: db.php drop-in missing inside plugin" fi # Install/activate plugin via WP-CLI (ok if already active) log "Installing SQLite Database Integration plugin" wp plugin install sqlite-database-integration --activate --allow-root || true log "SQLite plugin installed ✅" # Final step: install WordPress if not already installed if ! wp core is-installed --allow-root; then log "👉 Performing first WordPress install (SQLite) with URL: $INSTALL_URL" wp core install \ --url="$INSTALL_URL" \ --title="$SITE_TITLE" \ --admin_user="$ADMIN_USER" \ --admin_password="$ADMIN_PASS" \ --admin_email="$ADMIN_EMAIL" \ --skip-email \ --allow-root else log "WordPress already installed, skipping core install" fi # === activate essential plugin log "Activating HF Sync plugin" wp plugin activate wp-hf-sync --allow-root || true # ===== SANITIZE siteurl/home to remove container port and ensure SITE_URL if provided ===== if [[ -n "$SITE_URL" ]]; then CLEAN_SITE="$(echo "$SITE_URL" | sed 's:/*$::')" log "Setting DB siteurl/home -> $CLEAN_SITE" wp option update siteurl "$CLEAN_SITE" --allow-root || true wp option update home "$CLEAN_SITE" --allow-root || true else # If siteurl ends with :7860, strip it (common in container installs) CUR_SITE="$(wp option get siteurl --allow-root 2>/dev/null || true)" if [[ "$CUR_SITE" =~ :7860$ ]]; then NEW_SITE="$(echo "$CUR_SITE" | sed 's/:7860$//')" log "Stripping :7860 from DB siteurl/home -> $NEW_SITE" wp option update siteurl "$NEW_SITE" --allow-root || true wp option update home "$NEW_SITE" --allow-root || true fi fi ) # --- Fix ownership and permissions for wp-content after WP-CLI actions --- log "Fixing ownership and permissions for wp-content..." chown -R www-data:www-data "$WP_PATH/wp-content" || true chmod -R 775 "$WP_PATH/wp-content" || true log "SQLite setup completed ✅" } # === 4) First-boot WP setup + Remote MySQL/MariaDB === setup_wp_mysql() { ( cd "$WP_PATH" || exit # Remote DB credentials (expect provided via environment variables) DB_NAME="${DB_NAME:-wordpress}" DB_USER="${DB_USER:-avnadmin}" DB_PASS="${DB_PASS:-YOUR_PASSWORD}" DB_HOST="${DB_HOST:-DB_IP_OR_DOMAIN}" DB_PORT="${DB_PORT:-3306}" export SITE_URL="${SITE_URL:-http://127.0.0.1}" log "Using remote DB: ${DB_USER}@${DB_HOST}:${DB_PORT}/${DB_NAME}" # Ensure WordPress core is present if [[ ! -f "$WP_PATH/wp-settings.php" ]]; then if [[ -d /usr/src/wordpress && -f /usr/src/wordpress/wp-settings.php ]]; then log "Populating WordPress core from /usr/src/wordpress" cp -a /usr/src/wordpress/. "$WP_PATH"/ chown -R www-data:www-data "$WP_PATH" else log "Downloading WordPress core (fallback)" wp core download --allow-root --path="$WP_PATH" fi fi # Generate wp-config.php (for MySQL) if [[ ! -f "$WP_PATH/wp-config.php" ]]; then log "Generating wp-config.php for MySQL" wp config create \ --dbname="$DB_NAME" \ --dbuser="$DB_USER" \ --dbpass="$DB_PASS" \ --dbhost="$DB_HOST:$DB_PORT" \ --dbprefix="wp_" \ --allow-root fi # Optional: add SSL enforcement for Aiven if ! grep -q "MYSQL_CLIENT_FLAGS" "$WP_PATH/wp-config.php"; then log "Adding SSL enforcement for Aiven MySQL" cat <<'EOC' >> "$WP_PATH/wp-config.php" # Enforce SSL for Aiven MySQL define('MYSQL_CLIENT_FLAGS', MYSQLI_CLIENT_SSL); EOC fi # Run installation if not already installed if ! wp core is-installed --allow-root; then log "Installing WordPress (remote MySQL)" wp core install \ --url="$SITE_URL" \ --title="$SITE_TITLE" \ --admin_user="$ADMIN_USER" \ --admin_password="$ADMIN_PASS" \ --admin_email="$ADMIN_EMAIL" \ --skip-email \ --allow-root else log "WordPress already installed, skipping core install" fi # Fix site URLs log "Setting DB siteurl/home -> $SITE_URL" wp option update siteurl "$SITE_URL" --allow-root || true wp option update home "$SITE_URL" --allow-root || true # Fix ownership and permissions chown -R www-data:www-data "$WP_PATH/wp-content" || true chmod -R 775 "$WP_PATH/wp-content" || true log "Remote MySQL setup completed ✅" ) } backup_sqlite_to_archive() { lognew "[sqlite-backup]" "ARCHIVE_ITEM_ID: $ARCHIVE_ITEM_ID" lognew "[sqlite-backup]" "Encrypting Sqlite Content..." openssl enc -aes-256-cbc -salt -pbkdf2 \ -in "$DB_FILE" \ -out /tmp/.ht.sqlite.enc \ -pass pass:"$SQLITE_ENC_PASSWORD" lognew "[sqlite-backup]" "Creating compressed SQLite backup..." mkdir -p /tmp/sqlite-backups ZIP_PATH="/tmp/sqlite-backups/sqlite_backup.zip" zip -j -q "$ZIP_PATH" "/tmp/.ht.sqlite.enc" lognew "[sqlite-backup]" "Uploading backup to Archive.org..." ia upload "${ARCHIVE_ITEM_ID}" "$ZIP_PATH" \ --metadata="collection:opensource_media" \ --metadata="mediatype:data" \ --metadata="title:WordPress SQLite ENC Backup" \ --metadata="creator:Automated HF Space" \ --retries=3 --delete --no-backup --sleep 30 lognew "[sqlite-backup]" "SQLite DB backup uploaded successfully ✅" } export -f backup_sqlite_to_archive #--- Backup trggered by hook backup_themes_and_plugins_to_hf() { # --- Initial backup (Note: .empty will only exist for 1st time and will be removed during rsync operation) if [[ -f /var/www/html/wp-content/uploads/hf_sync_needed ]]; then backup_sqlite_to_archive lognew "[wp-sync]" "Detected change — syncing to HF..." cd /tmp/wp-store git pull --rebase # Sync updated wp-content back to store rsync -aq --delete /var/www/html/wp-content/themes/ wp-content/themes/ rsync -aq --delete /var/www/html/wp-content/plugins/ wp-content/plugins/ git add . git commit -m "Auto-sync: $(date)" git push origin main rm -f /var/www/html/wp-content/uploads/hf_sync_needed lognew "[wp-sync]" "Sync completed." cd - else lognew "[wp-sync]" "No Changes" fi } export -f backup_themes_and_plugins_to_hf mkdir -p "$WP_PATH/wp-content/plugins/wp-hf-sync/" log "Creating custom plugin: wp-hf-sync.php" cat /tmp/wp-hf-sync.php > "$WP_PATH/wp-content/plugins/wp-hf-sync/wp-hf-sync.php" || true # Run setup if [[ -n "$IA" ]]; then restore_sqlite_backup fi setup_wp_sqlite #setup_wp_mysql # Exec Apache in foreground (base image behaviour) log "Launching Apache on port ${PORT}" # --- Ensure WordPress and Apache both believe they are on HTTPS 443 --- # export HTTPS=on # export SERVER_PORT=443 # Start sync loop AFTER Apache is launched { sleep 5 /usr/local/bin/hf-sync-loop & /usr/local/bin/backup-loop & } & exec "$@"