Making a Gopherhole

2019-11-20

I have heard people on youtube, mostly DistroTube and Hex DSL , talking about Gopher . I also saw it being discussed on Hacker News once.

The youtubers and digitial minimalist / linux try-hards have recently begun lauding Gopher as a sane alternative to browsing the internet with HTTP and the World Wide Web, which they say are bloated and beyond redemption since advertisers and data harvesters have taken over.

Gopher is an internet protocol that was created in 1991. In my mind it sits alongside FTP more than it does HTTP, in that it is merely a way of organising file delivery in a heirarchical fashion. It doesn’t have the flexibility of HTTP, providing only plain text formatted by certain conventions and a smattering of links to connect files and pages. Some think this inflexibility is a good thing, Gopher sites are: simple, transparent, text based (good for the visually impaired) and consistent. In Gopher it’s hard to implement most of the more destructive mechanisms present on the World Wide Web like user tracking, data harvesting and advertising. Gopher sites are also phenomenally light on resources, providing just plain text. It’s not that HTTP can’t be fast as well, but there is a tendency to use all the features that the flexibility of HTTP can afford. That being said, I think a lot of people are confusing the World Wide Web with the internet. Gopher is an internet protocol, but it satisfies a different set of needs to HTTP and they shouldn’t be compared so readily.

I set up a Gopher site (aka a Gopherhole) on the Super Dimension Fortress , which provides its registered and validated users with gopherspace running on the gophernicus server software for free. It also provides lots of other services run through a shell account that you can SSH into, such as POP3/IMAP mail, and IRC. They are a good community of hobbyists which provides a valuable if computationally limiting service. There are lots of other places to host a Gopherhole and it’s also possible to self-host, and there are a few Gopher server softwares out there, the most popular right now being pygopherd , I think.

First I created a shell account, logged in, and validated my membership with a $3 USD donation to the SDF by PayPal. My validation came through in about 12 hours, but I imagine this varies a bit. I SSH’d into my shell account with:

ssh username@tty.sdf.org

After entering my password I could then create a gopher with mkgopher, which creates a directory ~/gopher. Inside this directory is where I store all my gopher content. mkgopher also allows various site level options to be configured, such as the site title and the site description. It’s also important to set file and directory permissions so that other users can read the material in the gopherhole. This can be done automatically within mkgopher with the chmod command, or manually:

find ~/gopher/ -type f -print0 | xargs -0 chmod 644
find ~/gopher/ -type d -print0 | xargs -0 chmod 755

Gophermaps

At the root of ~/gopher there should be a file called gophermap. This file defines the homepage of your gopherhole, with plain text and links to reach other content.

An example gophermap looks like this:

iWelcome to gopherspace	/

0This is a text file in a link	file.txt
9This is a pdf file in a link	file.pdf
1This is a link to a directory	subdir

iSome more text.	/

IAn image	img.gif

0A file on another server	/gopher/relevance.txt	gopher.floodgap.com	70
hA HTTP link to another server	URL:http://sdf.lonestar.org/

The numbers, and some letters are called itemtypes. They denote what type of information the line holds. There are a bunch of itemtypes, but I think the commonly used itemtypes nowadays are:

Itemtype Content
0 Text file
1 Directory
7 Search query
9 Binary file
g GIF image
h HTML URL
i inline text
s Sound file
I Image (not-GIF)
= Execute shell command

One extra itemtype that I haven’t found documented ANYWHERE is =. This can be used to start a shell command on the server. For example, to show the current date and time:

=echo "`date`"

This could come in really useful if hosting a server on your own machine, where you could point the shell to a script to do basically anything you want. This makes gopher more extensible than I originally thought. Maybe if Gopher had remained popular for a long time, we might have ended up with gopher developers abusing = to gather data on users and subversively advertise to us.

The full syntax of the whole line is, for a text file for example:

0Description of file<TAB>/path/to/content.md<TAB>domain.org<TAB>port_number

Note that <TAB> must be an ACTUAL tab character, not expanded to multiple spaces as some text editors ‘helpfully’ adjust it. The 0 defines the line as pointing to a text file. Description of file will appear in the page as a selectable link. /path/to/content defines the path to the text file to be opened by the link. File paths can be defined relative to the current gophermap, so if file.txt is located in the same directory as gophermap the path can just be file.txt. If the file is located on the same server as gophermap, domain.org and port_number can be omitted. If the file is on a different server, the server domain (domain.org) should be added and the port number, which is usually 70. So if the address of the remote file linked is gopher://gopher.floodgap.com/0/gopher/relevance.txt, the domain name is gopher.floodgap.com.

As a side note, I’ve found that in gopher browsers, if you want to visit the rendered version of a gophermap, you can enter the address like this, with a 1 after the domain:

gopher://gopher.floodgap.com/1/gopher

If you want to view the unrendered version of the gophermap, you can replace the 1 with a 0.

For a piece of text, the gophermap syntax is similar, but not exactly the same:

iSome text that will appear on its own<TAB>/

A single slash should be included after a single <TAB> following the text to be displayed. An i should be included before the text.

I’ve found that the 9 itemtype can cover many non-standard filetypes, as it basically just prompts the web browser to download the file.

Directories can be nested below the top level gopherspace directory. Each of these directories can have their own gophermap, but they don’t have to. In the top level gophermap the directory can be called as:

1This is a link to a directory<TAB>subdir

If there is a gophermap in subdir/ it will be opened. This subdir/gophermap can contain relative links to files the same as the top level gophermap.

There isn’t a lot more to creating a simple functional gophermap, the rest is just text formatting to design a well formatted page. I like to split the top level gophermap into sections with headers wrapped in == symbols, and to have an ASCII art header at the very top of the top level gophermap. It’s also customary to limit the width of a gopher page to 69 characters, but I haven’t found any technical reason why this would be the case:

i      _       _            _         _____           _ _           	/
i     | |     | |          | |       / ____|         | | |          	/
i     | | ___ | |__  _ __  | |      | |  __  ___   __| | | ___  ___ 	/
i _   | |/ _ \| '_ \| '_ \ | |      | | |_ |/ _ \ / _` | |/ _ \/ _ \	/
i| |__| | (_) | | | | | | || |___ _ | |__| | (_) | (_| | |  __/  __/	/
i \____/ \___/|_| |_|_| |_||_____(_) \_____|\___/ \__,_|_|\___|\___|	/
                                                                       
iJohn L. Godlee	/

0Contact details	contact.txt
0CV	cv.txt

i==== Phlog posts =================================================	/

0Post 1	post_1.txt
0Post 2	post_2.txt

i==== Recent recipes ==============================================	/

0Mac and cheese	mac_cheese.txt
0Pizza dough	pizza_dough.txt

Browsers

To browse Gopher pages the Lynx browser in the terminal is the most common way I think. Otherwise there are plugins for some web browsers, like the Overbite plugin for Firefox . There are also a few different online Gopher to HTML proxy services where you type in the gopher address and the output is rendered in HTML, e.g. GopherProxy , Floodgap&rsquo;s proxy , or Gopher Commons .

I like to use the <code>w3m</code> browser which I couldn’t get to load gopher pages by default, but I did find an awk script on Bitbucket which converts Gopher to HTML and then serves it through w3m. So far it is working pretty well, but I still found myself loading up Lynx when I was building my page initially to make sure everything was formatted correctly.

Converting a Github-pages blog to Jekyll

I created a shell script which generates a gopherhole with a directory tree like this:

.
├── contact.txt
├── cv.txt
├── gophermap
├── posts
│   ├── 2017-07-20-ranger-rifle-conf-mac.txt
│   ├── 2017-08-14-bash-prompt.txt
│   ├── 2019-11-10-beamer.txt
│   ├── 2019-11-15-gginext.txt
│   └── gophermap
└── recipes
    ├── Apricot_orange_blossom_baklava.txt
    ├── Baked_pumpkin_with_apple.txt
    └── gophermap 

It’s basically just a load of shell scripts. First I use pandoc to convert the recipes and blog posts to plain text with something like:

pandoc --from markdown --to plain --reference-links --reference-location=block -o posts/post_1.txt post_1.md

Then I put the title of each blog post as a link into the gophermap using sed in a for loop, with something like this:

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 1 $i)
	printf "0$line\t$i\n" >> gophermap
done

Those were just simplified examples, it’s easy to add header material from another file or format the link text differently.

Update 2019_12_25

Note that my gopher hole is now hosted on tilde.club/ , at gopher://tilde.club/1/~johngodlee because scp was being problematic on SDF. I’ve since shut down my SDF gopherhole.

Update 2020-03-28

Note that my gopher hole is now hosted on republic.circumlunar.space/ , at gopher://republic.circumlunar.space/1/~johngodlee because tilde.club kept being unavailable. I’ll be shutting down my tilde.club gopherhole soon.