GEOMYIDAE(8)
π GEOMYIDAE(8) π β System Manager's Manual β a gopher daemon for Linux/BSD
π¦ NAME π¦
geomyidae β a gopher daemon for Linux/BSD
β¨ SYNOPSIS β¨
geomyidae [-4] [-6] [-c] [-d] [-e] [-n] [-s] [-y] [-l logfile]
[-v loglevel] [-b base] [-p port] [-o sport] [-u user]
[-g group] [-h host] [-i interface ...] [-t keyfile certfile]
π DESCRIPTION π
geomyidae is a daemon for serving the protocol specified in RFC 1436 (Gopher). Under 1000 lines of C by design, it is lightweight yet supports dynamic content, automatic file/directory indexing, logging and privilege separation. iconic behavior honestly π
π IMPLEMENTATION π
Installation is straightforward: grab the zipped tar file, expand it in an appropriate temp directory, change to the ../geomyidae-x.xx directory, tweak the Makefile if desired (installs in /usr/bin by default), then run the make ; make install commands. The resulting executable should be run by root.
π Basic Installation and Startup π
$ wget ftp://bitreich.org/releases/geomyidae/geomyidae-$VERSION.tar.lz
$ lzip -d geomyidae-$VERSION.tar.lz
$ tar -xvf geomyidae-*.tar
$ cd geomyidae-*
$ make; sudo make install
$ sudo mkdir -p /var/gopher
$ sudo cp index.gph /var/gopher
$ sudo geomyidae -l /var/log/geomyidae.log -b /var/gopher -p 70
$ tail -f /var/log/geomyidae.log
Use whatever gopher client you like (ie. sacc) to browse:
$ sacc gopher://localhost
π«Ά Running π«Ά
geomyidae should normally be started by root, although it can be started by a regular user provided that the base directory and its contents are owned by the same user. geomyidae will only serve content within the base directory tree and will drop privileges to the -u user and -g group values if set. See βOPTIONSβ below for specifics. Launching geomyidae automatically is best done via a UNIX run-time (rc.d) script; several sample rc.d scripts are included in the geomyidae source archive. Logging in geomyidae can be done through either logfiles or syslog.
π₯ OPTIONS π₯
geomyidae options and default settings:
-4β Only use IPv4.-6β Only use IPv6.-cβ Usechroot(2)for the base directory (by default off).-dβ Don't fork into background. If no logfile is given, this implies logging to the standard output.-eβ Disable execution of any CGI or DCGI script.-nβ Perform reverse lookups.-sβ Log using syslog for logging.-yβ Enable HAProxy support.-llogfile β Specify file where log output is written (no default).-vloglevel β Set the logging level (default: 47). Loglevels:0β no logging1β served plain files2β directory listings4β HTTP redirects8β errors (e.g., not found)16β client connections32β gopher+ redirects
E.g.:
1 + 2 + 4 + 8 + 32 = 47
(files + directories + HTTP + errors + gopher+)
-bbase β Root directory to serve (default:/var/gopher).-pport β Portgeomyidaeshould listen on (default: 70).-osport β Portgeomyidaedisplays within base directory (default: 70). Use in conjunction with-pfor obfuscating actual portgeomyidaeis running on.-uuser β Sets the user to which privileges drop whengeomyidaeis ready to accept network connections (default: usergeomyidaeruns as). Helps improve security by reducing privileges during request processing.-ggroup β Sets the group to which privileges drop whengeomyidaeis ready to accept network connections (default: groupgeomyidaeruns as). Helps improve security by reducing privileges during request processing.-hhost β Host to use in directory listings (default:localhost).-iinterface β Defines the interface to whichgeomyidaebinds to (default:0.0.0.0). Multiple interfaces can be given.-tkeyfile certfile β Activate gopher TLS and use the private key keyfile and the public key certfile for TLS connections (if the feature is compiled in.) See βENCRYPTION ONLYβ support below.
π§ FORMATTING π§
Structured Gopher space(s) can be created with geomyidae through the use of special indexing files of the form <name>.gph which, if present, geomyidae uses to format and/or filter the contents of the base directory (/var/gopher by default) and create gopher menus. However, index files are not required: if no index.gph, index.cgi or index.dcgi file is found, geomyidae simply lists the directory contents in alphanumeric order. In addition, a directory can utilize multiple index files to create a layered gopher environment without the use of sub-directories: ie. pictures.gph, music.gph and documents.gph could be "directories" within main.gph, yet all reside in /var/gopher along with their respective files (*.jpg, *.mp3, *.pdf for example).
πΈ Anatomy of an index.gph file πΈ
A gph file consists of informational text and links. A link has the form:
[<type>|<desc>|<path>|<host>|<port>]
where,
<type>β A valid gopher Item Type.
Some common Gopher Types as defined in RFC 1436:
0β Item is a file.1β Gopher directory.3β Error.7β Item is an Index-Search server.8β Item points to a text-based telnet session.9β Binary file. Client reads until TCP connection closes!gβ GIF format graphics file.Iβ Indeterminate image file. Client decides how to display.
In addition, geomyidae provides these:
hβ Item is a hypertext (HTTP) link.iβ Informational Item (used for descriptive purposes).
Unknown file types default to Type "9" (binary).
<desc>β Description of gopher item. Most printable characters should work.<path>β Full or relative path to gopher item (base value is"/"). Use the"Err"path for items not intended to be served.<host>β Hostname or IP hosting the gopher item. Must be resolvable for the intended clients. If this is set to"server", the server's hostname is used.<port>β TCP port number (usually 70). If this is set to"port", the default port of the server is used.
Note:geomyidaedoesn't require "informational" text to be formally typed as[i|...]; any line not beginning with[is treated as informational, greatly simplifying the formatting ofindex.gphfiles. If you want to display some informational text beginning with[you can use the special case of an empty item type.[|[some linkwill be shortened to[some link. For dynamically generated content it may be desirable to either formally type informational text or run it through a filter to prepend[|- .iesed 's,^[,[|&,'.
Note 2: You can escape a pipe (|) character in for example a<desc>field by prepending a slash ("\").
Note 3: The gph parser is very forgiving. If the link structure is not parsed correctly, then the original line is printed.
π index.gph Example π
A root.gph file for a server running on host=frog.bog, port=70. Note use of optional [i]nformational Item (line 2) for vertical space insertion:
Welcome to Frog.bog
[i||Err||]
[0|About this server|about.txt|frog.bog|70]
[0|Daily Log|/dtail.cgi|frog.bog|70]
[1|Phlog: like a blog, but not|/PHLOG|frog.bog|70]
[9|Some binary file|widget.exe|frog.bog|70]
[I|Snowflake picture|snowflake.jpg|frog.bog|70]
try our snowflakes!
Links and Searches
[1|Go to R-36.net|/|gopher.r-36.net|70]
[h|Go to NetBSD.org|URL:http://netbsd.org|frog.bog|70]
[7|Query US Weather by Zipcode|/weather.cgi?|frog.bog|70]
[7|Search Veronica II|/v2/vs|gopher.floodgap.com|70]
[8|Telnet to SDF Public Access Unix System|null|freeshell.org|23]
The above looks something like this in a text-based gopher client:
Welcome to Frog.bog
(FILE) About this server
(FILE) Daily Log
(DIR) Phlog: like a blog, but not
(BIN) Some binary file
(IMG) Snowflake picture
try our snowflakes!
Links and Searches
(DIR) Go to R-36.net
(HTML) Go to NetBSD.org
(?) Query US Weather by Zipcode
(?) Search Veronica II
(TEL) Telnet to SDF Public Access Unix System
π DYNAMIC CONTENT (gopher CGI) π
okay so for dynamic content creation there are two options plus a special case, bestie: standard CGI (.cgi), dynamic CGI (.dcgi), and HTTP compatibility mode. Despite the names, all three can accept input and generate dynamic content; the only difference is that dcgi re-formats its output so it appears to the server as a standard geomyidae index (.gph) file. That makes creating on-the-fly gopher directories so much easier (see the examples). All scripts must be under the gopher root directory and be executable by the same user:group running geomyidae. Consequently, it is best to use the -u and -g server options to avoid running as root. π
Executed scripts get the full I/O of the socket bound to stdin and stdout. You are thus able to write long-lasting streaming services. Radio or TV stations over gopher are possible that way. iconic. π»
Both .cgi and .dcgi scripts have the same argument call structure (as seen by geomyidae):
executable.[d]cgi search arguments host port traversal selector
where:
searchβ Query string (type7) or""(type0).argumentsβ String behind"?"in selector or"".hostβ Server's hostname ("localhost"by default).portβ Server's port ("70"by default).traversalβ Remaining path from path traversal in REST case.selectorβ Raw selector or full req (See HTTP compatibility mode.)
All terms are tab-separated (per gopher protocol) which can cause some surprises depending on how a script is written. See the CGI file (included in the geomyidae source archive) for further elaboration. π«Ά
For a special REST path case for the arguments, see the CGI file for the description.
QUIRK: The original gopher client tried to be too intelligent. It is using gopher+ when you request some resource. When"search"is just the value+,!,$or empty, geomyidae will display a gopher+ redirect instead of invoking the script. Be careful to design your search script so the user is unlikely to enter those values. The designers of gopher+ did not think of classic gopher to survive. It survived gopher+. π
Additionally to the above arguments several environment variables are set. Only the programmatically relevant variables are listed here. For further information, see ind.c:setcgienviron() in the geomyidae source code.
PATH_INFOβ Traversal (See above.)PATH_TRANSLATEDβ Absolute path to script.QUERY_STRINGβ Arguments (See above.)REMOTE_ADDR,REMOTE_HOSTβ IP of the clientSCRIPT_NAMEβ Script which is executed.SERVER_NAMEβ Server's hostname.SERVER_PORTβ Server's port.GOPHER_SELECTORβ Raw gopher selectorGOPHER_REQUESTβ Raw gopher selectorGOPHER_SEARCHβ Search (See above.)GOPHER_SCRIPT_FILENAMEβ Absolute path with script which is executed.GOPHER_DOCUMENT_ROOTβ Base root for serving files.SERVER_LISTEN_NAMEβ Ip the server received the connection on.HTTPS,GOPHERSβ Set, if TLS is used.
π§ The REST path handling
If a client requests a path in a selector, which has no corresponding file or path found, geomyidae will try to traverse from the -b base path until a path component / directory is not found. Then geomyidae tries to find some index.dcgi or index.cgi file in the last existing directory. If this is found and the index files are executable, geomyidae will execute them using the traversal and PATH_INFO parameter and environment variable being set to the rest path. slay. β¨
Selector: /some/v1/service/add/something?args=value
-> /some/v1/service exists
-> /some/v1/service/index.dcgi exists
-> /some/v1/service/index.dcgi "" "args=value" $host $port
"/add/something" "/some/v1/service/add/something?args=value" is called
π HTTP compatibility
For maximum flexibility in case someone sends a HTTP request to gopher, geomyidae supports a special case of CGI. See this example:
Client request: GET /some/path HTTP/1.1
-> /GET exists and is executable
-> /GET "" "" $host $port "" "GET /some/path HTTP/1.1" is called
This allows for example simple scripts for icecast upload compatibility or handling transparent HTTP right next to gopher, getting TLS for free. π¦
π Some CGI Examples
Note: these are a very simple examples with no fitness checks with respect to safety/security.
ex. uptime.cgi - standard CGI, no queries
#!/bin/sh
# uptime.cgi - prints system uptime(1)
/usr/bin/uptime
exit 0
Call the above with the following index.gph entry:
[0|System Uptime|/uptime.cgi|frog.bog|70]
A search query request must have an item Type of "7" to be called from an (index.gph) file. It also needs a "?" suffix in the <path> field:
ex. hello.cgi - standard CGI with query
#!/bin/sh
# hello.cgi - welcome user
NAME=$1
HOSTNAME=$2
echo ""
echo Hello $NAME - welcome to $HOSTNAME
exit 0
Call the above with the following index.gph entry:
[7|Hello You - Please enter your name|/hello.cgi?FROG.bog|frog.bog|70]
And do a simple snarf(1) query (note the inserted TAB):
% snarf "gopher://frog.bog/7/hello.cgi?FROG.bog[TAB]Christoph" -
Hello Christoph - welcome to FROG.bog
Dynamic CGI entries are similar to above except that the script needs to create output as described in the FORMATTING section:
ex. jughead.dcgi - dynamic CGI script with query
#!/bin/sh
# jughead.dcgi - jughead-like local gopher search
KWRD="$1"
ARCHIVE="/var/gopher/textfiles/"
echo "[i|Search results for \"${KWRD}\":|Err||]"
echo "[i||Err||]"
# grep(1) recursive, case-insensitive KWRD search of ARCHIVE:
for RESULT in $(/usr/bin/grep -i -l -m1 ${KWRD} -r $ARCHIVE)
do
DESC=$(/usr/bin/basename ${RESULT})
PATH=$(echo "$RESULT" | /usr/bin/sed 's/^\/var\/gopher//')
echo "[0|${DESC}|${PATH}|frog.bog|70]"
done
exit 0
Call the above with the following index.gph entry:
[7|Search this Gopher|/jughead.dcgi?|frog.bog|70]
A successful query might look like this:
Search results for "fubar":
(FILE) How_Things_Break.txt
(FILE) Origins_of_Words.txt
(FILE) Phrases_of_the_Ages.txt
Care should to be exercised to avoid creating mistyped entries, unwanted recursions, and/or unintended writes in the working directory. no cap. π
π₯ HAPROXY SUPPORT π₯
geomyidae has HAProxy support. It can be enabled using the -y parameter. periodt.
πΈ LOG FILES πΈ
The log file (ie. /var/log/gopherd.log) has the following structure:
[<date>|<IP/Host>|<port>|<status>] <item path>
where,
<date>β Access date and time (std'date'format). ex."2018-01-31 14:18:34 +0000"<IP/Host>β Client IP/Host served ex."104.23.33.1"<port>β Client port served ex."16857"<status>β Status of client request ex. - some common status entries:"serving"β A successful request."not found"β An unsuccessful request."HTTP redirect"β Web link redirect (Typeh)."dir listing"β Unindexed directory listing.
<item path>β Full path to item served ex."/PICS/simple2.jpg"for an image file;"/PICS"for a directory access.
π ENCRYPTION ONLY π
If you set the sticky bit (βchmod +tβ) on some file or directory, geomyidae will only serve it over an encrypted connection. There is the special case, that when the sticky bit is set on the base directory, all content will only be served over TLS. bestie, thatβs the vibe check. π
π FILES π
READMELICENSECGIindex.gphrc.d/LINKSgph/
π SEE ALSO π
Links for further information on gopher:
- Floodgap Systems:
gopher://gopher.floodgap.com - The Gopher Project:
gopher://gopherproject.org
β STANDARDS β
F. Anklesaria, M. McCahill, P. Lindner, D. Johnson, D. Torrey, and B. Alberti, The Internet Gopher Protocol (a distributed document search and retrieval protocol), RFC 1436, March 1993.
π¦ HISTORY π¦
geomyidae started as a Linux/BSD port of the Plan 9 gopherd_P9 server. Originally called gopherd_BSD, the name was later changed to "Geomyidae" (latin), the taxonomic family of burrowing rodents known as "pocket gophers" which are in fact the true gophers. Due to inconsistencies and the UNIX culture, the name was changed to lowercase in 2010. iykyk. π§
π AUTHORS π
See LICENSE file for authors in the distribution.
π LICENSE π
geomyidae is released under the MIT/X Consortium License.
π BUGS π
Dynamic content functionality may vary across gopher clients.
π Reporting Bugs
Report bugs to: Christoph Lohmann <20h@R-36.net>
π and thatβs the whole GEOMYIDAE(8) page, bestie β source/version is Debian, dated January 4, 2025. mwah. π
π¦ where this page comes from
- nixos 26.05: geomyidae 0.99
- nixpkgs unstable: geomyidae 0.99
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms