___________________________________________
title: Making a Gopherhole and Phlog
tags: gopher 100daystooffload
date: 2021-01-31
___________________________________________

But Why?

The obvious questions is why make a Gopherhole (what gopher sites are
called) when all the action is on the World Wide Web over html and
http? Didn’t those protocols win the Internet two decades ago? I
didn’t really think much about Gopher until I started reading more
about the newer Gemini protocol on my foray into Mastodon last week
and figuratively went “down” the Gopherhole.

  [gopher]: https://en.wikipedia.org/wiki/Gopher_(protocol)
  [World Wide Web]: https://en.wikipedia.org/wiki/World_Wide_Web
  [Gemini]: https://gemini.circumlunar.space
  [into Mastodon]: https://www.ecliptik.com/One-Week-With-Mastodon/

[Slides from 1992 Gopher presentation]

  [Slides from 1992 Gopher presentation]: /assets/images/posts/gopher-slides.png

Slides from 1992 Gopher presentation
I was suprised to find not only a flourishing community, but was drawn
to the simplicity of the protocol and creating for it. No more
thinking about CSS oddities, having to learn whole web stacks with the
latest-and-greatest toolsets. Most of what Gopher is now is the same
as it was in the early 90s and it’s something you can easily start
learning about and doing without sinking a lot of time and effort just
to get started. It reminds of learning Latin, even though it’s a dead
language, it’s still useful and it will never change. It also has the
advantages of being almost entirely text based and there’s no
tracking, cookies, or any of the risks and privacy concerns associated
with the modern web.

For a much more in-depth look on modern Gopher, I recommend reading
Burrowing A Gopher Hole.

  [Burrowing A Gopher Hole]: https://tedium.co/2017/06/22/modern-day-gopher-history/

Start Burrowing

The first thing I needed to to was figure out how to host a
Gopherhole. I could run it myself locally, and was thinking of
re-purposing one of my numerous raspberrypis to self-host it over port
70. I even got as far as trying to make a Dockerfile to run
gophernicus in a container and maybe even get it to run in Kubernetes!
I quickly realized this was missing the point of slowing down and
focusing on the simplicity that intially drew me in the first place
and scrapped this idea.

  [my numerous raspberrypis]: https://www.ecliptik.com/Raspberry-Pi-Kubernetes-Cluster/
  [gophernicus]: http://www.gophernicus.org

While browsing Gemini capsules (the term for Gemini sites), I came
across the PubNix RawText.club, whose mission fit with the themes of
simplicity and do-it-yourself while offering some basic hosting
services for gopher, gemini, and web.

  [PubNix]: https://github.com/cwmccabe/pubnixhist
  [RawText.club]: https://rawtext.club

  RTC is a non-profit, do-it-yourself social network that uses a
  smaller, simpler, user-built toolkit. We are proudly the polar
  opposite of the big, exploitative, corporate-owned social media
  mega-sites. Not cool. Not easy. Not big. rawtext.club is what you
  make it. The point is that you can do a LOT using very minimal
  resources by stringing together command line tricks on a Linux
  system.

I pondered joining for a few days to make sure I would stick with the
commitment and didn’t want to join and then lose interest a few weeks
later. Even though RTC is a “slow” social network, I wanted to
actively particpate in the community and not just be passive and
looking for a free handout. Eventually I sent an invite request and
was extended a membership. The first few days I spent checking out RTC
from the cli; creating a prescense and reading the man pages for the
local tools (which are excellent).

Finally I started adding things in ~ecliptik/public_gopher and got to
work on making a gohperhole. Creating a gopherhole has been well
covered by others in other blog posts, which I heavily referenced when
making the site,

-   Making a Gopherhole
-   Generating a Gopher site with Hugo
-   Gopher? Gopher.

  [Making a Gopherhole]: https://johngodlee.github.io/2019/11/20/gopher.html
  [Generating a Gopher site with Hugo]: https://jfm.carcosa.net/blog/computing/hugo-gopher/
  [Gopher? Gopher.]: https://petermolnar.net/article/gopher/

On RTC, home directories are world readable, so I poked around in some
more well-known users public_gopher dirs and saw how their gopherholes
were setup. I used the gopher browser Bombadillo as my main tool to
view Gopherspace, and coincidentally Lagrange, the browser I was using
to browse Gemini, also supported gopher and would use it occasionally
as a GUI view.

  [Bombadillo]: https://bombadillo.colorfield.space
  [Lagrange]: https://gmi.skyjake.fi/lagrange/

The resulting gopherhole was relatively simple,

    [ecliptik@rawtext public_gopher]$ tree .
    .
    ├── about.txt -> ../.who-is
    ├── gophermap
    └── phlog

    1 directory, 2 files

The about page is a symlink to my ~/.who-is (which is used on RTC as a
profile), a link to the Phlog dir, a web link to the www page, and a
link back to the RTC gopherhole. The gophermap for this was simple.

    Welcome to ecliptik's Gopherhole

    Nav:
    0About  about.txt
    1Phlog  ./phlog

    Links:
    hecliptik.com   URL:https://www.ecliptik.com
    1rawtext.club   /       rawtext.club    70

The most difficulty I had was getting the link identifiers and tabs in
the correct places.

Adding these files made the site live at
gopher://rawtext.club:70/1~ecliptik. If you don’t have a gopher
browser installed it’s viewable through a gopher proxy from Floodgap.

  [gopher://rawtext.club:70/1~ecliptik]: gopher://rawtext.club:70/~ecliptik
  [gopher proxy]: https://gopher.floodgap.com/gopher/gw?a=gopher%3A%2F%2Frawtext.club%3A70%2F1%7Eecliptik
  [Floodgap]: https://www.floodgap.com

               Welcome to ecliptik's Gopherhole
               
               Nav:
    TXT   [1]  About
    MAP   [2]  Phlog
               
               Links:
    HTM   [3]  ecliptik.com
    MAP   [4]  rawtext.club
               ___________________________________________________________________
                                  Gophered by Gophernicus/3.1 on Arch/5.10 x86_64

Viewed in Bombadillo
[Gopherhole in Lagrange Browser]

  [Gopherhole in Lagrange Browser]: /assets/images/posts/gopher-lagrange-01.png

Gopherhole in Lagrange Browser
Phlog

After getting the basic site up I wanted to update it frequently with
a Phlog, which is the gopher equivalent of a Blog. Since I already
have this blog with Jekyll and uses markdown for posts, I thought I
might as well mirror these posts to the Phlog. I also decided to only
do the pure markdown posts, as some of the older posts on the blog
were converted from my old blogger site and are HTML. Having to
convert all of those to markdown or writing scripts to also convert
HTML was a bit too much for this project.

  [Jekyll]: https://www.ecliptik.com/Building-a-website-with-Github-and-Jekyll/
  [my old blogger site]: https://junocake.blogspot.com

A few others have already done this, as referenced above for Jekyll
and Hugo already, but I wanted to do my own take on it. Originally I
wrote a script that would convert a post to a gophermap, converting
the links to blocks, identifying what type they were and creating item
links.

    #!/bin/bash
    #Convert a jekyll markdown post to a gophermap
    #Will create a sub-directory with the name of the post and a gophermap
    #converted to  70 columns with links. Tries to do basic http or gopher
    #linking. May not work well, but works well enough.

    # usage: ./md2gophermap.sh ../_posts/post-to-convert.md

    #Know Bugs
    #Pandoc does not wrap code blocks to the columns length and will get cut
    #off when rendered in the gophermap.
    #see: https://github.com/jgm/pandoc/issues/4302#issuecomment-360669013

    #Take input and craft output file and directory vars for use later on
    input=$1
    output=`basename ${input}`
    outdir=`basename -s .md ${output}`

    echo "converting ${input}"
    pandoc --from markdown --to markdown --reference-links --reference-location=block --columns=70 -o ${output} ${input}

    #Do some IFS changes in order to properly parse individual lines after conversion
    IFSORIG=${IFS}
    IFS="
    "

    #Create gophermap

    ##HTML link syntax
    #hecliptik.com  URL:https://www.ecliptik.com

    ##Gopher link syntax
    #1rawtext.club  /   rawtext.club    70

    #Go through the file line-by-line looking for http or gopher linkes and convert
    for line in `cat ${output}`; do
      IFS=${IFSORIG}
      if echo "${line}" | egrep -e "^.+\[.+\]:.+" >/dev/null; then

        case ${line} in
          *http*)
            itemname=`echo ${line} |sed -r 's/\[(.*)\]/\1/' | awk -F: {'print $1'} |xargs`
            itemlink=`echo ${line} |awk -F] {'print $2'} | sed -e "s%:\ %%"`
            item="h${itemname}\tURL:${itemlink}"
          ;;
          *gopher*)
            itemname=`echo ${line} |sed -r 's/\[(.*)\]/\1/' | awk -F: {'print $1'} |xargs`
            itemserver=`echo ${line} |awk -F/ {'print $3'} | awk -F: {'print $1'}`
            itemlink=`echo ${line} |awk -F/ {'print $4'}`
            item="1${itemname}\t/${itemlink}\t${itemserver}\t70"
        esac
    #Set IFS to new line in order to remove leading spaces
     IFS="
    "

        #Escape all special chars so they're replaced in sed
        linemung=$(echo ${line} | sed -e 's`[][\\/.*^$]`\\&`g')
        itemmung=$(echo ${item} | sed -e 's`[][\\/.*^$]`\\&`g')

        #Replace markdown blocks with gophermap
        sed -i -e "s/${linemung}/${itemmung}/" ${output}
        sed -i -e "s/\\\t/\t/g" ${output}
     fi
    done

    #Make the subdirectory
    mkdir -p ${outdir}

    #Use the top of the original Markdown file to create a basic header
    head -6 ${input} | grep -v "layout" | grep -v "category" > ${outdir}/gophermap
    echo "" >> ${outdir}/gophermap
    cat ${output} >> ${outdir}/gophermap

    #Convert --- lines to underscore
    sed -i -E "s/^--.+$/$(printf '%.0s_' {0..69})/g" ${outdir}/gophermap
    sed -i -E "s/^==.+$/$(printf '%.0s_' {0..69})/g" ${outdir}/gophermap

    #Remove the pandoc output file to clean up
    rm -fr ${output}

This worked out well, where a gophermap for each post under _posts was
formatted properly into their own directories, wrapping was done, and
the item links worked. However it just looked sort of off, and there
was an issue where code blocks would not be wrapped by pandoc.

  [pandoc]: https://pandoc.org/

I decided then to just convert them to plaintext and not do a full
gophermap, which preserved the formatting, wrapped text blocks more
accurately, and just looked better in general. Most of the links in
the posts are http anyway, so if they were followed they’d open in a
web browser anyway.

    #!/bin/bash
    #Convert a jekyll markdown post to plaintext suitable for gopher,
    #converted to  70 columns

    #usage: ./md2gopher.sh ../_posts/post-to-convert.md

    #Take input and craft output file and directory vars for use later on
    input=$1
    outdir="_posts"
    output="${outdir}/`basename -s .md ${input}`.txt"

    mkdir -p ${outdir}

    echo "converting ${input} to ${output}"
    pandoc --from markdown --to plain --reference-links --reference-location=block --columns=70 -o ${output}.tmp ${input}

    #Use the top of the original Markdown file to create a basic header
    head -6 ${input} | grep -v "layout" | grep -v "category" > ${output}
    echo "" >> ${output}
    cat ${output}.tmp >> ${output}
    rm -fr ${output}.tmp

These plaintext posts rendered much nicer and I was happy with how
they turned out.

[Phlog post in Bombadillo]

  [Phlog post in Bombadillo]: /assets/images/posts/gopher-phlog-post-01.png

Phlog post in Bombadillo
One final step was automatically generating a Phlog index of posts.
The post Making a Gopherhole that I used when making my own Gopherhole
had a script on taking the last 10 posts and generating a gophermap of
them. I took this script and modified it some to include some things
like a basic layout template.

  [Making a Gopherhole]: https://johngodlee.github.io/2019/11/20/gopher.html

    #!/bin/bash

    #Create gophermap of last 10 posts
    #Originally from: https://johngodlee.github.io/2019/11/20/gopher.html

    #Use layout file for header on gophermap
    cat _layouts/phlog > gophermap

    all=(_posts/*.txt)

    # Reverse order of posts array
    for (( i=${#all[@]}-1; i>=0; i-- )); do
      rev_all[${#rev_all[@]}]=${all[i]}
    done

    # Get 10 most recent posts
    recent="${rev_all[@]:0:10}"

    # Add recent post links to gophermap
    for i in $recent; do
      line=$(head -n 4 $i | grep -i "title:" | awk -F: {'print $2'} | xargs)
      printf "0$line\t$i\n" >> gophermap
    done

    #Append footer with html link
    echo "" >> gophermap
    printf '%.0s_' {0..69} >> gophermap
    echo "" >> gophermap
    echo "hecliptik.com URL:https://www.ecliptik.com" >> gophermap

The gophermap created while not fancy works well in displaying the
latest 10 posts,

                                      ecliptik's phlog
               ___________________________________________________________________
               
                     These posts are mirrored from https://www.ecliptik.com
               ___________________________________________________________________
               
               Latest 10 posts
               ___________________________________________________________________
               
    TXT   [1]  One Week With Mastodon
    TXT   [2]  ACI Connector for k8s on a Raspberry Pi Cluster
    TXT   [3]  Raspberry Pi Kubernetes Cluster
    TXT   [4]  Cross Building and Running Multi-Arch Docker Images
    TXT   [5]  Automating Container Updates With Watchtower
    TXT   [6]  Containerizing a Perl Script
    TXT   [7]  Emulating ARM64 on Linux
    TXT   [8]  Decompiling Interactive Fiction
    TXT   [9]  Building a website with Github and Jekyll
    TXT  [10]  Vim, rdesktop, external monitors, and X Forwarding on a Google CR-48
               
               ___________________________________________________________________
    HTM  [11]  ecliptik.com
               ___________________________________________________________________
                                  Gophered by Gophernicus/3.1 on Arch/5.10 x86_64

While writing these tools I initially was creating them on my laptop,
putting them into a tarball, scping them to RTC and then untarring
them. This added a lot of manual steps into the process, so I took the
more modern workflow of checking the converted posts into git, cloning
them to RTC, the symlinking them from the gopherhole. This way after
writing a post (such as this one), I’ll run the scripts, push and then
pull on RTC and my phlog will be updated along with the WWW site.

These tools and usage are describe more in their README.md

  [README.md]: https://github.com/ecliptik/ecliptik.github.io/blob/master/_gopher/README.md

Conclusions

While gopher didn’t win against the web in the early 90’s, it’s sense
of simplicity really shines in todays modern and complex Internet.
I’ve already found a lot of interesting content while browsing
gopherspace that I wouldn’t find on the WWW and there is much more a
sense of community, similar to what the web was like in the early days
before modern social networking.