How to Migrate From Bitrix CMS to WordPress: A 6-Step Guide
How to Migrate From Bitrix CMS to WordPress: A 6-Step Guide
Migrating enterprise web architecture from a proprietary framework like Bitrix CMS to WordPress requires a meticulous engineering strategy. This transition is not merely a visual redesign or a routine file transfer; it is a fundamental shift in database schemas, routing logic, execution lifecycles, and security paradigms. A poorly executed migration frequently results in catastrophic data loss, broken database relations, severe SEO ranking degradation, and wide-open security vectors. To achieve a seamless transition without service disruption, engineers must systematically execute a rigorous six-step migration framework.
Problem Statement & Impact
The core technical challenge in moving from Bitrix CMS to WordPress stems from fundamentally divergent architectural designs. Bitrix relies heavily on a proprietary relational database schema, custom ORM layers, and a file structure that tightly couples business logic with proprietary modules. Conversely, WordPress utilizes a normalized MySQL/MariaDB database structure centered around posts, postmeta, terms, and options tables, governed by an extensible hooks and filters system.
When administrators attempt naive data transfers using generic CSV imports or ad-hoc database queries, several systemic failures occur:
Chat with an engineer on WhatsApp within 15 minutes.
- Orphaned Metadata: Custom fields in Bitrix lose their context when mapped incorrectly to the WordPress
wp_postmetatable, resulting in missing product attributes, disconnected categories, and unreferenced user roles. - Broken URI Routing: Bitrix utilizes complex, customizable URL rewrite rules managed via its internal routing engine. Without explicit mapping, legacy URLs generate 404 errors, obliterating accumulated link equity and organic search engine rankings.
- Asset Desynchronization: Media attachments stored within Bitrix’s proprietary file-hash directory structure fail to align with the standard WordPress
/wp-content/uploads/YYYY/MM/structure, causing broken images across thousands of pages. - Security Regression: Exposure of temporary staging environments, unhashed legacy passwords during user migration, and improperly configured server file permissions leave the nascent WordPress instance vulnerable to automated exploit scripts.
The business consequences of these technical failures include immediate drops in organic revenue, severe brand erosion due to degraded user experience, and prolonged downtime during business hours. Mitigating these risks demands strict adherence to programmatic extraction, transformation, and loading (ETL) pipelines.
Root Cause Analysis & Architecture
Understanding the underlying data mechanics is mandatory before executing database transformations. Bitrix CMS organizes content into Information Blocks (IBlocks), which act as flexible containers for catalogs, news, and dynamic pages. Each IBlock contains sections (categories) and elements (posts or products), accompanied by high-dimensional property tables (b_iblock_element_property).
WordPress stores equivalent data across multiple normalized tables:
wp_posts: Stores core post types, pages, attachments, and custom post types.wp_postmeta: Stores key-value pairs for post metadata (analogous to Bitrix IBlock properties).wp_terms,wp_term_taxonomy,wp_term_relationships: Manages hierarchical and flat taxonomies (categories, tags, custom taxonomies).
During migration, the primary architectural obstacle is translating the hierarchical IBlock structure into the flat, post-type-driven architecture of WordPress while maintaining relational integrity. Furthermore, user authentication hashes differ between Bitrix and WordPress. Bitrix stores passwords using salted MD5 or phpass variations, whereas WordPress utilizes portable PHP password hashing (phpass via wp_hash_password()). Direct migration of raw password hashes without an intermediate authentication adapter forces users to perform password resets upon launch.
Step 1: Audit and Backup Your Existing Bitrix CMS Site
Before initiating any data extraction, perform an exhaustive architectural audit of the source Bitrix installation. Enumerate all active modules, custom components, database table sizes, and file directory volumes.
Execute the following shell commands on your Bitrix server to generate a complete backup archive and database dump:
# Create a secure backup directory
mkdir -p /var/backups/bitrix_migration/$(date +%F)
cd /var/backups/bitrix_migration/$(date +%F)
# Export the MySQL database associated with Bitrix
mysqldump -u bitrix_user -p --single-transaction --routines --triggers bitrix_db > bitrix_database_dump.sql
# Compress the entire Bitrix web root (excluding cache directories to save space)
tar --exclude='./bitrix/backup' \
--exclude='./bitrix/cache' \
--exclude='./bitrix/managed_cache' \
--exclude='./bitrix/stack_cache' \
-czvf bitrix_web_root.tar.gz /var/www/html/bitrix/
# Verify archive integrity
sha256sum bitrix_database_dump.sql bitrix_web_root.tar.gz > checksums.txt
cat checksums.txt
Audit your database for orphaned records and bloated tables. Run the following SQL queries directly on the Bitrix database to identify high-volume tables that may complicate extraction:
SELECT
table_name AS "Table",
round(((data_length + index_length) / 1024 / 1024), 2) AS "Size (MB)"
FROM information_schema.TABLES
WHERE table_schema = "bitrix_db"
ORDER BY (data_length + index_length) DESC;
Step 2: Set Up Your New WordPress Environment
Provision a production-grade LEMP (Linux, Nginx, MySQL, PHP) or LAMP stack configured for optimal WordPress performance and security. Avoid shared hosting environments that restrict server configuration access.
Configure your Nginx virtual host with hardened security headers and clean permalink support:
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/html/wordpress;
index index.php index.html;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
security_headers; # Custom security header configuration
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_intercept_errors on;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {
expires max;
log_not_found off;
}
# Deny access to sensitive files
location ~* /(wp-config.php|xmlrpc.php|license.txt|readme.html) {
deny all;
}
}
Install the latest WordPress core via WP-CLI and enforce baseline security hardening:
wp core download --path=/var/www/html/wordpress --locale=en_US --allow-root
wp config create --path=/var/www/html/wordpress \
--dbname=wordpress_db \
--dbuser=wordpress_user \
--dbpass='SecureComplexPassword_2024!' \
--dbhost=localhost \
--dbprefix=wp_sec_ \
--allow-root
wp core install --path=/var/www/html/wordpress \
--url="https://example.com" \
--title="Enterprise Migration" \
--admin_user="sysadmin_secure" \
--admin_password="EnterpriseAdminPassword#99" \
--admin_email="[email protected]" \
--allow-root
Step 3: Export Data from Bitrix CMS
Because Bitrix structure is complex, extraction requires targeted SQL queries to pull content out of IBlocks and reformat it into an intermediary structured JSON or CSV format that WordPress importers can ingest.
Execute the following SQL query on the Bitrix database to extract blog posts or catalog elements along with their URLs, titles, text bodies, and creation dates:
SELECT
e.ID AS bitrix_id,
e.NAME AS post_title,
e.CODE AS post_slug,
p.DETAIL_TEXT AS post_content,
e.DATE_CREATE AS post_date,
e.ACTIVE AS post_status
FROM b_iblock_element e
LEFT JOIN b_iblock_element_prop_s* p ON e.ID = p.IBLOCK_ELEMENT_ID
WHERE e.IBLOCK_ID = 5; -- Replace 5 with your specific Bitrix IBlock ID
Export the resulting dataset to a CSV file:
mysql -u bitrix_user -p bitrix_db -e "
SELECT
e.ID, e.NAME, e.CODE, p.DETAIL_TEXT, e.DATE_CREATE
FROM b_iblock_element e
LEFT JOIN b_iblock_element_prop_s1 p ON e.ID = p.IBLOCK_ELEMENT_ID
WHERE e.IBLOCK_ID = 5
INTO OUTFILE '/var/lib/mysql-files/bitrix_export_iblock_5.csv'
FIELDS TERMINATED BY ',' ENCLOSED BY '\"'
LINES TERMINATED BY '\n';
"
Ensure that all media files stored in Bitrix (`/upload/iblock/`) are rsynced to a temporary staging directory on your new WordPress server:
rsync -avz -e "ssh -i /root/.ssh/id_rsa" [email protected]:/var/www/html/bitrix/upload/ /var/www/html/wordpress/wp-content/uploads/migration_temp/
Step 4: Import Content into WordPress
With data extracted into structured CSV files, write a custom PHP script utilizing WordPress core functions to programmatically insert the records into the database. This approach prevents data corruption compared to GUI importers.
Create an import script named import_bitrix.php within your WordPress root:
<?php
define('WP_USE_THEMES', false);
require_once('./wp-load.php');
if (!current_user_can('manage_options')) {
wp_die('Unauthorized execution.');
}
$csv_file = '/var/www/html/wordpress/wp-content/uploads/migration_temp/bitrix_export_iblock_5.csv';
if (($handle = fopen($csv_file, 'r')) !== FALSE) {
// Skip header if necessary
// fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",", '"')) !== FALSE) {
$bitrix_id = $data[0];
$post_title = sanitize_text_field($data[1]);
$post_slug = sanitize_title($data[2]);
$post_content = wp_kses_post($data[3]);
$post_date = $data[4];
$post_data = array(
'post_title' => $post_title,
'post_name' => $post_slug,
'post_content' => $post_content,
'post_status' => 'publish',
'post_type' => 'post',
'post_date' => $post_date,
'post_author' => 1
);
$post_id = wp_insert_post($post_data);
if (!is_wp_error($post_id)) {
// Store mapping for redirection later
update_post_meta($post_id, '_bitrix_original_id', $bitrix_id);
}
}
fclose($handle);
echo "Import completed successfully.";
}
else {
echo "Failed to open CSV file.";
}
?>
Execute the import script via WP-CLI to bypass HTTP timeout restrictions:
wp eval-file import_bitrix.php --path=/var/www/html/wordpress --allow-root
Step 5: Implement 301 Redirects and Preserve SEO
Because Bitrix URL structures (e.g., /news/category/element-name.html) rarely match WordPress slugs (e.g., /element-name/), failing to configure explicit 301 redirects destroys your search engine optimization authority.
Query your imported WordPress database to map old Bitrix paths to new WordPress slugs:
SELECT
pm.meta_value AS bitrix_id,
p.post_name AS wp_slug
FROM wp_sec_postmeta pm
JOIN wp_sec_posts p ON pm.post_id = p.ID
WHERE pm.meta_key = '_bitrix_original_id';
Generate Nginx rewrite rules based on this mapping and inject them directly into your Nginx server block configuration. For programmatic management, utilize an Nginx map directive in nginx.conf:
map $uri $new_uri {
include /etc/nginx/conf.d/bitrix_redirects.map;
}
server {
# ... previous server configuration ...
if ($new_uri) {
return 301 $new_uri;
}
}
Format your bitrix_redirects.map file with precise URI pairings:
/news/item_1024.html /enterprise-software-launch/;
/catalog/laptops/model_a.html /product/model-a/;
/about/contacts/ /contact-us/;
Test your redirect rules using curl to verify that HTTP status codes return precisely 301 Moved Permanently:
curl -I https://example.com/news/item_1024.html
# Expected Output: HTTP/2 301
# Location: https://example.com/enterprise-software-launch/
Step 6: Rigorous Testing and Launch
Before updating DNS records to point your production domain to the new WordPress server, perform comprehensive verification.
- Database Integrity Check: Verify that all post meta fields, term relationships, and user assignments populated correctly without truncated characters or encoding mismatches (ensure UTF8mb4 compliance).
- Broken Link Audit: Run an internal link crawler across your staging domain to identify missing assets, dead internal links, or misconfigured permalink structures.
- Form and API Validation: Test all interactive endpoints, contact forms, caching layers (Redis/Memcached), and CDN integrations.
- Security Penetration Scan: Verify that sensitive files (
wp-config.php,xmlrpc.php, database backups) are inaccessible via public HTTP requests.
Update your DNS A records to point to the new IP address, and monitor server access logs in real-time for unexpected client errors:
tail -f /var/log/nginx/access.log | grep "HTTP/1.1\" 5"
Production Hardening & Edge Cases
Post-migration environments frequently suffer from caching conflicts and performance bottlenecks. When transitioning high-traffic sites from Bitrix to WordPress, configure object caching via Redis to eliminate redundant database calls generated by complex plugins.
Add the following directives to your wp-config.php to enforce strict security boundaries and memory allocations:
define('DISALLOW_FILE_EDIT', true);
define('FORCE_SSL_ADMIN', true);
define('WP_AUTO_UPDATE_CORE', 'minor');
define('FS_METHOD', 'direct');
define('WP_MEMORY_LIMIT', '512M');
define('WP_MAX_MEMORY_LIMIT', '1024M');
Restrict file system permissions on your WordPress root directory to prevent unauthorized code injection:
find /var/www/html/wordpress/ -type d -exec chmod 755 {} \;
find /var/www/html/wordpress/ -type f -exec chmod 644 {} \;
chmod 440 /var/www/html/wordpress/wp-config.php
chown -R www-data:www-data /var/www/html/wordpress/
Diagnostic Verification & Checklist
Use the following verification matrix to confirm that your migration meets enterprise-grade security and functionality standards prior to sign-off.
| Verification Metric | Target State | Diagnostic Command / Tool |
|---|---|---|
| Database Prefix | Non-default (e.g., wp_sec_) |
wp db tables --all-tables --allow-root |
| File Permissions | Root: 755 / Files: 644 / Config: 440 | name /var/www/html/wordpress/ -perm 777 (Must return empty) |
| SSL/TLS Configuration | A+ Rating, TLS 1.2/1.3 Only | Qualys SSL Labs API / openssl s_client -connect example.com:443 |
| Redirect Status | 301 Permanent on all legacy URIs | curl -I https://example.com/legacy-path |
| XML-RPC Protocol | Disabled or Blocked | curl -X POST https://example.com/xmlrpc.php (Expect 403/404) |
Continuous monitoring of server error logs, intrusion detection systems, and database transaction throughput ensures that your newly migrated WordPress infrastructure maintains peak operational integrity and robust security posture.
Is Your Website Fast & Secure?
Run an instant scan for security vulnerabilities, bloated plugins, and TTFB latency.
Need Help Securing or Speeding Up Your Site?
Get 24/7 proactive security WAF, daily cloud backups, and sub-second speed optimization from ₹3,470/mo.