Introduction
A while back I decided to host my blog on my own servers and cut the cord with WordPress.com. There were no hard feelings really; I just didn’t like the limited options for plugin choices I had. I didn’t like all the extra features they forced me to use that made my blog (response time) slower.
The standalone version of WordPress is much more scaled down and fits my requirements better. The standalone version also allows me to pick and choose from a sea of amazing plugins at my disposal.
Prerequisite
You’ll need to have full (Linux) shell access to the server you’re intending to host this from. I set up my hosting using a CentOS 6.x machine; therefore the instructions I identify here are for that. That said, the instructions won’t stray too far off (requiring a tweak here an there) from those people who choose to use other Linux distributions.
You’ll want to first install a few packages:
# You'll basically need PHP, MySQL # As root (or a user with sudoer's permission) type the following: sudo yum -y install php-fpm php-mbstring php-mcrypt \ php-mysql nginx mysql mysql-server gawk \ openssl
Optional FTP Support
FTP support is really nice to have with a WordPress setup! You can use it to automate the installation of plugins through the admin page. This is great for situations where you’re setting up a WordPress account for someone who isn’t too teksavvy. It also allows grants your users enough access to install plugins through WordPress’s administration interface.
I strongly suggest you read my blog entry on Configuring and Installing VSFTPD on CentOS 6 if you’re interested in going this route.
It’s important to note that WordPress functions just fine without an FTP(S) server too!
Step 1 of 8: Prepare our Environment.
To make life really easy (so you can cut and paste this right to your command line without any effort at all), lets create some environment variables.
Please note that this step MUST be ran before any of the other steps are. If you’re returning to this blog entry to resume from a step you left off at, be sure to apply these environment variables again!
Please note that you must be root or have sudoer’s permission to be able to perform any of these tasks successfully on your server.
# Our WordPress user WPUSER=nuxref # The FQD you will be serving your data from. If you # don't have your own domain, then set this to an # underscore '_' (without the quotes '') WPURL=nuxref.com # Some Database Information # - what are we going to call our database name? DBNAME="wordpress_$WPUSER" # - it's easier to just use the WordPress user account here # but if you want to change it to something else; here is # where you can do it: DBUSER=$WPUSER # - we will want to create a confusing password that others # can't guess. I don't recommend you use what i've identified # here because anyone else who knows you read my blog will # guess this first. But here is where you should set your # database password you intend to use. DBPASS="v3ryC0nFU51Ng-Pw%" # If you plan on creating an FTP Account; you'll want to # populate these variables too. This account does not have # to be the same as the $WPUSER account. In fact making it # different (even just slightly) would be a good idea! # Below i just add '-ftp' to the end of the already # determined user above. Feel free to change this. WPFTPUSER="$WPUSER-ftp" # Set an FTP password; It would be a good idea to not use # the one identified below as it's merely display only. # some special character don't work with VSFTPD (like '!') # if you plan on using it . WPFTPPASS="4nt3rP455%rd" # The following is only used for our SSL Key Generation COUNTRY_CODE="7K" PROV_STATE="Westerlands" CITY="Lannisport" SITE_NAME="Life as a Lannister"
Step 2 of 8: Create our User Account
You’ll want to create an isolated environment for our client (or you) to work within. By securing an environment; in the event anything is ever compromised, destruction will be limited to what we allow our client access to.
# First create a system directory to host our project. sudo mkdir -p /opt/$WPUSER/html/static # Create a dummy, favicon.ico file for now. If you feel # ambitious, Google this if you're not sure what it's for # so you can place your own custom one here touch /opt/$WPUSER/html/static/favicon.ico # Create System User sudo useradd nuxref -M --system \ --comment "$WPUSER WordPress Account" \ --home /opt/$WPUSER \ --shell /sbin/nologin # Secure our new directory we created chmod 711 /opt/$WPUSER chown -R $WPUSER.$WPUSER /opt/$WPUSER
If you’ve followed my blog on Securing and Protecting Your CentOS 6 System then you might have wisely chosen to set up disk quotas. If not; then you can skip over to the next step.
# Detect the device using our home directory DEV=$(df -l -P /opt/$WPUSER | awk 'END{print $1}') # Restrict Users Disk Quota to 600MB sudo setquota -u $WPUSER 180000 600000 0 0 $DEV
Step 3 of 8: Generate SSL Keys
We need to generate some Secure Socket Layer (SSL) keys so that we can provide a secure connection for logins. Otherwise our passwords we choose to work with the site could be exposed.
To make things simple, you can use my genssl tool first discussed in an earlier blog I wrote here. available for download from my github page and then just do the following:
# Generate a self signed key: genssl -s $WPURL # Install it: sudo install -m 0400 $WPURL.key /etc/pki/tls/private/$WPUSER.key sudo install -m 0444 $WPURL.crt /etc/pki/tls/certs/$WPUSER.crt
Or you can simply do the following:
# The following will generate SSL Keys (if you don't have any already) sudo openssl req -nodes -new -x509 -days 730 -sha256 -newkey rsa:2048 -keyout /etc/pki/tls/private/$WPUSER.key -out /etc/pki/tls/certs/$WPUSER.crt -subj "/C=$COUNTRY_CODE/ST=$PROV_STATE/L=$CITY/O=$SITE_NAME/OU=IT/CN=$WPURL" # Permissions; protect our Private Key chmod 400 /etc/pki/tls/private/$WPUSER.key # Permissions; protect our Public Key chmod 444 /etc/pki/tls/certs/$WPUSER.crt
Step 4 of 8: Install our WordPress Bundle
Now we need to Download and install WordPress into our environment.
# WordPress Configuration # Acquire latest version from here https://wordpress.org/download/ # (At the time it was 4.4.2) wget --no-check-certificate https://wordpress.org/latest.tar.gz -O wordpress.$(date +'%Y.%m.%d').tgz # Extract our downloaded copy sudo tar xvfz wordpress.$(date +'%Y.%m.%d').tgz \ -C /opt/$WPUSER/html --strip 1 # Apply some more permissions sudo find /opt/$WPUSER/html -type d -exec chmod 755 {} \; sudo find /opt/$WPUSER/html -type f -exec chmod 664 {} \; sudo find /opt/$WPUSER/html -exec chown $WPUSER.apache {} \; # Grant write permissions to a few tools our plugin installers # will need access to later on: find /opt/$WPUSER/html/wp-content/ -type d -exec chmod 775 {} \; sudo chmod 660 /opt/$WPUSER/html/wp-config.php
Step 5 of 8: Configure and Prepare our Database
Now we need to configure our MySQL (or MariaDB) database. First make sure it is running:
# The below command will start the database if it isn't # already running: sudo service mysqld status &>/dev/null || \ sudo service mysqld start # Next make sure you're system is configured to start # the database each and every time your server turns on sudo chkconfig --level 345 mysqld on
Now we need to prepare our database that WordPress can use.
# SQL Initialization ( cat << _EOF CREATE DATABASE $DBNAME; GRANT ALL PRIVILEGES ON $DBNAME.* TO "$DBUSER"@"localhost" IDENTIFIED BY " $DBPASS"; FLUSH PRIVILEGES; _EOF ) | sudo mysql
Step 6 of 8: Configure our Web Hosting Service
Okay now we need to host our website. Effectively linking the database we just prepared with the WordPress software we just installed. We do this as follows using NginX:
# By default (assuming a CentOS installation), we can # plug into our configuration by writing our data in # /etc/nginx/conf.d/ # So lets do just that: cat << _EOF > /etc/nginx/conf.d/wordpress_$WPUSER.conf # # $WPUSER WordPress Web Hosting # server { # Support Web Traffic at port 80 listen 80; server_name $WPURL; root /opt/$WPUSER/html; # Our log files access_log /var/log/$WPUSER/$WPUSER.access.log main; error_log /var/log/$WPUSER/$WPUSER.error.log; # Our main handler location / { root /opt/$WPUSER/html; index index.html index.htm index.php; # Support Permalink changes try_files \$uri \$uri/ /index.php?q=\$request_uri; } # Anyone logging into our site should do it securely location /wp-admin/ { # Always redirect to secure site rewrite ^/(.*) https://$host/\$1 permanent; } location /wp-login/ { # Always redirect to secure site rewrite ^/(.*) https://\$host/\$1 permanent; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # Support the favicon (for those wanting to use it) location = /favicon.ico { root /opt/$WPUSER/html/static; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php\$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; include fastcgi_params; } # Deny access to the wp-config file location ~ /wp-config\.php { deny all; } } server { # We should listen on a secure URL too so that we can # hide our admin login credentials from prying eyes listen 443; server_name $WPURL; root /opt/$WPUSER/html; ssl on; ssl_certificate /etc/pki/tls/certs/$WPUSER.crt; ssl_certificate_key /etc/pki/tls/private/$WPUSER.key; ssl_session_timeout 5m; # Secure our site by only allowing the TLS protocol ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128:AES256:AES:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK'; ssl_prefer_server_ciphers on; ssl_session_cache builtin:1000 shared:SSL:10m; access_log /var/log/nginx/$WPUSER.access.log main; error_log /var/log/nginx/$WPUSER.error.log; location / { root /opt/$WPUSER/html; index index.html index.htm index.php; # Support Permalink changes try_files \$uri \$uri/ /index.php?q=\$request_uri; } error_page 404 /404.html; location = /404.html { root /usr/share/nginx/html; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } # Handle favicon location = /favicon.ico { root /opt/$WPUSER/html/static; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php\$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name; include fastcgi_params; } # Deny access to the wp-config file location ~ /wp-config\.php { deny all; } } _EOF
Now restart our web services
# Ensure our web browser and php handler will start # even if our server is restarted chkconfig --levels 345 php-fpm on chkconfig --levels 345 nginx on # The following just makes sure we reload and take # on our new configuration. If we're not running # then we start the services up service php-fpm status &>/dev/null && \ service php-fpm restart || \ service php-fpm start service nginx status &>/dev/null && \ service nginx restart || \ service nginx start
Step 7 of 8: Optionally Setup an FTP Account
Most people can skip this step; it again presumes you’ve followed my other blog on Configuring and Installing VSFTPD on CentOS 6. If you have not gone here or have set up FTP your own way, you can also skip this step and move on with Configuring WordPress.
# Create a WordPress Plugins FTP Account echo $WPFTPUSER >> /etc/vsftpd/users.passwd echo $WPFTPPASS >> /etc/vsftpd/users.passwd # Protect Password chmod 600 /etc/vsftpd/users.passwd chown root.root /etc/vsftpd/users.passwd # Now convert content into a db structure db_load -T -t hash -f /etc/vsftpd/users.passwd /etc/vsftpd/virtual.users.db chmod 600 /etc/vsftpd/virtual.users.db chown root.root /etc/vsftpd/virtual.users.db cat << _EOF > /etc/vsftpd/virtual.users/$WPFTPUSER local_root=/opt/$WPUSER/html # ------------------------------------------------------------------------- # User # ------------------------------------------------------------------------- guest_enable=YES guest_username=apache local_root=/opt/$WPUSER/html # ------------------------------------------------------------------------- # Permissions # ------------------------------------------------------------------------- # write_enabled is required if the user is to make use of any of the # anon_* commands below write_enable=YES # give the user the ability to make directories anon_mkdir_write_enable=YES # give the user the ability delete and overwrite files anon_other_write_enable=YES # give the user the ability upload new files anon_upload_enable=YES # Give the user permission to do a simple directory listings dirlist_enable=YES # Give the user permission to download files download_enable=YES # if the user has can upload or make new directories, then this will be # the umask applied to them anon_umask=0002 # delete failed uploads (speaks for itself) delete_failed_uploads=NO _EOF sudo chmod 600 /etc/vsftpd/virtual.users/$WPFTPUSER sudo chown root.root /etc/vsftpd/virtual.users/$WPFTPUSER # Ensure our FTP Server will restart if our server # is ever restarted: sudo chkconfig --level 345 vsftpd on # Update Service (to read in new configuration) sudo service vsftpd status &>/dev/null && \ service vsftpd restart || \ service vsftpd start
Step 8 of 8: Configure WordPress
If you successfully pulled off all of the earlier steps, then you shouldn’t have any trouble from this point forward. The hard part is done with!
You now need to open up your browser and access your new WordPress website to continue with the setup. Simply visit your website by browsing to http://your.wordpress.url/ (whatever you set this up as).
First you’ll be immediately presented with webpage that needs some information about the database we set up back in Step 5 (an environment variables defined in Step 1.
After you press the [Submit] button, you’ll then be asked to define some basic information about the blog you intend to set up. You can change all this later, so don’t worry. The important fields here are the administrator user and password you create.
You’re done now and ready to use WordPress
Great WordPress Plugins
The following plugins are worthy of a mention:
- Google Analytics Dashboard for WP by Alin Marcu: Displays Google Analytics Reports and Real-Time Statistics in your Dashboard.
- WordPress ReCaptcha Integration by Jörn Lund: Integrate reCaptcha in your blog
- WP Super Cache by Automattic: Very fast caching plugin for WordPress.
- Yoast SEO by Team Yoast: A very good SEO tool for your blog. The auto analysis of your entries provide very useful information!
Credit
Please note that this information took me several days to put together and test thoroughly. I may not blog often; but I want to re-assure the stability and testing I put into everything I intend share.
If you like what you see and wish to copy and paste this HOWTO, please reference back to this blog post at the very least. It’s really all I ask.