Tag Archives: wordpress

Set up WordPress on CentOS

The purpose of this post is to document the steps to set up WordPress on a server.

The server operating system is going to be CentOS which currently is my preferred server operating system.

The final objective is to have a WordPress website accessible via wordpress.hazrulnizam.com.

Perform operating system installation

First of all, the latest version of CentOS, which is 6.4, is installed on the server and the server is given the hostname server.hazrulnizam.com.  A minimal install is chosen to prevent unwanted programs to be installed, which can both be a security risk and a waste of disk space.

A non-root user is then created.

[root@server ~]# useradd hnizam
[root@server ~]# passwd hnizam
Changing password for user hnizam.
New password:<type password here>
Retype new password:<re-type password here>
passwd: all authentication tokens updated successfully.

This user is then given sudo permissions.

[root@server ~]# vi /etc/sudoers
## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##      user    MACHINE=COMMANDS
## The COMMANDS section may have other options added to it.
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL
hnizam  ALL=(ALL)       NOPASSWD: ALL

This user is going to be used for all subsequent commands, to limit exposure on the root account.

The OS is then updated to the latest version.

[hnizam@server ~]$ sudo yum check-update

[hnizam@server ~]$ sudo yum upgrade

[hnizam@server ~]$ sudo shutdown -ry now

Check WordPress requirements

Now that the operating system is properly set up, it is time to begin the process of installing WordPress.  First, the requirements for installing WordPress should be reviewed.  At the time of writing, the current version of WordPress is 3.7.1 and according to the WordPress requirements page, the requirements for installing WordPress are:

  • PHP version 5.2.4 or greater
  • MySQL version 5.0 or greater
  • Web server capable of supporting the above (Apache or Nginx is recommended)

To enable pretty permalinks, the Apache module mod_rewrite is needed.

Apache is being chosen as the web server for this particular case as it is one of the earliest web servers and also one of the most used web server software.

Install web server (Apache)

Install the Apache software

The package group feature of the yum package manager is used to install the Apache web server software.

[hnizam@server ~]$ sudo yum grouplist | grep -i web
   Web Server
   Web Servlet Engine
   Web-Based Enterprise Management
[hnizam@server ~]$ sudo yum groupinstall "Web Server"

The Apache web server is installed as the httpd service.  The chkconfig command is used to enable the httpd service at server boot-up.

[hnizam@server ~]$ sudo chkconfig httpd --list
httpd           0:off   1:off   2:off   3:off   4:off   5:off   6:off
[hnizam@server ~]$ sudo chkconfig httpd on
[hnizam@server ~]$ sudo chkconfig httpd --list
httpd           0:off   1:off   2:on    3:on    4:on    5:on    6:off

Next, the Apache web server is started, and the ports used by the web server (port 80 for http and port 443 for https) is opened at the firewall to enable the web server to be accessed by the public.

[hnizam@server ~]$ sudo service httpd start
Starting httpd:                                            [  OK  ]
[hnizam@server ~]$ sudo iptables -L -vn
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 1930  156K ACCEPT     all  --  *      *             state RELATED,ESTABLISHED
    3   236 ACCEPT     icmp --  *      *  
    0     0 ACCEPT     all  --  lo     *  
    1    60 ACCEPT     tcp  --  *      *             state NEW tcp dpt:22
   98 26516 REJECT     all  --  *      *             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 1317 packets, 168K bytes)
 pkts bytes target     prot opt in     out     source               destination
[hnizam@server ~]$ sudo iptables -I INPUT 5 -m state --state NEW -p tcp --dport 80 -j ACCEPT
[hnizam@server ~]$ sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 443 -j ACCEPT
[hnizam@server ~]$ sudo iptables -L -vn
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
 2277  186K ACCEPT     all  --  *      *             state RELATED,ESTABLISHED
    3   236 ACCEPT     icmp --  *      *  
    0     0 ACCEPT     all  --  lo     *  
    1    60 ACCEPT     tcp  --  *      *             state NEW tcp dpt:22
    0     0 ACCEPT     tcp  --  *      *             state NEW tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *             state NEW tcp dpt:443
  108 29500 REJECT     all  --  *      *             reject-with icmp-host-prohibited

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 REJECT     all  --  *      *             reject-with icmp-host-prohibited

Chain OUTPUT (policy ACCEPT 5 packets, 920 bytes)
 pkts bytes target     prot opt in     out     source               destination
[hnizam@server ~]$ sudo service iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:[  OK  ]

Post-installation checks

At this point, the URLs http://server.hazrulnizam.com and https://server.hazrulnizam.com should be accessible, and the default CentOS Apache welcome page is shown when these URLs are opened in a browser.

Set up WordPress - CentOS Apache http welcome page

For the https page, the browser will show a certificate error, because the SSL certificate used by the default Apache installation is a self-signed certificate based on the hostname of the system.

Set up WordPress - Certificate error

The certificate error should be ignored as it is the expected behavior.  To make SSL work without the browser showing a certificate error will require acquiring a certificate from a certificate authority like VeriSign or Comodo, which is outside the scope of this post.  A welcome page similar to the one from the http page is shown after the certificate error is ignored:

Set up WordPress - CentOS Apache https welcome page

The details of the self-signed certificate is shown when the padlock with the red cross is clicked and then ‘Certificate information’ is clicked.  Notice that the ‘Issued to:’ and ‘Issued by:’ fields are the same, which confirms that it is a self-signed certificate.

Set up WordPress - Self-signed certificate details

Install database server (MySQL)

Now that the web server has been successfully installed, it is time to install the database server.

Install the MySQL software

The method used to install MySQL is the same as the method used to install Apache, which is via yum.

[hnizam@server ~]$ sudo yum grouplist | grep -i mysql
   MySQL Database client
   MySQL Database server
[hnizam@server ~]$ sudo yum groupinstall "MySQL Database server"

The MySQL database server is installed as the mysqld service.  The chkconfig command is used to enable the mysqld service at server boot-up.

[hnizam@server ~]$ sudo chkconfig mysqld --list
mysqld          0:off   1:off   2:off   3:off   4:off   5:off   6:off
[hnizam@server ~]$ sudo chkconfig mysqld on
[hnizam@server ~]$ sudo chkconfig mysqld --list
mysqld          0:off   1:off   2:on    3:on    4:on    5:on    6:off

Next, the mysqld service is started for the first time.

[hnizam@server ~]$ sudo service mysqld start
Initializing MySQL database:  Installing MySQL system tables...
Filling help tables...

To start mysqld at boot time you have to copy
support-files/mysql.server to the right place for your system

To do so, start the server, then issue the following commands:

/usr/bin/mysqladmin -u root password 'new-password'
/usr/bin/mysqladmin -u root -h server.hazrulnizam.com password 'new-password'

Alternatively you can run:

which will also give you the option of removing the test
databases and anonymous user created by default.  This is
strongly recommended for production servers.

See the manual for more instructions.

You can start the MySQL daemon with:
cd /usr ; /usr/bin/mysqld_safe &

You can test the MySQL daemon with mysql-test-run.pl
cd /usr/mysql-test ; perl mysql-test-run.pl

Please report any problems with the /usr/bin/mysqlbug script!

                                                           [  OK  ]
Starting mysqld:                                           [  OK  ]

Post-installation tasks

Now that the MySQL database server is installed and running, it is time to run the secure installation command as per advised by the MySQL first-time-start script.  The command offers to change the MySQL root password, remove anonymous user access to the MySQL database, and several other changes to help secure the database.

[hnizam@server ~]$ sudo /usr/bin/mysql_secure_installation


In order to log into MySQL to secure it, we'll need the current
password for the root user.  If you've just installed MySQL, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): <Enter>
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MySQL
root user without the proper authorisation.

Set root password? [Y/n] Y
New password: mysqlrootpassword
Re-enter new password: mysqlrootpassword
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MySQL installation has an anonymous user, allowing anyone
to log into MySQL without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] Y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] Y
 ... Success!

By default, MySQL comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] Y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] Y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MySQL
installation should now be secure.

Thanks for using MySQL!

Install PHP

The next step is to install the PHP interpreter.

Install the PHP interpreter software.

Same as previously, the yum package manager is used to perform the installation.

[hnizam@server ~]$ sudo yum grouplist | grep -i php
   PHP Support
[hnizam@server ~]$ sudo yum groupinstall "PHP Support"

To be able to set up WordPress properly, the PHP-MySQL extension must also be installed.

[hnizam@server ~]$ sudo yum install php-mysql

Test PHP installation

To test whether the PHP interpreter is working correctly, first the web server needs to be restarted.

[hnizam@server ~]$ sudo service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]

Next, a test file containing the phpinfo() function is created in the web server root directory.

[hnizam@server ~]$ sudo vi /var/www/html/test.php

Now when the browser is set to http://server.hazrulnizam.com/test.php or https://server.hazrulnizam.com/test.php, a page with a lot of details about the system is shown similar to the screenshot below.

Set up WordPress - PHP info page

This indicates that the PHP installation is successful and that the PHP interpreter is working correctly with the web server.

The test file is then deleted.

[hnizam@server ~]$ sudo rm /var/www/html/test.php

Install and set up WordPress

With all the prerequisites now installed, it is time to install and set up WordPress itself, using the installation guide from the WordPress.org website.

Create the database and database user

A new database is created inside the installed MySQL database server to be used by WordPress and a new database user that owns the privileges to the new database is also created.

[hnizam@server ~]$ mysql -u root -p
Enter password: mysqlrootpassword
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.1.69 Source distribution

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database wordpressdb;
Query OK, 1 row affected (0.00 sec)

mysql> grant all privileges on wordpressdb.* to "wordpressdbuser"@"localhost" identified by "wordpressdbpassword";
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> exit
[hnizam@server ~]$

The above commands create a database named wordpressdb and a user named wordpressdbuser whose password is wordpressdbpassword.  Any other names can be used for the database, username, and password if desired.

Download and extract the WordPress software

The latest version of the WordPress software is downloaded to the server using wget and then extracted using the tar command.

[hnizam@server ~]$ sudo yum install wget
[hnizam@server ~]$ wget http://wordpress.org/latest.tar.gz
[hnizam@server ~]$ tar -xzvf latest.tar.gz

The above commands result in an extracted folder named wordpress which contains the WordPress software.

[hnizam@server ~]$ ls -l
total 4492
-rw-rw-r--. 1 hnizam hnizam 4594818 Oct 30 04:08 latest.tar.gz
drwxr-xr-x. 5 hnizam hnizam    4096 Oct 30 04:08 wordpress

Copy extracted WordPress folder into www folder

The extracted folder is then copied into /var/www/ folder to ensure that the SELinux contexts are properly set for Apache web server.  The WordPress site will be served by Apache from this location.  Moving the folder using the mv command will preserve the SELinux contexts from the original location which is not what is desired.  Therefore, the folder is copied using the cp command.

[hnizam@server ~]$ sudo cp -R wordpress /var/www/

Next, the owner of the WordPress folder is changed to the Apache user to enable the Apache web server to read and write to that folder.

[hnizam@server ~]$ sudo chown -R apache:apache /var/www/wordpress

Set up Apache virtual host

The Apache web server needs to be configured to make it use the directory above when a browser asks for http://wordpress.hazrulnizam.com or https://wordpress.hazrulnizam.com.

First, the httpd.conf file is modified.

[hnizam@server ~]$ sudo vi /etc/httpd/conf/httpd.conf
### Section 3: Virtual Hosts
# VirtualHost: If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
# Please see the documentation at
# <URL:http://httpd.apache.org/docs/2.2/vhosts/>
# for further details before you try to setup virtual hosts.
# You may use the command line option '-S' to verify your virtual host
# configuration.

# Use name-based virtual hosting.
#NameVirtualHost *:80
NameVirtualHost *:80
NameVirtualHost *:443
# NOTE: NameVirtualHost cannot be used without a port specifier
# (e.g. :80) if mod_ssl is being used, due to the nature of the
# SSL protocol.

# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for requests without a known
# server name.
#<VirtualHost *:80>
#    ServerAdmin webmaster@dummy-host.example.com
#    DocumentRoot /www/docs/dummy-host.example.com
#    ServerName dummy-host.example.com
#    ErrorLog logs/dummy-host.example.com-error_log
#    CustomLog logs/dummy-host.example.com-access_log common

<VirtualHost _default_:80>
    DocumentRoot "/var/www/html"

<VirtualHost *:80>
    DocumentRoot "/var/www/wordpress"
    ServerName wordpress.hazrulnizam.com
    <Directory "/var/www/wordpress">
        Options FollowSymLinks
        AllowOverride All
    ErrorLog logs/wordpress.hazrulnizam.com-error_log
    CustomLog logs/wordpress.hazrulnizam.com-access_log combined

Next, the SSL key and certificate for the https site are generated.

[hnizam@server ~]$ openssl genrsa -out wordpress.key -des3 2048
Generating RSA private key, 2048 bit long modulus
e is 65537 (0x10001)
Enter pass phrase for wordpress.key: passphrase
Verifying - Enter pass phrase for wordpress.key: passphrase
[hnizam@server ~]$ openssl req -new -key wordpress.key -out wordpress.csr
Enter pass phrase for wordpress.key: passphrase
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
Country Name (2 letter code) [XX]:MY
State or Province Name (full name) []:Kuala Lumpur
Locality Name (eg, city) [Default City]:Kuala Lumpur
Organization Name (eg, company) [Default Company Ltd]:hazrulnizam.com
Organizational Unit Name (eg, section) []:wordpress
Common Name (eg, your name or your server's hostname) []:wordpress.hazrulnizam.com
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[hnizam@server ~]$ openssl x509 -req -days 365 -in wordpress.csr -signkey wordpress.key -out wordpress.crt
Signature ok
subject=/C=MY/ST=Kuala Lumpur/L=Kuala Lumpur/O=hazrulnizam.com/OU=wordpress/CN=wordpress.hazrulnizam.com
Getting Private key
Enter pass phrase for wordpress.key: passphrase

The generated key and certificate are then copied to their proper destinations to apply correct SELinux contexts on them.  The read permissions are modified so that only the root user has access to them.

[hnizam@server ~]$ sudo cp wordpress.key /etc/pki/tls/private/
[hnizam@server ~]$ sudo chmod 600 /etc/pki//tls/private/wordpress.key
[hnizam@server ~]$ sudo cp wordpress.crt /etc/pki/tls/certs/
[hnizam@server ~]$ sudo chmod 600 /etc/pki//tls/certs/wordpress.crt
[hnizam@server ~]$ rm wordpress.crt wordpress.csr wordpress.key

Next, the virtual host configuration is added to the Apache SSL configuration file.

[hnizam@server ~]$ sudo vi /etc/httpd/conf.d/ssl.conf
<VirtualHost *:443>
    DocumentRoot "/var/www/wordpress"
    ServerName wordpress.hazrulnizam.com:443
    <Directory "var/www/wordpress">
        Options FollowSymLinks
        AllowOverride All
    ErrorLog logs/wordpress.hazrulnizam.com-ssl_error_log
    CustomLog logs/wordpress.hazrulnizam.comssl_access_log combined
    LogLevel warn
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCertificateFile /etc/pki/tls/certs/wordpress.crt
    SSLCertificateKeyFile /etc/pki/tls/private/wordpress.key

The Apache web server is then restarted to load the new configurations.

[hnizam@server ~]$ sudo service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd: Apache/2.2.15 mod_ssl/2.2.15 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide the pass phrases.

Server wordpress.hazrulnizam.com:443 (RSA)
Enter pass phrase:passphrase

OK: Pass Phrase Dialog successful.
                                                           [  OK  ]

Notice that there is a prompt for the passphrase of the private key when Apache is starting up.  This passphrase is going to be asked every time the Apache web server is started, including during server restarts.  This can be avoided by using a private key that is not protected by a pass phrase (do not use the -des3 flag when creating the key using the openssl genrsa command).  However, care must be taken to protect the key from being accessed by anyone else.

At this point, provided that the DNS entry for wordpress.hazrulnizam.com has been correctly added, pointing a browser to http://wordpress.hazrulnizam.com will show the following page:

Set up WordPress - WordPress error page

This shows that Apache is correctly reading the WordPress files and together with the PHP interpreter is serving out dynamic PHP pages to the browser.

Enable WordPress to send emails

Before proceeding with the final step of WordPress installation, SELinux needs to be configured to allow WordPress to send emails out from the system.  There are a few events that triggers WordPress to send notification emails such as when a new comment has been posted to a post.

The setsebool command is used to change the corresponding SELinux boolean to allow Apache, and in turn WordPress, to send out emails.

[hnizam@server ~]$ sudo getsebool httpd_can_sendmail
httpd_can_sendmail --> off
[hnizam@server ~]$ sudo setsebool httpd_can_sendmail on
[hnizam@server ~]$ sudo getsebool httpd_can_sendmail
httpd_can_sendmail --> on

Install and set up WordPress via the browser

The final step of installing WordPress involves creating a WordPress configuration file.  This configuration file can either be manually created at the server, or can be created by WordPress itself via the browser.  This post will continue via the browser method as all the prerequisites to make it successful has been performed above.

The URL http://wordpress.hazrulnizam.com is entered in the browser address bar.

Set up WordPress - WordPress error page

The ‘Create a Configuration File’ button is then clicked.

Set up WordPress - Create configuration file page

The next page shows that several information is needed to complete the installation such as database name, database username, database password, and database host.  The corresponding information are the one used in the ‘Create the database and database user’ section above.

The ‘Let’s go’ button is then clicked.

Set up WordPress - Setup Configuration page

The Database Name is changed to wordpressdb, while User Name is changed to wordpressdbuser and Password is changed to wordpressdbpassword.  The Database Host and Table Prefix fields are left at the default values.

The page is then submitted.

Set up WordPress - Configuration success

WordPress is now communicating correctly with the database.  The ‘Run the install’ button is then clicked.

Set up WordPress - Install page

On this page, the Site Title, Username, Password and email address will have to be provided.  The Site Title will be the title shown when the WordPress site is accessed once it is installed.  The Username and Password are different than the database username and password.  This will be the username that will be used to log in to the WordPress administration pages.

Once all the required fields are filled in and the ‘Install WordPress’ button pressed, the WordPress installation is completed and the website is now usable.

Set up WordPress - Install success page

An email about the new WordPress website will also be sent to the email address specified on the install page.

Set up WordPress - New WordPress Site email

This marks the end of the WordPress install.

Optional tasks

Force SSL on login and administration

The WordPress website is now working, but when you click ‘Log in’ from the main page, it will bring you to the http version of the login page.  The username and password that you type will be sent in clear-text through the internet, making them vulnerable to anyone who would want to steal your password.

WordPress has a built-in feature to force logins and/or the administration pages to be served via https instead of http.

To enable this, edit the WordPress config file and add the following line near the end.

[hnizam@server wordpress]$ sudo vi wp-config.php
 * For developers: WordPress debugging mode.
 * Change this to true to enable the display of notices during development.
 * It is strongly recommended that plugin and theme developers use WP_DEBUG
 * in their development environments.
define('WP_DEBUG', false);

define('FORCE_SSL_ADMIN', true);

/* That's all, stop editing! Happy blogging. */

/** Absolute path to the WordPress directory. */
if ( !defined('ABSPATH') )
        define('ABSPATH', dirname(__FILE__) . '/');

/** Sets up WordPress vars and included files. */
require_once(ABSPATH . 'wp-settings.php');

You can use FORCE_SSL_LOGIN instead of FORCE_SSL_ADMIN if you just want to protect the login page.  The administration pages will not be served via https unless you specifically asks for the https protocol via the browser.

Enable pretty permalinks

One of the first things that should be done after a WordPress install is to enable pretty permalinks.  The word-based URL will help the website to rank higher in search engine results compared to the default post ID URL.

Just go to the Settings > Permalinks via the administration pages, and choose Postname-based permalinks instead of the default.  If you followed the install steps above, pretty permalinks should work correctly.

Install plugins and themes

One of the great things about WordPress is the abundance of plugins and themes that exist in the ecosystem.  Use them to customize the website and to help in managing the website.

WordPress cannot send email because of SELinux

The default SELinux configuration will block WordPress from sending emails. Using the check email plugin, error messages can be found in /var/log/audit/audit.log:

type=AVC msg=audit(1368370436.817:271444): avc:  denied  { search } for  pid=13875 comm="sendmail" name="postfix" dev=dm-0 ino=1179960 scontext=unconfined_u:system_r:httpd_t:s0 tcontext=system_u:object_r:postfix_spool_t:s0 tclass=dir

To overcome this, the SELinux boolean ‘httpd_can_sendmail’ must be set to on.

# getsebool -a | grep httpd_can_sendmail
httpd_can_sendmail --> off
# setsebool -P httpd_can_sendmail=on
# getsebool -a | grep httpd_can_sendmail
httpd_can_sendmail --> on

The -P flag is for the boolean setting to persist across reboots.

Unable to use WordPress header crop

Tried to add a header image to the blog.  The image upload function worked fine but after the image was uploaded, WordPress asked to crop the image. Clicking on ‘Crop and Publish’ gives the error:

Image could not be processed. Please go back and try again.

Turns out you need an image manipulation tool called ‘gd’ to make WordPress header crop work. It is a module of php. Installation of gd:

# yum install php-gd

Had to restart apache and now header crop works!

Use subdomains with WordPress

My WordPress blog has been successfully installed.

Now, I want to run the blog under a sub-domain i.e. http://blog.domain.com instead of http://host.domain.com/blog.

Let’s see how this can be done.

Initial googling points to apache and mod_rewrite. Let’s read more.

Oops, further googling shows that this can be done without using URL rewrites. Just use the built-in apache virtual hosts feature by adding the following to the config file (/etc/httpd/conf/httpd.conf in CentOS):

NameVirtualHost *:80

<VirtualHost *:80>
    ServerAdmin webmaster@blog.domain.com
    DocumentRoot /path/to/wordpress/directory
    ServerName blog.domain.com
    ErrorLog logs/blog.domain.com-error_log
    CustomLog logs/blog.domain.com-access_log common

And.. voila! Not really. After doing this and restarting the apache service, http://blog.domain.com throws out a 404 error.

It turns out you need to change the WordPress working directory to the new URL via Settings>General before moving the files and implementing the virtual host. After that everything is OK.