If you’ve never used Ansible before, you a) are in for a treat and b) might find these playbooks useful to learn from, since they show off a fair bit of what the tool can do.
Background and Motivations
I had been a paying Google Apps customer for personal and corporate use since the service was in beta. Until several weeks ago, that is. I was about to set up another Google Apps account for a new project when I stopped to consider what I would be funding with my USD $50 per user per year:
- A seriously questionable privacy track record.
- A dwindling commitment to open standards.
- A lack of long-term commitment to products.
- Development of Google+: a cynical and unimaginative Facebook ripoff that’s intruding into progressively more Google products.
To each her/his own, but personally I saw little reason to continue participating in the Google ecosystem. It had been years since I last ran my own server for email and such, but it’s only gotten cheaper and easier to do so. Plus, none of the commercial alternatives I looked at provided all the services I was looking for.
Rather than writing up a long and hard-to-follow set of instructions, I decided to share my server setup in a format that you can more or less just clone, configure, and run. Ansible seemed like the most appropriate way to do that: it’s simple, straightforward, and easy to pick up.
I’ve been using this setup for about a month now and it’s been great. It’s also replaced some non-Google services I used, saving me money and making me feel like I’ve got a little more privacy.
A big chunk of the initial version was inspired by this post by Drew Crawford. Unlike Drew, my goal is not “NSA-proofing” email, just providing a reasonable alternative to Google Apps that isn’t wildly insecure. If you need serious privacy and security (ex: for dissident activities), Sovereign might be useful as a starting point but will require additional work. Be careful out there.
What do you get if you point this thing at a VPS? All kinds of good stuff!
- IMAP over SSL via Dovecot, complete with full text search provided by Solr.
- SMTP over SSL via Postfix, including a nice set of DNSBLs to discard spam before it ever hits your filters.
- Webmail via Roundcube.
- Virtual domains for your email, backed by MySQL.
- Secure on-disk storage for email and more via EncFS.
- Spam fighting via DSPAM and Postgrey.
- Mail server verification via OpenDKIM, so folks know you’re legit.
- CalDAV and CardDAV to keep your calendars and contacts in sync, via ownCloud.
- Your own private Dropbox, also via ownCloud.
- Your own VPN server via OpenVPN.
- An IRC bouncer via ZNC.
- Monit to keep everything running smoothly (and alert you when it’s not).
- Web hosting (ex: for your blog) via Apache.
- Firewall management via ferm.
- Intrusion prevention via fail2ban and rootkit detection via rkhunter.
- SSH configuration preventing root login and insecure password authentication
- Nightly backups to Tarsnap.
- A bunch of nice-to-have tools like mosh and htop that make life with a server a little easier.
No setup is perfect, but the general idea is to provide a bunch of useful services while being reasonably secure and low-maintenance. Set it up, SSH in every couple weeks, but mostly forget about it.
Don’t want one or more of the above services? Comment out the relevant role in
site.yml. Or get more granular and comment out the associated
include: directive in one of the playbooks.
What You’ll Need
- A VPS (or bare-metal server if you wanna ball hard). My VPS is hosted at Linode. You’ll probably want at least 512 MB of RAM between Apache, Solr, and MySQL. Mine has 1024.
- Debian 7 or an equivalent Linux distribution. (You can use whatever distro you want, but deviating from Debian will require more tweaks to the playbooks. See Ansible’s different packaging modules.)
- A wildcard SSL certificate. You can either buy one or self-sign if you want to save money.
- A Tarsnap account with some credit in it. You could comment this out if you want to use a different backup service. Consider paying your hosting provider for backups or using an additional backup service for redundancy.
1. Get a wildcard SSL certificate
Generate a private key and a certificate signing request (CSR):
openssl req -nodes -newkey rsa:2048 -keyout roles/common/files/wildcard_private.key -out mycert.csr
Purchase a wildcard cert from a certificate authority, such as Positive SSL or AlphaSSL. You will provide them with the contents of your CSR, and in return they will give you your signed public certificate. Place the certificate in
Download your certificate authority’s combined cert to
roles/common/files/wildcard_ca.pem. You can also download the intermediate and root certificates separately and concatenate them together in that order.
Lastly, test your certificates using the
security program on Mac OS X:
security verify-cert -L -p ssl -s example.com -c roles/common/files/wildcard_public_cert.crt -c roles/common/files/wildcard_ca.pem ...certificate verification successful.
2. Get a Tarsnap machine key
Create a new machine key for your server:
tarsnap-keygen --keyfile roles/common/files/root_tarsnap.key --user firstname.lastname@example.org --machine example.com
3. Prep the server
For goodness sake, change the root password:
Create a user account for Ansible to do its thing through:
useradd deploy passwd deploy mkdir /home/deploy
Authorize your ssh key if you want passwordless ssh login (optional):
mkdir /home/deploy/.ssh chmod 700 /home/deploy/.ssh nano /home/deploy/.ssh/authorized_keys chmod 400 /home/deploy/.ssh/authorized_keys chown deploy:deploy /home/deploy -R
This account should be set up for passwordless sudo. Use
visudo and add this line:
deploy ALL=(ALL) NOPASSWD: ALL
4. Configure your installation
Modify the settings in
vars/user.yml to your liking. If you want to see how they’re used in context, just search for the corresponding string.
5. Run the Ansible Playbooks
First, make sure you’ve got Ansible installed.
To run the whole dang thing:
ansible-playbook -i ./hosts site.yml
To run just one or more piece, use tags. I try to tag all my includes for easy isolated development. For example, to focus in on your firewall setup:
ansible-playbook -i ./hosts --tags=ferm site.yml
You might find that it fails at one point or another. This is probably because something needs to be done manually, usually because there’s no good way of automating it. Fortunately, all the tasks are clearly named so you should be able to find out where it stopped. I’ve tried to add comments where manual intervention is necessary. OpenVPN in particular requires a bunch of manual command line intervention to get running.
6. Set up DNS
If you’ve just bought a new domain name, point it at Linode’s DNS Manager or similar. Most VPS services (and even some domain registrars) offer a managed DNS service that you can use for this at no charge. If you’re using an existing domain that’s already managed elsewhere, you can probably just modify a few records.
A record for
example.com as well as
mail.example.com which points to your server IP. Create an
MX record for
example.com which assigns
mail.example.com as the domain’s mail server.
Set up SPF and reverse DNS as per this post. Make sure to validate that it’s all working, for example by sending an email to email@example.com and reviewing the report that will be emailed back to you.
7. Miscellaneous Configuration
- Sign in to the ZNC web interface and set things up to your liking.
- You’ll probably want to sign into your ownCloud installation and check out the settings there, too.
How To Use Your New Personal Cloud
We’re collecting known-good client setups on our wiki.
If you improve one of the provided playbooks or add an exciting new one, send a pull request. Everyone benefits.
Original content is GPLv3, same as Ansible. All files and templates based on third-party software should be considered under their respective licenses.