This article was originally published on https://lanre.wtf
I have been using Jekyll, Github pages plus Cloudflare to host my blog for a
while now. A simple push to my Github repo (adelowo.github.io) ===
a
deployment of my Jekyll site. They'd build it and deploy it automatically. For me, there was no infrastructure overhead.
While that is great, I wanted to have full control over the servers and software for a couple reasons.
- Selfhosting is (almost) always considered better.
- I want a real TLS certificate. While kudos should be given to Cloudflare for those free certificates, the way they basically work is "Connection is encrypted from the browser or client to Cloudflare which then proxies the request to the upstream server unecrypted". I strongly believe in security and would put anything except for a static site ( that does nothing interesting ) behind a TLS connection. But that has changed now, I am even putting static sites behind a TLS connection. Blog post by Troy Hunt
- Devops : At my place of work, alongside writing software, I also do a lot of system
administration setting up internal and external services - Awesome work by the way.
I would not call what I do Devops (modern Devops ???).
All internal and external facing APIs are written in Golang, and are just an
scp
away plus some restart logic (automated though). We use modern services (e.g we rely on consul heavily) but our deployment style is still pre Docker (pre Kubernetes ??? ). The next step of action for personal growth is improve on those administration skills and transform them into a more modern skillset, Devops. > We are not fans of Docker for production. We do make use of it for development though. > Although, there is a unstarted project in which we could benefit from dockerizing everything and using an orchestrator like Kubernetes.
Drone CI
Drone is a continous integration (s/integration/delivery) server written in Golang. But the most interesting thing is it's Docker usage. All build pipelines are executed in a container, makes perfect sense.
And since I moved from Github pages, I needed to be able to automate the
deployment as well. Push to a repo, the site is built and deployed.
I have set up a personal CI server at ci.lanre.wtf.
See installation docs on how to set up Drone CI .
Pipelines
Pipelines are the steps taken to build a project. For a larger project, it could
include a MongoDB server to run integration tests against, or just linting to make sure the code conforms to a certain quality. But for our Jekyll deployment, it is just
- Check site can be built by jekyll.. This is as simple as
bundle exec jekyll build
. Nothing more. - Copy the files to a remote location. I mean it's just
HTML
pages, nothing else to do.
Making sure the site builds
To do this, we would be needing the jekyll docker image since this build
pipeline is to run in a container. In your .drone.yml
file, add the following
;
pipeline:
build:
image: ruby
commands:
- gem install bundler
- bundle install
- bundle exec jekyll build
We use the standard ruby
container, install bundler, use bundler to install
the project's dependencies. After which we test to see if the repo still builds.
Continous Deployment
Awesome, we have set up continous integration to make sure the site doesn't
break randomly but we still need to be deeploy changes automatically. Since the
previous step built the site ( into the _site
directory ), all that is needed
is to copy those files to some location.
Here is where plugins in Drone CI come in. Plugins themselves too are regular
docker containers too. Write the plugin, then containerize it, capish.
I have choosen to make use of rsync
for this, so I am using this plugin for that. We would
be needing to supply some parameters to the plugin so it can do all the
hardlifting for us, they include the host, source file/directory, target on the
host, your private key .
You don't have to make your private key public. Drone has good support for
secrets.. Secret values are so flexible they can even be limited to a specific docker
image plus they aren't exposed on a PR. See docsThere is an scp plugin here if you want to
use that instead
To add our private key as a secret, we need to run the following :
drone secret add \
-repository repo/name \
-image drillster/drone-rsync \
-name rsync_key \
-value @./path_to_id_rsa
Note : You would have to do
export DRONE_SERVER=https://ci.yoursite.com
thenexport DRONE_TOKEN=TOKEN_HERE
. You can get your token at
https://ci.example.com/account/token plus it has a guide there anyways.
You can then update the .drone.yml
file
deploy:
image: drillster/drone-rsync
hosts: [ "example.com" ]
source: _site/*
target: ~/example.com
recursive: true
user: youruser
delete: true
secrets: [ rsync_key ]
You can also add your user as a secret stored in
rsync_user
though.
Your .drone.yml
should look like this now ;
pipeline:
build:
image: ruby
commands:
- gem install bundler
- bundle install
- bundle exec jekyll build
deploy:
image: drillster/drone-rsync
hosts: [ "example.com" ]
source: _site/*
target: ~/example.com
recursive: true
user: youruser
delete: true
secrets: [ rsync_key ]
There is an additional step you can take and that is making sure the deploy
pipeline runs on a push to master. This is to facilitate pull requests, you
wouldn't want PR builds to report as failed - remember secrets are not exposed
to a pull request, hence the deploy step
would always fail. To do that, you have to update your deploy step to include
when:
event: [ push ] ## Would run only on a push to master
branch: [ master ] ## Only the master branch can be deployed to production
You can take a look at the configuration that builds this site here plus my failed attempts at making sure this works
Top comments (0)