Docker-based self-hosted WordPress deployment system with: - Four-container stack (nginx, wordpress/php-fpm, mariadb, certbot) - Automatic SSL via Let's Encrypt with self-signed fallback - First-boot WordPress setup via WP-CLI (GeneratePress + child theme, plugins) - Interactive setup wizard and one-line install script - Backup, update, healthcheck, and SSL renewal scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
96 lines
3.3 KiB
Bash
Executable File
96 lines
3.3 KiB
Bash
Executable File
#!/bin/bash
|
|
set -eo pipefail
|
|
|
|
DOMAIN="${DOMAIN:-localhost}"
|
|
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@example.com}"
|
|
CERT_DIR="/etc/letsencrypt/live/${DOMAIN}"
|
|
SIGNAL_DIR="/var/run/certbot-signal"
|
|
|
|
# Create setup-pending placeholder page
|
|
cat > /usr/share/nginx/html/setup-pending.html <<'HTMLEOF'
|
|
<!DOCTYPE html>
|
|
<html>
|
|
<head><title>WebsiteBox - Setting Up</title>
|
|
<style>body{font-family:sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;margin:0;background:#f5f5f5}
|
|
.box{text-align:center;padding:2em;background:white;border-radius:8px;box-shadow:0 2px 10px rgba(0,0,0,0.1);max-width:500px}
|
|
h1{color:#333}p{color:#666;line-height:1.6}</style></head>
|
|
<body><div class="box">
|
|
<h1>Setting up SSL...</h1>
|
|
<p>Your WebsiteBox site is starting up and acquiring an SSL certificate.</p>
|
|
<p>If this page persists, your DNS may not be pointing to this server yet.
|
|
Once DNS is configured, restart nginx:</p>
|
|
<pre>docker compose restart nginx</pre>
|
|
</div></body></html>
|
|
HTMLEOF
|
|
|
|
echo "WebsiteBox nginx: checking SSL certificates for ${DOMAIN}..."
|
|
|
|
if [ -f "${CERT_DIR}/fullchain.pem" ] && [ -f "${CERT_DIR}/privkey.pem" ]; then
|
|
echo "SSL certificates found. Starting with SSL."
|
|
|
|
# Activate SSL config
|
|
sed "s/DOMAIN_PLACEHOLDER/${DOMAIN}/g" /etc/nginx/conf.d/wordpress-ssl.conf.disabled > /etc/nginx/conf.d/wordpress-ssl.conf
|
|
# Replace HTTP-only default with redirect
|
|
rm -f /etc/nginx/conf.d/default.conf
|
|
else
|
|
echo "No SSL certificates found. Starting HTTP-only for ACME challenge..."
|
|
|
|
# Generate temporary self-signed cert so nginx can start if needed
|
|
mkdir -p "${CERT_DIR}"
|
|
openssl req -x509 -nodes -days 1 -newkey rsa:2048 \
|
|
-keyout "${CERT_DIR}/privkey.pem" \
|
|
-out "${CERT_DIR}/fullchain.pem" \
|
|
-subj "/CN=${DOMAIN}" 2>/dev/null
|
|
|
|
# Start nginx in background with HTTP-only config
|
|
nginx -g "daemon on;"
|
|
|
|
echo "Requesting Let's Encrypt certificate for ${DOMAIN}..."
|
|
|
|
# Attempt certificate acquisition
|
|
if certbot certonly --webroot \
|
|
-w /var/www/certbot \
|
|
-d "${DOMAIN}" \
|
|
--agree-tos \
|
|
--email "${ADMIN_EMAIL}" \
|
|
--non-interactive \
|
|
--no-eff-email; then
|
|
|
|
echo "SSL certificate acquired successfully!"
|
|
|
|
# Activate SSL config
|
|
sed "s/DOMAIN_PLACEHOLDER/${DOMAIN}/g" /etc/nginx/conf.d/wordpress-ssl.conf.disabled > /etc/nginx/conf.d/wordpress-ssl.conf
|
|
rm -f /etc/nginx/conf.d/default.conf
|
|
|
|
# Stop background nginx — will be restarted by CMD
|
|
nginx -s stop
|
|
sleep 1
|
|
else
|
|
echo "WARNING: SSL certificate acquisition failed."
|
|
echo "This usually means DNS is not pointing to this server yet."
|
|
echo "Once DNS is configured, run: docker compose restart nginx"
|
|
|
|
# Stop background nginx — will be restarted by CMD with HTTP-only
|
|
nginx -s stop
|
|
sleep 1
|
|
|
|
# Remove the self-signed certs so we retry on next start
|
|
rm -rf "${CERT_DIR}"
|
|
fi
|
|
fi
|
|
|
|
# Start background loop to watch for certbot renewal signal
|
|
(
|
|
while true; do
|
|
if [ -f "${SIGNAL_DIR}/reload" ]; then
|
|
echo "Certbot renewal detected. Reloading nginx..."
|
|
rm -f "${SIGNAL_DIR}/reload"
|
|
nginx -s reload 2>/dev/null || true
|
|
fi
|
|
sleep 60
|
|
done
|
|
) &
|
|
|
|
# Execute the CMD (nginx -g daemon off)
|
|
exec "$@"
|