Web Server Hardening for NZ Sites: Block Exposed .env, .git and Backup Files
How to block exposed files like .env, .git, backup.zip, phpinfo.php and server-status on nginx and Apache, with NZ examples and 404 verification.
Quick answer
Exposed backup files, environment files, and version-control directories are one of the most common ways New Zealand school and small-business websites get compromised. Files like .env, .git/, backup.zip, phpinfo.php, and server-status should all return a clean 404 Not Found to the outside world — never 403 Forbidden, never the file itself. Paste the nginx or Apache snippets in this article, reload the service, and verify each path returns 404 using curl -I or the Free Website Security Check.
If your site is on shared hosting (cPanel, Managed WordPress, N4L), you may not have direct access to nginx or Apache — in that case use the hosting control panel's "Block access to .env" or .htaccess fallback shown at the end.
What "exposed files" actually means
Every web server has a document root — the folder it serves files from. Most servers will happily serve any file inside that folder if asked by URL: .env, .git/config, phpinfo.php, backup.zip, even database.sql. By default, nginx and Apache have no idea these files are sensitive; they just serve them.
The reason this is a problem:
.envfiles store API keys, database passwords, and cloud credentials. A leaked.envis an instant takeover of whatever it connects to..git/directories contain the entire commit history of your site, including old code, old keys, and old secrets that were removed in later commits but still live in history.- Backup files (
backup.zip,site.tar.gz,dump.sql) are often full snapshots of the site or database, copied into the document root for convenience during a migration. phpinfo.phpdumps PHP configuration, including file paths, environment variables, and sometimes the contents of$_SERVERand$_ENV.server-statusis a built-in Apache module page that shows live request data — useful for debugging, devastating in public.
A scanner that reports exposed findings is telling you one or more of these paths currently returns 200 OK or 403 Forbidden from the public internet. The fix is to either remove the file or make the web server return 404 Not Found for any request to it.
403 Forbidden is not the same as 404 Not Found. A 403 confirms the file exists — it tells an attacker "yes, the thing you guessed is here, but you cannot read it." A 404 denies the existence entirely and forces the attacker to keep guessing. Always block at 404, not 403.
Why exposed files matter for New Zealand sites
The NZAI baseline treats exposed files as a critical-tier scanner finding, alongside missing HSTS and missing CSP. Three reasons it sits in that bracket:
- CERT NZ incident patterns. The published NZ incident reports repeatedly list exposed
.gitdirectories and backup files as the initial-access vector for NZ small-business compromises (1). - Privacy Act 2020 scope. If a
.envfile leaks a database connection string that holds student data, the disclosure does not need a sophisticated attacker — it just needs one automated bot that tried/backup.zip. Defending this is one of the cheapest reasonable steps available (2). - NCSC baseline controls. The National Cyber Security Centre baseline treats public access to source code, environment files, and admin pages as a misconfiguration that should not exist on any internet-facing host (3).
For context on the wider NZ baseline (devices, accounts, phishing), see Building Cyber-Safe Habits as an NZ Educator.
The five files that matter most
| Path | What it leaks | Fix priority |
|---|---|---|
| /.env | Database URLs, API keys, cloud credentials | Critical — replace any leaked keys immediately |
| /.git/ | Full source history, old secrets, committer emails | Critical — rotate any secret that ever appeared in a commit |
| /backup.zip, /site.tar.gz, /dump.sql | Full site or database snapshot | Critical — delete the file, never store backups in document root |
| /phpinfo.php | PHP configuration, environment variables, file paths | High — delete the file; use it on staging only |
| /server-status | Live Apache request data, client IPs, URLs | High — restrict to localhost or a specific admin IP |
A small minority of NZ hosts (managed WordPress providers, some N4L setups) place these files outside the document root by default. Check first; the Free Website Security Check tells you which ones your specific site is exposing.

nginx — block exposed paths at the server config level
If you have root access to your nginx config (typical on VPS hosts like DigitalOcean, Linode, Vultr, or self-managed servers), add the deny rules inside your server { ... } block, just below the server_name and listen directives:
# Deny access to common exposed files and directories.
location = /.env { return 404; }
location = /.git { return 404; }
location = /.git/ { return 404; }
location = /.gitignore { return 404; }
location ~* ^/\.git(/|$) { return 404; }
location = /backup.zip { return 404; }
location = /backup.tar.gz { return 404; }
location = /backup.sql { return 404; }
location = /site.tar.gz { return 404; }
location = /dump.sql { return 404; }
location = /database.sql { return 404; }
location = /phpinfo.php { return 404; }
location = /server-status { return 404; }
location = /server-info { return 404; }
In plain language:
return 404— every request to this exact path gets a404 Not Foundresponse, with no file servedlocation = /path— exact-match only; the path must be requested preciselylocation ~* ^/\.git(/|$)— regex match that catches any URL starting with/.git, including/.git/config,/.git/HEAD,/.git/logs/HEAD
Reload nginx with nginx -s reload (or sudo systemctl reload nginx on systemd hosts). Verify each path returns 404:
curl -sI https://yourschool.nz/.env | head -1
curl -sI https://yourschool.nz/.git/config | head -1
curl -sI https://yourschool.nz/backup.zip | head -1
You should see HTTP/1.1 404 Not Found (or the HTTP/2 equivalent) for each.
301 Moved Permanently on /.env, you have an HTTPS redirect issue, not a deny-rule issue. Fix the redirect chain first, then re-check.
Apache — block exposed paths with .htaccess or VirtualHost
On Apache (typical on cPanel, many shared hosts, and some managed WordPress providers), the same deny rules go inside an <IfModule mod_rewrite.c> block in either the site <VirtualHost> or an .htaccess in the document root:
<IfModule mod_rewrite.c>
RewriteEngine On
# Block exposed files and directories — return 404, not 403.
RewriteRule ^\.env$ - [R=404,L]
RewriteRule ^\.git(/|$) - [R=404,L]
RewriteRule ^\.gitignore$ - [R=404,L]
RewriteRule ^backup\.(zip|tar\.gz|tar|sql)$ - [R=404,L]
RewriteRule ^dump\.sql$ - [R=404,L]
RewriteRule ^database\.sql$ - [R=404,L]
RewriteRule ^phpinfo\.php$ - [R=404,L]
RewriteRule ^server-status$ - [R=404,L]
RewriteRule ^server-info$ - [R=404,L]
</IfModule>
If mod_rewrite is not available on your host (rare, but it happens on minimal containers), use the simpler <Files> and <FilesMatch> form:
<FilesMatch "^(\.env|\.env\..*|\.git|\.gitignore|backup\.(zip|tar\.gz|tar|sql)|dump\.sql|database\.sql|phpinfo\.php|server-status|server-info)$">
Require all denied
</FilesMatch>
# Replace Require all denied with this pair on Apache 2.2:
# Order allow,deny
# Deny from all
Note: <FilesMatch> returns 403 Forbidden, not 404 Not Found. That is the best Apache will do without mod_rewrite. The RewriteRule form above is preferred because it returns 404.
Reload Apache with sudo systemctl reload apache2 (or apache2ctl graceful on cPanel). Verify:
curl -sI https://yourschool.nz/.env | head -1
curl -sI https://yourschool.nz/.git/config | head -1
curl -sI https://yourschool.nz/phpinfo.php | head -1
You should see HTTP/1.1 404 Not Found for the RewriteRule paths and HTTP/1.1 403 Forbidden for the <FilesMatch> paths. Either is acceptable; 404 is preferred.
Shared hosting and managed WordPress — what to do
If you do not have root access (typical on cPanel shared hosting, managed WordPress hosts like WP Engine or SiteGround, and some N4L setups), use the hosting control panel's tooling. Most control panels expose one or more of:
- cPanel → Files → File Manager — rename
.envto.env.bak(servers do not serve.bakfiles by default), or move the file one directory above the document root - cPanel → Security → ModSecurity — enable the OWASP rule set, which blocks many of these paths automatically
- Managed WordPress → Settings → File Access — most managed hosts let you add specific path denies via the dashboard
- N4L managed WordPress — file-access changes go through the N4L service desk; open a ticket with the path list
For the .htaccess snippet to work on shared hosting, the host must have AllowOverride All (or at least AllowOverride FileInfo) enabled in the Apache config. Most cPanel hosts do; some managed WordPress hosts override .htaccess on every deploy. Check with the host's documentation.
.htaccess) leaves the file exposed — a deleted file cannot be exposed.
Verify with curl and the free scanner
Two ways to confirm the deny rules are live:
1. curl from the command line. For each path you blocked, request it and confirm the status code:
for path in /.env /.git/config /backup.zip /phpinfo.php /server-status; do
echo -n "$path -> "
curl -sI "https://yourschool.nz$path" | head -1
done
Expected output (for an nginx RewriteRule-style setup):
/.env -> HTTP/2 404
/.git/config -> HTTP/2 404
/backup.zip -> HTTP/2 404
/phpinfo.php -> HTTP/2 404
/server-status -> HTTP/2 404
2. The Free Website Security Check at nzscan.nzaisecurity.com. It runs the same checks in about ten seconds and tells you which paths are still exposing files. If a path shows up in the report, the deny rule has not taken effect — either the config did not reload, the host is caching, or there is a layer (Cloudflare, Varnish, a CDN) stripping your rule.
If you are behind Cloudflare, set the deny rule at the Cloudflare edge (Security → WAF → Custom Rules) as well as at the origin. Cloudflare's edge runs before the origin server, so a Cloudflare rule will block the request without ever hitting your nginx or Apache config.
Common mistakes to avoid
From running the free scanner across New Zealand school and small-business sites, the most frequent missteps are:
- Blocking at 403, not 404. A 403 confirms the path exists. Always return 404 for sensitive paths.
- Caching the 404 response. Some hosts cache 404 responses for hours. A cached 404 is fine; a cached 200 or cached file content is not. Verify with
curl -Iand a cache-busting query string. - Only blocking
/.env, not/.env.local,/.env.production, etc. Multiple.env*files are common. Use a regex match (location ~* /\.env). - Leaving the file in the document root after blocking access. Block and delete. The file should not exist on the server.
- Cloudflare rule set but no origin rule. A direct-origin attack (DNS pointed at the origin IP) bypasses Cloudflare entirely. Always block at both layers.
.htaccesson shared hosting but the host strips it. Some managed WordPress hosts overwrite.htaccesson deploy. Use the host's built-in file-access controls instead.
For the wider NZ context on which controls are baseline expectations, see Cyber Security for NZ Educators and Small Business Cybersecurity Guide: Protect Your NZ Company in 2026.
Knowledge check
Test your understanding of web server hardening with these questions. Click or tap each card to flip it and see the answer.
curl -sI https://yourschool.nz/.env returns HTTP/2 403 instead of 404. Your config clearly says return 404. What is happening?tap to flip/.env with 403), a ModSecurity rule on a shared host, or a hosting provider's own security layer. Test by curling the origin IP directly (bypassing Cloudflare) to confirm nginx is returning 404 — if origin returns 404 but Cloudflare returns 403, the rule is at Cloudflare and you do not need to fix anything (1)..htaccess, reload, and now every request to the site returns "500 Internal Server Error". The deny rule block is the only thing you changed. What is the most likely cause?tap to flipAllowOverride None in the Apache config, which means .htaccess is not read at all. With AllowOverride None, directives like RewriteRule in .htaccess cause a 500 error. The fix is either to contact the host and ask them to enable AllowOverride FileInfo, or to use the hosting control panel's built-in file-access controls instead. On shared hosting, the control panel is usually the safer path.backup.zip from your document root and add a deny rule, just to be safe. The scanner still flags /backup.zip as exposed. What could be going on?tap to flip/backup.zip?nocache=1) and from a different geographic location. If the file is genuinely gone but a CDN is still serving it, purge the cache. The other possibility is a second copy of the file in a subdirectory the scanner found — check /wp-content/uploads/backup.zip, /old/backup.zip, and any backup plugin output directory.Sources and references
[1] CERT NZ. (2025). Critical controls for small organisations. https://www.cert.govt.nz/
[2] New Zealand. Parliament. (2020). Privacy Act 2020. https://www.legislation.govt.nz/act/public/2020/0031/latest/whole.html
[3] New Zealand. National Cyber Security Centre. (2025). Cyber security baseline controls for organisations. https://www.ncsc.govt.nz/
[4] Mozilla. (2025). MDN Web Docs — NGINX rewrite rules and deny locations. https://developer.mozilla.org/en-US/docs/Web/HTTP/
[5] Apache Software Foundation. (2025). Apache HTTP Server — mod_rewrite documentation. https://httpd.apache.org/docs/current/mod/mod_rewrite.html
[6] Cloudflare. (2025). Custom rules for Cloudflare WAF. https://developers.cloudflare.com/waf/custom-rules/
What to do next
- Run the Free Website Security Check to see exactly which paths your site is exposing. The scanner returns the curl command for any path it flags.
- If your site is on shared hosting or managed WordPress, contact your host about enabling
AllowOverride FileInfoor use the host's built-in file-access controls instead of.htaccess. - For the connection-side piece that pairs with
/.envremoval — TLS that protects the data in transit — see the TLS 1.2 and 1.3 Explained for NZ Sites guide. - For the secrets-management piece (what to do if your
.envwas leaked, how to rotate keys, when to use a secrets manager), see Environment File Leaks: Detecting and Rotating Leaked Secrets for NZ Sites. - For the response-header piece that complements blocking (CSP, HSTS, X-Frame-Options), see Security Headers Explained for NZ Sites.
- For the cookie-security piece (Secure, HttpOnly, SameSite flags), see Secure Cookie Flags for NZ Sites.
- For everything else the scanner checks (TLS, cookies, mixed content, redirects), the free scanner covers all of it in one pass.