Astronomical Theater is a Node.js Gemini server. I use it because I believe using code that you wrote is a good thing. In almost all cases, I would recommend writing your own Gemini server, or using another server, rather than using this one.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Matthias Portzel 6a412a2dec Update README 2 months ago
handlers Reverse proxy fixes and changes 2 months ago
static Non gemtext static files 1 year ago
.gitignore Non gemtext static files 1 year ago
GeminiServer.js Reverse proxy fixes and changes 2 months ago
LICENSE Move to Unlicense 9 months ago
README.gmi Update README 2 months ago
example.js Reverse proxy fixes and changes 2 months ago
main.js Add ReverseProxy 1 year ago
package-lock.json Non gemtext static files 1 year ago
package.json Move to Unlicense 9 months ago


# Astronomical Theater
A Node.js Gemini server and proxy.

## Do not use.
This is known to be buggy.
I use it because the promise of Gemini is that people are able to write their own software, and that's an ideal that I believe in.
And I open-source it because I believe code should be free.

### Known bugs
* It reads the certificates into memory at start up, and never again. This means that if you (like me) use Let's Encrypt and rotate certs, then after three months the server needs to be restarted.
* It suffers from a Node JS bug which causes it to allocate ~10.8GB of virtual memory (not actual memory so this theoretically doesn't matter).
* Most importantly, it sometimes drops requests that it's proxying before they've completed. I kind of suspect this is also a Node.js bug, but I don't have a minimum reproduction case.

### We require SNI!
The Gemini spec requires clients to implement SNI. This server requires SNI to connect.

echo "gemini://localhost/\r" | openssl s_client -connect "localhost:1965" # WILL FAIL
If you want to use `openssl s_client` to debug, you must pass the `-servername` option so that openSSL will send a hostname to the server.

echo "gemini://localhost/\r" | openssl s_client -connect "localhost:1965" -servername "localhost" # All good!

There are a lot of paths.

A `urlPath` is the absolute path given in the Gemini request (new URL().pathname)

A `basePath` is the first argument to register path. We match the `urlPath` against a basePath when determining how to handle a request.

A `relativePath` is the difference between a `basePath` and a `urlPath`. It's normally `""`.

Sometimes these paths will include their hostnames

A path in the pathRegistry is a `p`, which is an object with a hostname, a basePath, and a handler

### Creating certificates for dev

# Generate private key
openssl genrsa -out private-key.pem 2048
# Generate cert. signing request
# All fields can be left blank except for Common Name, where I enter "localhost"
openssl req -new -sha256 -key private-key.pem -out csr.pem
# Self-sign, generating cert
openssl x509 -req -in csr.pem -signkey private-key.pem -out public-cert.pem

# For debugging clients, it can be useful to start a openssl server with these certs:
openssl s_server -key private-key.pem -cert public-cert.pem -accept 1965

# And of course creating a client with openssl. The -servername is needed for SNI
openssl s_client -connect -servername

It's possible to imagine a situation where astronomical theater is behind a proxy and the proxy doesn't do address translation, passing the raw gemini request to us.
In this case, our behavior is undefined.

Similarly, SNI is not supported with IP addresses.