Friday, October 10, 2014

Converting Wordpress Multisite to Single Site

Wow this is not easy.  Here are some notes on the steps that I took.
  1. Create a new fresh wordpress install.  Some basic instructions are here
    NOTE: This tutorial assumes you will using the same MySQL database server and a MySQL database user that can access both databases.
  2. Make a copy of all the plugins and themes that you need.  If this on the same server it is easy.  If not use rsync, scp or ftp.
    cp -r /old/path/to/wordpress/mu/wp-content/plugins/* /new/single/site/wordpress/wp-content/plugins/.
    cp -r /old/path/to/wordpress/mu/wp-content/themes/* /new/single/site/wordpress/wp-content/themes/.
  3. Get the blog number of the old site.  You can use the network admin and go to the Sites or /wp-admin/network/sites.php and the link to the blog will have ?id=#.  This will be used to prefix the tables that are needed wp_#_tableName.
  4. Copy over the existing data from the old database to the new one
    mysql -u root -p NewDb
    mysql> INSERT INTO wp_commentmeta SELECT * FROM wpmu.wp_#_commentmeta;
    mysql> INSERT INTO wp_comments SELECT * FROM wpmu.wp_#_comments;
    mysql> INSERT INTO wp_links SELECT * FROM wpmu.wp_#_links;
    mysql> INSERT INTO wp_posts SELECT * FROM wpmu.wp_posts;
    mysql> INSERT INTO wp_term_relationships SELECT * FROM wpmu.wp_#_term_relationships;
  5. Empty tables that have data in them already and then copy over old data.
    mysql> TRUNCATE TABLE wp_options;
    mysql> INSERT INTO wp_options SELECT * FROM wpmu.wp_#_options;
    mysql> TRUNCATE TABLE wp_posts;
    mysql> INSERT INTO wp_posts SELECT * FROM wpmu.wp_posts;
    mysql> TRUNCATE TABLE wp_term_taxonomy;
    mysql> INSERT INTO wp_term_taxonomy SELECT * FROM wpmu.wp_#_term_taxonomy;
    mysql> TRUNCATE TABLE wp_terms;
    mysql> INSERT INTO wp_terms SELECT * FROM wpmu.wp_#_terms;
    mysql> TRUNCATE TABLE wp_usermeta;
    mysql> INSERT INTO wp_usermeta SELECT * FROM wpmu.wp_usermeta;
    mysql> TRUNCATE TABLE wp_users;
    mysql> INSERT INTO wp_users
    (`ID`,`user_login`,`user_pass`,`user_nicename`,`user_email`,`user_url`,`user_registered`,`user_activation_key`,`user_status`,`display_name`) SELECT `ID`,`user_login`,`user_pass`,`user_nicename`,`user_email`,`user_url`,`user_registered`,`user_activation_key`,`user_status`,`display_name` FROM wpmu.wp_users;
    mysql> TRUNCATE TABLE wp_postmeta;

    mysql> INSERT INTO wp_postmeta SELECT * FROM wpmu.wp_#_postmeta;
  6. Create tables and copy data for plugins as necessary
    mysql> CREATE TABLE wp_calendar LIKE wpmu.wp_#_calendar;
    mysql> CREATE TABLE wp_calendar_categories LIKE wpmu.wp_#_calendar_categories;
    mysql> CREATE TABLE wp_calendar_config LIKE wpmu.wp_#_calendar_config;
    mysql> CREATE TABLE wp_contact_form_7 LIKE wpmu.wp_#_contact_form_7;
    mysql> CREATE TABLE wp_duplicator LIKE wpmu.wp_#_duplicator;
    mysql> CREATE TABLE wp_duplicator_packages LIKE wpmu.wp_#_duplicator_packages;
    mysql> CREATE TABLE wp_eventscalendar_main LIKE wpmu.wp_#_eventscalendar_main;
    mysql> CREATE TABLE wp_forum_forums LIKE wpmu.wp_#_forum_forums;
    mysql> CREATE TABLE wp_forum_groups LIKE wpmu.wp_#_forum_groups;
    mysql> CREATE TABLE wp_forum_posts LIKE wpmu.wp_#_forum_posts;
    mysql> CREATE TABLE wp_forum_threads LIKE wpmu.wp_#_forum_threads;
    mysql> CREATE TABLE wp_forum_usergroup2user LIKE wpmu.wp_#_forum_usergroup2user;
    mysql> CREATE TABLE wp_forum_usergroups LIKE wpmu.wp_#_forum_usergroups;
    mysql> CREATE TABLE wp_ngg_album LIKE wpmu.wp_#_ngg_album;
    mysql> CREATE TABLE wp_ngg_gallery LIKE wpmu.wp_#_ngg_gallery;
    mysql> CREATE TABLE wp_ngg_pictures LIKE wpmu.wp_#_ngg_pictures;
    mysql> INSERT INTO wp_calendar SELECT * FROM wpmu.wp_#_calendar;
    mysql> INSERT INTO wp_calendar_categories SELECT * FROM wpmu.wp_#_calendar_categories;
    mysql> INSERT INTO wp_calendar_config SELECT * FROM wpmu.wp_#_calendar_config;
    mysql> INSERT INTO wp_contact_form_7 SELECT * FROM wpmu.wp_#_contact_form_7;
    mysql> INSERT INTO wp_duplicator SELECT * FROM wpmu.wp_#_duplicator;
    mysql> INSERT INTO wp_duplicator_packages SELECT * FROM wpmu.wp_#_duplicator_packages;
    mysql> INSERT INTO wp_eventscalendar_main SELECT * FROM wpmu.wp_#_eventscalendar_main;
    mysql> INSERT INTO wp_forum_forums SELECT * FROM wpmu.wp_#_forum_forums;
    mysql> INSERT INTO wp_forum_groups SELECT * FROM wpmu.wp_#_forum_groups;
    mysql> INSERT INTO wp_forum_posts SELECT * FROM wpmu.wp_#_forum_posts;
    mysql> INSERT INTO wp_forum_threads SELECT * FROM wpmu.wp_#_forum_threads;
    mysql> INSERT INTO wp_forum_usergroup2user SELECT * FROM wpmu.wp_#_forum_usergroup2user;
    mysql> INSERT INTO wp_forum_usergroups SELECT * FROM wpmu.wp_#_forum_usergroups;
    mysql> INSERT INTO wp_ngg_album SELECT * FROM wpmu.wp_#_ngg_album;
    mysql> INSERT INTO wp_ngg_gallery SELECT * FROM wpmu.wp_#_ngg_gallery;
    mysql> INSERT INTO wp_ngg_pictures SELECT * FROM wpmu.wp_#_ngg_pictures;

  7. To ensure that there is no wp_#_tableName in the data you may need to dump the DB and then search and replace that string then import it again.
    mysqldump -u root -p database > database.sql
    sed -i 's/wp_#_/wp_/g' database.sql
    mysql -u root -p database < database.sql
  8. This assumes you have a new apache or nginx setup pointing to the old domain and the domain name is not changing.  If you want to change the domain you can edit the wp_options table
    mysql> UPDATE wp_options SET option_value = '' where option_name=siteurl;
    mysql> UPDATE wp_options SET option_value = '' where option_name=home;
That should do most of it.  If you have issues turn on debug in the wp-config.php file, and get your google foo going, most wordpress issues have been addressed in the forums or elsewhere.

Sunday, November 03, 2013

Client Certificate Authentication Issues with Apache and OS X Mavericks

Found some good tutorials online but took a few days of troubleshooting for me to figure out why they were not working.  Still don't understand SSL and cryptography as much as I would like to.  Posting this incase anyone else runs into similar issues.

The 3 tutorials I found via googling were:

  • Apache
  • Nginx
I will recap the commands here for additional info on how it works read either of those.

# Create the CA Key and Certificate for signing Client Certs 
openssl req -config ./openssl.cnf -newkey rsa:2048 -nodes -keyform PEM -keyout ca.key -x509 -days 3650 -extensions certauth -outform PEM -out ca.cer
# Create the Server Key, CSR, and Certificate 
openssl genrsa -out server.key 2048

openssl req -config ./openssl.cnf -new -key server.key -out server.req

# We're self signing our own server cert here. This is a no-no in production. 
openssl x509 -req -in server.req -CA ca.cer -CAkey ca.key -set_serial 100 -extfile openssl.cnf -extensions server -days 365 -outform PEM -out server.cer
rm server.req

 # Create the Client Key and CSR I made a client.cnf file for attributes to match the client
openssl genrsa -out client.key 2048
openssl req -config ./client.cnf -new -key client.key -out client.req

# Sign the client certificate with our CA cert. Unlike signing our own server cert, this is what we want to do. 
openssl x509 -req -in client.req -CA ca.cer -CAkey ca.key -set_serial 101 -extfile openssl.cnf -extensions client -days 365 -outform PEM -out client.cer
openssl pkcs12 -export -inkey client.key -in client.cer -out client.p12
rm client.key client.cer client.req
This is where I ran into problems with some of the tutorials. Testing with CURL to connect to NGINX worked based on the tutorial at worked.

curl -v -s -k --key client.key --cert client.cert

But connecting following the first apache tutorial did not and the second one needed some additional steps.

There seems to be 2 reasons why:
  • OS X Mavericks hacked up CURL to not work with client certificates -
  • CURL prefers certificates to be combined in PEM format with Data Bags included -

# Install CURL via Homebrew (assuems you have brew installed and up to date) openssl is not required but the OS X version is old 
brew install openssl curl

# Convert the certificate to pkcs12 and back to pem 
openssl pkcs12 -in client.p12 -out client.pem -clcerts

Here is the apache config
SSLCACertificateFile /var/www/conf/ssl.crt/ca.crt
    SSLVerifyClient require 
    SSLVerifyDepth 10 

Now I can connect with (NOTE: do not use the built in curl)
/usr/local/Cellar/curl/7.33.0/bin/curl -v -s -k --key client.pem --cert client.pem

Wednesday, October 23, 2013

OS X Maverick pkg_resources.DistributionNotFound: pip==1.1

Kept getting the following issue with PIP and easy_install
Traceback (most recent call last):
  File "/usr/local/bin/pip", line 5, in
    from pkg_resources import load_entry_point
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/", line 2603, in
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/", line 666, in require
    needed = self.resolve(parse_requirements(requirements))
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/", line 565, in resolve
    raise DistributionNotFound(req)  # XXX put more info here
pkg_resources.DistributionNotFound: pip==1.1
Ran the following to fix it:
sudo python
sudo easy_install -U pip

Tuesday, April 23, 2013

Django Admin Filter OR queries

Django admin in 1.4+ support the query parameter __in for filtering on multiple values of the same field.  Adding this to the admin took some work but is possible, I am not sure if this is the best way to do it but it does work.

Here is a snippet of my file

Sunday, April 07, 2013

Securing LAMP for Ubuntu 12.04 LTS

This is a summary of this post

Setup non root user

useradd -G sudo YOUNONROOTUSER
sudo -i
Install LAMP, Security and other useful stuff
sudo apt-get install lamp-server^ ufw denyhosts fail2ban psad rkhunter chkrootkit nmap logwatch libdate-manip-perl apparmor apparmor-profiles tiger htop libxml2 libxml2-dev libxml2-utils libaprutil1 libaprutil1-dev libapache-mod-security -y
Setup UFW
sudo ufw enable
ufw status verbose
sudo ufw allow ssh
sudo ufw allow http
Secure shared mem (requires reboot)
echo 'tmpfs /dev/shm tmpfs defaults,noexec,nosuid 0 0' >> /etc/fstab
Disallow root ssh logins (can also change SSH PORT)
sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config
sed -i 's/Port 22/Port 2222/g' /etc/ssh/sshd_config
sudo /etc/init.d/ssh restart
Limit su command to users that have sudo
sudo dpkg-statoverride --update --add root sudo 4750 /bin/su
Harden network with sysctl settings.  This is what my /etc/sysctl.conf file ends up looking like with no comments
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0
net.ipv4.conf.all.log_martians = 1
net.ipv4.icmp_ignore_bogus_error_responses = 1
net.ipv4.icmp_echo_ignore_broadcasts = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_synack_retries = 2
net.ipv4.tcp_syn_retries = 5
net.ipv4.icmp_echo_ignore_all = 1 
sudo sysctl -p
Prevent IP Spoofing
# The "order" line is only used by old versions of the C library.
order bing,hosts
nospoof on
multi on 
Secure PHP (assumes that exec, system, shell_exec, passthru are not already there)

sed -i 's/expose_php = On/expose_php = Off/g' /etc/php5/apache2/php.ini
sed '/^disable_functions/ s/$/,exec,system,shell_exec,passthru/' /etc/php5/apache2/php.ini > /etc/php5/apache2/php.ini
Secure Apache
sed -i 's/ServerTokens OS/ServerTokens Prod/g' /etc/apache2/conf.d/security
sed -i 's/ServerSignature On/ServerSignature Off/g' /etc/apache2/conf.d/security
echo 'Header unset ETag' >> /etc/apache2/conf.d/security
echo 'FileETag None' >> /etc/apache2/conf.d/security
a2enmod headers
/etc/init.d/apache2 restart
Update fail2ban
sed -s 'action = %(action_)s/action = %(action_mwl)s/g' s//etc/fail2ban/jail.conf

Monday, February 25, 2013

Vagrant on Cygwin

Not fully tested taken from memory and history so if anything is missing please comment.

Taken mostly from a good post here Assumes you have latest cygwin and virtualbox installed.

Cygwin need svn and bash Install other deps
svn --force export /bin/
chmod +x /bin/apt-cyg
apt-cyg install make ruby curl git bsdtar ssh

Get Vagrant 1.1.0 dev from git (once this is stable then this step is not needed).
git clone
cd vagrant 

Update pull request for cygwin fix from here
curl | git am

Install gem so deps are install then rake install to update to dev version with patches applied
gem install vagrant
rake install

export VBOX_USER_HOME=`pwd`/.VirtualBox/

Add symlink to VBoxManage
ln '/cygdrive/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe' /usr/local/bin/VBoxManage

Use vagrant
vagrant box add lucid32
vagrant init lucid32
vagrant up

You May get an error when starting up. This is because the Virtual box guest additions need to be installed so the directory can be mounted
vagrant ssh
sudo apt-get install virtualbox-guest-addition

Tuesday, November 06, 2012


cd Stackato-VM
VBoxManage import Stackato-v2.4.3.ovf
VBoxManage modifyvm Stackato-v2.4.3 --nic1 bridged --bridgeadapter1 eth0
VBoxManage startvm Stackato-v2.4.3 --type headless
To figure out the ip
# scan port 22
nmap -p 22 --open -sV 192.168.X.0/24
VBoxManage showvminfo Stackato-v2.4.3 | grep MAC
# OUTPUT IS: NIC 1:           MAC: 080027656420, Attachment: Bridged Interface 'eth0', Cable connected: on, Trace: off (file: none), Type: 82540EM, Reported speed: 0 Mbps, Boot priority: 0, Promisc Policy: deny
arp -an | grep -i 08:00:27:65:64:20 
Install stackato client
cd stackato-1.5-linux-glibc2.3-x86_64/
sudo mv stackato /usr/local/bin/.