Updating docs

This commit is contained in:
Michael Lazar 2019-08-29 23:35:29 -04:00
parent 8abb027288
commit 97e6a5bfb5
2 changed files with 50 additions and 47 deletions

View File

@ -39,9 +39,10 @@ Use the ``--help`` flag to view command-line options:
```bash ```bash
$ jetforce --help $ jetforce --help
usage: jetforce [-h] [--host HOST] [--port PORT] [--tls-certfile FILE] usage: jetforce [-h] [--host HOST] [--port PORT] [--hostname HOSTNAME]
[--tls-keyfile FILE] [--hostname HOSTNAME] [--dir DIR] [--tls-certfile FILE] [--tls-keyfile FILE] [--tls-cafile FILE]
[--cgi-dir DIR] [--index-file FILE] [--tls-capath DIR] [--dir DIR] [--cgi-dir DIR]
[--index-file FILE]
An Experimental Gemini Protocol Server An Experimental Gemini Protocol Server
@ -49,63 +50,68 @@ optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
--host HOST Server address to bind to (default: 127.0.0.1) --host HOST Server address to bind to (default: 127.0.0.1)
--port PORT Server port to bind to (default: 1965) --port PORT Server port to bind to (default: 1965)
--hostname HOSTNAME Server hostname (default: localhost)
--tls-certfile FILE Server TLS certificate file (default: None) --tls-certfile FILE Server TLS certificate file (default: None)
--tls-keyfile FILE Server TLS private key file (default: None) --tls-keyfile FILE Server TLS private key file (default: None)
--hostname HOSTNAME Server hostname (default: localhost) --tls-cafile FILE A CA file to use for validating clients (default: None)
--dir DIR Local directory to serve (default: /var/gemini) --tls-capath DIR A directory containing CA files for validating clients
(default: None)
--dir DIR Root directory on the filesystem to serve (default:
/var/gemini)
--cgi-dir DIR CGI script directory, relative to the server's root --cgi-dir DIR CGI script directory, relative to the server's root
directory (default: cgi-bin) directory (default: cgi-bin)
--index-file FILE If a directory contains a file with this name, that --index-file FILE If a directory contains a file with this name, that
file will be served instead of auto-generating an index file will be served instead of auto-generating an index
page (default: index.gmi) page (default: index.gmi)
If the TLS cert/keyfile is not provided, a self-signed certificate will
automatically be generated and saved to your temporary directory.
``` ```
### Hostname
Because the gemini protocol sends the whole URL in the request, it's necessary
to declare the hostname that your server is expecting to receive traffic under.
Jetforce will reject any request that doesn't match your hostname with a status
of ``Proxy Request Refused``.
### TLS Certificates ### TLS Certificates
The gemini specification *requires* that all connections be sent over TLS. The gemini specification *requires* that all connections be sent over TLS.
Before you deploy jetforce, you should either generate your own self-signed
certificate, or obtain one from a Certificate Authority like
[Let's Encrypt](https://letsencrypt.org).
In order to make local development easier, if you do not specify the certificate If you do not provide a TLS certificate file using the ``--tls-certfile`` flag,
arguments, jetforce will automatically generate a temporary ad-hoc TLS certificate jetforce will automatically generate a temporary cert for you to use. This is
to use. Here's the OpenSSL command that jetforce uses internally: great for making development easier, but before you expose your server to the
public internet you should configure something more permanent. You can generate
your own self-signed server certificate, or obtain one from a Certificate
Authority like [Let's Encrypt](https://letsencrypt.org).
Here's the OpenSSL command that jetforce uses to generate a self-signed cert:
``` ```
$ openssl req -newkey rsa:2048 -nodes -keyout {hostname}.key \ $ openssl req -newkey rsa:2048 -nodes -keyout {hostname}.key \
-nodes -x509 -out {hostname}.crt -subj "/CN={hostname}" -nodes -x509 -out {hostname}.crt -subj "/CN={hostname}"
``` ```
There are currently no plans to support transient self-signed client certificates. Jetforce also supports verified client TLS certificates. You can specify your
This is due to a technical limitation of the python standard library's ``ssl`` client CA with the ``--tls-cafile`` or ``--tls-capath`` flags. Verified
module, which is described in detail connections will have the ``REMOTE_USER`` variable added to their environment,
which contains the client certificate's CN attribute. Instructions on how to
generate TLS client certificates are outside of the scope of this readme, but
you can find many helpful tutorials
[online](https://portal.mozz.us/?url=gemini%3A%2F%2Fmozz.us%2Fjournal%2F2019-08-21.txt).
There are currently no plans to support unverified (transient) client
certificates. This is due to a technical limitation of the python standard
library's ``ssl`` module, which is described in detail
[here](https://portal.mozz.us/?url=gemini%3A%2F%2Fmozz.us%2Fjournal%2F2019-08-21.txt). [here](https://portal.mozz.us/?url=gemini%3A%2F%2Fmozz.us%2Fjournal%2F2019-08-21.txt).
Support for verified client certificates will be added in a future version. ### Static Files
### Hostname Jetforce will serve static files in the ``/var/gemini/`` directory:
Because the gemini protocol sends the *whole* URL in the request, it's required - Files ending with **.gmi** will be interpreted as the *text/gemini* type
that you declare the hostname that your server is expecting to receive traffic - If a directory is requested, jetforce will look for a file in that directory
under. Jetforce will reject any request that doesn't match your hostname with a with the name of **index.gmi**
status of ``Proxy Request Refused``. - If it exists, the index file will be returned
- Otherwise, jetforce will generate a directory listing
Using python, you can modify this behavior to do fancy things like building a
proxy server for HTTP requests. See [http_proxy.py](examples/http_proxy.py) for
an example of how this is done.
### Serving Files
Jetforce serves files from the ``/var/gemini/`` directory by default:
- Files with the **.gmi** extension will be interpreted as *text/gemini*.
- Other files will have their *mimetype* guessed based on their file extension.
- Directories will look for a file with the name **index.gmi**.
- If an index file does not exist, a directory listing will be generated.
### CGI Scripts ### CGI Scripts
@ -113,14 +119,17 @@ Jetforce implements a slightly modified version of the official CGI
specification. Because Gemini is a less complex than HTTP, the CGI interface is specification. Because Gemini is a less complex than HTTP, the CGI interface is
also inherently easier and more straightforward to use. also inherently easier and more straightforward to use.
The main difference in this implementation is that the CGI script is expected The main difference in jetforce's implementation is that the CGI script is
to write the entire gemini response *verbatim* to stdout: expected to write the entire gemini response *verbatim* to stdout:
1. The status code and meta on the first line 1. The status code and meta on the first line
2. Any additional response body on subsequent lines 2. The optional response body on subsequent lines
Unlike HTTP's CGI, there are no request/response headers or other special Unlike CGI v1.1, there are no headers or other special values that the script
fields to perform actions like redirects. can respond with.
Some of the HTTP-specific environment variables like ``REQUEST_METHOD`` are not
used, because they don't make sense in the context of a Gemini request.
## License ## License

View File

@ -39,11 +39,6 @@ An Experimental Gemini Server, v{__version__}
https://github.com/michael-lazar/jetforce https://github.com/michael-lazar/jetforce
""" """
EPILOG = """
If the TLS cert/keyfile is not provided, a self-signed certificate will
automatically be generated and saved to your temporary directory.
"""
class Status: class Status:
""" """
@ -616,7 +611,6 @@ def command_line_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
prog="jetforce", prog="jetforce",
description="An Experimental Gemini Protocol Server", description="An Experimental Gemini Protocol Server",
epilog=EPILOG,
formatter_class=argparse.ArgumentDefaultsHelpFormatter, formatter_class=argparse.ArgumentDefaultsHelpFormatter,
) )
parser.add_argument("--host", help="Server address to bind to", default="127.0.0.1") parser.add_argument("--host", help="Server address to bind to", default="127.0.0.1")