How to duplicate a live site to use as a test site

Did you change the config.php file in the cloned path with your new database credentials?
Of course
This is nuts, unless perhaps you have left "Enable board URL canonicalization" turned on?
Enable board URL canonicalization was enabled by default.
It's not a case of two databases being synced, it's a case of one database viewed by two different URLS. As above the config.php must be changed to reference the test database, not the live database.
Both configuration files contain distinct database information, indicating that the live site operates with a different database setup. I have copied the database tables from the live site to the newly created test database and updated the configuration file to reflect the relevant details.
 
OK, that's potentially your problem.
Unfortunately, If I change it from the subdomain or newly cloned site original/live site is changing it too.


Let me explain What I did from the beginning.

1. Copied all files from the live site to the subdomain.
2. Created a database for a subdomain and copied all the database tables from the live site to the newly created database.
3. Edit config.php on a subdomain change the information with the newly created database and added this code on config.php

Code:
$config['enableMail'] = false;

$config['cookie'] = array(
'prefix' => 'testsf_',
'path' => '/',
'domain' => 'beta.subdomain.com'
);

Did I do all the steps correctly?
 
Last edited:
Did I do all the steps correctly?
Well, they certainly sound OK.

The canonicalisation thing will bite you though, if you didn't (a) change the board URL or (b) turn off canonicalisation entirely. The symptom will be somewhat obvious but only if you look for it, which is easier said than done because you kind-of assume that if you load test.domain.com instead of www.domain.com, then you will still be on test.domain.com when the page loads. Instead, the canonicalisation will send you to www.domain.com, automagically.
Quoting from the ACP text on this:
If enabled, the board URL setting will be treated as the canonical installation URL. If visitors access your site through a different URL, they will be redirected to the appropriate canonical URL. When enabled, you must ensure that your board URL setting is correct. If it is not correct, areas outside the admin control panel will not be accessible!

So, you can simply check your address bar to see if it stays on the test site where you sent it.
If it does, then canonicalisation isn't your problem.
 
@Neilski Do I need to disable it on both sites? Live and Cloned one?
Thanks.
Only the cloned site.
But you don't even need to do that much - once you suspect that this is the issue, just carefully check the URL in the address bar after sending your browser to the cloned site. If it automagically redirects to the live site, then bingo, that's why you've been having the issues you've had...
 
I'm planning on creating a staging site to test and upgrade from 2.2 -> 2.3, and hopefully then 2.4 relatively easily when that gets released hopefully in the not too distant future.

Main reason is to get the Oauth feature from 2.3 so another developer can use XF credentials for a 3rd party content app that uses XF logins and user groups to control access to content, and get the new improved subscription management and cancellation features.

Is this 10 year old guide still best practice and applicable now that we have payment integrations in XF?

The site heavily relies on subscriptions (all users are paid members) and I want to ensure the staging site doesn't talk to stripe and accidentally charge anyone. Can anyone confirm if I need to do anything additional with the config to ensure this doesn't happen?

It would be password protected instance at domain.com/staging or something similar unless recommended otherwise. (Root domain is WordPress), forum is currently domain.com/forum

Thanks

EDIT: Found the enableLivePayments config setting, I think that's what I need.
 
Last edited:
The following is what chatGPT wrote. Does it make sense?
Suggestion: Updating this guide for XenForo 2.3 and modern server environments

Thank you for putting together this guide. It's very helpful for anyone who wants to create a development or test installation from an existing live XenForo forum.

I've recently set up a XenForo 2.3 development environment, and I think the tutorial could benefit from a few additions and updates.

1. Using a separate subdomain

Instead of installing the test forum in a /test directory, it would be useful to include instructions for a separate subdomain, such as:

Both installations could be hosted on the same VPS, with separate document roots, databases, and configuration files.

2. Nginx support

The guide currently relies on .htaccess for password protection and URL rewriting. Since Nginx doesn't process .htaccess files, an additional section covering Nginx would be useful.

This could explain how to configure XenForo's friendly URLs, prevent direct access to private directories such as /src/ and /internal_data/, and secure the development installation.

3. Cloudflare Access as an alternative to HTTP Basic Authentication

For websites using Cloudflare, Cloudflare Access provides another way to restrict the development environment.

For example, access to dev.mydomain.com could be limited to specific Google accounts, allowing developers to authenticate without maintaining IP allowlists or configuring .htpasswd files.

4. Development-specific settings

The existing instructions for disabling outgoing email and using a separate cookie prefix are particularly important and worth emphasizing.

For example:

$config['enableMail'] = false;
$config['cookie']['prefix'] = 'mydomain_dev_';
It would also be helpful to mention separate cache prefixes, search indexes, API credentials, payment integrations, webhooks, and scheduled tasks where applicable.

5. Clarifying synchronization between production and development

This is probably the most important addition.

The guide explains how to copy a live website to a test installation, but it would be useful to distinguish between two operations:

  • Production → Development: Refresh the test environment using a copy of the live database and files.
  • Development → Production: Deploy tested software updates, add-ons, templates, and customizations without overwriting live member data.
For example, directly replacing the production database with the development database after launch could result in the loss of new members, posts, conversations, and other live data.

Some guidance on safely deploying tested changes back to production would make the tutorial considerably more useful.

6. Backups and automation

It would also be helpful to include examples using rsync and mariadb-dump, along with recommendations for storing backups outside the server and avoiding database passwords in shell command arguments.

A basic script for refreshing the development environment, with appropriate safeguards against accidentally overwriting production, would be a valuable addition.

Overall, the original guide is still a very useful starting point. These additions would make it more relevant to XenForo 2.3 users running modern Nginx-based VPS environments, especially those maintaining separate development and production installations.

Thanks again for sharing it!
 
Again, by chatGPT:

Setting Up Separate Development and Production XenForo 2.3 Websites on the Same VPS​

Introduction​

This tutorial explains how to maintain two separate XenForo installations on a single VPS:

  • Production: https://mydomain.com — the live forum, accessible to members.
  • Development: https://dev.mydomain.com — a private testing environment used to develop new features, test upgrades, install add-ons, and experiment with the design.
The objective is to test changes safely before applying them to the production website, without losing live member registrations, discussions, private messages, or attachments.

The tutorial also explains how to refresh the development environment from production when realistic test data is required.

It is designed for XenForo 2.3 running on Linux with Nginx, PHP-FPM and MariaDB. The examples use a Centmin Mod-style directory structure, but the concepts apply to other VPS configurations.

Important: This is a controlled deployment workflow, not automatic two-way database synchronization.


1. Understanding the Two Different Workflows​

There are two distinct operations:

A. Production → Development: Refreshing the test website​

This involves copying the live database and website files to development, allowing you to test against a realistic copy of the live forum.

It can overwrite existing development data.

B. Development → Production: Deploying tested changes​

This involves selectively transferring tested updates, custom code, add-ons and configurations to the live website.

The development database must not replace the production database after the site has launched.

Otherwise, any new members, posts and messages created on the live website since the databases diverged could be lost.

The two workflows require different procedures.

2. Recommended Server Structure​

Both XenForo installations can reside on the same VPS:

VPS
│
├── Nginx
├── PHP-FPM
├── MariaDB
│ ├── mydomain_prod
│ └── mydomain_dev
│
├── /home/nginx/domains/mydomain.com/
│ └── public/ Production XenForo
│
└── /home/nginx/domains/dev.mydomain.com/
└── public/ Development XenForo
Each installation must have:

ComponentProductionDevelopment
Domainmydomain.comdev.mydomain.com
Document rootSeparateSeparate
Databasemydomain_prodmydomain_dev
DB usermydomain_prodmydomain_dev
src/config.phpSeparateSeparate
CookiesSeparate prefixSeparate prefix
Uploaded filesSeparateSeparate
EmailEnabled when configuredDisabled
AccessPublicRestricted
Cache and search indexesProduction-specificDevelopment-specific
This provides logical separation, but both installations still share the VPS operating system and resources. It does not provide the same isolation as two separate servers.

3. Prepare the Two Websites​

Create two Nginx virtual hosts:

mydomain.com
dev.mydomain.com
Configure DNS records, HTTPS certificates and PHP-FPM for both websites.

For example, the document roots could be:

/home/nginx/domains/mydomain.com/public
/home/nginx/domains/dev.mydomain.com/public
Use valid HTTPS certificates and test both virtual hosts separately.

If using Cloudflare, enable Full (Strict) TLS and configure appropriate origin security.

Protect the development website before uploading any private or sensitive production data.

Secure the development website with Cloudflare Access​

For a Cloudflare-proxied development hostname, create a self-hosted Cloudflare Access application for:

dev.mydomain.com
Create an Allow policy for only the authorized developers or administrators.

Google authentication, one-time PINs or another supported identity provider can be used.

Test access in a private browser window:

  1. An approved account should successfully authenticate.
  2. An unauthorized account should be denied.
  3. An unauthenticated visitor should not reach the development site.
If using Nginx rather than Apache, do not depend on .htaccess for access control. Nginx does not process .htaccess files.

Keep the production and development Cloudflare security rules clearly scoped by hostname. A broad IP-based Zone Lockdown rule can unintentionally block development administrator URLs.

4. Configure Nginx for XenForo​

Each XenForo virtual host should have appropriate routing and private-directory restrictions.

Inside the relevant HTTPS server block, use the following as a starting point:

# Prevent direct access to private directories
location ^~ /src/ {
deny all;
}

location ^~ /internal_data/ {
deny all;
}

location ^~ /library/ {
deny all;
}

# XenForo friendly URL routing
location / {
try_files $uri $uri/ /index.php?$uri&$args;
}
These rules must be integrated with the existing PHP-FPM handler and any included Nginx security configuration, rather than pasted as a complete replacement for the virtual host.

Do not block /data/ entirely. XenForo uses that directory for public assets such as avatars and attachment thumbnails.

For additional hardening, restrict executable PHP files to the entry points actually required by XenForo and installed add-ons. Also protect configuration backups, temporary archives and database dumps.

Do not leave complete XenForo installation ZIPs or backup files in publicly accessible directories.

After editing Nginx:

nginx -t
systemctl reload nginx
Confirm that the configuration test succeeds before reloading.

5. Create Separate Databases​

Connect to MariaDB using an administrative account:

mariadb
Create production and development databases:

CREATE DATABASE mydomain_prod
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;

CREATE DATABASE mydomain_dev
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
Create separate database accounts:

CREATE USER 'mydomain_prod'@'localhost'
IDENTIFIED BY 'REPLACE_WITH_UNIQUE_PRODUCTION_PASSWORD';

CREATE USER 'mydomain_dev'@'localhost'
IDENTIFIED BY 'REPLACE_WITH_UNIQUE_DEVELOPMENT_PASSWORD';

GRANT ALL PRIVILEGES ON mydomain_prod.*
TO 'mydomain_prod'@'localhost';

GRANT ALL PRIVILEGES ON mydomain_dev.*
TO 'mydomain_dev'@'localhost';
Use unique, randomly generated passwords and keep them out of shell history, screenshots and source control.

For each installation, its src/config.php must reference only its own database.

Never configure the development site to connect to the production database.

6. Install XenForo​

Download the official XenForo installation package from the XenForo Customer Area.

Extract the archive and copy the contents of its upload directory into the respective website document root.

For example:

rsync -a /path/to/xenforo/upload/ \
/home/nginx/domains/dev.mydomain.com/public/
Run the XenForo installer at:

Provide the development database credentials.

Use the appropriate ownership and directory permissions for the PHP-FPM worker account. Avoid unnecessarily making files writable by every system user.

For production, deploy the same tested XenForo release to its own document root and connect it to mydomain_prod.

There is no need to install production immediately while development is still in progress.

7. Development-Specific Configuration​

Edit:

/home/nginx/domains/dev.mydomain.com/public/src/config.php
Retain the development database connection details and add:

// Development environment only
$config['enableMail'] = false;
$config['cookie']['prefix'] = 'mydomain_dev_';
Disabling mail prevents XenForo from sending messages to actual members when the development database contains copied production data.

The separate cookie prefix reduces interference between logins on the two installations.

Keep the cookie domain at its default host-only setting unless there is a specific reason to change it.

Consider disabling real payment processing on development:

$config['enableLivePayments'] = false;
Also review any active third-party email clients, webhooks, payment integrations, OAuth applications, external storage services and background tasks. XenForo's enableMail setting does not automatically disable those external systems.

For Redis or another shared cache, configure separate namespaces, database numbers or instances where supported. If using XenForo Enhanced Search, configure separate indexes.

You should also give the development installation a distinct title such as:

MyDomain — Development
Set its Board URL to:

Keep the licensed production URL configured as:

8. Keep Production and Development Backups Separate​

Before making changes to either installation, take independent backups.

A complete XenForo backup should account for:

  • The MariaDB database.
  • The application files and custom add-ons.
  • The data directory.
  • The internal_data directory, including attachments.
  • Configuration files and relevant Nginx settings.
Do not assume a database backup contains attachments.

A VPS snapshot is useful for disaster recovery, but it should not be the only backup method.

Prefer keeping encrypted backup copies outside the VPS and periodically testing restoration.


Part II — Refresh Development from Production​

9. Before You Begin​

The following procedure deliberately replaces the development environment with a copy of production.

Do not run it if there are development-only changes you still need to preserve.

First:

  1. Back up the existing development database and files.
  2. Commit or export custom development code and add-on development output.
  3. Record development-specific settings and secrets.
  4. Identify any external integrations that must remain disabled.
  5. Confirm that production is healthy and that sufficient disk space is available.
For small forums, a transaction-consistent MariaDB dump and a file copy may be sufficient. For larger, actively changing forums, coordinate database and attachment snapshots or use a consistent backup window so the database and files represent compatible states.

10. Export the Production Database​

On the VPS:

mkdir -p /root/xf-refresh
chmod 700 /root/xf-refresh
Export the database:

mariadb-dump --single-transaction \
--quick --routines --triggers \
-u mydomain_prod -p \
mydomain_prod > /root/xf-refresh/prod.sql
The command prompts for the production database password instead of placing it in the command line.

Check that the dump completed successfully and has a plausible file size.

For a fully consistent backup with attachments, coordinate any active writes before the final snapshot of data and internal_data.

Do not store the database dump inside either website's public directory.

11. Copy Production Files to a Staging Directory​

Avoid directly copying files into the active development installation before preserving the settings that are unique to it.

Create a protected staging directory:

mkdir -p /root/xf-refresh/site
chmod 700 /root/xf-refresh/site
Copy production files:

rsync -a \
/home/nginx/domains/mydomain.com/public/ \
/root/xf-refresh/site/
The trailing slash ensures hidden files are included.

This copy is the starting point for the new development environment.

Before promoting it, replace its production-specific configuration with the saved development configuration and verify that the application will not connect to live services.
 

12. Refresh the Development Database​

The safest repeatable approach is to import into a separate temporary database first, verify it, and then perform a controlled development cutover.

For a smaller test installation, you can also recreate the dedicated development database during a scheduled refresh.

Destructive operation — development only:

After verifying that backups exist and the database name is exactly mydomain_dev, an administrator can recreate it:

DROP DATABASE mydomain_dev;

CREATE DATABASE mydomain_dev
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
This removes all existing development database content.

Import the production snapshot:

mariadb -u mydomain_dev -p \
mydomain_dev < /root/xf-refresh/prod.sql
If the dump includes database-selection statements or account-management operations, inspect and adjust it before importing. The example assumes an ordinary single-database dump with no such statements.

Never run DROP DATABASE against mydomain_prod.

13. Restore Development-Specific Configuration​

Before exposing the copied site, restore the separate development src/config.php containing:

  • Database: mydomain_dev.
  • User: mydomain_dev.
  • The development database password.
  • Disabled outgoing mail.
  • Development-only cookie prefix.
  • Separate cache, search and integration settings.
Keep the development site behind Cloudflare Access throughout the procedure.

After importing the database, change the copied Board URL to:

Update the board title to identify it as a development installation.

Do not perform broad SQL replacements of domain names throughout XenForo's database. Some data may contain serialized or structured values that should be modified through XenForo's application tools instead.

Review external services, webhooks, payment processors, job queues and scheduled tasks before allowing the refreshed development installation to operate normally.

If production includes real personal information, restrict who can access the copied data and consider masking sensitive values when full production data is unnecessary.

14. Validate the Refreshed Development Website​

Test at least:

  • Forum homepage and friendly URLs.
  • Administrator login.
  • Threads, posts and permissions.
  • Avatars and attachments.
  • Custom styles, widgets and add-ons.
  • Search functionality.
  • Cache and background jobs.
  • Cloudflare Access restrictions.
  • Development-only email and payment safeguards.
Confirm that the development website is connecting to mydomain_dev, not mydomain_prod.

Only after these checks should you begin experimenting with upgrades or new features.


Part III — Deploy Tested Changes to Production​

15. Why Full Database Synchronization Is Unsafe​

Once production has launched, the two databases will gradually diverge.

For example:

Production might contain new members, posts, conversations and reactions created while development changes are being tested.

If you replace the production database with the development database, those new records may disappear.

Therefore, release tested features rather than copying the entire development database.

16. Use Git for Custom Code​

Git is useful for recording and reviewing changes to:

  • Custom XenForo add-on source files.
  • JavaScript, CSS and other custom assets.
  • Deployment scripts and infrastructure configuration.
  • Tests and documentation.
Use a private Git repository.

Do not commit:

src/config.php
data/
internal_data/
database dumps
backups
credentials
private keys
Whether additional core files should be excluded depends on how you package XenForo itself. A practical approach is to keep licensed vendor distributions and custom code clearly separated.

Version control allows you to identify which code changes belong to a particular release, but it does not automatically migrate XenForo's database-based configuration.

17. Package Custom XenForo Add-ons​

For custom functionality, prefer writing an add-on rather than modifying XenForo core files directly.

XenForo provides developer tools that export development output and build installable add-on releases.

From the XenForo installation root, a custom add-on can be packaged with:

php cmd.php xf-addon:build-release Vendor/AddOn
Replace Vendor/AddOn with the actual add-on ID.

The resulting release can be installed or upgraded on production through XenForo's supported add-on deployment process.

This is preferable to copying arbitrary files and database tables.

18. Treat Different Changes Differently​

ChangeRecommended production deployment
XenForo core updateTest, back up production, run official upgrade
Third-party add-onTest same version, then perform supported install/upgrade
Custom add-onBuild a release and upgrade production
Custom code or assetsDeploy reviewed version-controlled changes
Templates and phrasesUse supported exports, development output or packaged add-ons
Forum categoriesApply planned changes to production
Permissions and optionsApply documented configuration changes
WidgetsRecreate or deploy through supported custom tooling
Members, threads and messagesPreserve production data
AttachmentsKeep production data; do not replace with test uploads
A key limitation is that XenForo does not provide a universal built-in one-click mechanism to promote every change made in the development Admin Control Panel into production.

For that reason, custom add-ons, migration routines and a written release checklist are especially useful.

19. Production Deployment Procedure​

For each production release, follow this sequence.

A. Prepare the release​

  • Finish implementation in Development.
  • Test under the XenForo version and PHP environment used by Production.
  • Check relevant administrator and member permissions.
  • Verify any required database migrations.
  • Record the release version, files and configuration changes.

B. Back up Production​

Create a fresh database backup and appropriate file backup.

Verify that the backup can be restored and that enough disk space is available.

C. Restrict writes if required​

For upgrades involving schema changes, add-on migrations or replacement of application files, enable an appropriate maintenance window or close the forum temporarily to avoid incompatible writes.

D. Deploy tested changes​

Deploy the same tested package to Production.

Run official XenForo or add-on upgrade steps as required.

Avoid overwriting the production src/config.php, member uploads or other environment-specific data.

E. Validate Production​

Test:

  • Homepage and login.
  • Administrator access.
  • New thread and reply creation.
  • Permission checks.
  • Attachments and images.
  • Search.
  • Email delivery.
  • Scheduled jobs.
  • Error logs and application performance.
Reopen the site only after the release passes the necessary checks.

20. Rollback Planning​

Not every upgrade can be safely rolled back by simply copying old PHP files over new ones.

If an upgrade has modified the database schema, the previous application code may no longer be compatible.

For significant database migrations, the recovery plan may require restoring both the pre-upgrade database and the matching application files from the same recovery point.

Any data written after that recovery point may be lost unless separately reconciled.

Define and test the rollback plan before major upgrades, rather than trying to invent one during an outage.


Part IV — Automation and Operational Recommendations​

21. Automate Carefully​

Once the manual refresh and deployment procedures work reliably, they can be scripted.

A safe Production → Development refresh script should:

  1. Verify the source and target environment names.
  2. Create a development backup.
  3. Obtain a consistent production backup.
  4. Copy files to a staging location.
  5. Import only into the development database.
  6. Restore development-specific configuration.
  7. Confirm mail and external payment actions are disabled.
  8. Validate the application before reopening it.
The script should refuse to run if it detects that the target database is the production database.

For Development → Production deployment, automation should use tested release packages and an approval step. It should not blindly synchronize databases.

22. Monitor Shared VPS Resources​

Running both installations on one VPS saves money, but they still compete for:

  • CPU.
  • RAM.
  • Database connections.
  • Storage.
  • Disk I/O.
  • PHP-FPM workers.
A development task such as rebuilding a large search index can affect production performance.

As production traffic grows, consider placing Development on a separate VPS, using separate PHP-FPM pools and resource limits, or scheduling intensive development operations outside busy periods.

23. Final Checklist​

Before launch:

  • Production and Development have separate document roots.
  • Production and Development have separate databases and database users.
  • Development is protected by identity-based access control.
  • Development mail sending is disabled.
  • Cookies and shared caches are separated.
  • Search indexes and external service credentials are separated.
  • XenForo private directories are protected by Nginx.
  • Both installations have independent backups.
  • The Production → Development refresh process has been tested.
  • The Development → Production release process has been tested.
  • A rollback plan exists for major upgrades.
  • No automatic process can overwrite the production database with development data.

Conclusion​

The most important principle is to separate application releases from live content.

Production remains the authoritative source for members, posts, messages and other operational data.

Development provides a safe environment for testing XenForo upgrades, add-ons, designs and customizations.

Production data may occasionally be copied to Development for testing, but tested changes must be deployed back to Production through controlled releases—not by replacing the production database.

With that distinction in place, both XenForo installations can coexist on the same VPS while supporting a disciplined, predictable development process.
 
Back
Top Bottom