wp-cli CentOS rpms

wp-cli is a really, REALLY useful tool. I’m pretty much using it on all of the wordpress servers that I manage now. But it can be a little awkward to install / keep up to date. And its usually nicer to have something managed by the OS’s package manager.

As such, I’ve created wp-cli rpms for EL6 and EL7, incase anyone wants to use them. The intention is to keep them up to date with the latest version. I’ll create a repo at some point, as there may be other tools that I would rather as rpms, but for now..here’s the download links:

CentOS 6 (i386 and x86_64)


CentOS 7 (x86_64)



…and the source RPM



WordPress Webroot Ownership / Permissions Script

Ok, so I’ve seen a fair amount of “run this script to fix your permissions” posts about, and for a number of reasons I don’t really like them.

Not saying that mine is perfect ofcourse, but the emphasis is trying to be around security.

With all security, you’re always compromising convenience. If you really want to secure your WordPress file ownership and permissions. Give it user:apache and 750/640 permissions throughout. But it won’t do you much good when it comes to installing plugins, etc.

So, here’s what you can do.

NOTE: The outcome of this script (should you read it and use it properly) is that your wordpress web root will be read only to apache (this is how we want it really) and wp-content and below will be writeable by apache (you need this if you want to install plugins, upload media). Having apache write to wp-content is the compromise here, because its undesirable for the web process to have write permissions…but we’re balancing security and convenience here. Because apache cannot write to a directory higher than wp-content, then it will NOT be able to update itself. So you’ll need to organise that when the times comes. I might write a post about that, but because it sucks to have apache writing to the webroot, I possibly won’t


## ok, you want to replace my ‘dcr226’ with whatever user you
## login to your server with. Change all of these settings to suit your system


chown -R $username:web_user $web_directory
find $web_directory -type d -exec chmod 750 {} \;
find $web_directory -type f -exec chmod 640 {} \;
find $web_directory/wp-content -type d -exec chmod 770 {} \;
find $web_directory/wp-content -type f -exec chmod 660 {} \;

#selinux stuff because…you should be using it

chcon -R -t httpd_sys_content_t $web_directory
chcon -R -t httpd_sys_rw_content_t $web_directory/wp-content
setsebool httpd_unified 0

SSL Certificates

Generating SSL Certificates With StartSSL

I’ve been meaning to do a how-to on generating your own SSL/TLS certificates using StartSSL ‘s free service.

These certificates are useful for a number of different things, most notably apache/nginx SSL security. But they are also widely used with other software, for example Bacula is much nicer when all of the various daemons are talking over SSL/TLS encrypted connections.

Step 1 – get an account at StartSSL.com

Its fairly self explanatory how to get you free account and validate domains with StartSSL..if anyone is struggling with it, make a comment below and I’ll do a how-to for that.

Step 2 – generate a rsa encrypted private key for the request.

In this example, we’re going to use the Triple DES cipher (168 bit key size) and our key is going to be 2048 bits in size. The default for OpenSSL is 512 bits but StartSSL won’t accept anything less than 2048 bits.

[plain]# openssl genrsa -des3 -out bruce.example.com.key 2048

Generating RSA private key, 2048 bit long modulus
e is 65537 (0x10001)
Enter pass phrase for bruce.example.com:[/plain]

So enter a passphrase (because you need to) to conclude this step. You should now have a file in your current working directory : bruce.example.com.key

Step 3 – make a passphrase-less version of your key

This is going to be important in most cases, the last thing you want to do when apache starts..is login to the console and enter a passphrase..so its handy to have a passwordless key

[bash] openssl rsa -in bruce.example.com.key -out bruce.example.com.nopass.key [/bash]

You will be asked for the passphrase you previously entered, after which you will have a second file in your cwd : bruce.example.com.nopass.key

Step 4 – generate a certificate signing request

Because we’re going to want a signed certificate (by StartSSL) then we’re going to need to generate a signing request.

Note: You’re going to need to answer some questions here, make sure you change my responses for yours. Also, the Organization Name must be your machine’s FQDN

[plain]openssl req -new -sha256 -key bruce.example.com.nopass.key -out bruce.example.com.csr

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]:GB
State or Province Name (full name) []:London
Locality Name (eg, city) [Default City]:London
Organization Name (eg, company) [Default Company Ltd]:Xreflow
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server’s hostname) []:bruce.example.com
Email Address []:

Please enter the following ‘extra’ attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:[/plain]

You should now have bruce.example.com.csr sat in your cwd.

Step 5 – get your certificate!

Sign in to your StartSSL control panel, and authenticate..you should be here

StartSSL Control Panel

Select “Certificates Wizard” then in the dropdown select “Web Server SSL/TLS Certificate”, you should be here.

StartSSL Control Panel

Click “Continue” and go to the next step in the wizard, where you will be given a choice to Skip This Step. You should skip that step because you’ve already generated a csr request. Now, you should be at the following screen..

Copy and paste the contents of your bruce.example.com.csr into the text area box, and click “Continue”..this information looks something like


and so on…paste this into the text area, and click “Continue”, a few seconds later you will be presented with your signed SSL certificate.

Open a new file with your favourite text editor bruce.example.com.cert, and paste the copied content into that file.

Step 5 – You’re done! go use your newly created, signed SSL/TLS certificate!

Google Apps Outlook Migration

Google Apps For Business – Migrating Outlook Emails

Google Apps For Business is a really useful (paid) service for businesses that do not want to administrative implications of maintaining their own mailserver infrastructure, but still need business-grade mail functions.

In order to configure Outlook to use Google Apps For Business , and migrate your existing email..this guide might be useful.

Step 1 – Login to gmail using your Google Apps credentials.

If Xreflow have configured your Google Apps account, then you will have received an email with your connection credentials on, use these.

go to https://mail.google.com and login using your credentials..


Login to your gmail/google apps for business account

Once logged in, you will either get to accept the terms and conditions, then change your password…or go straight to the inbox..


Step 2 – Download Google Apps Sync

go to https://tools.google.com/dlpage/gappssync and download the latest version of the google apps sync tool


Step 3 –  install Google Apps sync

Click the downloaded file in your browser, or go to your Downloads folder and double click the downloaded file.

The application will start up and configure itself



Step 4 – Configure Google Apps Sync

Once the tool is installed, it will ask you to login to your Google Apps account..The email address is the one you have setup with Google Apps ( yourname@example.com )


You may be asked for your password again, if so enter your password and click to continue.

Once you’ve authenticated, a new browser window will open, asking you to confirm the permissions for Google Apps Sync, scroll to the bottom and agree these settings.



Next, select your existing Outlook profile (if you have one) to migrate to Google Apps. Check “Migrate all data”, then click “Next”



Next, select the items (Calendar, Contacts, etc) that you wish to migrate to Google Apps. Then click “migrate”




If everything went well, you should get the following message



Step 5 – Start Outlook

On first run, Outlook should ask you which profile to use, choose the Google Apps profile you just created, and click “OK”



Apps sync will now start to syncronize and migrate your profile to your Google Apps account. You can minimise this window, or close it when completed.




It may take some time to migrate all of your email and calendar items to your new account, but the process should happen in the background, allowing you to continue with your work. Each time you start Outlook you will be presented with the following to confirm that sync is taking place.







WordPress IPtables – Security Tips – How To

WordPress IPTables

Please note, this is a working document. If you see anything thats missing, or needs more info..please do let me know

We really don’t want much in the way of outbound traffic coming from File our WordPress install. Malicious scrips and plugins will try to “phone home” or potentially deny someone else’s webserver of service, or possibly download more malicious scripts to be used on your website.

Unfortunately, in some cases we *want* wordpress to connect outbound, for example in the case of installing new plugins.

Now, if you want to install your plugins and themes manually you don’t need to do any of this, you can just upload the zip file onto your webserver, and unzip it into the wp-content/plugins directory. However, in the event that you want to search and install plugins from the dashboard, here’s how you can configure iptables.

The following assumes that your default firewall policy is to DROP outbound packets (OUTPUT -P DROP)

During my logging, it seems that the dashboard uses the same host/IP address when querying plugins ( which does indeed have a wordpress PTR record ( domain name pointer wordpress.org.) and when used in the browser resolves to wordpress.org. We need to allow outbound packets on port 80 from our server to this ip address.

the basic rule is:

OUTPUT -p tcp –dport 80 -d -m conntrack –ctstate NEW –syn -j ACCEPT

Now there are a couple of ways you Dinner can do this, you can insert this rule into the top of the OUTPUT chain with

iptables -I OUTPUT -p tcp --dport 80 -d -m conntrack --ctstate NEW --syn -j ACCEPT

or you can cheap NBA jerseys hand edit /etc/sysconfig/iptables and add the rule into the chain wholesale jerseys there.

Personally, I wanted to keep it a little tidier so created a new chain for wordpress (OUTPUT_WP) and Year added it there.


Turns out WordPress will try port 80 first (http) and then fall onto port 443 (https). Seeing as SSL is much more desirable in this context, we can actually allow to the destination port (–dport) 443.

Also, it would seem that WordPress have more ip addresses in that range, and although it will still work with just the one IP address..seems to make sense to Markierung allow it to failover onto another quickly enough. I’ll add more of these as time goes by.

So now we have:

OUTPUT -p tcp --dport 443 -m iprange --dst-range -m conntrack --ctstate NEW --syn -j ACCEPT

A word about email

In order for your wordpress instance to send email, it not only needs to have a MTA (postfix or sendmail perhaps) but needs to egress on port 25 (TCP)

OUTPUT -p tcp cheap MLB jerseys --dport smtp -m conntrack --ctstate NEW --syn -j ACCEPT


WordPress Security – File Permissions

We’ve been working recently on security, in this particular document we’re focussing on wordpress file and directory permissions.

This is a working document, which should be subject to updates and revisions

Firstly, there is no reason that I can find..that any of the files or directories in a wordpress installation should be world readable, so to that effect we can assume all permissions will end in a “0”, removing any world-readable permissions.

Secondly, we shouldn’t have the web user (apache, http, www-data for example) owning any of the files. In the very least a human should own the files in the web root, and the web process user should be accessing based on group permissions. The reason for this is, the owner can change file permissions as he wishes..which may well be undesirable in the event that a malicious script is executed for example. Additionally, we want the user to be able to write to files..whereas the web server process usually only a needs to *read* files. So in the very first place we’d do About something like this

[plain]chown -R (your username):(web server group) /path/to/webroot/[/plain]

so in the case of my system, I’d perhaps do something like this:

[plain]chown -R dcr226:apache /var/webroot/www[/plain]

So onto actual permissions for these user/group combinations. As stated before, there is no good wholesale mlb jerseys reason to have anything in the webroot world readable. So from an overarching perspective, files can How be 640 and directories 750. To explain how this works:

Files – 640 permission

Owner has read/write access (in this case a human owner, *not* the web server) (rw)
Group members have read access (in this case the web server’s user – perhaps apache, httpd or www-data) (r)
Everyone else has no access whatsoever (-)

Directories – 750 permission

Basically the same as above, with the exception that directories need to execute in wholesale jerseys order to change directory, etc. So both the owner and group get execution permissions (rwx)

Fixing the file permissions:

So, now we know what file permissions we want to issue..its time to do the work. This can be done as follows:

[plain]find /path/to/webroot -type d -exec chmod 750 {} ;[/plain]

the above command searches (find) through the defined web root, looking for directories (-type d), then executes chmod 750 on each of them. Should take a few seconds to complete.

[plain]find /path/to/webroot -type f -exec chmod 640 {} ;[/plain]

the above command does the same, but this time for actual files, instead of directories. ‘find’ in this case will recurse through directories.


so it looks like centos6 at least ships with the httpd_unified boolean set. With the boolean on, Apache processes can read/write/execute all httpd_sys_content* labels. This isn’t what we want to achieve.

[plain]setsebool -P httpd_unified 0[/plain]

then, we can create read only selinux labelling for the web root using:

[plain]semanage fcontext -a -t httpd_sys_content_t “/path/to/www(.*)?”
restorecon -Rv www[/plain]

now, apache simply isn’t allowed to write to any files, or execute any files in the webroot.


you’ve got a choice here, you can either manually copy/paste and .htaccess settings into the file yourself, or allow apache to write to the file using the following permissions

[plain]chown dcr226:apache /path/to/www/.htaccess
chmod wholesale jerseys 660 /path/to/www/.htaccess[/plain]

then set the correct selinux context..

[plain]semanage fcontext -a -t httpd_sys_rw_content_t /path/to/www/.htaccess
restorecon -v /path/to/www/.htaccess[/plain]

some things need write contexts and permissions…

Apache needs to write to the wp-content/ directory in the very least to add new media, themes and plugins, so we need to make that happen with file permissions and a selinux context.

[plain]find /path/to/webroot/wp-content -type d -exec chmod 770 {} ;

find /path/to/webroot/wp-content -type f -exec chmod 660 {} ;
semanage fcontext -a -t httpd_sys_rw_content_t “/path/to/www/wp-content(.*)?”
restorecon -Rv /path/to/www/wp-content[/plain]

Optional – protect xmlrpc.php

unless you’re posting using a desktop/mobile application, or connecting to the xmlrpc api, then you likely want to prevent access to xmlrpc.php. This can be done a couple of ways, one of which is using your httpd.conf (or relevant config file in the drop directory) as such

Inside of your <Directory>…</Directory> directive

[plain]<Files xmlrpc.php>
Order allow,deny
Deny from all


When Its Time To Update The Whole Thing

When you need to update wordpress core files, if you want wordpress to update itself, then you’re going to need to give the web process writeable permissions cheap jerseys throughout the webroot..

[plain]find /path/to/webroot -type d -exec chmod 770 {} wholesale jerseys ;

find /path/to/webroot -type f -exec chmod 660 {} ;

and if you’re using selinux..

[plain] chcon -R -t httpd_sys_rw_content_t /path/to/webroot


Not forgetting to Breach re-set Welcome them again afterwards!