Skip to content

Commit f648fa0

Browse files
committed
Updates to nginx proxy
1 parent 06c0a5f commit f648fa0

File tree

4 files changed

+150
-12
lines changed

4 files changed

+150
-12
lines changed

CLAUDE.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,21 +140,28 @@ The `ddev db-refresh` command includes intelligent backup management:
140140

141141
## Asset Proxy System
142142

143-
The add-on includes an intelligent asset proxy system that automatically serves missing uploads and files from your hosting provider:
143+
The add-on includes an intelligent nginx-based asset proxy system that automatically serves missing uploads and files from your hosting provider:
144144

145145
### How It Works:
146146
- **Local First**: Always tries to serve files locally from `wp-content/uploads/`
147-
- **Automatic Fallback**: If file doesn't exist locally, proxies from remote hosting provider
147+
- **Nginx Proxy**: If file doesn't exist locally, nginx directly proxies from remote hosting provider using `proxy_pass`
148148
- **Provider Support**: Works with Pantheon, WPEngine, and Kinsta
149149
- **Transparent**: No configuration needed - works automatically after setup
150150

151+
### Technical Implementation:
152+
- **Complete nginx Configuration**: Uses `nginx-site-main.conf` template to override DDEV's default WordPress configuration
153+
- **Template-Based**: `PROXY_URL_PLACEHOLDER` and `HOST_PLACEHOLDER` are replaced during `ddev project-configure`
154+
- **Native nginx Performance**: Uses nginx's built-in `proxy_pass` directive for optimal performance
155+
- **Configuration Location**: Creates `.ddev/nginx_full/nginx-site.conf` to take full control of nginx configuration
156+
151157
### Configuration:
152158
- **Automatic**: `PROXY_URL` is automatically configured based on your hosting provider during `ddev project-configure`
153159
- **Pantheon**: `https://dev-sitename.pantheonsite.io` (uses configured environment)
154160
- **WPEngine**: `https://sitename.wpengine.com` (uses install name)
155161
- **Kinsta**: `https://env-username-environment.kinsta.cloud` (e.g., `https://env-outandequalorg-build.kinsta.cloud`)
156162

157163
### Benefits:
164+
-**Native nginx Performance**: Direct proxy without PHP processing overhead
158165
-**Faster Development**: No need to download all uploads from production
159166
-**Automatic Updates**: New uploads appear automatically without syncing
160167
-**Bandwidth Efficient**: Only downloads files when actually needed
@@ -314,7 +321,10 @@ While maintaining consistency, respect platform differences:
314321
## Testing Notes
315322
- Always test changes to install.yaml thoroughly across all providers
316323
- Test multi-provider scenarios to ensure compatibility
317-
- Validate nginx proxy configuration for each hosting platform
324+
- Validate nginx proxy configuration for each hosting platform:
325+
- Test that `nginx-site-main.conf` template properly replaces placeholders
326+
- Verify proxy functionality with missing uploads from each provider
327+
- Confirm that complete nginx configuration overrides DDEV's default
318328
- Run integration tests before major releases
319329
- Tests pre-configure environment variables to avoid interactive prompts
320330
- Test changes in both add-ons when making cross-repository updates

commands/host/project-configure

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -399,22 +399,35 @@ if [ -n "$PROXY_URL" ]; then
399399
mkdir -p .ddev/nginx
400400

401401
# Extract hostname from PROXY_URL for Host header
402-
PROXY_HOST=$(echo "$PROXY_URL" | sed 's|https\?://||' | sed 's|/.*||')
402+
PROXY_HOST=$(echo "$PROXY_URL" | sed 's|https\://||' | sed 's|http://||' | sed 's|/.*||')
403403

404404
# Process nginx configuration template - use the current add-on source if available
405-
NGINX_TEMPLATE=""
405+
NGINX_MAIN_TEMPLATE=""
406+
NGINX_SNIPPET_TEMPLATE=""
407+
408+
# Try to find the templates in various locations
409+
if [ -f ".ddev/addon-metadata/ddev-kanopi-wp/config/nginx/nginx-site-main.conf" ]; then
410+
NGINX_MAIN_TEMPLATE=".ddev/addon-metadata/ddev-kanopi-wp/config/nginx/nginx-site-main.conf"
411+
elif [ -f "/Users/thejimbirch/Projects/ddev-kanopi-wp/config/nginx/nginx-site-main.conf" ]; then
412+
NGINX_MAIN_TEMPLATE="/Users/thejimbirch/Projects/ddev-kanopi-wp/config/nginx/nginx-site-main.conf"
413+
fi
406414

407-
# Try to find the template in various locations
408415
if [ -f ".ddev/addon-metadata/ddev-kanopi-wp/config/nginx/nginx-site.conf" ]; then
409-
NGINX_TEMPLATE=".ddev/addon-metadata/ddev-kanopi-wp/config/nginx/nginx-site.conf"
416+
NGINX_SNIPPET_TEMPLATE=".ddev/addon-metadata/ddev-kanopi-wp/config/nginx/nginx-site.conf"
410417
elif [ -f "/Users/thejimbirch/Projects/ddev-kanopi-wp/config/nginx/nginx-site.conf" ]; then
411-
NGINX_TEMPLATE="/Users/thejimbirch/Projects/ddev-kanopi-wp/config/nginx/nginx-site.conf"
418+
NGINX_SNIPPET_TEMPLATE="/Users/thejimbirch/Projects/ddev-kanopi-wp/config/nginx/nginx-site.conf"
412419
fi
413420

414-
if [ -n "$NGINX_TEMPLATE" ]; then
421+
if [ -n "$NGINX_MAIN_TEMPLATE" ]; then
422+
# Create complete nginx configuration to override DDEV's default
423+
sed "s|PROXY_URL_PLACEHOLDER|$PROXY_URL|g; s|HOST_PLACEHOLDER|$PROXY_HOST|g" \
424+
"$NGINX_MAIN_TEMPLATE" > ".ddev/nginx_full/nginx-site.conf"
425+
echo " ✅ Complete nginx proxy configuration created"
426+
elif [ -n "$NGINX_SNIPPET_TEMPLATE" ]; then
427+
# Fallback to snippet approach
415428
sed "s|PROXY_URL_PLACEHOLDER|$PROXY_URL|g; s|HOST_PLACEHOLDER|$PROXY_HOST|g" \
416-
"$NGINX_TEMPLATE" > ".ddev/nginx/nginx-site.conf"
417-
echo " ✅ Nginx proxy configuration created"
429+
"$NGINX_SNIPPET_TEMPLATE" > ".ddev/nginx/nginx-site.conf"
430+
echo " ✅ Nginx proxy snippet created"
418431
else
419432
echo " ⚠️ Nginx template not found - proxy configuration not updated"
420433
fi

config/nginx/nginx-site-main.conf

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#ddev-generated
2+
# ddev wordpress config with Kanopi proxy support
3+
# https://developer.wordpress.org/advanced-administration/server/web-server/nginx/
4+
5+
# Much of this config is adapted from
6+
# https://codex.wordpress.org/Nginx
7+
8+
server {
9+
listen 80 default_server;
10+
listen 443 ssl default_server;
11+
12+
root /var/www/html/public;
13+
14+
ssl_certificate /etc/ssl/certs/master.crt;
15+
ssl_certificate_key /etc/ssl/certs/master.key;
16+
17+
include /etc/nginx/monitoring.conf;
18+
19+
index index.php index.htm index.html;
20+
21+
# Disable sendfile as per https://docs.vagrantup.com/v2/synced-folders/virtualbox.html
22+
sendfile off;
23+
error_log /dev/stdout info;
24+
access_log /var/log/nginx/access.log;
25+
26+
# From wordpress demo global_restrictions.conf
27+
# Global restrictions configuration file.
28+
# Designed to be included in any server {} block.
29+
location = /favicon.ico {
30+
log_not_found off;
31+
access_log off;
32+
}
33+
34+
location = /robots.txt {
35+
allow all;
36+
log_not_found off;
37+
access_log off;
38+
}
39+
40+
# Deny all attempts to access hidden files such as .htaccess, .htpasswd, .DS_Store (Mac).
41+
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
42+
location ~ /\. {
43+
deny all;
44+
}
45+
46+
# Deny access to any files with a .php extension in the uploads directory
47+
# Works in sub-directory installs and also in multisite network
48+
# Keep logging the requests to parse later (or to pass to firewall utilities such as fail2ban)
49+
location ~* /(?:uploads|files)/.*\.php$ {
50+
deny all;
51+
}
52+
53+
# Image proxy configuration for wp-content/uploads
54+
location ~ ^/wp-content/uploads/.* {
55+
try_files $uri @proxy;
56+
}
57+
58+
location @proxy {
59+
# Proxy missing uploads to hosting provider environment
60+
resolver 8.8.8.8;
61+
proxy_pass PROXY_URL_PLACEHOLDER$request_uri;
62+
proxy_set_header Host HOST_PLACEHOLDER;
63+
proxy_set_header X-Real-IP $remote_addr;
64+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
65+
proxy_set_header X-Forwarded-Proto $scheme;
66+
proxy_ssl_verify off;
67+
proxy_intercept_errors on;
68+
}
69+
70+
location / {
71+
absolute_redirect off;
72+
# This is cool because no php is touched for static content.
73+
# include the "?$args" part so non-default permalinks doesn't break when using query string
74+
try_files $uri $uri/ /index.php?$args;
75+
}
76+
77+
# pass the PHP scripts to FastCGI server listening on socket
78+
location ~ \.php$ {
79+
try_files $uri =404;
80+
fastcgi_split_path_info ^(.+\.php)(/.+)$;
81+
fastcgi_pass unix:/run/php-fpm.sock;
82+
fastcgi_buffers 16 16k;
83+
fastcgi_buffer_size 32k;
84+
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
85+
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
86+
fastcgi_index index.php;
87+
include fastcgi_params;
88+
fastcgi_intercept_errors off;
89+
# fastcgi_read_timeout should match max_execution_time in php.ini
90+
fastcgi_read_timeout 10m;
91+
fastcgi_param SERVER_NAME $host;
92+
fastcgi_param HTTPS $fcgi_https;
93+
# Pass the X-Accel-* headers to facilitate testing.
94+
fastcgi_pass_header "X-Accel-Buffering";
95+
fastcgi_pass_header "X-Accel-Charset";
96+
fastcgi_pass_header "X-Accel-Expires";
97+
fastcgi_pass_header "X-Accel-Limit-Rate";
98+
fastcgi_pass_header "X-Accel-Redirect";
99+
}
100+
101+
# Expire rules for static content
102+
103+
# Media: images, icons, video, audio, HTC (exclude wp-content/uploads which has proxy)
104+
location ~* ^(?!/wp-content/uploads).*\.(jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|webp|htc)$ {
105+
expires max;
106+
log_not_found off;
107+
try_files $uri /index.php$is_args$args;
108+
}
109+
location ~* \.(js|css)$ {
110+
expires -1;
111+
log_not_found off;
112+
}
113+
include /etc/nginx/common.d/*.conf;
114+
include /mnt/ddev_config/nginx/*.conf;
115+
}

install.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,8 @@ removal_actions:
232232
233233
# Remove specific config files
234234
echo "🔧 Removing config files..."
235-
rm -f config/nginx/nginx-common.conf 2>/dev/null || true
236235
rm -f config/nginx/nginx-site.conf 2>/dev/null || true
236+
rm -f config/nginx/nginx-site-main.conf 2>/dev/null || true
237237
rm -f config/wp/block-template/block.json 2>/dev/null || true
238238
239239
# Remove specific script files

0 commit comments

Comments
 (0)