cPanelOps · Hosting guides for site operators
cPanelOpsv2.2.0
Plain-English cPanel help from the team behind FirstResponderHost
26 guides live
CpanelOps / PageOps

Home › Guides

Security

Blocking direct access to data folders with .htaccess

Settings files, logs and exports should never be downloadable. Four layers that keep them private, and how to test each one.

Small web apps often keep their data in files: a settings file, a list of records in JSON, a log, a database export left behind after a migration. If those files sit inside the public web folder, anyone who guesses the address can download them. Automated scanners request common names such as backup.sql, config.json and error_log on every site they find. Closing this off takes a few lines.

Layer 1: keep private files out of the web folder

The strongest protection is location. On cPanel your account's home folder sits one level above public_html, and nothing outside public_html can be requested by a browser at all. A script can still read a file there by its full path. If you control where an app stores its data, a folder such as /home/youraccount/private/ is the place.

That is not always possible; many apps expect their data folder beside their code. The remaining layers are for those cases.

/home/youraccount/private/browsers cannot reach thispublic_html/everything here has a web addresspages, imagesdata/ + .htaccess
Safest is the private folder. A data folder inside public_html needs its own .htaccess to stay closed.

Layer 2: deny the whole folder

Create a file named .htaccess inside the data folder containing one line:

Require all denied

The web server now answers 403 Forbidden for every address in that folder and below it. Scripts on the server are unaffected, because they read files directly from disk and not through the web server. This works on Apache 2.4 and on LiteSpeed, which covers nearly all cPanel hosting.

Layer 3: deny risky file types everywhere

As a safety net for files that end up in the wrong place, add this to the .htaccess in public_html:

<FilesMatch "\.(sql|bak|log|ini|env|old)$">
  Require all denied
</FilesMatch>

Think before adding json or txt to that list: many sites serve public JSON on purpose, and files such as robots.txt and ads.txt must stay readable.

Layer 4: switch off folder listings

When a folder has no index page, some servers show a clickable list of everything in it. That hands a visitor the file names they would otherwise have to guess. One line in the top-level .htaccess turns listings off for the whole site:

Options -Indexes

A belt-and-braces trick for PHP apps

If your app is written in PHP and stores data in files, give the data files a .php extension and make their first line:

<?php exit; ?>

The app skips that line when it reads the file. If the .htaccess protection is ever lost, say the folder is copied to a server that ignores .htaccess, a browser requesting the file gets an empty page, because the server runs the file as PHP and it stops at once.

Test it like an outsider

  1. Open a private browser window, so you are not signed in to anything.
  2. Request a real file in the data folder by its full address. You should get 403.
  3. Request the folder itself. You should get 403, not a list.
  4. Use the app normally and confirm it still reads and saves its data.

Repeat the test after moving hosts or restoring from a backup. Files whose names start with a dot are easy to miss when copying, and a restore that leaves .htaccess behind silently removes the protection.

Two limits to keep in mind

  • .htaccess is not universal. Nginx does not read it. If you ever move to a server running Nginx alone, the same rules must be written into the server's own configuration.
  • Old copies are still out there. If a sensitive file was public for a time, assume it was fetched. Change any passwords or keys it held; blocking the address now does not un-leak them.

Common questions

Will blocking the folder break my app?

Not if the app reads its data on the server, which is the normal case for PHP. It will break anything where the visitor's browser fetches the data file directly, for example a page that loads data/items.json with a script. Those files have to stay public, so keep anything private out of them.

How do I know whether my server honors .htaccess?

Run the outsider test. If a file in the protected folder still downloads, the rule is being ignored: the server may not be Apache or LiteSpeed, or the host has switched off .htaccess overrides. Ask your host before relying on it.

Is a hard-to-guess file name enough?

No. Names leak through folder listings, error messages, backups and browser history. Use a real block, and treat an odd name as nothing more than a small extra.

Spotted a mistake, or a step that has changed?

cPanel's screens differ a little between versions and hosts. Tell us at info@firstresponderhost.com and we will correct the guide.

More guides