Auto deploying Gatsby with Gitlab

gatsbygitlabdeploymentautomationblog

Auto deploying Gatsby with Gitlab

When I was redesigning this site, i decided to use Gatsby for building the site for its flexibility and ease of use, while still being able to use React.js. Gatsby is great because of the ease of 3rd party integrations with various sources for both data and images. Unplash is a great one for quickly adding images to your blog, while others like Netlify and Ghost allow for better content management.

After I had installed gastby

npm install -g gatsby-cli

and setup the repo with

gatsby new my-blog

I was thinking about the best way to deploy this. I have had a server with Digital Ocean since 2014 that I have hosted a variety of personal projects on, mainly my personal spirits management app Scotchy.co. I decided that i wanted to maintain that server and continue hosting my blog myself. I was not, however, looking for a complicated deploy process as, after all, this is just my personal blog.

I had previously used the CI/CD pipelines on Gitlab for automated tests and deployment, so i figured that would be a pretty simple way to set it up. First I went to my repo and clicked the Setup CI/CD button

gitlab-create-ci-button

this give you a decent template, but still requires additional configuration as I wanted to have gitlab SSH into my server and pull the code on each master merge. The first step is to create a new ssh key on your server

ssh-keygen -t rsa -b 2048 -C "gitlab deploy"

Then I had to add the private key to gitlab under Repo -> Settings -> CI/CD -> Variables, clicking Add Variable and save it as SSH_PRIVATE_KEY. We will need to add 2 more variable as well, SERVER_IP and USER_NAME to be able to login during the deployment.

Now for the gitlab ci file. If you used the template creator I mentioned above, you will already have a .gitlab-ci.yml in your repo, if not just create one now

touch .gitlab-ci.yml

The first thing to do is to define the type of image you want it to run in. Gitlab supports a large variety of images, but for our purposes, node is sufficient

image: node:10

Next you need to tell the image where all the packages are

cache:
  paths:
    - node_modules/

Before the script build the gatsby files, we need to tell it how to to get onto the server. We can do this with a before_script section like so

before_script:
  - apt-get update -qq && apt-get install -y -qq rsync
  ##
  ## Install ssh-agent if not already installed, it is required by Docker.
  ## (change apt-get to yum if you use an RPM-based image)
  ##
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

  ##
  ## Run ssh-agent (inside the build environment)
  ##
  - eval $(ssh-agent -s)

  ##
  ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
  ## We're using tr to fix line endings which makes ed25519 keys work
  ## without extra base64 encoding.
  ##
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -

  ##
  ## Create the SSH directory and give it the right permissions
  ##
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh

Now you can define your actual jobs. You can add multiple here, and each with call the before_script call, but for me I only add a production run. The complete file looks like this

image: node:10

cache:
  paths:
    - node_modules/

before_script:
  - apt-get update -qq && apt-get install -y -qq sshpass rsync
  ##
  ## Install ssh-agent if not already installed, it is required by Docker.
  ## (change apt-get to yum if you use an RPM-based image)
  ##
  - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'

  ##
  ## Run ssh-agent (inside the build environment)
  ##
  - eval $(ssh-agent -s)

  ##
  ## Add the SSH key stored in SSH_PRIVATE_KEY variable to the agent store
  ## We're using tr to fix line endings which makes ed25519 keys work
  ## without extra base64 encoding.
  ## https://gitlab.com/gitlab-examples/ssh-private-key/issues/1#note_48526556
  ##
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -

  ##
  ## Create the SSH directory and give it the right permissions
  ##
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh

deploy_production:
  only:
    refs:
      - master
  stage: deploy
  environment: Production
  script:
    - yarn install
    - ./node_modules/.bin/gatsby build --prefix-paths
    - cd public/
    - ls
    - rsync -r --omit-dir-times -e "ssh -p 2189 -o StrictHostKeyChecking=no" . $USER_NAME@$SERVER_IP:/var/www/my-blog

Now each time you push your code to master or merge a PR to master, this will trigger, build the gatsby source and deploy to your server.