ROPHY(8) System Manager's Manual ROPHY(8) NAME rophy -- a small Gopher server for OpenBSD written in Rust SYNOPSIS rophcatch [-l] [-n name] [-p port] [-r docroot] DESCRIPTION rophy is a simple Gopher server for Unix-like systems, preferably OpenBSD. It's implemented in Rust and there's no standalone dae- mon functionality. It's meant to be called by something like inetd(8) as an unprivileged user. rophy also works with systemd(1) socket activation (and probably also xinetd(8), but this is not tested). On OpenBSD, it will use pledge(2) and unveil(2) to further lock down the process. rophy supports o automatic indexing, o manual menus using plain text .INDEX files, o custom headers in auto-generated menus using .HEADER files, o manual annotation of single files in auto-generated menus us- ing ..ANN files, o ignoring sets of files in auto-generated menus using .FILES_IGNORED files, o search queries and o logging of requests. The options are as follows: -l Enable logging of IP addresses of remote hosts. (Be aware that something like inetd(8) or systemd(1) might still log remote addresses, so you have to configure these dae- mons, too.) -n name The server's hostname. This string will be used in menu items. This variable does NOT control on which network interfaces the server can be accessed; all of that must be configured in inetd(8) or systemd(1). (Default: "localhost") -p port The server's port. Again, this is only relevant for menu items. (Default: "70") -r docroot The document root. No files outside of this directory can be served. On OpenBSD, the process will also be locked via unveil(2) to this directory. (Default: "/srv/gopher") CONFIGURATION There is no special configuration file for rophy. Everything is configured using the command line arguments. The server in front of rophy, however, must be configured. inetd Have a look at your inetd(8) documentation to learn how to do this. As an example, the following could be used to integrate rophy into OpenBSD's inetd(8): gopher stream tcp4 nowait _rophy /usr/local/bin/rophy /usr/local/bin/rophy -l -r /srv/gopher/pub -n my.server.com gopher stream tcp6 nowait _rophy /usr/local/bin/rophy /usr/local/bin/rophy -l -r /srv/gopher/pub -n my.server.com systemd It's also possible to use systemd's socket activation to run rophy. rophy.socket and rophy@.service might look something like this: rophy.socket: [Socket] ListenStream=70 Accept=yes [Install] WantedBy=sockets.target On non-OpenBSD, all logging will be done to stderr, so you should configure your rophy@.service to connect that channel to the journal: [Unit] Description=rophy per-connection server [Service] User=http ExecStart=/usr/local/bin/rophy -n myhostname -r /srv/gopher StandardInput=socket StandardOutput=socket StandardError=journal INDEX FILE FORMAT The Gopher protocol is trivial in technical terms but it's cum- bersome to write Gopher menus by hand. Hence, the following file format simplifies this process. It's similar to the format of index.gph files in geomyidae(8), another Gopher server. A .INDEX file may contain arbitrary text which is translated into an "informational text" item in the Gopher menu. On the other hand, a line beginning with an opening bracket will be inter- preted by rophy and will create a menu item. It has the following structure: [||||] Where: is a valid Gopher item type (see RFC 1436). is the description of the item. is an absolute or relative path to the Gopher item. Rela- tive paths are meant to be relative to the current direc- tory and should only point to a location on the current host. "URL links" are also supported. is the target host. If this is set to server, then the server's hostname is used (see the -n flag). is the port of the target host. If this is set to port, then the local server's port is used (see the -p flag). Thus, an index file could read as follows: Welcome! Have fun browsing this server. [0|About this server|about.txt|server|port] [0|A quote|/random/quote.txt|server|port] [1|Pics|/pics|server|port] [1|My friend's server|/foo|friend.org|70] [h|A web page|URL:http://www.example.com|server|port] The index file format will be used under several circumstances, see below. Tabs (ASCII 0x09) are part of the Gopher protocol. Each tab will be replaced by four spaces by rophy -- no attempt will be made at retaining the visual layout created by using tabs. You should probably refrain from using them in your index files. INDEXING If a directory is requested by the client, rophy will o read and parse the special file .INDEX if it exists, or oth- erwise o create a simple menu containing all non-hidden files in the directory. Files and directories beginning with a dot are considered hidden. Special functions for auto-generated menus If a file called .HEADER exists in the directory, then this file will be parsed according to the index file format and it will be shown at the top of the menu. If a file called .DIR_REVERSED exists, then the generated listing will be in reversed order. This is useful if your file names con- tain timestamps and you want to show the latest file first. Sometimes, you may want to add an annotation to one single file. Normally, this would require you to write a complete .INDEX file. To avoid this, for each file or directory it is checked if an- other file called ..ANN exists. This file will be parsed according to the index file format and will be shown right before the menu item for the file . A directory may contain a file called .FILES_IGNORED. Similar to the environment variable GLOBIGNORE of bash(1), it can contain a list of patterns to be excluded from auto-generated menus (pat- terns must be separated by colons). You can use this to ignore specific files. For example, if your .FILES_IGNORED contained the following line, then all files ending in ".groff" or ".log" would not show up in auto-generated indices: *.groff:*.log When a file called .SEARCH exists in a directory, rophy will au- tomatically add a corresponding entry to auto-generated indices. This will allow you to search through files in this directory and all subdirectories. LOGGING o On OpenBSD, rophy rophy will log directly to syslogd(8). o On other systems, it will write to stderr. BUGS If you find a bug, I'd happy to hear about it. It's as easy as sending an e-mail, please see https://uninformativ.de/bugs.html. The RFC requires that, in some circumstances, a line containing only one single dot is sent. For example, Gopher menus must end with such a line. rophy does not send this extra dot. Most other servers I found don't do this, either. Nowadays, clients are in- telligent enough not to require this dot. LICENSE rophy is released under the MIT license. See the accompanying LICENSE file. HISTORY rophy was originally written by Peter Hofmann. The project was started in 2025. SEE ALSO inetd(8), logger(1), syslogd(8), geomyidae(8), RFC 1436. GNU 2025-08-02 ROPHY(8)