Migrating a Legacy PHP Site to Clean URLs and SSL Without Breaking It
You've inherited a PHP site on shared cPanel hosting. The URLs are ugly (?page=about), there's no SSL, assets load inconsistently, and nobody knows why. The client wants clean URLs, HTTPS everywhere, and no visible downtime. This is one of the most common briefs in Nigerian web development. Here's how to do it cleanly.
Step 1: Diagnose Before You Touch Anything
The three most common culprits on shared hosting: file permissions set incorrectly (PHP can't read files it doesn't own), mod_rewrite not enabled (.htaccess rewrite rules ignored), and AllowOverride not set (.htaccess rules ignored even with mod_rewrite enabled). Check error logs first — in cPanel: Error Logs under Metrics. A 403 or 500 error trail tells you in seconds whether this is a permissions or configuration issue.
Step 2: Fix File Permissions
Correct permissions: directories at 755, PHP files at 644, uploaded assets at 644. Fix recursively via SSH:
find /path/to/site -type d -exec chmod 755 {} \;\nfind /path/to/site -type f -exec chmod 644 {} \;After fixing, hard-reload a page with broken assets. If they load, permissions were the issue.
Step 3: Enable mod_rewrite
Test with a minimal .htaccess containing just Options -Indexes and RewriteEngine On. If the page loads without a 500 error, mod_rewrite is active. If not, contact your host — most cPanel providers enable this on request.
Step 4: Enforce SSL
After installing your SSL certificate (free via Let's Encrypt in cPanel), add the HTTPS redirect before any other rewrite rules:
RewriteEngine On\nRewriteCond %{HTTPS} off\nRewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]R=301 tells browsers and search engines the redirect is permanent — important for SEO.
Step 5: Clean URLs
The standard pattern for a PHP application with a single front controller:
RewriteCond %{REQUEST_FILENAME} !-f\nRewriteCond %{REQUEST_FILENAME} !-d\nRewriteRule ^(.*)$ index.php?url=$1 [QSA,L]The two RewriteCond lines are critical — they ensure real files (images, CSS, JS) are served directly without routing through index.php.
Step 6: Test on Staging
Specifically verify: assets load correctly, deep-linked clean URLs resolve, HTTP redirects to HTTPS, and original ugly URLs redirect to new equivalents if you need to preserve old links.
The most time-consuming part isn't the .htaccess config — it's convincing the hosting provider to enable AllowOverride.
Budget time for a hosting support ticket. Enabling AllowOverride on shared hosting sometimes requires a request to the provider. Choose a provider where this is enabled by default — it's a two-minute check before you sign up that can save a day of debugging later.
Have a question about this? Talk to us — we're happy to go deeper.