Do not have access to all folders except a specific folder by .htaccess

With Apache you can negate a regex (or expression) by simply prefixing it with ! (exclamation mark).

For example, to block every URL, except those that start /project/web/, you can use the following in the /project/.htaccess file:

RewriteRule !^web/ - [F]

Providing the .htaccess file is inside the /project subdirectory then you do not need to specify the project/ prefix, since the URL-path matched by the RewriteRule pattern is relative to the location of the .htaccess file.

This needs to go near the top of the .htaccess file.


RewriteRule (?!web)(/.*)?$ - [F,NC]

Alternatively, using a negative lookahead in the regex (NB: Apache uses PCRE, not the "Java 8" flavour of regex).

You are missing the start of string anchor. But then the slash won't match since the negative-lookahead assertion does not actually match anything (and the URL-path matched by the RewriteRule pattern does not start with a slash).

You could use the following instead:

RewriteRule ^(?!web($|/)) - [F]

We don't need to actually match anything, the regex just needs to be "successful" in order to trigger the directive and block the request. For example


Alternatively, you can use mod_authz_core instead. For example:

# /project/.htaccess

# Block access to everything
Require all denied

Create an additional access file in the /web sudirectory:

# /project/web/.htaccess

# Allow access
Require all granted

Or, you can do this all in /project/.htaccess with an Apache <If> expression (Apache 2.4). Although this is made a little more complex because it could be accessed by either the project subdomain or subdirectory and we are matching against the entire URL-path. For example:

# /project/.htaccess

# Block everything except the "/web" subdirectory
<If "%{REQUEST_URI} !~ m#^(/[^/]+)?/web($|/)#">
    Require all denied
</If>

The operator !~ does not match the regex.