Github pages inspired static site server which can run on your own server and deploy automatically using CI.
An example: https://tutorcruncher.com is deployed using nginx pages, you can view the site's repo on github.
Static sites builders like jekyll are very cool and deploying them using github pages is extremely convenient, however HTTPS is becoming more and more important for SEO.
HTTPS isn't the only win you get by moving beyond github pages; there are a myriad of other reasons why you might want the flexibility of deploying your site on a server you control. (The chances are, if you care about those reasons you can work them out for yourself, so I'll spare you the rant.)
We want the easy of updating sites with github pages while deploying to a server under our command.
The advent of very cheap, easy to use virtual servers and free CI means you can deploy on your own server for just a few $/£/€ a month.
nginx-pages uses:
- nginx to serve the site.
- letsencrypt to generate signed SSL certificates easily and for free.
- travis to build the site, check it's good and send the freshly built site to your server. Other CI services and manual deploy should work fine too.
- jekyll to build your site. Other static site generators should work fine too, but the example below assumes jekyll.
- scp to transfer the built site to your server, travis's encrypted environment variables mean this works even with public repos, see below.
- http2 the
vanilla.sh
install script installs the latest version of nginx which supports the much improved new version of http. Thehttp_setup.sh
script configures nginx to serve your site using http2. - scaleway are a great option as their virtual server at €2.99/month are very cheap. Obviously any other IaaS provider should work just as well.
The basic work flow of setting up nginx-pages is very simple:
- Use
vanilla.sh
to install requirements on a fresh Ubuntu virtual server - Use
scp_setup.sh
to setup a new user with limited permissions who can scp new sites to your server - Use
http_setup.sh
to setup nginx with the right sites. - scp a zip file containing staic file for your site to the server and it will be automatically deployed.
This has been tested on a fresh install of Ubuntu 16.04 LTS.
sudo apt-get update && sudo apt-get install wget
wget -O- https://raw.githubusercontent.com/samuelcolvin/nginx-pages/master/vanilla.sh | sh
In theory a machine image could be taken at this point and reused on different servers, but I haven't got round to that yet.
Note: nginx-pages doesn't work with scaleway's "C1" ARM based bare metal servers as their hardware doesn't support ipv6 which nginx expects, see this issue.
You now need to setup scp and nginx, to setup scp:
sudo /nginx-pages/scp_setup.sh
Which should create an ssh key for the user "bob" and print it to the terminal, the file itself will
be available in working directory as bob_key
. You'll use this key later to transfer new sites to the server.
You'll want to copy & paste it or scp it back home.
Setup nginx (the http server):
sudo /nginx-pages/http_setup.sh www.example.com
(where you obviously want to replace www.example.com
with your domain)
This will use letsencrypt to create ssh keys and setup nginx to use them.
done
The watch service should now be live (you can check with systemctl status watch
) and nginx running.
If you write to /home/bob/site.zip
the contents should be extracted and then served by nginx.
Every site build adds a /build.txt
file to your site which gives some details on the most recent build.
See https://tutorcruncher.com/build.txt for an example.
You should now be able to deploy to your server using scp, note the zip command to make sure the root
directory of the zip file is correct. Here we assume you're using jekyll so the built site is in _sites
.
#> jekyll build
#> (cd _site/ && zip -r - .) > site.zip
#> scp -i bob_key site.zip [email protected]:site.zip
(assuming you have the bob_key
file from above in your working directory)
Travis allows you to create encrypted files which are not available in fork pull requests.
This in turn allows you to encrypt the private key bob_key
generated above. Once you have the
travis cli installed and have download bob_key
to the root git
directory of the site you wish to deploy run:
# to create a random password
bob_key_pass="$(openssl rand -base64 32)"
# print the password for your reference (you probably won't need to know it at any point)
echo "bob_key_pass = $bob_key_pass"
# encypt bob_key with the password and delete the original
openssl aes-256-cbc -k $bob_key_pass -in bob_key -out bob_key.enc
rm bob_key
# add bob_key_pass as a secure variable to .travis.yml
travis encrypt bob_key_pass=$bob_key_pass --add
# download deploy.sh
curl https://raw.githubusercontent.com/samuelcolvin/nginx-pages/master/deploy.sh > deploy.sh
chmod a+x deploy.sh
This should have automatically edited your .travis.yml
file, you'll need to edit it further to call
deploy.sh
. In the end the file should look something like:
language: ruby
rvm:
- 2.1
script:
- bundle exec jekyll build
- bundle exec htmlproofer _site
env:
global:
- NOKOGIRI_USE_SYSTEM_LIBRARIES=true
- domain: <your domain name>
- secure: <your secure variable for bob_key_pass>
after_success:
- ./deploy.sh
(this is an example with site build using jekyll, see https://github.com/tutorcruncher/tutorcruncher.com
for a full example including the Gemfile
which the build commands require.)
You might want to modify the /etc/nginx/sites-enabled/main
eg. to tell nginx to use your own 404.html
.
...
error_page 404 /404.html;
location = /404.html {
root /var/www/html;
internal;
}
}
(any changes to /etc/nginx/sites-enabled/main
will be overwritten if you call http_setup.sh
again.)
(Really just a note for me, with luck you can ignore this)
A few useful commands when debugging the watch service (or indeed any other service):
# a summary of the current status of watch
service watch status
# to restart watch (will rebuild the site)
service watch restart
# journalctl live
journalctl -f
# journalctl live filtered to just this watch.service
journalctl -f _SYSTEMD_UNIT=watch.service
# journalctl live showing only error level logs
journalctl -f -p err
journalctl
can also show important information about nginx
and sshd
.