Ghost Static Pages part 2: Publish to static page hosting with git

This is the second part of my series (first part is here) on how to publish the content of Ghost CMS to static web pages in the context of blogging.

The first part was about exporting and previewing, this part is about publishing

┌──────────────────────────────┐                    ┌──────────────────────────────┐                        ┌──────────────────────────────┐                  ┌──────────────────────────────┐
│                              │                    │                              │                        │                              │                  │                              │
│                              │                    │                              │                        │                              │                  │                              │
│                              │    export          │                              │      preview           │                              │   git push       │                              │
│ Post editing and management  ├────────────────────► Static pages on file system   ├────────────────────────►Site served on local web server──────────────────►Site served on GitLab Pages   │
│                              │                    │                              │                        │                              │                  │                              │
│                              │                    │                              │                        │                              │                  │                              │
└──────────────────────────────┘                    └──────────────────────────────┘                        └──────────────────────────────┘                  └──────────────────────────────┘

Adding services to the Docker compose file

The part of the file that interest us is this:

  export:
    image: rija/gssg:20230124
    volumes:
      - "./site:/static"
    command: /usr/local/bin/gssg
    extra_hosts:
      - "localhost:172.31.238.10"
    networks:
      - app-net

  preview:
    image: nginx:1.23.3-alpine
    volumes:
      - ./site:/usr/share/nginx/html:ro
    ports:
      - 9999:80
part of docker-compose.yml

We can't use the same export service to generate the static page suitable to be deployed to the destination hosting because all absolute URLs have been converted to relative-to-root ones. On the Internet, we want to keep the absolute URLs to improve SEO, se we add a new container services named publish with a different set of parameters:

  publish:
    image: rija/gssg:20230124    
    volumes:
      - "./$PAGES_REPO_PATH/public:/static"
    command: /usr/local/bin/gssg --url $REMOTE_URL
    extra_hosts:
      - "localhost:172.31.238.10"
    networks:
      - app-net

The other difference is that the content exported for publishing is written to a different directory (inside a stage directory to distinguish from site) named after the hosting provider for convenience, that will be gitignored and in which we create the git repository of the remote hosting service, in my case GitLab.

Something else to note is the environment variable $PAGES_REPO_PATH, wich is stored in my .env file and its value in my case is stage/gitlab.

The publishing is based on a git repository that I clone locally (here, inside stage and  named gitlab), add content to it,  and then commit and push. [1]

The content of that repository will then be served as web pages by GitLab. The default address is something like <repository name>.gitlab.com, but one can associate its own domain name (and I did) to the GitLab pages [2].

This new container service can be invoked with the command:

docker-compose run --rm publish
In the previous instalment of this blog series, the command for the export container service had a different set of parameters than here. It was --ignore-absolute-paths --url $REMOTE_URL. I removed it completely because it caused a bug whereby the link to homepage on each post was incorrect when previewing. By removing all parameters, we leverage the fact that the gssg tool default to localhost:2368 which suits our need for previewing.

Configuring the remote repository for static publishing

In order for GitLab to know what in the repository is public, I need to set up a configuration file inside that GitLab repo, named .gitlab-ci.yml, and with this content:

image: alpine:latest

pages:
  stage: deploy
  script:
  - echo 'Publishing'
  artifacts:
    paths:
    - public
  only:
  - master

Notice that the public term here is the same one as in the Docker compose file for the new publish container services:

- "./$PAGES_REPO_PATH/public:/static"

So, one can change the directory name to something else, as long as the same name is used in both files.

The branch mentioned here  (master) is the only branch on which the change will trigger the static publishing. That can also be configured to be a different branch, which is why I've stored that value in an environment variable $DEST_BRANCH in the bash script I talk about in the next section.

GitLab Pages, GitHub Pages, and BitBucket Pages are all services that can host static web pages and they work very similarly. This section about configuring remote repo for static publishing is actually the only step that differ between all those services.

Publishing the content and putting it all together

Since we are working with a git repository, after the static pages are generated in the correct location, we can use typical git workflow to publish them online:

cd stage/gitlab
git add -A
git commit -m "Update on the website at $(date)"
git push origin master

Make sure that the branch you push to is the same as the one configured in the previous section. For convenience, I have created a bash script publish that will take care of all the steps to publishing:

#!/usr/bin/env bash
set -ex
source .env

docker-compose run --rm publish

cd $PAGES_REPO_PATH
git add -A
git commit -m "Update on the website at $(date)"
git push origin $DEST_BRANCH
cd ..
./publish

[1] https://docs.gitlab.com/ee/user/project/pages/getting_started/pages_from_scratch.html

[2] https://docs.gitlab.com/ee/user/project/pages/custom_domains_ssl_tls_certification/