First post here, but yeah I thought I’d document how I got this blog up and running on a Droplet running Ubuntu 14.04.

Guide


Blog Set Up


To get started with the blog, we are using awesome jekyll

now I really like to use rvm so I will assume that going forward, so if you need help setting it up locally follow that link.

gem istall jekyll

Now to get the most basic blog up and going, you can use

$ gem install jekyll
~ $ jekyll new blog
~ $ cd blog
~/blog $ jekyll serve
# => Now browse to http://localhost:4000

and boom! We are now serving the basic jekyll blog locally on port 4000.

To set up our basic git repo for github we can use the following commands.

be sure to change your origin to the repo you create on github

$ git init 
$ git add . # add all files 
$ git commit -m "First Commit" # commit message
$ git remote add origin git@github.com:danmanstx/blog.git
$ git push -u origin master


Server (Droplet) Set Up


To begin, I had a preconfigued droplet with a few rails apps aready on it and rvm (guide). In this case the droplet was the 1gb for $10/month, and this seems more than enough for running 3 rails apps and hosting this blog.

To get multiple users set up and going on your droplet use this guide. Following along, my new user is named rails and I just run the apps straight out of folders in its home directory for convenience. However Common practice is to use something like www

So to start, I created another folder for my blog as the rails user, and set up some needed default folders.

# switch to rails user if you aren't already 
$ sudo su - rails
~ $ mkdir blog
~ $ cd blog
~/blog $ mkdir shared 
~/blog $ mkdir shared/log

Just be sure this user doesn’t have root access and only owns these folders.

Next, I got NGINX installed.

sudo apt-get install nginx

simple enough right? Well, now we need to configure it. I don’t believe i changed much in this file /etc/nginx/nginx.conf, but here it is.

 1 user www-data;
 2 worker_processes 4;
 3 pid /run/nginx.pid;
 4 
 5 events {
 6   worker_connections 768;
 7   # multi_accept on;
 8 }
 9 
10 http {
11   # Basic Setting  
12   sendfile on;
13   tcp_nopush on;
14   tcp_nodelay on;
15   keepalive_timeout 65;
16   types_hash_max_size 2048;
17   
18   server_names_hash_bucket_size 64;
19   # server_name_in_redirect off;
20 
21   include /etc/nginx/mime.types;
22   default_type application/octet-stream;
23 
24   # SSL Setting
25   ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
26   ssl_prefer_server_ciphers on;
27 
28   # Logging Setting
29   access_log /var/log/nginx/access.log;
30   error_log /var/log/nginx/error.log;
31 
32   # Gzip Setting
33   gzip on;
34   gzip_disable "msie6";
35 
36   # Virtual Host Config
37   include /etc/nginx/conf.d/*.conf;
38   include /etc/nginx/sites-enabled/*;
39 }

However, I did have to create a site configuration file in sites-available using the following command:

sudo vi /etc/nginx/sites-available/<your_site_name>.conf

be sure to note that you probably don’t want to use <your_site_name>

Next, I just created a basic server block that looks at a directory named for my blog in the rails user’s home directory.

 1 server {
 2   listen 80;
 3   server_name dannypeters.me www.dannypeters.me;
 4 
 5   access_log /home/rails/blog/shared/log/nginx.access.log;
 6   error_log /home/rails/blog/shared/log/nginx.access.log;
 7 
 8   location / {
 9     root /home/rails/blog/current/public/;
10     index index.html index.htm;
11   }
12 }

Now to follow nginx convention i symlinked this config file to the sites-enabled folder

ln -s /etc/nginx/sites-available/<your_site_name>.conf /etc/nginx/sites-enabled/<your_site_name>.conf


Capistrano Set Up


this is done on your local machine

To begin we need to make sure that Capistrano is installed, if not

gem install capistrano

and then set up a Gemfile to monitor the gems we will be using.

~/blog $ vi Gemfile

1 source 'https://rubygems.org'
2 
3 ruby '2.1.5'
4 gem 'jekyll'
5 gem 'capistrano-rvm'
6 gem 'capistrano-bundler'
7 
8 gem 'rvm1-capistrano3', require: false

Next, we need to capify our blog. Just run the following command from your blog directory.

with capistrano 2.x this command was capify

$ cap install

Now we need to edit some of the files it created.


First, Capfile, we need to add require 'rvm1/capistrano3' because we are using rvm, and also uncomment some things.

 1 # Load DSL and set up stages
 2 require 'capistrano/setup'
 3 
 4 # Include default deployment tasks
 5 require 'capistrano/deploy'
 6 
 7 require 'capistrano/rvm'
 8 require 'rvm1/capistrano3'
 9 # require 'capistrano/rbenv'
10 # require 'capistrano/chruby'
11 require 'capistrano/bundler'
12 # require 'capistrano/rails/assets'
13 # require 'capistrano/rails/migrations'
14 # require 'capistrano/passenger'
15 
16 # Load custom tasks from `lib/capistrano/tasks' if you have any defined
17 Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }


Next, Our config/production.rb file, be sure to edit the server line with your settings.

 1 set :stage, :production
 2 
 3 # Extended Server Syntax
 4 # ======================
 5 # This can be used to drop a more detailed server definition into the
 6 # server list. The second argument is a, or duck-types, Hash and is
 7 # used to set extended properties on the server.
 8 
 9 server 'xxx.xxx.xxx.xxx', user: 'rails', port: 22, roles: %w{web app}
10 
11 set :bundle_binstubs, nil
12 
13 set :bundle_flags, '--deployment --quiet'
14 set :rvm_type, :user
15 
16 
17 SSHKit.config.command_map[:rake]  = "bundle exec rake"
18 SSHKit.config.command_map[:rails] = "bundle exec rails"
19 
20 namespace :deploy do
21 
22   desc "Restart application"
23   task :restart do
24     on roles(:app), in: :sequence, wait: 5 do
25       # execute :touch, release_path.join("tmp/restart.txt")
26     end
27   end
28 
29   after :finishing, "deploy:cleanup"
30 
31 end


Finally, We need to set up the deploy.rb file.

The key here is this bit of code which builds your jekyll blog into the public folder so you don’t need to compile and commit before each deploy. It’s my build_public task below.

 1 # config valid only for Capistrano 3.1
 2 # lock '3.2.1'
 3 
 4 set :application, 'blog'
 5 set :repo_url, "git@github.com:danmanstx/#{fetch(:application)}.git"
 6 
 7 # Default deploy_to directory is /var/www/my_app
 8 set :deploy_to, "/home/rails/#{fetch(:application)}"
 9 
10 # Default value for :scm is :git
11 set :scm, :git
12 
13 # Default value for :log_level is :debug
14 set :log_level, :debug
15 
16 # Default value for keep_releases is 5
17 set :keep_releases, 5
18 
19 namespace :deploy do
20 
21   desc 'Restart application'
22   task :restart do
23     on roles(:app), in: :sequence, wait: 5 do
24       # Your restart mechanism here, for example:
25       # execute :touch, release_path.join('tmp/restart.txt')
26     end
27   end
28 
29   before :restart, :build_public do
30     on roles(:app) do
31       within release_path do
32         execute '/home/rails/.rvm/gems/ruby-2.1.5/wrappers/jekyll',  "build --destination public"
33       end
34     end
35   end
36 
37   after :publishing, :restart
38 
39 end

At fist I was getting the following error:

remote: /usr/bin/env: ruby_executable_hooks: No such file or directory

So I switched from using the following command calling jekyll directly and ended up using the rvm wrapper, with help from this stack overflow answer

1 execute :jekyll, "build --destination public"`

became:

1 execute '/home/rails/.rvm/gems/ruby-2.1.5/wrappers/jekyll',  "build --destination public"


Deploying


Finally, any new post or updates can be commited and deployed using the following commands.

$ git add .
$ git commit -m "new post"
$ git push
$ cap production deploy


Congratulations you are now a blogger. 🍻