From af162505610181633a70c7f448cff6d3a7039dd8 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Tue, 14 Jul 2026 11:55:19 -0600 Subject: [PATCH] fix(wordpress): route loopback requests through Traefik to fix cURL error 28 WordPress resolves its own public domain to the server's public IP from inside the container, so REST API / WP-Cron / Site Health loopback requests depend on hairpin NAT, which times out (cURL error 28) on many hosts. Pin the site domain to the dokploy-traefik container IP in /etc/hosts at startup (with retries, since Traefik joins the compose network shortly after the container starts) so loopback traffic stays inside the Docker network for both HTTP and HTTPS. No-op fallback when dokploy-traefik is not resolvable. Co-Authored-By: Claude Fable 5 --- blueprints/wordpress/docker-compose.yml | 22 ++++++++++++++++++++++ blueprints/wordpress/template.toml | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/blueprints/wordpress/docker-compose.yml b/blueprints/wordpress/docker-compose.yml index 70b8aba3..75ab474a 100644 --- a/blueprints/wordpress/docker-compose.yml +++ b/blueprints/wordpress/docker-compose.yml @@ -1,6 +1,27 @@ services: wordpress: image: wordpress:latest + # Resolve the site's own domain to the Traefik container instead of the + # server's public IP. Loopback requests (REST API, WP-Cron, Site Health) + # otherwise depend on hairpin NAT, which times out on many hosts + # (cURL error 28). See https://github.com/Dokploy/templates/issues/128 + command: + - bash + - -c + - | + if [ -n "$$WP_DOMAIN" ]; then + ( + for i in $$(seq 1 60); do + TRAEFIK_IP="$$(getent hosts dokploy-traefik | awk '{print $$1; exit}')" + if [ -n "$$TRAEFIK_IP" ]; then + grep -q "[[:space:]]$$WP_DOMAIN\$$" /etc/hosts || echo "$$TRAEFIK_IP $$WP_DOMAIN" >> /etc/hosts + break + fi + sleep 2 + done + ) & + fi + exec docker-entrypoint.sh apache2-foreground volumes: - wp_app:/var/www/html - ../files/uploads.ini:/usr/local/etc/php/conf.d/uploads.ini @@ -10,6 +31,7 @@ services: WORDPRESS_DB_USER: root WORDPRESS_DB_PASSWORD: $DB_PASSWORD WORDPRESS_DEBUG: ${WORDPRESS_DEBUG:-0} + WP_DOMAIN: ${WP_DOMAIN} WORDPRESS_CONFIG_EXTRA: | define('WP_MEMORY_LIMIT', '256M'); define('DISALLOW_FILE_EDIT', true); diff --git a/blueprints/wordpress/template.toml b/blueprints/wordpress/template.toml index 91d95e9c..c11c63f2 100644 --- a/blueprints/wordpress/template.toml +++ b/blueprints/wordpress/template.toml @@ -9,7 +9,8 @@ env = [ "WORDPRESS_DEBUG=0", "DB_NAME=${db_name}", "DB_USER=${db_user}", - "DB_PASSWORD=${db_password}" + "DB_PASSWORD=${db_password}", + "WP_DOMAIN=${main_domain}" ] [[config.domains]]