🔐
Hosting

Protecting your .env file from public access

12.11.2026
← All articles

Modern PHP and Node.js projects keep their secrets in a single .env file: database credentials, SMTP settings, payment keys, bot tokens and more. Separating configuration from code is convenient, but if the file sits in the public web folder, anyone can read it as plain text at https://example.uz/.env. One request hands an attacker nearly every key your site uses.

Why this mistake is so common

Frameworks like Laravel expect the web root to point at public, with .env one level above. When a project is uploaded to hosting, developers often drop everything into the site root and add an .htaccess redirect to public/index.php, leaving .env exposed. Copies such as .env.backup, .env.old or an editor's .env~ are forgotten just as often. Bots scan for these paths constantly; your access log will show requests for /.env and /api/.env almost daily, regardless of how small the site is. These are automated scanners walking through every address on the internet, not a targeted attack, which is exactly why every site gets probed sooner or later.

Testing your site

A 403 or 404 with no DB_PASSWORD lines means the file is closed. A 200 with file contents means act now. Test the bare domain, www and every subdomain separately.

curl -s -o /dev/null -w "%{http_code}\n" https://example.uz/.env
curl -s https://example.uz/.env | head -5
grep '"GET /.env' access.log | tail -20

Best fix: keep it outside the web root

If the web server cannot see the file, no misconfiguration can leak it. Point the document root at the project's public folder. On sayt.uz hosting that setting lives in the ISPmanager panel, which opens from the sayt.uz cabinet, and support can help if you are unsure.

/home/user/example.uz/
├── .env          # not reachable from the web
├── app/
└── public/       # web root
    └── index.php

If the file must stay in the root

Deny dotfiles at the web server level. Nginx needs an exception for .well-known, which Let's Encrypt uses.

# .htaccess (Apache 2.4)
<FilesMatch "^\.env">
    Require all denied
</FilesMatch>

# Nginx, inside server { }
location ~ /\.(?!well-known) {
    deny all;
    return 404;
}

After editing Nginx, run nginx -t and then systemctl reload nginx, and repeat the curl test.

Permissions and Git

Only the site owner should be able to read the file, and it must never be committed. Commit a .env.example with variable names but no values.

chmod 600 .env
echo ".env" >> .gitignore
git rm --cached .env   # if it was committed by mistake

git rm --cached only affects future commits; the file remains in history, so treat any secrets that were ever committed as leaked.

If the file has already leaked

  1. Block the file immediately and re-test.
  2. Change the database password and update .env.
  3. Rotate payment, SMS, mail and bot keys in their dashboards.
  4. Consider rotating Laravel's APP_KEY, after checking its effect on encrypted data and sessions.
  5. Check access logs for when and from which IPs the file was fetched, and look for unknown users in the database.

Example: a hotel in Bukhara

A small Bukhara hotel's Laravel booking site was uploaded to hosting as a whole. One day the manager noticed hundreds of emails sent to strangers: the .env was public and its SMTP password was being used for spam. The developer moved the web root to public, changed the mail and database passwords and added an extra .htaccess rule. Since then he runs the curl check before launching every new project.

Related articles

⏰ Cron not running: 8 common mistakes and how to find them in the log 🐧 Choosing a VPS Operating System: Ubuntu, Debian or AlmaLinux 🖥️ New VPS: what to do in the first 30 minutes 🚀 Deploying NestJS to Production: Build, PM2, Nginx and SSL
🌐 Language
🇺🇿 O'zbek 🇺🇿 Ўзбек 🇷🇺 Русский 🇬🇧 English ✓