A few months back I [built a tool]({{< relref "/dev/2019-05-21-my-site-on-gopher.md" >}}) to cross-compile my [Hugo](https://gohugo.io) blog into one that can be accessed via the [Gopher](https://en.wikipedia.org/wiki/Gopher_(protocol)) protocol. More recently, I built a CI/CD pipeline on my [GitLab](https://about.gitlab.com)* instance which automatically compiled and uploaded [my website to AWS]({{< relref "/ops/2015-10-20-cloudfront-and-chills.md" >}}). I won't cover that here, but I found a wonderful and [perfect guide for it](https://alm-research.com/blog/deploying-hugo-on-aws-with-gitlab-ci/). Sometime yesterday I decided to take this all one step further and integrate my [`hugogopher`](https://github.com/judges119/hugogopher) into that CI/CD pipeline. This means every time I commit a new post, not only does the blog get uploaded to the world wide web, but another version of it is compiled to a Gopher site and uploaded to the server that I have running. ## Prerequisies You'll need a [`.gitlab-ci.yml`](https://docs.gitlab.com/ee/ci/quick_start/) file already in your Hugo project, this should be configured to upload your compiled HTML site to your hosting provider of choice. Here's a redacted version of mine as an example: ``` stages: - build_html - deploy_html variables: AWS_DEFAULT_REGION: ap-southeast-2 BUCKET_NAME: example.com CLOUDFRONT_DIST_ID: XXXXXXXXXXXXXX GIT_SUBMODULE_STRATEGY: recursive buildHugoSite: image: monachus/hugo stage: build_html script: - hugo artifacts: paths: - public only: - master deploys3: image: garland/aws-cli-docker stage: deploy_html dependencies: - buildHugoSite script: - aws configure set preview.cloudfront true - aws s3 sync ./public s3://$BUCKET_NAME --delete; - aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_DIST_ID --paths "/*"; only: - master ``` Create an account on your Gopher server that the GitLab Runner can access to upload the gopher files. Make sure it has the right groups to modify the directory where your Gopher files are stored. Also make sure that the Gopher files have permissions set recursively to allow writing by the group (traditionally `775` permissions on a POSIX system). You'll need to [generate an SSH key](https://confluence.atlassian.com/bitbucketserver/creating-ssh-keys-776639788.html) and store the **public key** in the `~/.ssh/authorized_keys` file on your Gopher server for the GitLab user account. ## Compiling Gopher Add `build_gopher` as a stage to `.gitlab-ci.yml`, then append the following: ``` buildGopherSite: image: node:lts-alpine stage: build_gopher script: - apk update && apk upgrade && apk add --no-cache bash git - git clone https://github.com/judges119/hugogopher.git - cd hugogopher - node index.js '../content' artifacts: paths: - hugogopher/gopher only: - master ``` This stage will do the following: 1. Use a tiny [Alpine Linux](https://alpinelinux.org) image with [Node.js](https://nodejs.org). 2. Install bash and git. 3. Clone the `hugogopher` repo. 4. Compile the project as a Gopher site. 5. Store the compiled files as an artifact. ## Uploading Gopher Copy the contents of the private key you have generated, then go to your project repository on your GitLab instance and click Settings -> CI/CD, then open the Variables section. Create a new variable and call it `SSH_PRIVATE_KEY`, and set the value to be the contents of the private key. Save the updated variables. Add a `deploy_gopher` stage to your `.gitlab-ci.yml`, then append the following: ``` deployGopher: image: alpine:latest stage: deploy_gopher dependencies: - buildGopherSite before_script: - apk update && apk upgrade && apk add --no-cache bash openssh-client - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - - mkdir -p ~/.ssh - chmod 700 ~/.ssh script: - scp -o StrictHostKeyChecking=no -r ./hugogopher/gopher gitlab@example.com:/var/gopher ``` This stage does the following: 1. Relies on the previous `build_gopher` stage (and it's artifacts). 2. Uses a minimal Alpine Linux image 3. Installed bash and an SSH client 4. Uses `ssh-agent` to add and manage the private key 5. Uses `scp` to transfer the artifact files to the Gopher server ## Finishing Off Commit the updated `.gitlab-ci.yml` file in your Hugo project and upload it to GitLab and very soon you should have your Gopher site uploaded and running! If you want, you can check mine out at `gopher://gopher.judges119.me:70` or [http://gopher.judges119.me:70](http://gopher.judges119.me:70). *\* Buy my book on GitLab! Available on [Packt](https://www.packtpub.com/au/virtualization-and-cloud/gitlab-quick-start-guide) or on [Amazon](https://www.amazon.com/GitLab-Quick-Start-Guide-repository-ebook/dp/B07L3Q35JZ).*