I'd been meaning to move my website to a new host for awhile, away from a Dreamhost VPS to a fully controlled VM of my own, but I was kind of forced to finally do it when I managed to rm -r the wrong directory on my VPS while I was in Vietnam. Not the end of the world -- my site is fully checked into GitHub and Ansiblized, so I could have quickly redeployed... but I didn't. I decided to use the opportunity to finally migrate to that new VM host.
I also decided to revisit a couple of deployment items as well...
- CertBot is packaged now which makes Let's Encrypt certs even easier
- HTTP/2 is actually really easy with apache, as long as you're using a version of apache that supports it (Ubuntu 16.04 doesn't come with that version currently, but here's a way around that)
- Mozilla has this awesome project called Observatory, which makes checking your site security settings really simple, as well as offering suggestions to improve your configuration (check out the Grade History on my site scan to see my improvement)
I'm still working on fully updating the Ansible deployment and update for my site, especially with my apache config updates, but eventually I'll have it checked into GitHub. In fact, I'm still working on a few remaining improvements on the apache config. By implementing this additional config security, I also revealed some bad coding practices on my site that I needed to fix, especially around inline html/css. Whoops.
TL;DR, not the ideal apache config yet, but getting closer.
ServerName bronwynlewis.com ServerTokens Prod ServerSignature Off <IfModule security2_module> SecRuleEngine on ServerTokens Full SecServerSignature " " </IfModule> [...] <IfModule mod_ssl.c> <VirtualHost *:443> [...] Header always set Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" </VirtualHost> </IfModule> [...]
For the SSL configuration (omitted here), I used Mozilla's SSL Config Generator.
Finally, here were some other settings in the config recommended by Observatory (plus a line for enabling HTTP/2 globally):
[...] # HTTP/2 globally Protocols h2 h2c http/1.1 ## Mozilla Observatory recommendations # Block site from being framed with X-Frame-Options and CSP # Header set Content-Security-Policy # Disable unsafe inline/eval and plugins, only load scripts and stylesheets from same origin, fonts from google, and images from same origin. Sites should aim for policies like this. #Header always set Content-Security-Policy: "frame-ancestors 'none'; default-src 'none'; font-src 'https://fonts.googleapis.com'; img-src 'self'; object-src 'self'; script-src 'self'; style-src 'self'" # Current working CSP... need to make website code improvements to make more strict Header always set Content-Security-Policy: "frame-ancestors 'none'; default-src 'none'; font-src 'https://fonts.googleapis.com'; object-src 'self'; script-src 'self' 'https://code.jquery.com' 'https://*.googleapis.com' 'https://apis.google.com'; img-src 'self' data:; style-src 'self' 'unsafe-inline'" Header always set X-Frame-Options "DENY" # Block pages from loading when they detect reflected XSS attacks Header always set X-XSS-Protection: 1;mode=block # Prevent browsers from incorrectly detecting non-scripts as scripts Header always set X-Content-Type-Options: nosniff # The browser will only set the referrer header on requests to the same origin Header always set Referrer-Policy: same-origin
Observatory was really helpful, but even when it pointed me in the right direction, a bit of research was usually required to actually get it right and working.
I also ran into a DNS issue, where I thought that my registrar was talking care of my MX records, but in fact didn't, so I ended up not having any email for ~24 hours (when I noticed the issue). Whoops. But that also led to me learning some useful things.
@ A 126.96.36.199 www A 188.8.131.52 mail CNAME ghs.googlehosted.com @ MX 1 ASPMX.L.GOOGLE.COM @ MX 5 ALT1.ASPMX.L.GOOGLE.COM @ MX 5 ALT2.ASPMX.L.GOOGLE.COM @ MX 10 ALT3.ASPMX.L.GOOGLE.COM @ MX 10 ALT4.ASPMX.L.GOOGLE.COM @ TXT v=spf1 include:_spf.google.com ~all
Most of these are self-explanatory -- host IP address, Google MX records of varying priority, CNAME for mail... but that last one, I will admit I didn't actually know about SPF records.
Anyway, hopefully that's helpful to other folks. I definitely learned a lot in migrating my site.