New WP_ADMIN_ALLOWED_IPS env var (space-separated CIDR ranges, matching Caddy's remote_ip syntax directly). Defaults to 0.0.0.0/0 ::/0 (today's open behavior) when unset, resolved at the Compose level rather than in the Caddyfile so an unset var can never leave `remote_ip` with zero arguments and fail Caddy's startup. admin-ajax.php stays exempt since WooCommerce routes logged-out storefront AJAX through it. Production only — staging is already LAN-only. Verified live: a scratch Caddy instance on a Docker network, with a sibling container's actual observed source IP used to prove both the blocked (403 on wp-admin/wp-login, everything else unaffected) and allowed (matching CIDR lets it through) cases, plus `docker compose config` to confirm the unset-var default resolves correctly. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MqhgnCRjjVLFnZ3Jpn93Vg
44 lines
1.5 KiB
Caddyfile
44 lines
1.5 KiB
Caddyfile
{$SITE_DOMAIN} {
|
|
encode gzip
|
|
|
|
root * /var/www/html
|
|
|
|
@no_cache path /cart* /checkout* /my-account* /wp-admin* /wp-login.php
|
|
header @no_cache Cache-Control "no-store, no-cache, must-revalidate"
|
|
|
|
request_body {
|
|
max_size 32MB
|
|
}
|
|
|
|
# bookstore-core's tests/, vendor/, composer.json/.lock, and
|
|
# phpunit.xml.dist ship in the repo (and are bind-mounted straight into
|
|
# this container — see docker-compose.*.yml) so they exist under the
|
|
# webroot, but nothing about a git-checkout deploy strips them before
|
|
# they land here. 404 instead of 403 so their existence isn't confirmed.
|
|
@dev_only path /wp-content/plugins/bookstore-core/tests/* /wp-content/plugins/bookstore-core/vendor/* /wp-content/plugins/bookstore-core/composer.json /wp-content/plugins/bookstore-core/composer.lock /wp-content/plugins/bookstore-core/phpunit.xml*
|
|
respond @dev_only 404
|
|
|
|
# WP_ADMIN_ALLOWED_IPS (.env.production) — defaults to 0.0.0.0/0 ::/0
|
|
# (unrestricted) in docker-compose.production.yml when unset. Excludes
|
|
# admin-ajax.php: WordPress/WooCommerce route logged-out-visitor AJAX
|
|
# (cart fragments, nonces, some add-to-cart flows) through that file
|
|
# even though it lives under /wp-admin/ — blocking it by IP would break
|
|
# the storefront for every visitor, not just admin access.
|
|
@blocked_admin {
|
|
path /wp-admin* /wp-login.php
|
|
not path /wp-admin/admin-ajax.php
|
|
not remote_ip {$WP_ADMIN_ALLOWED_IPS}
|
|
}
|
|
respond @blocked_admin 403
|
|
|
|
php_fastcgi wordpress:9000
|
|
file_server
|
|
|
|
log {
|
|
output file /data/access.log {
|
|
roll_size 50MiB
|
|
roll_keep 10
|
|
}
|
|
}
|
|
}
|