1. Before Attaching /local

1.1 Configuring App Armor

If your Linux distribution features App Armor, which restricts what directories programs can access, it may be necessary to add several directories to the App Armor configuration file for MySQL:

/etc/apparmor.d/usr.sbin.mysqld

We add the following -- the first two entries allow the mysql data directory to be stored under a '/local' directory, while the second two entries allow the retrieval of SSL certificates and keys from under a '/local' directory.

/local/data/mysql/   r,
/local/data/mysql/** rwk,
/local/data/mysql-replication/   r,
/local/data/mysql-replication/** rwk,
/local/settings/services/mysql/ssl/   r,
/local/settings/services/mysql/ssl/** r,

Important!!! You must then reload the apparmor profiles.

service apparmor restart

It goes without saying that if App Armor is not configured to allow access to directories that are used later in these instructions that the various services can show some very strange behaviour. Best to configure this first!

1.3 Configuring Apache

1.3.1 Installing Apache

If not already installed, Apache can be installed by executing the following line as root:

apt-get install apache2
apt-get install php5 libapache2-mod-php5 php5-cli php5-mysql

1.3.2 Setting Server name

Put the following text at the top of the 'apache2.conf' file.

ServerName localhost

1.3.3 Setting up Apache modules

Navigate to the /etc/apache2/mods-enabled directory and execute the following commands as root.

a2enmod expires
a2enmod headers
a2enmod rewiret
a2enmod ssl

1.3.4 Allow Apache access to '/local/served/'

In the '/etc/apache2/apache2.conf' file, fine the location of the following commented out text, and replace '/srv/', with '/local/served/'.

The following:

#{Directory /srv/}
#       Options Indexes FollowSymLinks
#       AllowOverride None
#       Require all granted
#{/Directory}

should become:

{Directory /local/served/}
       Options Indexes FollowSymLinks
       AllowOverride None
       Require all granted
{/Directory}

2. Attaching /local

2.1 Creating and formatting the partition

Next, the '/local' partition needs to be setup.

mke2fs /dev/xvdb1
e2label /dev/xvdb1 LOCAL

2.2 Adding entry to fstab file

Next the '/etc/fstab' needs to be edited so that the '/local' partition will be mounted when the system boots. The 'nofail' option prevents booting from stalling if the 'LOCAL' partition is not present.

LABEL=LOCAL    /local    ext2    nofail,defaults    0 0
mkdir /local
mount /local

3. After Attaching /local

3.1 Setting up MySQL (if it is needed)

3.1.1 Creating MySQL Data Dir

Using the following commands, stop MySQL, then generate a new data directory.
service mysql stop
mysql_install_db --datadir /local/data/mysql --basedir /usr --insecure

3.1.2 Configuring MySQL

You will now edit the '/etc/mysql.conf.d/mysqld.conf' file.

First, replace the data dir directive to point to '/local/data/mysql'.

#datadir        = /var/lib/mysql
datadir         = /local/data/mysql

Next, add an SQL mode line at the start of the [mysqld]

[mysqld]
sql_mode = "IGNORE_SPACE,NO_ZERO_IN_DATE,NO_ENGINE_SUBSTITUTION"

Now restart MySQL and run mysql_secure_installation to set a root password and secure the install.

service mysql start
# mysql_secure_installation

If you intend to have clients connect to your database using SSL, cut and paste the following to the top of the config file.

[client]
ssl-ca      = /local/settings/services/mysql/ssl/{DNS fully qualified domain name}/ca-cert.pem
ssl-cert    = /local/settings/services/mysql/ssl/{DNS fully qualified domain name}/client-cert.pem
ssl-key     = /local/settings/services/mysql/ssl/{DNS fully qualified domain name}/client-key.pem

[mysqld]
ssl-ca      = /local/settings/services/mysql/ssl/{DNS fully qualified domain name}/ca-cert.pem
ssl-cert    = /local/settings/services/mysql/ssl/{DNS fully qualified domain name}/server-cert.pem
ssl-key     = /local/settings/services/mysql/ssl/{DNS fully qualified domain name}/server-key.pem

Then replace '{DNS fully qualified domain name}' with the fully qualified domain name. Note, you will need to use this domain name later when generating keys.

3.1.3 Setting up SSL

To enable SSL, you need to generate public key certificates and private keys for each host. Unlike web SSL, as the communication to be secured is only between hosts you control, there is no need for a third party Certificate Authority. The next section will walk you through generating a self-signed Certificate Authority (CA) certificate, as well as private keys and certificates for each host.

3.1.3.1 Generating Certificates and Private Keys for MySQL

This section will assume that the keys are generated within the following directory:

/local/settings/services/mysql/ssl

The following generates a 2048 bit RSA private key, which will be used to sign the certificates you generate for each host, as well as the certificate that stores the public key used to validate each certificate.

First create directories to store the ca-key, server certificate and private key, and client certificate and private key.

# mkdir -p /local/settings/services/mysql/ssl/{domain}/ca-key/
# chmod 700 /local/settings/services/mysql/ssl/{domain}/ca-key/
# openssl genrsa 2048 > ca-key/ca-key.pem
# openssl req -new -x509 -nodes -days 3600 -key ca-key/ca-key.pem -out ca-cert.pem

Now create a private key and certificate for the mysql "server" and the mysql "client": The following creates a private key and also a key signing request.

# openssl req -newkey rsa:2048 -days 3600 -nodes -keyout server-key.pem -out server-req.pem

Make sure that when it asks for "Common Name" that you enter your fully qualified domain name.

The following strips the password from the key.

# openssl rsa -in server-key.pem -out server-key.pem

Finally, an X509 certificate is generated.

openssl x509 -req -days 3600 -CA ca-cert.pem -CAkey ca-key/ca-key.pem -set_serial 01 -in server-req.pem -out server-cert.pem
# openssl req -newkey rsa:2048 -days 3600 -nodes -keyout client-key.pem -out client-req.pem
# openssl rsa -in client-key.pem -out client-key.pem
# openssl x509 -req -days 3600 -CA ca-cert.pem -CAkey ca-key/ca-key.pem -set_serial 01 -in client-req.pem -out client-cert.pem

Once you have repeated the proceeding three commands, substituting 'server' for 'client', you should now be left with the following files:

ca-key/ca-key.pem Used to generate future certificates
ca-cert.pem Used to verify existing certificates
client-cert.pem Used to prove host's identity
client-key.pem Used to encrypt SSL secret
client-req.pem Used to generate certificate and can be deleted
server-cert.pem Used to prove host's identity
server-key.pem Used to encrypt SSL secret
server-req.pem Used to generate certificate and can be deleted

The following may be used to verify the certificates:

# openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem
3.1.3.2 Restart

Now restart MySQL for the configuration changes to take place.

$ service mysql restart

Once logged into MySQL you should see:

mysql> SHOW STATUS
...
| Ssl_cipher      | DHE-RSA-AES256-SHA                                  |
| Ssl_cipher_list | DHE-RSA-AES256-SHA:AES256-SHA:DHE-RSA-AES128-SHA:...|
...
3.1.3.3 Enforcing SSL Usage

When accounts are created by granting privileges to users the 'require' keyword can be used to require that an SSL connection is used, as well as require that the user connecting has a certificate signed by the same CA as the server.

To require an ssl connection 'require ssl' is used:

mysql> GRANT SELECT ON *.* TO 'someone'@'somewhere' IDENTIFIED BY 'password' require ssl;

To require a valid certificate 'require x509' is used:

mysql> GRANT SELECT ON *.* TO 'someone'@'somewhere' IDENTIFIED BY 'password' require x509;

References
http://dev.mysql.com/doc/refman/5.0/en/creating-ssl-certs.html

3.1.4 Setting up replication

3.1.4.1 Enabling binary logging

MySQL replication is achived by the slave server asynchronously copying the binary log of the master into a relay log. Binary logging can be enabled by editing the my.cnf file. Note that the only difference between the configurations is the unique server ID that is given to each host and that the master is not read only while the slave is.

The directory for the replication logs will need to be created, owned by the mysql account, and only accessible by that account, i.e.:

# mkdir -p          /local/data/mysql-replication
# chown mysql:mysql /local/data/mysql-replication
# chmod 700         /local/data/mysql-replication
Configuration for master
server_id         = 10
read_only         = 0
log_bin           = /local/data/mysql-replication/mysql-bin.log
relay_log         = /local/data/mysql-replication/mysql-relay.log
log_slave_updates = 1
sync_binlog       = 1
Configuration for slave
server_id         = 11
read_only         = 1
log_bin           = /local/data/mysql-replication/mysql-bin.log
relay_log         = /local/data/mysql-replication/mysql-relay.log
log_slave_updates = 1
sync_binlog       = 1

Restart each mysql server to apply the settings.

# service mysql restart
3.1.4.2 Setting up replication accounts

For both the master and slave add the following account substituting {IP Address} for the appropriate address and {Password} for an appropriate password. The 'REQUIRE x509' clause ensures that the connection is protected by SSL and that that a client certificate is also required -- this prevents somebody from spoofing the IP address of the slave and connecting even if they know the password.

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO repl@'{IP Address}' IDENTIFIED BY '{Password}' REQUIRE x509;

If you want to change the account you should delete the account first using:

mysql> DROP USER repl@'{IP Address}';
3.1.4.3 Pointing the Slave at the Master

Finally, the slave needs to be pointed to the master and told to start replicating. Login to the slave mysql prompt and enter a varient of the below:

According to the MySQL documentation it shouldn't be necessary to specify the SSL lines, however, I can't get it working without them...

First, ensure the slave process is not running.

STOP SLAVE;

Then change the master information.

CHANGE MASTER TO MASTER_HOST         = '{IP Address}',
                 MASTER_USER         = 'repl',
				 MASTER_PASSWORD     = '{Password}',
				 MASTER_LOG_FILE     = 'mysql-bin.000001,
				 MASTER_LOG_POS      = 0,
				 MASTER_SSL          = 1,
				 MASTER_SSL_CA       = '/local/settings/services/mysql/ssl/ca-cert.pem',
				 MASTER_SSL_KEY      = '/local/settings/services/mysql/ssl/client-key.pem',
				 MASTER_SSL_CERT     = '/local/settings/services/mysql/ssl/client-cert.pem';

Finally, start the slave process again:

START SLAVE;

You can check the status of the slave by typing:

SHOW SLAVE STATUS;

3.2 Apache Setup

This section describes a common configuration that is used and how to setup SSL.

3.3 Local account setup

# cd /local/home
# cp -Rp /home/local .

Now edit the /etc/passwd file to point to the new user directory.

local:x:1000:1000:local,,,:/local/home/local:/bin/bash

It is best to logout and relogin so the changes take hold.

3.4 Dropbox Setup

Dropbox is a useful service for syncing data with a VM.

3.4.1 Installing Dropbox

Dropbox should be installed at /local/software/services/Dropbox.

$ cd /local/software/services
$ wget -O - "https://www.dropbox.com/download?plat=lnx.x86_64" | tar xzf -
$ mv .dropbox-dist Dropboxd

Now you can edit the /etc/rc.local file so that Dropbox will be automatically started for specific users on reboot.

su local -c /local/software/services/Dropbox/dropboxd &

However you should first run the daemon on the command line as it will give you a URL that use to link the Dropbox daemon with your dropbox account. As the user account:

$ /local/software/services/Dropbox/dropboxd &