mirror of
https://github.com/tildeclub/tilde.club.git
synced 2026-10-25 00:55:38 +00:00
175 lines
7.1 KiB
Markdown
175 lines
7.1 KiB
Markdown
# Gopher, Gemini, and finger
|
|
|
|
These are separate services with separate public directories. Creating a
|
|
`public_gopher` or `public_gemini` directory does not make it reachable until
|
|
the corresponding service is configured and tested.
|
|
|
|
## Gopher with Fossor
|
|
|
|
The current host uses [Fossor](https://github.com/tildeclub/Fossor), with
|
|
systemd accepting TCP connections on port 70 and starting `fossor@.service` for
|
|
each connection. The effective collected settings are:
|
|
|
|
- `MaxConnections=128`, `MaxConnectionsPerSource=8` on the socket.
|
|
- Service UID/group `gopher`, a 300-second runtime limit, and a 10-second stop timeout.
|
|
- Options read from `/etc/default/fossor` and then `/etc/sysconfig/fossor`.
|
|
|
|
The values of those option files were not supplied. The new-host setup below
|
|
chooses its own root and initially disables executable maps/CGI. A proxy can
|
|
make every connection appear to come from one address; account for that before
|
|
copying a per-source connection limit.
|
|
|
|
### Build and install on a new host
|
|
|
|
The reviewed Fossor checkout provides release `v3.1.2`. Check the project's
|
|
release/security notes before installation and record the actual tag/commit:
|
|
|
|
```bash
|
|
dnf install gcc make git
|
|
git clone --branch v3.1.2 https://github.com/tildeclub/Fossor.git
|
|
cd Fossor
|
|
./configure --listener=systemd --hostname=tilde.example.net \
|
|
--gopherroot=/srv/gopher --systemd=/etc/systemd/system
|
|
make
|
|
```
|
|
|
|
Review the generated files, then create a dedicated service identity and install
|
|
from that reviewed checkout:
|
|
|
|
```bash
|
|
useradd --system --user-group --no-create-home --shell /usr/sbin/nologin gopher
|
|
install -d -o root -g root -m 0755 /srv/gopher
|
|
make install
|
|
```
|
|
|
|
Run the privileged commands as root; do the source checkout and build as an
|
|
ordinary build account. `make install` installs the executable, options, and
|
|
units. It can replace existing Fossor files, so these commands are for a new
|
|
installation. For migration, use the project's migration notes and preserve
|
|
existing content and config first.
|
|
|
|
Set `OPTIONS` in `/etc/sysconfig/fossor` to a new-host configuration such as:
|
|
|
|
```bash
|
|
OPTIONS="-h tilde.example.net -r /srv/gopher -u public_gopher -nv -nx"
|
|
```
|
|
|
|
`-nx` disables executable content; `-nv` disables Gopher virtual hosting. Keep
|
|
one authoritative options value: the service reads both option files, with the
|
|
later environment file taking precedence for repeated variables.
|
|
|
|
Use `systemctl edit fossor@.service` for a local override:
|
|
|
|
```ini
|
|
[Service]
|
|
User=gopher
|
|
Group=gopher
|
|
RuntimeMaxSec=300
|
|
TimeoutStopSec=10
|
|
```
|
|
|
|
Create a root `gophermap` and one member's public directory. A menu file uses
|
|
literal tabs between link fields:
|
|
|
|
```bash
|
|
printf '!Our tilde\n~\n' > /srv/gopher/gophermap
|
|
install -d -o member -g member -m 0755 /home/member/public_gopher
|
|
printf '!My gopher space\nHello from my tilde.\n' > /home/member/public_gopher/gophermap
|
|
chown member:member /home/member/public_gopher/gophermap
|
|
chmod 0644 /srv/gopher/gophermap /home/member/public_gopher/gophermap
|
|
systemctl daemon-reload
|
|
systemctl enable --now fossor.socket
|
|
```
|
|
|
|
Allow TCP 70 in the chosen firewall manager, then test a Gopher client against
|
|
`gopher://tilde.example.net/` and `gopher://tilde.example.net/1/~member/`.
|
|
Use world-readable public content with traversable parent directories; Fossor's
|
|
public-file checks are stricter than merely allowing its UID to read a file.
|
|
Test that private files and traversal attempts are refused. Keep an executable
|
|
map test out of the live service until you deliberately enable execution and
|
|
understand which UID will run it.
|
|
|
|
Check `systemctl status fossor.socket` and `journalctl -u 'fossor@*'`. Keep a
|
|
version/update record for the manually installed binary; an OS package update
|
|
will not update it automatically.
|
|
|
|
## Gemini with gemserv
|
|
|
|
The collected service runs as `gemini`, with working directory
|
|
`/srv/gemini/gemserv` and this command:
|
|
|
|
```text
|
|
/srv/gemini/gemserv/target/release/gemserv config.toml
|
|
```
|
|
|
|
Its actual `config.toml` and source revision were not supplied. Do not infer
|
|
its vhosts, TLS keys, or execution policy from the unit alone.
|
|
|
|
For a new installation, review the
|
|
[upstream project](https://git.sr.ht/~int80h/gemserv), its dependency/update
|
|
status, and the example config shipped with the revision you choose. Build as
|
|
an ordinary account with the lockfile, using `cargo build --release --locked`.
|
|
If the chosen revision supports the static-only feature set, use
|
|
`--no-default-features` when that is all you intend to offer. Install the built
|
|
binary as root-owned `/usr/local/sbin/gemserv`; record its source revision.
|
|
|
|
The published gemserv config schema uses `interface`, `[[server]]`, `hostname`,
|
|
`dir`, `cert`, `key`, `index`, and **`usrdir`** for `~/public_gemini`. Use the
|
|
[small example](../examples/gemserv/config.toml) only with a revision supporting
|
|
that schema; it is not a copy of the uncollected live config.
|
|
|
|
Create a dedicated `gemini` system user/group, root-owned public content at
|
|
`/srv/gemini/content`, and a root-owned config directory at `/etc/gemserv`.
|
|
Create the new-host service identity and paths before installing its config:
|
|
|
|
```bash
|
|
useradd --system --user-group --no-create-home --shell /usr/sbin/nologin gemini
|
|
install -d -o root -g gemini -m 0750 /etc/gemserv
|
|
install -d -o root -g root -m 0755 /srv/gemini/content
|
|
```
|
|
|
|
A self-signed Gemini certificate for the example hostname can be made with:
|
|
|
|
```bash
|
|
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -sha256 \
|
|
-days 365 -noenc -subj '/CN=tilde.example.net' \
|
|
-addext 'subjectAltName=DNS:tilde.example.net' \
|
|
-keyout /etc/gemserv/key.pem -out /etc/gemserv/cert.pem
|
|
chown root:gemini /etc/gemserv/key.pem
|
|
chmod 0640 /etc/gemserv/key.pem
|
|
chmod 0644 /etc/gemserv/cert.pem
|
|
```
|
|
|
|
Gemini clients commonly keep certificate fingerprints. Record your replacement
|
|
and renewal policy so a changed certificate can be explained. Do not loosen the
|
|
permissions on a shared HTTPS private key to make a different service work.
|
|
|
|
Install [the example unit](../examples/gemserv/gemserv.service) as
|
|
`/etc/systemd/system/gemserv.service`, after creating its user and paths. Add
|
|
`index.gmi` under the main content root and a member's `public_gemini` at 0755,
|
|
with public files at 0644. Load the unit and start it:
|
|
|
|
```bash
|
|
systemctl daemon-reload
|
|
systemctl enable --now gemserv
|
|
journalctl -u gemserv --since today
|
|
```
|
|
|
|
Open TCP 1965 only when ready. Test the root and the member's URL with a Gemini
|
|
client, both externally and over IPv6 if advertised. Also test missing paths,
|
|
private files, symlinks, encoded traversal, and the deliberately disabled CGI
|
|
policy. Set timeouts and resource controls using the chosen version and the
|
|
service manager; do not assume a web server's limits apply to Gemini.
|
|
|
|
## Finger
|
|
|
|
The current host runs a local Python `fingerd.py` as `efingerd`, with only the
|
|
bind-service capability needed to listen on a privileged port. Its source was
|
|
not part of the collection, so this guide does not invent its response format
|
|
or access policy.
|
|
|
|
Finger is optional. Before offering it, decide which account/profile fields
|
|
are public, how members opt out, what the response says about logged-in users,
|
|
and how much output or request volume you allow. A public finger response
|
|
should not disclose private files just because the daemon can read them.
|