Deploying Nanoc sites

Nanoc provides functionality for automating deployment through the nanoc deploy command. The automated deployment setup is described below.

The Nanoc configuration file (nanoc.yaml, or config.yaml on older sites) can contain a deploy section, such as the following:

deploy:
  default:
    kind: git
    remote: [email protected]:/srv/http/nanoc.ws.git
    branch: prod
    forced: true
  staging:
    kind: rsync
    dst:  "int.nanoc.ws:/srv/http/staging.nanoc.ws"

The deploy section describes deployment targets, which describe where to deploy to and how to do the deployment. In the example above, the targets are default and staging. The kind attribute describes the deployer to use. In the example above, git and rsync are used for the default and staging targets, respectively.

With GitHub Pages or Bitbucket

GitHub and Bitbucket are repository hosting services that support publishing websites. This section explains how to use their functionality for publishing a website in combination with Nanoc.

Disable .git pruning

Because GitHub Pages and Bitbucket both use Git to publish, it’s important to prevent the .git directory from being pruned away. In nanoc.yaml, look for a prune section, and if it exists, ensure that it has an exclude configuration option, and that it includes .git. The following is a correct set-up:

prune:
  auto_prune: true
  exclude: [ '.git' ]

GitHub Pages setup

The publishing of a website based on a Git repository to GitHub Pages is described in GitHub's help pages.

Clone the current repository into the output/ directory, create an orphaned branch dedicated to GitHub Pages named gh-pages, check out the new branch and remove everything in it:

% rm -rf output
% git clone . output
% cd output
[email protected]% git checkout --orphan gh-pages
[email protected]% git rm -rf .

Change the remote for this repository to point to the GitHub repository, rather than the local repository. To do so, execute the following git remote commands, replacing repo-url with the URL to the repository:

[email protected]% git remote rm origin
[email protected]% git remote add origin repo-url

Add the output/ directory to your .gitignore. Make sure that the base repository doesn’t contain the output/ directory.

Bitbucket setup

The publishing of a website based on a Git repository to Bitbucket is described in Bitbucket's help pages.

Bitbucket supports publishing a website at username.bitbucket.org, where username is your Bitbucket account name. The contents of the website will be read from a repository named username.bitbucket.org.

First of all, create a Bitbucket repository corresponding to your Bitbucket website address, e.g. ddfreyne.bitbucket.org.

Create a new Git repository inside the output/ directory, replacing repo-url with the URL to the repository (e.g. [email protected]:ddfreyne/ddfreyne.bitbucket.org.git):

% git init output/
% cd output/
output% git remote add origin repo-url

Add the output/ directory to your .gitignore. Make sure that the base repository doesn’t contain output/.

Automated deployment

To deploy the site using the nanoc deploy command, add a deployment target with the target git to the Nanoc configuration file (nanoc.yaml, or config.yaml on older sites):

deploy:
  default:
    kind: git
    branch: gh-pages

For Bitbucket, set branch to master, and for GitHub, set it to gh-pages.

Publish

To publish a site, compile it and run deploy:

% bundle exec nanoc
% bundle exec nanoc deploy

After a few seconds, the updated site will appear at http://username.github.io/repo-name for GitHub, or http://username.bitbucket.org for Bitbucket.

For GitHub, we recommend removing the gh-pages branch from the base repository, since it is likely to be out of sync with the gh-pages branch in the repository in the output/ directory.

With CI pipeline tools

It is possible to let CI pipeline tools, such as GitLab CI, perform the compilation and deployment. With this approach, git push is used rather than a nanoc deploy.

GitLab CI setup

The publishing of a website based on a Git repository to GitLab is described in GitLab Pages’s documentation pages. This guide assumes you are deploying to gitlab.com; please follow this documentation if you are running your own GitLab instance.

GitLab supports publishing a website at namespace.gitlab.io, where namespace is your GitLab account or group name. The contents of the website will be read from a repository named namespace.gitlab.io.

First of all, create a GitLab project corresponding to your GitLab website address, e.g. ddfreyne.gitlab.io.

GitLab Pages only serves content from the public/ directory, so rename the output/ directory to public/ and change the value of output_dir in nanoc.yaml to public.

Create a .gitlab-ci.yml file with the following content:

image: ruby:2.4
pages:
  script:
    - bundle install -j4
    - bundle exec nanoc
  artifacts:
    paths:
      - public
  only:
    - master

Push to trigger the build:

% git push -u origin master

GitLab CI will build and deploy the website. Once it has finished, the site will be accessible at namespace.gitlab.io.

Setting up checks

To run deployment checks, add bundle exec nanoc check --deploy to the .gitlab-ci.yml file, after bundle exec nanoc:

image: ruby:2.4
pages:
  script:
    - bundle install -j4
    - bundle exec nanoc
    - bundle exec nanoc check --deploy
  artifacts:
    paths:
      - public
  only:
    - master

A deploy will now only succeed if checks pass.

With Netlify

Netlify supports Nanoc out of the box, and deploying onto Netlify is as simple as giving it the Git repository containing your Nanoc site source.

With rsync

To use rsync as the deployment method, set kind to rsync in the deployment configuration, and set dst to the destination, in the format used by rsync. For example:

deploy:
  public:
    kind: rsync
    dst:  "stoneship.org:/var/www/sites/example.com/public"
  staging:
    kind: rsync
    dst:  "stoneship.org:/var/www/sites/example.com/public/staging"

By default, the rsync deployer will upload all files in the output directory to the given location. None of the existing files in the target location will be deleted, but existing files with the same name will be overwritten. To deploy, run deploy with the name of a target, like this:

% nanoc deploy staging

This will deploy using the “staging” configuration. Replace “staging” with “public” if you want to deploy to the location marked with “public”.

To check whether the executed rsync command is correct, perform a dry run by passing --dry-run. The rsync command will be printed, but not executed. For example:

% nanoc deploy public --dry-run

Deleting stray files

Nanoc will, by default, only update files that have changed, and not remove any files from the remote destination. If you want to let nanoc deploy remove any files on the destination that are not part of the Nanoc site, you can modify the options used for rsync to include --delete-after, like this:

options: [ '-aP', '--delete-after' ]
This will remove all files and directories that do not correspond to Nanoc items from the deployment destination.

With fog

fog is a Ruby gem for interfacing with various cloud services, such as AWS or Google Cloud.

To use fog for deployment, install the fog gem (or add it to the Gemfile and run bundle install). Change the deployment configuration in nanoc.yaml to reflect the fog configuration. Here is an example for Amazon S3:

deploy:
  default:
    kind:                  fog
    provider:              aws
    region:                eu-west-1
    bucket:                nanoc.ws
    aws_access_key_id:     AKIAABC123XYZ456MNO789
    aws_secret_access_key: fd6eb5b112a894026d7b82aab3cafadaa63fce39
    path_style:            true

The kind attribute, which identifies the kind of deployer to use, should be set to fog. You’ll also need to specify provider, containing the name of the fog provider that you want to use. Each provider has their own configuration; see the fog provider documentation for details. For buckets whose names contain periods, path_style should be set to true.

To publish your Nanoc site, use the deploy command, as usual:

% nanoc deploy
Loading site data… done
Connecting
Getting bucket
Uploading local files
Removing remote files
Done!
%