Setting Up Automated Backups for WordPress and Others to S3 with Serverpilot


Serverpilot is an automated server building solution, similar to forge from the creators of laravel.  These are great solutions for those of us who want to focus on building applications and programming and not on server maintenance.  While the server setup is not difficult, particularly for one or a few sites, if you have many sites on your server and many development environments with multiple ssl certificates, etc. these tools can save a lot of time and headaches.

While this is written for serverpilot, the majority of it is applicable regardless of what solution you use to manage your server, even if you set them up yourself.  Serverpilot will also run on vultr, digital ocean, or other vps providers, so there might be some other tailoring as well. Additionally, while serverpilot is often used with WordPress sites, this script will backup all databases and all files so it will work for drupal, processwire, anything you have on your server.

While serverpilot handles many aspects of managing your web sites, it doesn’t provide any backup services.  And while, vultr and digital ocean, for example, offer server wide backups these are impractical for many usages, particularly on servers with multiple sites for different clients.

On to the steps:

  1. ssh into your server
  2. su to root on your server and cd /tmp
    su -root
  3. Now download and setup the command line tools for amazon web services (AWS)
    curl "" -o ""
    unzip ** note that on serverpilot administered servers unzip is not available by default so you will need to apt-get install unzip
    ./awscli-bundle/install -b ~/bin/aws
  4. Now you need to configure with your keys
    aws configure ** if you don’t know how to get your keys, read this.
  5. Now you should be able to do a command like aws s3 ls (dir list of s3 buckets), if you cannot, you need to give the user associated with the keys you entered in the configuration appropriate s3 permissions.

Now we are going to setup the database backup script.  In serverpilot by default you have .my.cnf file which contains your root mysql password.  This means that commands like mysqldump do not require a password if run by this user.  You can create this file manually, or better, use mysql_config_editor (5.6+) to create mylogin.cnf which hashes the password.

  1. cd ~
  2. touch && chmod 700 && nano
  3. Enter the following into this file (modify as needed).  For the most part this would simple be changing the “ExcludeDatabases” line to contain any other databases you don’t want to backup.  If you only have one database you can drop all of that and just use the mysqldump command for that one database.  This script assumes you have multiple sites setup, otherwise you probably wouldn’t be using serverpilot anyhow…
    databases=`mysql -u mysqladminuser -e "SHOW DATABASES;" | tr -d "| " | egrep -v $ExcludeDatabases`
    for db in $databases; do
    echo "Dumping database: $db"
    mysqldump --add-drop-table -u mysqladminuser $db | bzip2 -c > /whereyouwantthem/backups/`date +%Y%m%d`.$db.sql.bz2

Now we will open the script and clean it up a bit and add our tar backups and then copy everything off to s3.  So nano and the entire script is below:

  1. #!/bin/bash
    databases=`/usr/bin/mysql -u mysqladminuser -e "SHOW DATABASES;" | tr -d "| " | /bin/egrep -v $ExcludeDatabases`
    TodaysDate=`date +%Y%m%d`#Setup or Clear Backups Directory
    if [ -d "$BackUpDir" ]; then
    rm $BackUpDir/*.bz2
    fiif [ ! -d "$BackUpDir" ]; then
    mkdir $BackUpDir
    fi#Dump all the Databases into Backup Directory
    for db in $databases; do
    echo "Dumping database: $db"
    /usr/bin/mysqldump --add-drop-table -u mysqladminuser $db | bzip2 -c > $BackUpDir/$TodaysDate.$db.sql.bz2
    doneExcludeDirectories="--exclude=/directory/to/exclude/*.jpg --exclude=/directory/to/exclude/logs"

    # This will copy all serverpilot user accounts and all of their files for a complete backup

    tar -cvpjf $BackUpDir/$TodaysDate.allsites.tar.bz2 $ExcludeDirectories /srv/users/

    #Copy Everything in the Directory to S3 for offsite backup
    #Occasionally you should delete some of these on aws to save space
    /usr/local/bin/aws s3 cp $BackUpDir/ s3://bucketname/$TodaysDate --recursive --include "*.bz2" --region your-region-1

  2. Then add this to the root (or admin user) crontab, crontab -e, to run, perhaps weekly on saturdays at 2am – 0 2 * * sun /root/

That’s about it, obviously you should tailor this for you own needs and also clean up your aws buckets from time to time so that you are not paying for storage you don’t need.  I hope this is helpful for others.

Postfix Relay Setup With Drupal and Basic Postfix Management


This article covers some basic steps to install the postfix mail server as a relay on Ubuntu, get Drupal to work properly in all mail environments, plus some general postfix management commands. These instructions may have to be adapted slightly to your environment and linux distribution, but they are generally applicable.

For more help in getting an intial server setup, please read Ubuntu Setup on a Linode VPS, and our PHP, Mysql, Apache Setup on Ubuntu articles.

  1. Postfix Installation
  2. Postfix Configuration Notes (As A Relay)
  3. Relaying Postfix Mail From Root – Localhost
  4. Drupal Email Configuration for Restrictive SMTP Servers
  5. Postfix Queue Management Commands

1. Postfix Installation

Below are the basic installation steps for postfix on an ubuntu server (many have it already installed). You can also use the drupal smtp module for this function but for high volume mailing and/or better control a local relay, such as postfix, is often helpful.

sudo apt-get install postfix If already installed you can reconfigure it by issuing the following command:
sudo dpkg-reconfigure postfix
Then enter the following for our purposes of setting up a relay:

Choose Satellite Configuration
System Mail Name: your maildomain name
SMTP relay (we often use authsmtp, but whatever your ISP smtp server is wold go here)
Root and Postmaster mail recipient:
Other destinations to accept mail for: localhost.localdomain,localhost (accept defaults)
Force synchronous updates on mail queue: No, unless you know what you are doing
Local Networks: defaults
Procmail for local delivery: Yes
Mailbox size limit: 0
Local address extension character: +
Internet Protocol:All

2. Postfix Configuration

If you ran the reconfigure command above you are most of the way there, but you should edit your config file anyhow and look over the following. It should look like this:

sudo nano /etc/postfix/

myhostname =
mydomain =
myorigin = localhost
smtpd_banner = $myhostname ESMTP $mail_name
biff = no
append_dot_mydomain = no
alias_maps = hash:/etc/aliases
alias_database = hash:/etc/aliases
mydestination = localdomain, localhost, localhost.localdomain, localhost
mynetworks =
mailbox_size_limit = 0
recipient_delimiter = +
# SECURITY NOTE: Listening on all interfaces. Make sure your firewall is
# configured correctly
inet_interfaces = loopback-only
relayhost = ## whatever your is
smtp_connection_cache_destinations =
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = static:username:password
smtp_sasl_security_options = noanonymous
default_destination_concurrency_limit = 4 ## to stay within your ISP’s policy
soft_bounce = yes
inet_protocols = all

Then make sure your aliases are ok:

You then want edit your /etc/aliases file (sudo nano /etc/aliases) and fill it out for your needs:

# See man 5 aliases for format
postmaster:    root

After this you can run:

sudo newaliases

And finally restart postfix

sudo /etc/init.d/postfix restart

3. Relaying Postfix Mail From Root – Localhost

As we have setup postfix above to relay all mail to an external smtp server you will lose mail from root – or root@localhost accounts.  To remedy this you can setup an alias via the following steps:

# cd /etc/postfix
# touch canonical
# echo "sender_canonical_maps = hash:/etc/postfix/canonical" >> /etc/postfix/
# echo "root" > /etc/postfix/canonical
# echo "root@localhost >> /etc/postfix/canonical
# postmap /etc/postfix/canonical
# /etc/init.d/postfix restart

To Test:
# echo TEST | mail -s TEST

4. Drupal Email Configuration for Restrictive SMTP Servers

By default, drupal doesn’t work well with ISP that require appropriately formed From and Reply-To Headers. There are issues in the queue to have this work properly in version 7 but for 5 and 6 you will need to edit the core contact module (sites/modules/contact.module).

Below is a copy of the patch file for version 5 of drupal, but it is very close to 6. It is best to edit the file yourself rather than try to submit this as a patch as we have other edits in the file and the line numbers may not be correct for you.

+++ contact.module 2009-01-29 20:48:45.000000000 -0500
@@ -418,10 +418,17 @@ function contact_mail_user_submit($form_
// Prepare all fields:
$to = $account->mail;
if ($user->uid) {
–    $from = $user->mail;
+//    $from = $user->mail;
+// Changed To Set Proper From and Reply-To And Add New Variable For User Copy
+ $usercopy = $user->mail;
+ $from = variable_get(‘site_mail’,”);
+ $headers = array(‘Reply-To’ => $user->mail);
else {
–    $from = $form_values[‘mail’];
+//    $from = $form_values[‘mail’];
+// Changed To Set Proper From and Reply-To
+ $from = variable_get(‘site_mail’,”);
+ $headers = array(‘Reply-To’ => $form_values[‘mail’]);

// Format the subject:
@@ -431,11 +438,14 @@ function contact_mail_user_submit($form_
$body = implode(“nn”, $message);

// Send the e-mail:
–  drupal_mail(‘contact-user-mail’, $to, $subject, $body, $from);

+//  drupal_mail(‘contact-user-mail’, $to, $subject, $body, $from);
+//  Changed To Add Headers
+ drupal_mail(‘contact-user-mail’, $to, $subject, $body, $from, $headers);
// Send a copy if requested:
if ($form_values[‘copy’]) {
–    drupal_mail(‘contact-user-copy’, $from, $subject, $body, $from);
+//    drupal_mail(‘contact-user-copy’, $from, $subject, $body, $from);
+//  Changed To Add Headers
+    drupal_mail(‘contact-page-copy’, $from, $subject, $body, $from, $headers);

5. Postfix Queue Management Commands

Now that you have everything working correctly, here are some useful postfix commands

# mailq  (show items in the queue – when you are relaying this is generally failed items)
# postcat -q queueid (read the contents of a message in the queue)
# postqueue -f (try to deliver all items in the queue immediately)
# postsuper -d ALL (remove all items in the queue)

Linux VPS Apache And Virtual Hosts Setup


This article contains the basic information to setup Mysql and Apache on an Ubuntu Linux VPS or Dedicated Server. This setup includes instructions on a virtual hosts setup with two main domains, one of which that has two subdomains. These instructions will likely need to be tailored to your local environment, but the basics are here.

If you haven’t yet setup your server, please read our Ubuntu VPS/Diedicated Server Setup article to help get you started.

These instructions should work on any linux distribution and the apache configuration information should be nearly universal. Some of the install lines will change depending on your linux distribution but for debian based distro’s these should work just fine.

1. Login in to your server

2. Installation of Apache

sudo aptitude install apache2 apache2.2-common apache2-mpm-prefork apache2-utils libexpat1 ssl-cert

sudo nano /etc/apache2/apache2.conf

add ServerName yourserver

sudo apache2ctl graceful (domain name error is now gone)

sudo nano /etc/apache2/sites-available/default

uncomment – RedirectMatch ^/$ /apache2-default/

sudo /etc/init.d/apache2 reload

3. Installation of PHP

sudo aptitude install libapache2-mod-php5 php5 php5-common php5-curl php5-dev php5-gd php5-imagick php5-mcrypt php5-memcache php5-mhash php5-mysql php5-pspell php5-snmp php5-sqlite php5-xmlrpc php5-xsl

sudo /etc/init.d/apache2 reload

4. Installation of MySQL

sudo aptitude install mysql-server and set server when asked “+++”

Now you have Apache, PHP, and MySQL installed and ready to be configured. Following is some basic Apache 2 Configurations for 2 Main Hosts, 1 with 2 Virtual Hosts. The file locations, etc. are all up to personal preference, but the following file locations are just as good as any. The apache settings in particular will need to be fine tuned for various situations, we use Drupal extensively – so these are sufficient for most small to medium sized Drupal (or other database driven CMS’s) sites.

5. Apache Configurations

sudo nano /etc/apache2/apache2.conf

Timeout 300 -> 100

MaxKeepAliveRequests 100 -> 200

KeepAliveTimout 15 -> 5

ServerTokens Full -> Prod

ServerSignature On -> Off

6. Apache2 Virtual Hosts Setup (using /srv/ as document root – you can use anything else)

mkdir -p /srv/{public,private,logs,cgi-bin,backup}

mkdir -p /srv/{public,private,logs,cgi-bin,backup}

Add the following to the bottom of /etc/apache2/apache2.conf

NameVirtualHost *:80

<IfModule mod_ssl.c>

NameVirtualHost *:443


sudo nano /etc/apache2/sites-available/default

Remove NameVirtualHost and change to listen to port 80

So you should have:

<VirtualHost *:80>


at the top of your file

7. Setup First Virtual Host (replace “domain1″ with your hostname)

sudo nano /etc/apache2/sites-available/

Should look generally like:

++++Start File++++

# Place any notes or comments you have here

# It will make any customization easier to understand in the weeks to come

# domain:

# public: /srv/

# Admin email, Server Name (domain name) and any aliases




# Index file and Document Root (where the public files are located)

DirectoryIndex index.html

DocumentRoot /srv/

# Custom log file locations

LogLevel warn

ErrorLog /srv/

CustomLog /srv/ combined
++++End File++++

8. Setup Second Virtual Host (which also a domain alias and two independent Subdomains – replace hostname2., hostname2alias, sub1, and sub2 with your hostname, your top level domain alias, subdomain1 name, and subdomain2 name respectively)

sudo nano /etc/apache2/sites-available/

Should look generally like:

++++Start File++++

# Place any notes or comments you have here

# It will make any customisation easier to understand in the weeks to come

# domain:

# public: /srv/

# Admin email, Server Name (domain name) and any aliases




UseCanonicalName Off



# Index file and Document Root (where the public files are located)

DirectoryIndex index.html

DocumentRoot /srv/
Options Indexes FollowSymLinks +Includes

AllowOverride All

Order allow,deny

allow from all

# Custom log file locations

LogLevel warn

ErrorLog /srv/

CustomLog /srv/ combined

ScriptAlias /cgi-bin/ /srv/

# Admin email, Server Name (domain name) and any aliases




# Index file and Document Root (where the public files are located)

DirectoryIndex index.html

DocumentRoot /srv/

# Custom log file locations

LogLevel warn

ErrorLog /srv/

CustomLog /srv/ combined

# Admin email, Server Name (domain name) and any aliases






# Index file and Document Root (where the public files are located)

DirectoryIndex index.html

DocumentRoot /srv/

# Custom log file locations

LogLevel warn

ErrorLog /srv/

CustomLog /srv/ combined
++++End File++++

Now you can enable your sites – this command simply makes a symbolic link from sites-enabled to the configuration files you just setup in sites-available.

9. Enable Sites

sudo a2ensite

sudo a2ensite

Then Restart Apache:

sudo /etc/init.d/apache2 reload

The next section involves enabling the apache module mod_rewrite (and any other modules you require for your particular setup)

10. Enable mod_rewrite

sudo a2enmod rewrite

sudo /etc/init.d/apache2 force-reload

Basic EXIM Commands For SMTP Relay


Exim is an alternative mailhandler similar to postfix – with both being replacements for sendmail.  We generally use google apps for many of our domains, but some websites require outbound mail setups.  For this we tend to use authsmtp as our smtp relay service and setup exim or postfix to accomodate this.

The instructions below provide basic exim management commands, largely useful for debugging in a relay environment:

  • Queue Management
  • exim -bp ## list messages in the queue
  • exim -q -v ## send messages in queue
  • exim -Mrm <message-id> ## Message remove from queue
  • exiqgrep -i | xargs exim -Mrm ## Remove **all** messages in the queue
  • Message Management
  • exim -Mvh <message-id> ## Message view header
  • exim -Mvb <message-id> ## Message view body
  • exim -Mvl <message_id> ## Message view message log

APC Cache Installation on Ubuntu


This article covers the basics of setting of the APC PHP Cache on your Ubuntu Linux machine with the Apache web server. These instructions will also work for a variety of other linux distributions as well. This is part of our series on setting up a Linode VPS with a fully working PHP, Apache, MySQL setup with multiple domains.

The following articles may be of interest to you:
Basic Linode VPS Setup
PHP, Apache, MySQL Setup on Ubuntu
Drupal Setup on Ubuntu
APC, or the “Alternative PHP Cache” is a php module that can significantly effect performance on sites that makes heavy use of PHP, such as Drupal. Below you will find the steps necessary to install and enable the APC Cache on an Ubuntu server.
1. Install APC PHP Cache and Related Tools
sudo aptitude install php-pear
sudo aptitude install php5-dev (if not already)
sudo aptitude install apache2-dev
sudo pecl install apc
sudo echo "" > /etc/php5/apache2/conf.d/apc.ini
restart apache /etc/init.d/apache2 restart

Installation of Ubuntu Server on a Linode VPS With Basic Security Setup


This article will cover the installation of Ubuntu Linux (7.10) on a Linode VPS with startup management tasks, ip tables firewalling, and basic server security techniques. This article assumes you are using a linux machine locally as well, but for the majority you are using a simple ssh client, web browser, and an editor – so adapt these to your local configuration.

Note: While these instructions are for a VPS within Linode, they are essentially the same for any hosting company/distribution with the exception of some differences between debian based linux systems and redhat based ones (apt-get vs. yum, etc.).

If you don’t have a dedicated server, or a VPS, we often recommend Linode as your hosting company. Their support is quite good and their offerings are well provisioned. There are a vast number of hosting companies, but in our opinion Linode is one of the best.

1. Install Ubuntu 7.10 on linode (through the dashboard system, very easy…)

2. While waiting clear your local ssh known_hosts (if necessary, reinstall, etc.)

nano ~/.ssh/known_hosts  (remove all references to vps ip)

3. ssh in as your linode account to lish on your host and then login to your linode as root or for non linode customers (or linode users alternatively)

ssh root@yourip   – then change your pass


4. Create a new account (so you are not logging in as root)

adduser username

5. Grant new user su privileges

visudo  (at the end of the file add:)

username ALL=(ALL) ALL

6. Login & Set Hostname:


echo > /etc/hostname

This next section will setup SSH encryption between your local computer(s) and your server. These steps essentially disallow any logins besides those coming from a machine with your SSH key. If you need to travel from computer to computer you will need to perform these steps on all the computers you use. On linode (and other hosts) you can always login through the web interface provided through the dashboard management system.

Set up correctly, these steps stop any number of security attacks from randomly guessing the root password, etc. It enables a fairly high level of initial security.

7. SSH Keygen public/private key (stop logins with just a password)

On Local Machine:

mkdir ~/.ssh

ssh-keygen -t rsa (this makes 2 files – (public key) – id_rsa (private key)

Copy public key to Linode:

scp ~/.ssh/ username@ip:/home/username/

On Your Linode VPS:

mkdir /home/username/.ssh

mv /home/username/ /home/username/.ssh/authorized_keys


chown -R username:usergroup /home/username/.ssh

chmod 700 /home/username/.ssh

chmod 600 /home/username/.ssh/authorized_keys

8. SSH config

nano /etc/ssh/sshd_config

Change SSH Port to something (i.e. 30100, 30211, anything high really)

Protocol 2

PermitRootLogin no

Unpound AuthorizedKeyFiles…

PasswordAuthentication no

X11Forwarding no

UsePAM no

UseDNS no

AllUsers username

This next section runs through a basic configuration of the IP Tables Firewall system. There are many other helper applications for establishing a firewall on a linux machine, but doing it by hand helps people to understand the concepts involved.

9. Firewall setup (iptables)

iptables-save > /etc/iptables.up.rules

iptables -L

nano /etc/iptables.test.rules config below:

Below is a basic IP Tables Configuration File that locks nearly everything down. As you add services you can open required ports for traffic, but for most people this configuration will meet all their needs.

++++Begin File++++


#  Allows all loopback (lo0) traffic and drop all traffic to 127/8 that doesn’t use lo0

-A INPUT -i lo -j ACCEPT

-A INPUT -i ! lo -d -j REJECT

#  Accepts all established inbound connections


#  Allows all outbound traffic

#  You can modify this to only allow certain traffic


# Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)

-A INPUT -p tcp –dport 80 -j ACCEPT

-A INPUT -p tcp –dport 443 -j ACCEPT

#  Allows SSH connections




-A INPUT -p tcp -m state –state NEW –dport 30000 -j ACCEPT

# Allow ping

-A INPUT -p icmp -m icmp –icmp-type 8 -j ACCEPT

# log iptables denied calls

-A INPUT -m limit –limit 5/min -j LOG –log-prefix “iptables denied: ” –log-level 7

# Reject all other inbound – default deny unless explicitly allowed policy




++++End File++++

10. Store new IP Tables Information

iptables-restore > /etc/iptables.test.rules

iptables -L

iptables-save > /etc/iptables.up.rules

11. Ensure iptables loads at startup

nano /etc/network/interfaces

after iface…

pre-up iptables-restore > /etc/iptables.up.rules

12. Test connections (don’t logout yet!)

/etc/init.d/ssh reload

From a new local terminal test ssh:

ssh -P portyouset username@yourip

13. Set Locale

sudo locale-gen en_US.UTF-8

sudo /usr/sbin/update-locale LANG=en_US.UTF-8

14. Reboot and login as your newuser via the ssh command:

ssh -P portyouset username@yourip

Now that you have established your ssh keys and a connection and locked down the majority of the open ports on the computer you can setup your local environment. These can be changed according to your needs – just a basic setup that many people will find satisfactory.

15. Configure your local environment

nano ~/.bashrc

export PS1='[�33[0;32m]h[�33[0;36m] w[�33[00m]: ‘

alias dir=”ls -lartF”

alias free=”free -m”

alias update=”sudo aptitude update”

alias install=”sudo aptitude install”

alias upgrade=”sudo aptitude safe-upgrade”

alias remove=”sudo aptitude remove”

16. Get Your Ubuntu Server up to date

sudo nano /etc/apt/sources.list

enable all repositories

sudo aptitude update

sudo aptitude safe-upgrade

sudo aptitude full-upgrade

Finally install the build essentials package which has the tools necessary to install apache, mysql, and other applications you are going to install on your server.

17. Install build essentials

sudo aptitude install build-essential

Install PHPMyAdmin On A Linux VPS


This article covers the basics of setting of PHPMyAdmin to manage your MySQL databases on your Ubuntu Linux machine. These instructions will also work for a variety of other linux distributions as well. This is part of our series on setting up a Linode VPS with a fully working PHP, Apache, MySQL setup with multiple domains.

The following articles may be of interest to you:
Basic Linode VPS Setup
PHP, Apache, MySQL Setup on Ubuntu
Drupal Setup on Ubuntu

1. PhpMyAdmin Setup
sudo aptitude install phpmyadmin
This sets up phpmyadmin at your default server /phpmyadmin
PhpMyAdmin uses the following components/locations by default:


Below is a minor security change to the location of phpmyadmin to offset hackers who try to break in via the interface by going to . This isn’t all that strong, but every little thing helps.

2. Minor PhpMyAdmin Security Change
sudo nano /etc/apache2/conf.d/phpmyadmin.conf
Change Alias /myphpalias to /usr/share/phpmyadmin
Then available at http://domainname/myphpalias instead of phpmyadmin