diff --git a/ummah-wordpress/deploy.sh b/ummah-wordpress/deploy.sh index 1ba117c..f3af685 100644 --- a/ummah-wordpress/deploy.sh +++ b/ummah-wordpress/deploy.sh @@ -1,117 +1,114 @@ #!/usr/bin/env bash -# deploy.sh — spin up ummah2.falahos.my WordPress on Contabo -# Run on Contabo: bash deploy.sh +# deploy.sh — spin up ummah2.falahos.my on Contabo via Traefik set -euo pipefail DEPLOY_DIR="/opt/ummah-wordpress" SITE_URL="https://ummah2.falahos.my" -WP_PLUGINS_DIR="$DEPLOY_DIR/wp-data/wp-content/plugins" +REPO="https://github.com/maifors/falah-os.git" +BRANCH="community-edition" -echo "▶ Deploying ummah2.falahos.my WordPress on Contabo" +echo "▶ Deploying ummah2.falahos.my" -# ── Prerequisites ──────────────────────────────────────────────────────────── -command -v docker >/dev/null || { echo "❌ docker not found"; exit 1; } -docker compose version >/dev/null 2>&1 || { echo "❌ docker compose plugin not found"; exit 1; } - -# ── Setup deploy dir ───────────────────────────────────────────────────────── -mkdir -p "$DEPLOY_DIR" -cd "$DEPLOY_DIR" +# ── Clone / update repo ─────────────────────────────────────────────────────── +if [ -d "$DEPLOY_DIR/.git" ]; then + git -C "$DEPLOY_DIR" fetch origin + git -C "$DEPLOY_DIR" reset --hard origin/$BRANCH +else + git clone --branch "$BRANCH" --depth 1 "$REPO" "$DEPLOY_DIR" +fi +cd "$DEPLOY_DIR/ummah-wordpress" +# ── .env setup ──────────────────────────────────────────────────────────────── if [ ! -f .env ]; then cp .env.example .env echo "" - echo "⚠️ Fill in .env before continuing:" - echo " DB_ROOT_PASSWORD, DB_PASSWORD, WP_ADMIN_PASSWORD" - echo " nano $DEPLOY_DIR/.env" + echo "⚠️ Fill .env before continuing:" + echo " nano $DEPLOY_DIR/ummah-wordpress/.env" + echo "" + echo " DB_ROOT_PASSWORD — strong random password" + echo " DB_PASSWORD — strong random password" + echo " WP_ADMIN_PASSWORD — strong password for /wp-admin" exit 0 fi source .env -# ── Start stack ─────────────────────────────────────────────────────────────── -echo "── Starting MariaDB + WordPress + Nginx ──" -docker compose up -d db -echo " Waiting for DB to be ready…" -sleep 10 -docker compose up -d +# ── Detect Traefik network name ─────────────────────────────────────────────── +TRAEFIK_NETWORK=$(docker network ls --format '{{.Name}}' | grep -iE "traefik|proxy|public" | head -1 || echo "traefik-public") +export TRAEFIK_NETWORK +echo " Using Traefik network: $TRAEFIK_NETWORK" -# ── Wait for WordPress to be ready ─────────────────────────────────────────── -echo "── Waiting for WordPress container ──" -for i in $(seq 1 30); do +# ── Check https-redirect middleware exists ──────────────────────────────────── +# If not, add it (some Traefik setups define it globally, some don't) +if ! docker inspect traefik 2>/dev/null | grep -q "https-redirect"; then + echo " Note: https-redirect middleware may need to be pre-defined in Traefik config" +fi + +# ── Start stack ─────────────────────────────────────────────────────────────── +echo "── Starting DB ──" +docker compose up -d db +echo " Waiting for MariaDB…" +until docker compose exec -T db mysqladmin ping -u root -p"$DB_ROOT_PASSWORD" --silent 2>/dev/null; do + sleep 2 +done +echo " DB ready ✅" + +echo "── Starting WordPress ──" +docker compose up -d wordpress + +echo " Waiting for WordPress files…" +for i in $(seq 1 40); do if docker compose exec -T wordpress test -f /var/www/html/wp-includes/version.php 2>/dev/null; then - echo " WordPress files ready." break fi sleep 3 done -# ── Install WordPress via WP-CLI ────────────────────────────────────────────── -echo "── Installing WordPress ──" +# ── WP-CLI install ──────────────────────────────────────────────────────────── +echo "── Running WP install via WP-CLI ──" docker compose run --rm wpcli core install \ --url="$SITE_URL" \ - --title="$WP_SITE_TITLE" \ - --admin_user="$WP_ADMIN_USER" \ + --title="${WP_SITE_TITLE:-Ummah FalahOS}" \ + --admin_user="${WP_ADMIN_USER:-admin}" \ --admin_password="$WP_ADMIN_PASSWORD" \ - --admin_email="$WP_ADMIN_EMAIL" \ - --skip-email 2>/dev/null || echo " (already installed)" + --admin_email="${WP_ADMIN_EMAIL:-wanjauhari@gmail.com}" \ + --skip-email 2>/dev/null || echo " Already installed." + +# ── Set permalink ───────────────────────────────────────────────────────────── +docker compose run --rm wpcli rewrite structure '/%postname%/' --hard 2>/dev/null # ── Install plugins ─────────────────────────────────────────────────────────── -echo "── Installing plugins ──" +echo "── Installing Falah plugins ──" -# Hermes AI Bridge (from Gitea raw) +# Falah Shortcodes from GitHub raw docker compose run --rm wpcli plugin install \ - "https://git.falahos.my/wmj/hermes-cpanel-agent/archive/main.zip" \ - --activate 2>/dev/null || echo " hermes-ai-bridge: manual install needed" + "https://github.com/maifors/falah-os/raw/community-edition/wordpress-plugins/falah-shortcodes.zip" \ + --activate --force 2>/dev/null && echo " falah-shortcodes ✅" || echo " falah-shortcodes: upload manually" -# Falah Shortcodes (from Gitea raw via falahos org) +# Hermes AI Bridge from GitHub raw docker compose run --rm wpcli plugin install \ - "https://git.falahos.my/falahos/falah-os-ce/raw/branch/community-edition/wordpress-plugins/falah-shortcodes.zip" \ - --activate 2>/dev/null || echo " falah-shortcodes: manual install needed" + "https://github.com/maifors/falah-os/raw/community-edition/wordpress-plugins/hermes-ai-bridge.zip" \ + --activate --force 2>/dev/null && echo " hermes-ai-bridge ✅" || echo " hermes-ai-bridge: upload manually" -# Essential plugins from WP.org -for plugin in astra-sites tutor learndash-gutenberg-blocks mailpoet woocommerce easy-digital-downloads redis-cache; do - docker compose run --rm wpcli plugin install "$plugin" --activate 2>/dev/null || true +# Essential WP.org plugins +echo "── Installing WP.org plugins ──" +for plugin in astra tutor-lms mailpoet woocommerce easy-digital-downloads litespeed-cache; do + docker compose run --rm wpcli plugin install "$plugin" --activate 2>/dev/null \ + && echo " $plugin ✅" || echo " $plugin ⚠️" done -# ── Set permalink structure ─────────────────────────────────────────────────── -docker compose run --rm wpcli rewrite structure '/%postname%/' --hard +# ── Astra theme ─────────────────────────────────────────────────────────────── +docker compose run --rm wpcli theme install astra --activate 2>/dev/null || true -# ── Configure Caddy ─────────────────────────────────────────────────────────── -echo "── Configuring Caddy reverse proxy ──" -CADDY_FILE="/etc/caddy/conf.d/ummah2.conf" -mkdir -p /etc/caddy/conf.d - -cat > "$CADDY_FILE" << 'CADDY' -ummah2.falahos.my { - reverse_proxy localhost:8888 - - encode gzip - - header { - Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" - X-Frame-Options SAMEORIGIN - X-Content-Type-Options nosniff - Referrer-Policy strict-origin-when-cross-origin - -Server - } -} -CADDY - -# Reload Caddy if running -if systemctl is-active --quiet caddy 2>/dev/null; then - systemctl reload caddy - echo " Caddy reloaded ✅" -elif docker ps --format '{{.Names}}' | grep -q caddy; then - docker kill --signal=USR1 "$(docker ps --format '{{.Names}}' | grep caddy)" - echo " Caddy (docker) reloaded ✅" -else - echo " ⚠️ Caddy not found — add ummah2.falahos.my block to your reverse proxy manually" - echo " Nginx port 8888 → ummah2.falahos.my" -fi +# ── WP performance settings ─────────────────────────────────────────────────── +docker compose run --rm wpcli option update blogdescription "Learn, Discuss, and Grow Together" 2>/dev/null || true +docker compose run --rm wpcli option update timezone_string "Asia/Kuala_Lumpur" 2>/dev/null || true +docker compose run --rm wpcli option update date_format "d F Y" 2>/dev/null || true echo "" -echo "✅ ummah2.falahos.my is up on port 8888" -echo " WP Admin: $SITE_URL/wp-admin (user: $WP_ADMIN_USER)" +echo "✅ ummah2.falahos.my is live!" +echo " WP Admin: $SITE_URL/wp-admin" +echo " User: ${WP_ADMIN_USER:-admin}" echo "" -echo "── Next: point DNS ──" -echo " ummah2.falahos.my A → 13.140.161.244" +echo "── DNS (add in Cloudflare) ──" +echo " ummah2.falahos.my A 13.140.161.244 (proxied)" diff --git a/ummah-wordpress/docker-compose.yml b/ummah-wordpress/docker-compose.yml index 530c85e..dbd7b12 100644 --- a/ummah-wordpress/docker-compose.yml +++ b/ummah-wordpress/docker-compose.yml @@ -1,19 +1,23 @@ version: "3.9" +# ummah2.falahos.my — WordPress on Contabo +# Reverse proxy: Traefik (already running) +# Run: docker compose up -d + services: db: image: mariadb:11 - container_name: ummah-db + container_name: ummah2-db restart: unless-stopped environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} - MYSQL_DATABASE: ummah_wp - MYSQL_USER: ummah_wp + MYSQL_DATABASE: ummah2_wp + MYSQL_USER: ummah2_wp MYSQL_PASSWORD: ${DB_PASSWORD} volumes: - - ummah-db-data:/var/lib/mysql + - ummah2-db-data:/var/lib/mysql networks: - - ummah-net + - ummah2-internal healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 10s @@ -21,66 +25,69 @@ services: retries: 5 wordpress: - image: wordpress:6.7-php8.3-fpm-alpine - container_name: ummah-wp + image: wordpress:6.7-php8.3-apache + container_name: ummah2-wp restart: unless-stopped depends_on: db: condition: service_healthy environment: WORDPRESS_DB_HOST: db:3306 - WORDPRESS_DB_NAME: ummah_wp - WORDPRESS_DB_USER: ummah_wp + WORDPRESS_DB_NAME: ummah2_wp + WORDPRESS_DB_USER: ummah2_wp WORDPRESS_DB_PASSWORD: ${DB_PASSWORD} WORDPRESS_TABLE_PREFIX: wp_ WORDPRESS_DEBUG: "false" - # Performance PHP_MEMORY_LIMIT: 256M - PHP_MAX_EXECUTION_TIME: 300 - PHP_UPLOAD_MAX_FILESIZE: 64M - PHP_POST_MAX_SIZE: 64M + WORDPRESS_CONFIG_EXTRA: | + define('WP_MEMORY_LIMIT', '256M'); + define('WP_HOME', 'https://ummah2.falahos.my'); + define('WP_SITEURL', 'https://ummah2.falahos.my'); + $_SERVER['HTTPS'] = 'on'; + define('FORCE_SSL_ADMIN', true); volumes: - - ummah-wp-data:/var/www/html - - ./wordpress-config/php.ini:/usr/local/etc/php/conf.d/ummah.ini:ro + - ummah2-wp-data:/var/www/html + - ./wordpress-config/php.ini:/usr/local/etc/php/conf.d/ummah2.ini:ro networks: - - ummah-net - - nginx: - image: nginx:alpine - container_name: ummah-nginx - restart: unless-stopped - depends_on: - - wordpress - ports: - - "8888:80" - volumes: - - ummah-wp-data:/var/www/html:ro - - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro - networks: - - ummah-net + - ummah2-internal + - traefik-public + labels: + - "traefik.enable=true" + - "traefik.http.routers.ummah2.rule=Host(`ummah2.falahos.my`)" + - "traefik.http.routers.ummah2.entrypoints=websecure" + - "traefik.http.routers.ummah2.tls.certresolver=letsencrypt" + - "traefik.http.services.ummah2.loadbalancer.server.port=80" + # Redirect http→https + - "traefik.http.routers.ummah2-http.rule=Host(`ummah2.falahos.my`)" + - "traefik.http.routers.ummah2-http.entrypoints=web" + - "traefik.http.routers.ummah2-http.middlewares=https-redirect" wpcli: image: wordpress:cli-2-php8.3 - container_name: ummah-wpcli + container_name: ummah2-wpcli depends_on: - wordpress - db + user: "33:33" environment: WORDPRESS_DB_HOST: db:3306 - WORDPRESS_DB_NAME: ummah_wp - WORDPRESS_DB_USER: ummah_wp + WORDPRESS_DB_NAME: ummah2_wp + WORDPRESS_DB_USER: ummah2_wp WORDPRESS_DB_PASSWORD: ${DB_PASSWORD} volumes: - - ummah-wp-data:/var/www/html + - ummah2-wp-data:/var/www/html networks: - - ummah-net + - ummah2-internal entrypoint: ["tail", "-f", "/dev/null"] profiles: ["tools"] networks: - ummah-net: + ummah2-internal: driver: bridge + traefik-public: + external: true + name: ${TRAEFIK_NETWORK:-traefik-public} volumes: - ummah-db-data: - ummah-wp-data: + ummah2-db-data: + ummah2-wp-data: