Getting Started with Gemini
In this post we'll take a quick dip into the gemini protocol, the
.gmi file format, how you can access
gemini:// sites and host your own gemini server.
Gemini is a Protocol
You can't decide that your text will be yellow or green, it's out of your hands. You focus on content in this privacy and bandwidth aware space. The default port for gemini servers is 1965, which I would recommend running your gemini site (capsule) on.
Gemini Clients / Browsers
There are a few "browsers" for gemini, funnily enough more for the terminal than ones with a GUI, must be a minimalist thing, for Gemini. If you want something that works cross platform, give Lagrange a try. It formats stuff in a bearable way, except for code blocks with long lines. They all look like they're from the 90s, don't be too picky.
In practise, you're on a page in your gemini browser, for example
gemini://geminispace.info/ you could encounter a link to
https://jonathanmh.com and it would open that in Firefox. So both clients can co-exist like magnet links or spotify playlists are opened in another application as well.
The GMI/Gemtext file format
If you're familiar with markdown, gemtext will look very familiar, some key differences are:
- Links look like this
=> https://example.com A cool website
- Links are always rendered on a new line
- There are only three headline levels: h1, h2, h3 equivalents
If you want to mirror existing markdown content there's a great rust command line utility md2gemtext which can convert your existing content. Be aware: it's very lenient, which means that it will try to parse and convert frontmatter blocks instead of ignoring them.
Since I am using MDX on this blog I stole a few blog posts which I'll use as a content example for the server in a bit:
# Nginx 410 maps and Custom Error Page
In order to bulk retire multiple URLs of your web site at once
The full code can be found in the repository: https://github.com/JonathanMH/nginx-410-map
=> https://github.com/JonathanMH/nginx-410-map https://github.com/JonathanMH/nginx-410-map
I can convert my mdx posts relatively painlessly with the following script, but I'll need to tweak it to extract the frontmatter to a title and remove the rest:
for document in content/*.mdx; do
echo processing $document
md2gemtext $document content/$(basename $document .mdx).gmi
Since Gemini is another protocol than HTTP it will probably not run on your regular webserver like apache or nginx. Instead there are a few different community projects to serve a gemini site.
A very simple to run server I have found is agate, which you can get via cargo:
cargo install agate
Afterwards you can run a server with
agate --content content/ --addr "[::]:1965" --addr 0.0.0.0:1965 --hostname localhost --lang en-GB
where you probably should have some example gmi file in the
content directory relative to where you run the command.
If you want to list your content files on your index page, you can create an empty file called
.directory-listing-ok in the same directory as your content.
which will make your agate server directory look like this:
│ ├── .directory-listing-ok
│ ├── next-js-rss-with-static-site-generation.gmi
│ ├── nginx-410-maps-and-custom-error-page.gmi
│ └── processing-files-with-docker-volumes.gmi
Now if you run the server, you should see something like this:
Each of the links can be clicked and it'll show the article as well:
Note that Lagrange also styles the first article of the page with slight emphasis and the inline link from the markdown source is moved below the paragraph.
Should you want to run a docker container with agate, you can use this as a starting point with an alpine linux dockerfile:
RUN apk --no-cache add gcc musl-dev \
&& apk --no-cache add rust cargo
# create content directory
RUN mkdir -p /var/app/content
# copy your content directory
COPY content/ /var/app/content
RUN cargo install agate
# run your agate server in /var/app
CMD ["agate", "--content path/to/content/", "--addr [::]:1965", "--addr 0.0.0.0:1965", "--lang en-GB" ]
If you have any great recommendations for blogs or content in the gemini-verse, let me know!