💾 Archived View for republic.circumlunar.space › users › johngodlee › posts › 2019-11-20-gopher.gmi captured on 2024-05-12 at 16:04:49. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2021-12-04)
-=-=-=-=-=-=-
DATE: 2019-11-20
AUTHOR: John L. Godlee
I have heard people on youtube, mostly DistroTube[1] and Hex DSL[2], talking about Gopher[3]. I also saw it being discussed on Hacker News[4] once.
1: https://www.youtube.com/watch?v=lUBhOgK5zQI
2: https://www.youtube.com/watch?v=ORgk-AwD7SQ
3: https://en.wikipedia.org/wiki/Gopher_(protocol)
4: https://news.ycombinator.com/item?id=13855634
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[5], which provides its registered and validated users with gopherspace running on the gophernicus server software[6] 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[7], I think.
6: http://www.gophernicus.org/
7: https://github.com/jgoerzen/pygopherd
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
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
To browse Gopher pages the Lynx[8] 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[9]. 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[10], Floodgap's proxy[11], or Gopher Commons[12].
8: https://lynx.invisible-island.net/
9: https://gopher.floodgap.com/overbite/
10: https://gopherproxy.meulie.net/
11: https://gopher.floodgap.com/gopher/gw
12: https://gopher.commons.host/
I like to use the w3m browser[13] which I couldn't get to load gopher pages by default, but I did find an awk script on Bitbucket[14] 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.
13: http://w3m.sourceforge.net/
14: https://bitbucket.org/iamleot/gopher2html/src
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.
Note that my gopher hole is now hosted on tilde.club/[15], at gopher://tilde.club/1/~johngodlee because scp was being problematic on SDF. I've since shut down my SDF gopherhole.
Note that my gopher hole is now hosted on republic.circumlunar.space/[16], at gopher://republic.circumlunar.space/1/~johngodlee because tilde.club kept being unavailable. I'll be shutting down my tilde.club gopherhole soon.