More in-depth information about several topics essential to understanding how to move a WordPress site and what is involved in the process.

Absolute URLs vs. Relative URLs vs. Protocol-relative/agnostic URLs

Absolute URLs vs. Relative URLs vs. vs. Protocol-relative URLs can be a very big pain for many people since WordPress stores URLs in the database such as: internal linking, media files, host/domain name, etc as absolute URLs. Developing with relative URLs can make moving much easier, but at some point there will be something that is saved as an absolute URL which you will either be unaware of or can do nothing about.

  • Absolute URL |
  • Relative URL | /page/ or page/
  • Protocol-relative or agnostic URL | //
  • Also see the WordPress function set_url_scheme
  • There is no “right” or “wrong” method here in terms of absolute vs. relative URLs. This is purely an argument of opinion and and has no bearing on how search engines grade you or how your site is accessed. The important factors to keep in mind here are: WordPress stores URLs as absolute, and that *your site configuration should only resolve to one location* (http/s and www/non-www).

    For each new or existing website, 4 potential sites exist, you should pick only one and setup your webserver configuration to reflect that.

    The first step usually is to decide www or no-www, again, whatever you choose here is largely irrelevant. The next step is to decide SSL or non-SSL, your webserver should not serve both secure and insecure versions of your site, if you’ve gone to the trouble of getting an SSL certificate, to avoid messages about mixed or duplicate content use https only in this scenario and redirect all http traffic → https.

    Ideally, we want people to simply type in our root domain name “” and land in the correct place. This can be done directly with DNS and/or within the VirtualHost configuration (Apache httpd)

    To avoid MITM (man-in-the-middle) attacks where a user hijacks the communication during the process, which is possible for a split second during a redirect see this article about HSTS (HTTP Strict Transport Security).

Use *one* of these to change serialized URL/domain (or other) values in your WordPress database
interconnectit’s SearchReplaceDB tool
wp-cli’s Search-Replace command
Better Search Replace WordPress Plugin

Edit wp-config.php

.htaccess files

.htaccess files, what are they and why do I need them?

Probably the single most misunderstood facet of webserver configuration, .htaccess files are a feature and a part of Apache httpd controlled by the AllowOverride directive and will not work with other popular webservers such as nginx, they have their own mechanisms. .htaccess files are hidden on Linux systems, all files or directories starting with a . are hidden by default, they can be seen using the -a flag for the Linux ls command ls -a. The following “Purpose” and “Use” are taken directly from Apache #httpd live support on Freenode IRC.

.htaccess Purpose: Don’t confuse htaccess with password-protection. The purpose of htaccess is to enable users to configure apache locally for their own directories, when they have no privilege to do so in httpd.conf. Using htaccess slows the server. Also rewriterules and redirects are more complex in htaccess

.htaccess Use: if you have access to httpd.conf, there is no reason to use htaccess. You can get a significant performance boost disabling htaccess altogether with AllowOverride None. Your RewriteRules will be simpler too!

WordPress Assumptions

In an effort to help the majority of unskilled users, WordPress erroneously makes several assumptions which are often false and can lead to puzzling results for people new to Apache httpd and .htaccess files.

  1. You’re using Apache httpd as a webserver, not nginx or something else that isn’t aware of or doesn’t support .htaccess files
  2. You have no access to your main webserver virtualhost config
  3. .htaccess files are enabled per the AllowOverride directive in the main webserver config
  4. FallbackResource is not set/used in your webserver virtualhost config
  5. mod_rewrite is enabledin the main webserver config
  6. Everyone understands what .htaccess is, how it’s used, enabled and controlled

File Permissions

File permissions control who can view, edit, create or delete files in a given location. On Linux and Unix-like systems WordPress needs directories set to 755 and files set to 644 at a bare minimum. Ideally, with proper webserver and filesystem configuration: 750 and 640.

File permissions are controlled using the Linux chmod command (Change Mode), it controls the permissions set on a file or directory based on 3 (technically 4) octals or numbers which represent:

From ‘man chmod’
“A numeric mode is from one to four octal digits (0-7), derived by adding up the bits with values 4, 2, and 1. Any omitted digits are assumed to be leading zeros. The first digit selects the set user ID (4) and set group ID (2) and sticky (1) attributes.”

1st Octal | Owner (u)2nd Octal | Group (g)3rd Octal | Other (o)
7 → -rwx5 → -r-x5 → -r-x
6 → -rw-4 → -r--4 → -r--

Each octal or number has 8 possible values which can be assigned to it (7,6,5,4,3,2,1,0), each value has one or more of the following permissions:

4 → r (read)2 → w (write)1 → x (execute)0 → – (none)

Full table:

OctalOctal ValuesSymbolic NotationNumeric NotationEnglish Meaning
00----------0000(no permissions)
32 + 1--wx-wx-wx0333(write / execute)
54 + 1-r-xr-xr-x0555(read / execute)
64 + 2-rw-rw-rw-0666(read / write)
74 + 2 + 1-rwxrwxrwx0777(read / write / execute)

File Ownership

File ownership is controlled using the Linux chown command (Change Owner), it controls the ownership and group set on a file or directory.

A typical WordPress DocumentRoot with files and directories owned by user/group “webdev” and PHP-FPM enabled in the Apache httpd VirtualHost configuration.

PHP Handlers

One of the biggest misunderstandings about WordPress is that it requires write access for updates, installing themes or plugins and uploads. Write access is not only determined by file/directory permissions but also file/directory ownership. It matters what user/group owns the WordPress DocumentRoot and how the PHP is being processed and interpreted by the webserver if writes are to be successful. This is where the PHP Handler comes in.

Currently the standard is either PHP-FPM (PHP Fast Process Manager), mod_php DSO (Dynamic Shared Object) or FastCGI. Others such as suPHP or mod_ruid2 are depreciated and no longer developed.

While these will still technically continue to work for the near future, neither have been updated in over 2 years and are not currently actively developed. This certainly presents unnecessary security risks as the underlying webservers and systems are in constant development. If you’re currently using either of these they should be phased out and no longer used in favor of one of the options below.

Currently supported and/or actively developed
  • PHP-FPM (PHP Fast Process Manager)
  • FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features (mostly) useful for heavy-loaded sites.

  • suEXEC
  • The suEXEC feature provides users of the Apache httpd server the ability to run CGI and SSI programs under user IDs different from the user ID of the calling webserver. Normally, when a CGI or SSI program executes, it runs as the same user who is running the webserver.

  • FastCGI
  • FastCGI offers the security benefits of suPHP by executing files as the owner of the file. Unlike suPHP however, it keeps an open session for the file when the processing is done resulting in significant memory use, but also allowing for the use of OPCode caching such as APC or memcached. If you do have the memory for it however FastCGI is arguably the fastest handler even in comparison with mod_php.

  • mod_php DSO (Dynamic Shared Object)
  • DSO (Dynamic Shared Object) or mod_php is the oldest and, some would say, the fastest PHP handler available. It essentially makes PHP a part of Apache httpd by having the Apache httpd server interpret the PHP code itself through use of a module known as mod_php. This is the default handler typically installed when installing a webserver package on your server.

Depreciated, discontinued / abandoned methods
  • suPHP
  • suPHP (Single user PHP) also runs PHP as a CGI module instead of an Apache httpd module. It differs from CGI in that PHP scripts that are called from the web browser will run on the server under the user that owns them, as opposed to ‘nobody’ or ‘apache’.

  • mod_ruid2
  • mod_ruid2 is an suEXEC module for Apache httpd which takes advantage of POSIX.1e capabilities to increase performance.

You may also try adding this to your wp-config.php file, like the example below, just above the line that reads: “/* That’s all, stop editing! Happy blogging. */”

define('FS_METHOD', 'direct');
/* That’s all, stop editing! Happy blogging. */

FS_METHOD forces the filesystem method. It should only be “direct“, “ssh2“, “ftpext“, or “ftpsockets“. Generally, you should only change this if you are experiencing update problems. If you change it and if it doesn’t help, change it back / remove it. Under most circumstances, setting it to “ftpsockets” will work if the automatically chosen method does not.

  • (Primary Preference) “direct” forces it to use Direct File I/O requests from within PHP, this is fraught with opening up security issues on poorly configured hosts, This is chosen automatically when appropriate.
  • (Secondary Preference) “ssh2” is to force the usage of the SSH PHP Extension if installed.
  • (3rd Preference) “ftpext” is to force the usage of the FTP PHP Extension for FTP Access, and finally..
  • (4th Preference) “ftpsockets” utilises the PHP Sockets Class for FTP Access.

Increase PHP file upload limits

Edit this file: /etc/php.ini

To set your upload limit to 18MB, find and edit these lines:

upload_max_filesize = 18M
post_max_size = 36M

Restart your webserver:
C6, httpd: service httpd restart
C6, nginx: service nginx restart

C7, httpd: systemctl restart httpd.service
C7, nginx: systemctl restart nginx.service

Serialized Arrays
WordPress stores internal links and media links as absolute URLs in the database. When moving WordPress, changing these values by hand is not advised and could lead to your database being corrupted. Use a method described below to change the serialized values safely.

Use *one* of these to change serialized URL/domain (or other) values in your WordPress database
interconnectit’s SearchReplaceDB tool
wp-cli’s Search-Replace command
Better Search Replace WordPress Plugin

DO NOT USE sed, this will break your site and corrupt the database guaranteed.

A example of a normal PHP array and a serialized PHP array from Andrew Nacin’s site

Let’s examine what’s going on:
Normal PHP array: array( 'apple', 'banana', 'orange' );
Serialized PHP array: a:3:{i:0;s:5:"apple";i:1;s:6:"banana";i:2;s:6:"orange";}

33 elements in array
{open array
0integer value = 0
;break, next element
55 chars in string
}close array

Additional Help & Resources

If you have more questions or need additional help, try connecting to #wordpress live support on Freenode IRC or follow these steps to join the official WordPress Slack live support.

Manage multiple (10’s or 100’s) of WordPress installs from a single location using one of these applications

Last Modified: 19 Aug, 2017 at 18:58:12