TLDR;

Ghost does not offer file downloads, so I published my docker-compose file which adds a simple file manager sidecar. I call it ghost-compose.

You can download see it on github here:

https://github.com/simplecto/ghost-compose

Tell me a story

The talented people over at ghost.org have made a good-looking and simple blogging platform. It strikes the right balance between need-to-have and nice-to-have, all while keeping it in a user-friendly package.

However, those choices come with consequences. Good product management and development is more about saying "no" than saying yes. Some features might have to wait.

Ghost does not offer file downloads

One of those features, apparently, is file downloads. It does not appear that one is currently able to upload a PDF into a post and make it available for download (er, at least I was not able to figure it out). Consulting the community forums suggests a simple solution: use Dropbox, Google Drive, or another file host.

Screenshot of the answer in Ghost Forums

Great, but what if I don't use DropBox or Google Drive?

No problem.

There is a simple Golang app called Filehosting (filebrowser.xyz), and they convienently offer a docker image.

The idea is this:

  1. I use Traefik as my webserver and reverse proxy to docker-hosted servics in a VM.
  2. Relevant containers will spin up and send Traefik their routing and SSL configuration information via Docker labels.
  3. Once spun up the Traefik will provision an SSL certificate via Letsencrypt, and then we are ready.
  4. From here on, I will simply upload my files via a web interface to the filebrowser, produce the public link, and then paste that into my blog posts as needed.

Ok, what does the code look like?

The meat of this is in the docker-compose file. Let's have a look.

version: '3'

services:

    filebrowser:
        image: filebrowser/filebrowser
        container_name: filebrowser
        restart: unless-stopped

        volumes:
            - /files:/srv
            - ./database.db:/database.db
            - ./filebrowser.json:/.filebrowser.json
        networks:
            - web
        labels:
            - "traefik.docker.network=web"
            - "traefik.enable=true"
            - "traefik.frontend.rule=Host:files.simplecto.com"
            - "traefik.port=80"
            - "traefik.default.protocol=http"
            - "traefik.backend=filebrowser"
            - "traefik.frontend.headers.SSLRedirect=true"
            - "traefik.frontend.headers.SSLHost=files.simplecto.com"
            - "traefik.frontend.headers.SSLForceHost=true"

    ghost:
        image: ghost:2-alpine
        container_name: simplecto
        restart: unless-stopped
        volumes:
            - "./ghostdata:/var/lib/ghost/content"

        environment: 
            url: https://www.simplecto.com

        networks:
            - web

        labels:
            - "traefik.docker.network=web"
            - "traefik.enable=true"
            - "traefik.frontend.rule=Host:www.simplecto.com,simplecto.com"
            - "traefik.port=2368"
            - "traefik.protocol=http"
            - "traefik.backend=simplecto"
            - "traefik.frontend.headers.SSLRedirect=true"
            - "traefik.frontend.headers.SSLHost=www.simplecto.com"
            - "traefik.frontend.headers.SSLForceHost=true"

networks:
    web:
        external: true

The sections named labels tell Traefik that they want to have access to the outside world on http/s on those assigned domain names.

Check it out on github. https://github.com/simplecto/ghost-compose