DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowHalloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
FREEDOM251

Freedom251 › Blog › Apache

How to Redirect a Domain to a Subfolder With .htaccess (Internal Rewrite or 3xx Redirect)

By Freedom251 Team · · 9 min read

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

If example.com should use files stored in a physical /public directory, decide first whether the folder should remain hidden. An internal rewrite serves /public while the browser keeps showing https://example.com/path. An external redirect sends a 3xx response and changes the browser address to https://example.com/public/path.

For a root .htaccess file, the working internal-rewrite pattern is:

As an Amazon Associate I earn from qualifying purchases.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
RewriteEngine On

RewriteCond %{HTTP_HOST} ^(?:www.)?example.com$ [NC]
RewriteCond %{REQUEST_URI} !^/public(?:/|$) [NC]
RewriteRule ^ public%{REQUEST_URI} [END]

The host check belongs in RewriteCond, the rule pattern is relative because this is per-directory configuration, and the destination-prefix condition prevents repeated /public additions.

Choose between a hidden subfolder and a visible redirect

“Redirect the domain to a subfolder” can describe two different Apache operations. Choosing the wrong one produces either an unexpected URL change or a rewrite loop.

Goal Apache operation Browser address Typical use
Serve the site from a folder without exposing it Internal rewrite (path substitution without R) Remains https://example.com/path A document root contains a public directory and that directory should be an implementation detail.
Tell clients that the public URL includes the folder External redirect (fully qualified URL or R flag) Changes to https://example.com/public/path A URL migration or deliberate public path change.

An internal rewrite is normally the answer when the requirement is “point the root domain at /public without showing the folder.” A redirect is appropriate only when clients, bookmarks and search engines should receive the new URL.

Prerequisites and assumptions

The examples below assume all of the following:

  • DNS for example.com already resolves to the Apache site handling the request.
  • The .htaccess file is in the document root, not inside /public.
  • The real files are in a physical document-root directory named public.
  • Apache’s mod_rewrite module is enabled.
  • The virtual host permits the required .htaccess overrides. A server that disallows overrides will silently ignore or reject these rules.

Confirm the actual document root and the directory containing the active .htaccess. A rule in a file inside /public is evaluated in a different per-directory context and cannot be copied unchanged from the document-root example.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure an internal rewrite that keeps /public hidden

Use this root .htaccess pattern

RewriteEngine On

# Apply only to the intended host.
RewriteCond %{HTTP_HOST} ^(?:www.)?example.com$ [NC]

# Do not prepend /public a second time.
RewriteCond %{REQUEST_URI} !^/public(?:/|$) [NC]

# In document-root .htaccess, the RewriteRule pattern is relative.
RewriteRule ^ public%{REQUEST_URI} [END]

Replace example.com with the host you have deliberately chosen to serve. The optional www. in the condition allows both example.com and www.example.com; remove it if only one host should be accepted, or add a separate canonical-host redirect as described later.

What each directive does

Directive or fragment Purpose
RewriteEngine On Enables mod_rewrite processing for this file.
RewriteCond %{HTTP_HOST} ... [NC] Limits the rule to the allowlisted host name. [NC] makes the comparison case-insensitive.
RewriteCond %{REQUEST_URI} !^/public(?:/|$) [NC] Skips requests already beginning with /public, whether the path is exactly /public or continues below it. The negation mark (!) is the loop guard.
RewriteRule ^ Matches the path presented to this document-root .htaccess. In per-directory context Apache removes the directory prefix before matching, so the pattern starts with ^, not ^/.
public%{REQUEST_URI} Maps the requested URI to the physical public directory while leaving the client unaware of the mapping.
[END] Stops per-directory rewrite processing for the request on Apache versions that support this flag.

For a request such as /docs/start.html, Apache internally looks for public/docs/start.html, but it does not send a redirect response. The address bar therefore remains /docs/start.html. A request for the root URI is mapped to the public directory itself.

If [END] is unavailable

Some older Apache versions or hosting environments do not provide [END]. Use [L] instead, and keep the destination-prefix exclusion in place:

RewriteRule ^ public%{REQUEST_URI} [L]

[L] ends the current rewrite pass, not every later per-directory pass. The exclusion condition is therefore essential when using it. Verify the Apache version and test the complete request flow before deploying.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Configure a visible redirect when the folder belongs in the URL

Start with a temporary redirect

Use a fully qualified destination and a temporary status while checking the behavior:

RewriteEngine On
RewriteCond %{HTTP_HOST} ^(?:www.)?example.com$ [NC]
RewriteCond %{REQUEST_URI} !^/public(?:/|$) [NC]
RewriteRule ^ https://example.com/public%{REQUEST_URI} [R=302,END,NE]

The R=302 flag makes Apache send a temporary redirect. The browser should receive a Location header such as https://example.com/public/docs/start.html. The NE flag prevents Apache from unnecessarily escaping characters that are already part of the intended URL.

Change to permanent status only after testing

After you have checked both HTTP and HTTPS requests, existing and missing paths, query strings, host variants and canonical-host behavior, change R=302 to R=301 only if the change is genuinely permanent:

RewriteRule ^ https://example.com/public%{REQUEST_URI} [R=301,END,NE]

Browsers and intermediary caches can retain a 301 response. Clear cached permanent redirects or use a fresh test profile when validating a changed rule.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Understand matching context before changing the pattern

RewriteRule matches a path, not a hostname

Apache does not pass the domain name to the RewriteRule pattern. A pattern such as ^example.com is looking for those characters in the URL path, not testing the host. Host selection belongs in a condition using %{HTTP_HOST}, as in the examples above.

Per-directory rules do not start with a slash

In a document-root .htaccess, Apache strips the directory prefix and leading slash before applying the rule pattern. A request for /about is therefore matched as about. Writing ^/about in this context normally fails to match. Virtual-host configuration has different matching rules, so a snippet copied from the main Apache configuration may need its leading slash removed for .htaccess.

The file’s location changes the relative path

If the file is placed in /public/.htaccess, Apache is already operating relative to that directory. A rule intended for the document root can then prepend public again or point at the wrong location. Put the supplied root rule in the document-root file, or rewrite the pattern specifically for the directory where the file lives.

Paths, query strings and existing files

The substitution uses %{REQUEST_URI}, so the requested path is carried into the public tree. Query strings are normally retained when a rewrite substitution does not provide a new query string. For example, a request for /search?q=apache is internally handled as public/search with ?q=apache still available to the application.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not add a second question mark or manually concatenate a query string unless you intentionally want to replace or append parameters. If an application generates its own front-controller rules, place the directory mapping where it will not be undone by a later rule, and inspect the resulting request with the server’s rewrite trace or error log when available.

The mapping does not guarantee that a target exists. A missing public/assets/site.css remains a missing resource and should produce the site’s normal 404 behavior. Test a real static file and a deliberately nonexistent path rather than assuming every request is valid.

Test the result before making it permanent

Use headers-only requests

curl -I shows status and response headers without downloading the body. Substitute your real host and paths:

curl -I http://example.com/
curl -I https://example.com/
curl -I https://example.com/docs/start.html
curl -I https://example.com/assets/site.css
curl -I https://example.com/does-not-exist
curl -I https://www.example.com/
curl -I https://example.com/search?q=apache
curl -I https://example.com/public/docs/start.html

Expected results by configuration

Request Internal rewrite Visible redirect
Root or nested public path Final response is the application or file response; no redirect is required and the URL stays unchanged. A 302 during testing, or 301 after approval, with Location: https://example.com/public....
Existing static file Served from public while retaining the requested URL. Redirects first, then the client requests the /public URL.
Missing path Normal application or web-server 404, without repeated prefixing. One redirect to the corresponding /public path, followed by the normal 404 if that target is absent.
Request already beginning /public Excluded from the prefixing rule so it is not changed to /public/public.... Also excluded, preventing a redirect chain.
Query string Should remain available unless another rule replaces it. Should appear after the redirected path unless another rule deliberately changes it.

Inspect the complete redirect chain with curl -I -L only after the single-response checks are clear. A chain that keeps adding /public indicates that the exclusion condition is missing or does not match the actual path.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot common failures

The rule never matches

  • Check that the file is the active document-root .htaccess, not a similarly named file in another directory.
  • Remove a leading slash from the RewriteRule pattern in per-directory context.
  • Confirm that mod_rewrite is enabled and that the virtual host allows the required overrides.
  • Verify that the request is reaching the expected virtual host. A different host definition can select another document root or another configuration.

Apache returns a 500 error

Read the Apache error log for the exact directive error. Typical causes include a misspelled flag, unsupported [END] on an older version, or rewrite directives being disallowed in .htaccess. Temporarily replace [END] with [L] only after confirming that the destination-prefix condition remains present.

The browser shows repeated /public segments

This is a rewrite or redirect loop. The rule is processing a URI that is already under the destination prefix. Ensure the condition is exactly broad enough to exclude both /public and descendants: !^/public(?:/|$). Also check that a second rule elsewhere is not adding the same prefix.

The hostname condition does not behave as expected

Check the value received in HTTP_HOST, including a port in some development requests and the presence or absence of www. Keep the condition narrowly allowlisted rather than matching arbitrary host input. If you need one canonical host, use an explicit condition and fixed destination, not a destination assembled from whatever host the client supplied.

HTTPS rules conflict with a proxy

When TLS terminates at a reverse proxy, Apache may see the connection to the origin as HTTP even though the visitor used HTTPS. Before adding an HTTP-to-HTTPS rule, establish which request variable your proxy sets to represent the original scheme and whether it is trusted. Stacking an unconditional HTTPS redirect on top of an unverified proxy header can create a redirect loop.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The file is served from the wrong place

Confirm the physical path and permissions for public, then request a known file directly through the expected URL. A successful rewrite cannot serve a directory that is outside the selected document root or blocked by filesystem permissions. If only some extensions fail, inspect later application or content-negotiation rules rather than changing the host condition.

Protect canonical hosts and redirect destinations

A redirect URL must not be built from unvalidated user input. If an attacker can influence the host value that Apache copies into a Location header, they may turn the rule into an open redirect. The fixed https://example.com destination in the visible-redirect example avoids that problem. Keep the HTTP_HOST condition allowlisted, and add explicit rules for any other legitimate host instead of accepting arbitrary names.

Decide separately whether www.example.com or example.com is canonical. The subfolder mapping and host canonicalization solve different problems. Test every combination of HTTP/HTTPS and both host variants so that only the intended number of redirects occurs. If a proxy, load balancer or CDN performs part of this process, document which layer owns scheme and host normalization.

Use virtual-host configuration when you control Apache

If you can edit the main Apache configuration, a dedicated virtual-host Redirect is Apache’s preferred mechanism for a simple host move. It avoids per-directory rewrite processing and makes the host boundary explicit. The examples in this article target the common shared-hosting situation in which only .htaccess is available; in that situation, mod_rewrite is the appropriate mechanism.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Do not combine a virtual-host redirect and an equivalent .htaccess redirect without a reason. Two layers can produce duplicate hops, hide which rule is active and make troubleshooting harder.

Deployment checklist

  1. Confirm DNS points the intended domain to the Apache virtual host and identify the document root.
  2. Choose internal rewriting if /public should stay hidden; choose an external redirect if it should become part of the public URL.
  3. Back up the current .htaccess file.
  4. Place the rule in the document-root file and use a relative RewriteRule pattern.
  5. Allowlist the host in RewriteCond %{HTTP_HOST} and use a fixed redirect destination.
  6. Keep the destination-prefix exclusion so an already mapped request is not processed again.
  7. Use [END] where supported; otherwise use [L] with the exclusion intact.
  8. Test root, nested paths, an existing static file, a missing path, query strings, both host variants and both schemes with curl -I.
  9. For visible redirects, keep R=302 until the Location header and final content are correct.
  10. Change to R=301 only for a permanent move, and clear cached permanent redirects when retesting.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Apachehtaccessmod_rewriteURL redirectsWeb hosting

Leave a Reply

Your email address will not be published. Required fields are marked *

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Recommended PC Tool
Recommended PC Tool
Windows Errors? Fix Them Before They SpreadFree repair scan
Outdated Drivers Are Slowing You DownFree scan - exact matches

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.