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.
Go to file
2022-10-09 22:40:17 -04:00
handlers Reverse proxy fixes and changes 2022-09-24 20:35:14 -04:00
static Non gemtext static files 2021-10-09 21:05:56 -04:00
.gitignore Non gemtext static files 2021-10-09 21:05:56 -04:00
example.js Reverse proxy fixes and changes 2022-09-24 20:35:14 -04:00
GeminiServer.js Reverse proxy fixes and changes 2022-09-24 20:35:14 -04:00
LICENSE Move to Unlicense 2022-02-28 11:12:36 -05:00
main.js Add ReverseProxy 2021-09-15 17:16:01 -04:00
package-lock.json Non gemtext static files 2021-10-09 21:05:56 -04:00
package.json Move to Unlicense 2022-02-28 11:12:36 -05:00
README.gmi Update README 2022-10-09 22:40:17 -04:00

# 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.

```sh
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.

```sh
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

```sh
# 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 example.com:1965 -servername example.com
```


# TODO
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.