Merge pull request 'chore: version-control the WHMCS KB redirect rules' (#10) from chore/save-whmcs-redirects into main
Build and deploy / deploy (push) Successful in 27s
Build and deploy / deploy (push) Successful in 27s
This commit was merged in pull request #10.
This commit is contained in:
@@ -0,0 +1,59 @@
|
|||||||
|
# Deploy artefacts
|
||||||
|
|
||||||
|
Config that lives on other servers but belongs under version control here,
|
||||||
|
because it exists to serve this KB.
|
||||||
|
|
||||||
|
## `whmcs-kb-redirects.conf`
|
||||||
|
|
||||||
|
301 redirects that send the retired WHMCS knowledgebase
|
||||||
|
(`secure.anhonesthost.com/knowledgebase/*`) to its replacement pages on
|
||||||
|
kb.anhonesthost.com. Installed 2026-08-01.
|
||||||
|
|
||||||
|
**Where it lives in production:** `/home/whmcs/public_html/.htaccess` on
|
||||||
|
`secure.anhonesthost.com`, prepended **before** the
|
||||||
|
`### BEGIN - WHMCS managed rules ###` marker. It has to come first — WHMCS's
|
||||||
|
own block ends with a catch-all that routes everything to `index.php`, so
|
||||||
|
rules placed after it never run.
|
||||||
|
|
||||||
|
The canonical copy on that server is `/root/kb-redirects.conf`, and the
|
||||||
|
pre-migration `.htaccess` is backed up at
|
||||||
|
`/root/htaccess-backup-20260801.bak`.
|
||||||
|
|
||||||
|
### Reinstalling
|
||||||
|
|
||||||
|
WHMCS rewrites `.htaccess` during some updates, which will silently drop
|
||||||
|
these rules. To restore:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /home/whmcs/public_html
|
||||||
|
cp -a .htaccess /root/htaccess-backup-$(date +%Y%m%d).bak # keep whatever WHMCS wrote
|
||||||
|
cat /root/kb-redirects.conf /root/htaccess-backup-$(date +%Y%m%d).bak > /tmp/htaccess.new
|
||||||
|
install -o whmcs -g whmcs -m 644 /tmp/htaccess.new .htaccess
|
||||||
|
apachectl -t
|
||||||
|
```
|
||||||
|
|
||||||
|
Then spot-check a redirect:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -sI https://secure.anhonesthost.com/knowledgebase/13/x.html | grep -i location
|
||||||
|
# expect: https://kb.anhonesthost.com/support/remote-support/
|
||||||
|
```
|
||||||
|
|
||||||
|
### Two things that will bite you when editing it
|
||||||
|
|
||||||
|
**Article and category IDs collide.** Both use the shape
|
||||||
|
`/knowledgebase/<id>/<slug>`, and the same number means different things —
|
||||||
|
article 5 is "What are my Name Servers?", category 5 is "WordPress Specific".
|
||||||
|
The *only* discriminator is the trailing `.html` on articles. That's why every
|
||||||
|
article rule appears before every category rule and terminates with `[L]`: by
|
||||||
|
the time the broad category patterns run, anything ending `.html` is already
|
||||||
|
gone. Reordering the file breaks this silently, and the wrong page still
|
||||||
|
returns 200.
|
||||||
|
|
||||||
|
**The slug is ignored.** WHMCS reads only the id, so any slug with the right
|
||||||
|
id resolves. The rules match `[^/]*` for the slug for the same reason.
|
||||||
|
|
||||||
|
Legacy pre-SEO URLs (`knowledgebase.php?action=displayarticle&id=N` and
|
||||||
|
`?action=displaycat&catid=N`) are mapped explicitly. `(^|&)id=` cannot match
|
||||||
|
`catid=` — the preceding character is `t`, not `&` or start-of-string — so the
|
||||||
|
two sets can't cross-fire.
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
### BEGIN - KB migration redirects to kb.anhonesthost.com ###
|
||||||
|
# Added 2026-08-01. The WHMCS knowledgebase is retired; these 301s send its
|
||||||
|
# URLs to the equivalent page on the dedicated KB.
|
||||||
|
#
|
||||||
|
# ORDER MATTERS. Article and category URLs share the shape
|
||||||
|
# /knowledgebase/<id>/<slug>
|
||||||
|
# and their IDs COLLIDE (article 5 is "What are my Name Servers?", category 5
|
||||||
|
# is "WordPress Specific"). The only discriminator is the trailing ".html" on
|
||||||
|
# articles. Article rules therefore come first and terminate with [L]; the
|
||||||
|
# category rules below can then match broadly because anything ending .html
|
||||||
|
# has already been redirected and will never reach them.
|
||||||
|
#
|
||||||
|
# The slug is ignored by WHMCS (only the id is read), so it is ignored here
|
||||||
|
# too — any slug with the right id resolves to the right destination.
|
||||||
|
#
|
||||||
|
# The trailing "?" on each target discards the inbound query string.
|
||||||
|
<IfModule mod_rewrite.c>
|
||||||
|
RewriteEngine on
|
||||||
|
RewriteBase /
|
||||||
|
|
||||||
|
# --- Articles (.html) -------------------------------------------------
|
||||||
|
RewriteRule ^knowledgebase/2/[^/]*\.html$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/3/[^/]*\.html$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/4/[^/]*\.html$ https://kb.anhonesthost.com/email/spam-filtering-changes/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/5/[^/]*\.html$ https://kb.anhonesthost.com/cpanel/nameservers/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/6/[^/]*\.html$ https://kb.anhonesthost.com/cpanel/fix-a-403-error/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/7/[^/]*\.html$ https://kb.anhonesthost.com/cpanel/wordpress-email-from-your-domain/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/8/[^/]*\.html$ https://kb.anhonesthost.com/cpanel/free-ssl-certificate/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/9/[^/]*\.html$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/10/[^/]*\.html$ https://kb.anhonesthost.com/domains/transferring-a-domain-to-us/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/11/[^/]*\.html$ https://kb.anhonesthost.com/domains/transferring-a-domain-to-us/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/12/[^/]*\.html$ https://kb.anhonesthost.com/domains/flush-your-dns-cache/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/13/[^/]*\.html$ https://kb.anhonesthost.com/support/remote-support/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/14/[^/]*\.html$ https://kb.anhonesthost.com/whp/getting-started/welcome/? [R=301,L]
|
||||||
|
|
||||||
|
# --- Categories (no .html) --------------------------------------------
|
||||||
|
RewriteRule ^knowledgebase/2/[^/]*/?$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/3/[^/]*/?$ https://kb.anhonesthost.com/email/spam-filtering-changes/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/4/[^/]*/?$ https://kb.anhonesthost.com/cpanel/nameservers/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/5/[^/]*/?$ https://kb.anhonesthost.com/cpanel/wordpress-email-from-your-domain/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/6/[^/]*/?$ https://kb.anhonesthost.com/domains/transferring-a-domain-to-us/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/7/[^/]*/?$ https://kb.anhonesthost.com/cpanel/fix-a-403-error/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/8/[^/]*/?$ https://kb.anhonesthost.com/support/remote-support/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase/9/[^/]*/?$ https://kb.anhonesthost.com/whp/getting-started/welcome/? [R=301,L]
|
||||||
|
|
||||||
|
# --- Legacy query-string URLs -----------------------------------------
|
||||||
|
# Pre-SEO-URL links still in old tickets and emails:
|
||||||
|
# knowledgebase.php?action=displayarticle&id=<id>
|
||||||
|
# knowledgebase.php?action=displaycat&catid=<id>
|
||||||
|
# WHMCS used to 301 these to the friendly URL itself, but our rules above
|
||||||
|
# now intercept first — so map them explicitly or they all land on the KB
|
||||||
|
# home page and lose their destination.
|
||||||
|
#
|
||||||
|
# "(^|&)id=" cannot match "catid=" (the preceding char is "t", not & or
|
||||||
|
# start-of-string), so the two sets can't cross-fire.
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=2(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=3(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=4(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/email/spam-filtering-changes/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=5(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/nameservers/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=6(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/fix-a-403-error/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=7(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/wordpress-email-from-your-domain/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=8(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/free-ssl-certificate/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=9(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=10(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/domains/transferring-a-domain-to-us/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=11(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/domains/transferring-a-domain-to-us/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=12(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/domains/flush-your-dns-cache/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=13(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/support/remote-support/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)id=14(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/whp/getting-started/welcome/? [R=301,L]
|
||||||
|
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=2(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/email/set-up-your-email-client/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=3(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/email/spam-filtering-changes/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=4(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/nameservers/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=5(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/wordpress-email-from-your-domain/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=6(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/domains/transferring-a-domain-to-us/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=7(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/cpanel/fix-a-403-error/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=8(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/support/remote-support/? [R=301,L]
|
||||||
|
RewriteCond %{QUERY_STRING} (^|&)catid=9(&|$)
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/whp/getting-started/welcome/? [R=301,L]
|
||||||
|
|
||||||
|
# --- Tags, search, index, and anything else under /knowledgebase ------
|
||||||
|
# Catch-all last: any KB URL not matched above lands on the KB home page
|
||||||
|
# rather than a WHMCS 404.
|
||||||
|
RewriteRule ^knowledgebase\.php$ https://kb.anhonesthost.com/? [R=301,L]
|
||||||
|
RewriteRule ^knowledgebase(/.*)?$ https://kb.anhonesthost.com/? [R=301,L]
|
||||||
|
</IfModule>
|
||||||
|
### END - KB migration redirects to kb.anhonesthost.com ###
|
||||||
|
|
||||||
Reference in New Issue
Block a user