Gemini Mirror from Hugo
For this little tutorial, we'll use the Hugo Getting Started guide and create a small blog with exactly one blog post and then start serving it over
The markdwon to gemtext conversion and serving will be done through some GO packages, so remember to install go.
Setting up Hugo
Firstly we'll set up hugo, either through your package manager or through the GO toolchain. Open up a terminal and run the default tutorial instructions:
hugo new site quickstart cd quickstart git init git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke echo "theme = 'ananke'" >> config.toml hugo server
Now we also need some example content, so we'll add
my-first-post.md to the
--- title: "My First Post" date: 2022-11-20T09:03:20-08:00 --- ## Introduction This is **bold** text, and this is *emphasized* text. Visit the [Hugo]( ) website!
now we should see the post show up at
localhost:1313. So far so good!
Serving Gemini from Hugo Content
There are three related projects all by n0x1m that are going to enable us to serve gemfiles from the existing hugo content. What they did is to grab some hugo code from a few versions ago to generate an identical path tree and they also serve it over gemini, perfect, right?
With the go toolchain installed you can run:
go install github.com/n0x1m/hugoext@latest go install github.com/n0x1m/md2gmi@latest go install github.com/n0x1m/gmifs@latest
Now we can run:
hugoext -ext gmi -pipe md2gmi
and it will build the
.gmi file output in the
Next, to serve the content we can run:
What we should see in a gemini browser is this:
Brilliant, we can conclude it works!
Now we just need to deploy it somewhere and point a domain at it.
Deploying hugoext / gmifs with Docker
I'm used to Docker at this point and I don't have the nerve to learn 100 different hosting providers own config syntax, so we'll write a small Dockerfile.
One of the providers I've been wanting to try out is fly.io, but you can obviously deploy anywhere where Docker images are supported, like heroku, AWS, Azure or whatever you can think of.
FROM golang:1.19-alpine # install GO dependencies RUN go install github.com/n0x1m/hugoext@latest RUN go install github.com/n0x1m/md2gmi@latest RUN go install github.com/n0x1m/gmifs@latest RUN mkdir -p /var/site WORKDIR /var/site COPY content /var/site EXPOSE 1965 CMD ["gmifs", "-autoindex", "-autocertvalidity=666"]
CMD line we add
because by default our certificate the self-signed cert would only be valid for 1 day:
-autocertvalidity int valid days when using a gmifs provisioned certificate (default 1)
Now let's build it with
docker build . -t hugo-gmi and run with:
docker run --init -p 1965:1965 -t hugo-gmi
which maps the exposed port to the same post on the host system. If you get an error, it's because you still have
gmifs running on the same port in another terminal.
gemini://localhost should now again show you your website.
Deploying Docker Image to fly.io
If you want to use fly.io, head on over and create an account first, you'll need to punch in your credit card if you want to deploy.
You'll get some things for free, but be vary of excess bandwidth you might have to pay for:
Up to 3 shared-cpu-1x 256mb VMs 3GB persistent volume storage (total) 160GB outbound data transfer
First we need to install the [flyctl][flyctl], for me that is:
curl -L https://fly.io/install.sh | sh
Then you will want to authenticate your flyctl to your fly.io account, so you run:
flyctl auth login
which will open your browser and let you authenticate the request, after that you're logged in on your system.
Next, to trigger the interactive dialogue for deployment, we run the following in our
quickstart directory or where your gmi-hugo blog is located.
We answer a few questions, but the defaults are pretty good. We need to answer with
y when it comes to if we actually want to deploy.
Now we can watch some terminal output of our image being built in production, after it's done we can go to our fly.io dashboard, find our app and access the random subdomain with our gemini browser!
Now you just need to grab your DNS settings and point
gmi.yourdomain.com at this IP address or host to make sure you can be reached at the desired address!
I got incredibly lucky finding the awesome projects thata are gmifs and hugoext because they were exactly my use case. Trying out fly.io was very pleasant and really perfect for tiny projects and niche blogs!
Your deploy process might vary, you might already have a Dockerfile and might just want to copy your content directory to a different project directory that will only have the dockerfile above to push to a separate remote.
For my own blog I had to use a slightly different approach to get my content in shape to be served through
gemini://jonathanmh.com, because I don't personally use hugo.