Remove public from URL
August 19, 2025 · AI Conversations
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|baiduspider|yandex|duckduckbot) [NC]
RewriteRule .* – [F,L]
Header set X-Robots-Tag "noindex, nofollow"
# New rule to override robots.txt
RewriteEngine On
RewriteRule ^robots.txt$ robots.txt [L]
# End: Block all search engine bots from accessing the site – (Do not Edit)
remove public from url in silstripe cms
That means your website should load from `https://example.com/` instead of `https://example.com/public/`.
Here’s the correct way to do it:
—
### ✅ Steps to Remove `/public` from URL in SilverStripe CMS
1. **Move `index.php` and `.htaccess` up one level**
– Copy the following files from the `/public` folder to your project root:
– `index.php`
– `.htaccess`
2. **Update `index.php` include path**
– Open the `index.php` you just moved.
– Find:
require_once __DIR__ . '/vendor/autoload.php';
– Change it to:
require_once __DIR__ . '/public/vendor/autoload.php';
– And for the line:
require_once __DIR__ . '/vendor/silverstripe/framework/src/includes/constants.php';
– Change it to:
require_once __DIR__ . '/public/vendor/silverstripe/framework/src/includes/constants.php';
3. **Fix `.htaccess` paths**
– In the `.htaccess` you copied, update any reference to `/public/` if present.
– Most of the time you don’t need to change much unless you had custom rules.
4. **Update Apache/Nginx DocumentRoot**
– Instead of pointing your DocumentRoot to `/public`, point it to your project root.
– For Apache (example):
DocumentRoot /var/www/yourproject
<Directory /var/www/yourproject>
AllowOverride All
Require all granted
</Directory>
5. **Clear caches**
– Run:
vendor/bin/sake dev/build flush=all
– Or append `?flush=1` to your site URL.
—
👉 This way, SilverStripe will still use `public` internally for assets, but the user-facing URL will no longer include `/public`.
—
Do you want me to give you the **exact modified `index.php` code** ready to paste after moving it from `/public` to root?
That means `/public` will stay in your folder structure, but users won’t see it in the URL.
—
### ✅ `.htaccess` solution (place in project root, not inside `/public`):
# Enable Rewrite
<IfModule mod_rewrite.c>
RewriteEngine On
# If request is for an existing file or folder in root, allow it
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Send everything else to /public
RewriteRule ^(.*)$ public/$1 [L]
</IfModule>
—
### How it works:
– When someone visits `https://example.com/`, the `.htaccess` forwards the request to `/public/index.php`.
– Direct file access (like `/assets/`, `/robots.txt`, `/favicon.ico`) will still work without showing `/public`.
– You keep SilverStripe’s recommended `/public` separation for security.
—
👉 This is the **safe and recommended way** if you want to hide `/public` but keep SilverStripe’s folder structure intact.
Do you want me to also adjust this so it **merges with your existing `.htaccess` that blocks bots** (the code you pasted earlier)?
RewriteEngine On
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|baiduspider|yandex|duckduckbot) [NC]
RewriteRule .* – [F,L]
Header set X-Robots-Tag "noindex, nofollow"
# New rule to override robots.txt
RewriteEngine On
RewriteRule ^robots.txt$ robots.txt [L]
# End: Block all search engine bots from accessing the site – (Do not Edit)
update above
You only need one `RewriteEngine On` and all rules should be inside the same “ block.
Here’s the cleaned-up version:
# Start: Block all search engine bots from accessing the site - (Do not Edit)
<IfModule mod_rewrite.c>
RewriteEngine On
# Block major bots
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|baiduspider|yandex|duckduckbot) [NC]
RewriteRule .* - [F,L]
# Rewrite requests to /public (remove "public" from URL)
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ public/$1 [L]
# Override robots.txt
RewriteRule ^robots.txt$ robots.txt [L]
</IfModule>
<IfModule mod_headers.c>
Header set X-Robots-Tag "noindex, nofollow"
</IfModule>
# End: Block all search engine bots from accessing the site - (Do not Edit)
—
### 🔎 What changed:
1. Only one `RewriteEngine On`.
2. Added rules to forward everything into `/public` (so `/public` doesn’t appear in URL).
3. Kept your bot-blocking and robots.txt override intact.
—
👉 Put this **in your project root `.htaccess`** (where `/public` folder lives).
Do you also want me to make sure **`robots.txt` inside `/public`** is still used correctly, even after hiding `/public`?
Let me fix this for you.
—
### ✅ Correct `.htaccess` (root folder)
Put this in your **project root** (same level as `/public`):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# 1. Block bots
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|baiduspider|yandex|duckduckbot) [NC]
RewriteRule .* - [F,L]
# 2. Redirect everything to /public/
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ public/$1 [L]
# 3. Override robots.txt (must come after public rule)
RewriteRule ^robots.txt$ robots.txt [L]
</IfModule>
<IfModule mod_headers.c>
Header set X-Robots-Tag "noindex, nofollow"
</IfModule>
—
### 🔎 Why your old one failed
– Apache was still serving the root directory listing because no `DirectoryIndex` or rewrite was catching `/`.
– The `RewriteRule ^(.*)$ public/$1` was being skipped for `/` (homepage).
– That’s why only `/public` worked.
—
### ✅ Extra step: Disable directory listing
If you don’t want users to see all folders when visiting `/`, add this to the same `.htaccess`:
Options -Indexes
DirectoryIndex index.php index.html
—
### End result:
– Visiting `https://example.com/` → internally serves `/public/index.php`.
– All subpages (`/about`, `/contact`) → served from `/public/` automatically.
– No more `/public` in the URL.
– No folder listing exposed.
—
👉 Do you want me to merge `Options -Indexes` + `DirectoryIndex` into your final `.htaccess` so you can just paste and go?
—
### ✅ Final `.htaccess` for root (put in the project root, same level as `/public`)
Options -Indexes
DirectoryIndex public/index.php
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# 1. Block bots
RewriteCond %{HTTP_USER_AGENT} (googlebot|bingbot|baiduspider|yandex|duckduckbot) [NC]
RewriteRule .* - [F,L]
# 2. Force everything into /public
RewriteCond %{REQUEST_URI} !^/public/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ public/$1 [L]
# 3. Override robots.txt (so /robots.txt is used from root)
RewriteRule ^robots.txt$ robots.txt [L]
</IfModule>
<IfModule mod_headers.c>
Header set X-Robots-Tag "noindex, nofollow"
</IfModule>
—
### 🔎 Key Fixes
1. **`DirectoryIndex public/index.php`** → makes homepage (`/`) load `/public/index.php`.
2. **`Options -Indexes`** → disables folder listing.
3. The rewrite now only triggers if the request is not already going into `/public`.
—
### 🚀 What you should see
– `https://example.com/` → loads `/public/index.php` (SilverStripe homepage).
– `https://example.com/about` → loads `/public/about` internally.
– No more directory listing.
– `/public` never shows in URL.
—
⚡ Important: After updating `.htaccess`, clear cache & restart Apache:
sudo service apache2 restart
—
👉 Do you want me to also give you the **Apache VirtualHost config** version (cleaner, no need for `.htaccess` rewrites), in case `.htaccess` still doesn’t take effect?