Aerobatic.io enticed me to use their free offer for static website hosting and, after days of struggling with their service to set things up, they suddently changed the offer to $15 a month for the same ($180 a year). Whereas I can understand business triggers behind this decision, I just can say I wasted a lot of time because of them. $180 for static website hosting is more than 10x more expensive than the competition. In the article below I’ll show how to get the same (and a lot more) for just $10.
Let’s start from describing what aerobatic really sells. They provide static website hosting generated by few static website generators (like Hugo or Jekyll). That means they only host static HTML and additionally provide two more features:
hugo
command, generating the HTML website from Hugo templates).Static website hosting is something you can get for few cents a month, so it looks these both points does cost $180 a year.
Ok, enough with complaining, let’s do it.
For me this is an ultimate and N-th time confirmed truth: your own machine will always be 100x better than any external services. You don’t have to rely on their support (like “I’ve clicked this button but it doesn’t work as expected” - after which you have to wait 3 days for someone who can check logs). You can use it for a lot of more purposes than the initial one. And first and the foremost - it’s extremely cheap nowadays.
You can easily choose and buy low-end VPS on lowendstock.com. I, for example, have bought nodeserv.com for $10 a year with 50GB HDD and 256MB RAM (which is perfectly enough for this use case and a lot more).
Initialize the machine by installing required software and setting up firewall. For static website hosting we will use lighttpd
package:
$ apt-get update
$ apt-get install wget ufw git lighttpd
Configure and install firewall:
$ ufw allow ssh
$ ufw allow http
$ ufw enable
Finally install your static website generator - I use Hugo:
$ wget https://github.com/spf13/hugo/releases/download/v0.18.1/hugo_0.18.1-64bit.deb
$ dpkg -r hugo_0.18.1-64bit.deb
$ rm hugo_0.18.1-64bit.deb
$ hugo version
Hugo Static Site Generator v0.18.1 BuildDate: 2016-12-30T05:05:34-05:00
Now it’s time to make a first checkout of bitbucket repository. As a first approach I’ve just used my git URL with previously configured ~/.git-credentials
. Unfortunately it turned out there’s a problem accessing git credentials from lighttpd CGI script. Then I’ve just used full URL with credentials and it apparently works from CGI:
$ mkdir -p /var/www/lifeinide.support/lifeinide.com
$ chown -R www-data:www-data /var/www/lifeinide.support/lifeinide.com
$ su www-data
$ cd /var/www/lifeinide.support/lifeinide.com
$ git clone https://MYUSER:MYPASS@bitbucket.org/MYREPO.git ./
You can now check if everything works without asking for credentials:
$ git pull
Already up-to-date.
Now, use you static website generator to build you website, which is hugo
command for Hugo generator:
$ su www-data
$ cd /var/www/lifeinide.support/lifeinide.com
$ hugo
Started building sites ...
Built site for language en:
0 draft content
0 future content
0 expired content
45 regular pages created
35 other pages created
0 non-page files copied
37 paginator pages created
30 tags created
total in 965 ms
In Hugo this process creates ./public
directory which contains whole generated static website. We will link it now to lighttpd htdocs directory. I configured multiple virtual hosts for my lighttpd for further usages, but if you don’t need this, it will be as simple as (if your /etc/lighttpd/lighttpd.conf
points to /var/www
as server.document-root
):
$ rm -rf /var/www
$ ln -s /var/www/lifeinide.support/lifeinide.com/public /var/www
Now, you should be able to display your website going to your server URL.
Now it’s time to move from cheap job (which costs few cents a month) to more expensive one, worth $180 a year. The automatic regeneration of website from the sources, triggered on bitbucket push webhook. Firstly we need to enable CGI module for lighttpd:
$ lighttpd-enable-mod
Disabled modules: ...
Enabled modules: ...
Enable module: cgi
We will setup bash intepreter for .sh
scripts accessed by HTTP editing /etc/lighttpd/conf-enabled/10-cgi.conf
:
# /usr/share/doc/lighttpd/cgi.txt
server.modules += ( "mod_cgi" )
$HTTP["url"] =~ "^/cgi-bin/" {
alias.url += ( "/cgi-bin/" => "/usr/lib/cgi-bin/" )
cgi.assign = ( ".sh" => "/bin/bash" )
}
Then you can create test script /usr/lib/cgi-bin/check.sh
(don’t forget to chmod 0755
it) to check if CGI works:
#!/bin/bash
echo "checking... ok :)"
And restart lighttpd:
$ /etc/init.d/lighttpd restart
Now you should execute you script after going to http://YOURSERVER/cgi-bin/check.sh.
The next work is to setup bitbucket webhook to point to website redeployment script. For the beginning I’d recommend to create a script with random name, which only bitbucket knows. It can be for example /usr/lib/cgi-bin/mysecretredeploymentscript.sh
. But before doing that you should create log file where it can send execution logs:
$ touch /var/log/bitbucket.log
$ chown www-data:www-data /var/log/bitbucket.log
Now, in your script you should put following test:
#!/bin/bash
LOG=/var/log/bitbucket.log
set >> $LOG
And then set the script URL as a bitbucket webhook:
After test push you can read /var/log/bitbucket.log
to check your HTTP_X_HOOK_UUID
, which is unique hook ID generated by bitbucket. We will use it in a while for additional script security:
$ grep HTTP_X_HOOK_UUID /var/log/bitbucket.log
HTTP_X_HOOK_UUID=of-course-this-is-not-my-weebhook-uuid
Having HTTP_X_HOOK_UUID
we can finally write our redeployment script:
#!/bin/bash
DATE=`date`
LOG=/var/log/bitbucket.log
CWD=`pwd`
echo "" >> $LOG
echo "" >> $LOG
echo "******* NEW WEBHOOK: $DATE *******" >> $LOG
if [ "$HTTP_X_HOOK_UUID" = "of-course-this-is-not-my-weebhook-uuid" ]; then
echo "HTTP VARS:"
set >> $LOG
echo "WEBHOOK EXECUTION:" >> $LOG
echo ~ >> $LOG
cd /var/www/lifeinide.support/lifeinide.com
git pull >> $LOG 2>&1
hugo >> $LOG 2>&1
else
echo "invalid HTTP_X_HOOK_UUID=$HTTP_X_HOOK_UUID" >> $LOG
fi
echo "thanks ;)"
cd $CWD
And enjoy own aerobatic-like service for $10 a year.
Here is the resources usage after few days of running (I’m on ssh, which seems to be the most expensive at the moment):
Tasks: 24 total, 1 running, 23 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0,5 us, 0,2 sy, 0,0 ni, 99,3 id, 0,0 wa, 0,0 hi, 0,0 si, 0,0 st
KiB Mem: 262144 total, 123424 used, 138720 free, 0 buffers
KiB Swap: 262144 total, 600 used, 261544 free, 102316 cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
22130 root 20 0 71212 3612 2804 S 0,0 1,4 0:00.17 sshd
22643 root 20 0 69880 3424 2652 S 0,7 1,3 0:00.02 sshd
22645 root 20 0 51232 2996 2368 S 0,0 1,1 0:00.00 sshd
1627 root 20 0 122m 2944 1244 S 0,0 1,1 0:13.43 rsyslogd
1827 www-data 20 0 86316 2340 1072 S 0,0 0,9 0:03.60 lighttpd
22132 root 20 0 19448 2332 1700 S 0,0 0,9 0:00.10 bash
1 root 20 0 30176 2040 1432 S 0,0 0,8 0:01.11 init
22642 root 20 0 23072 1620 1216 R 0,3 0,6 0:00.01 top
22644 sshd 20 0 51232 1556 864 S 0,0 0,6 0:00.00 sshd
1706 root 20 0 49888 1248 640 S 0,0 0,5 0:04.11 sshd
22646 sshd 20 0 51232 1144 508 S 0,0 0,4 0:00.00 sshd
104 root 20 0 21068 1100 796 S 0,0 0,4 0:00.00 udevd
1672 root 20 0 57568 992 404 S 0,0 0,4 0:00.00 saslauthd
1738 root 20 0 19520 968 768 S 0,0 0,4 0:00.00 xinetd
1848 root 20 0 14532 876 720 S 0,0 0,3 0:00.00 getty
1846 root 20 0 14532 864 716 S 0,0 0,3 0:00.00 getty
90 root 20 0 16988 860 668 S 0,0 0,3 0:00.01 upstart-udev-br
1778 root 20 0 18836 824 748 S 0,0 0,3 0:00.20 cron
163 root 20 0 21064 784 476 S 0,0 0,3 0:00.00 udevd
164 root 20 0 21064 784 476 S 0,0 0,3 0:00.00 udevd
328 root 20 0 15068 744 452 S 0,0 0,3 0:00.00 upstart-socket-
1674 root 20 0 57568 640 52 S 0,0 0,2 0:00.00 saslauthd
2 root 20 0 0 0 0 S 0,0 0,0 0:00.00 kthreadd/3428
3 root 20 0 0 0 0 S 0,0 0,0 0:00.00 khelper/3428