GmCapsule is an extensible server for [Gemini](https://gemini.circumlunar.space/) and [Titan](https://transjovian.org/titan/).

See the [User manual](https://geminispace.org/gmcapsule/gmcapsule.html) for configuration and usage instructions.

## Installation

Install "gmcapsule" via `pip`:

    pip install gmcapsule

Then run the server daemon:

    gmcapsuled

## Running via systemd

Create the following service file and save it as _~/.config/systemd/user/gmcapsule.service_:

    [Unit]
    Description=GmCapsule: extensible Gemini/Titan server
    After=network.target

    [Service]
    Type=simple
    ExecStart=<YOUR-INSTALL-PATH>/gmcapsuled
    ExecReload=/bin/kill -HUP $MAINPID
    Restart=always
    Environment="PYTHONUNBUFFERED=1"
    StandardOutput=syslog
    StandardError=syslog
    SyslogIdentifier=gmcapsule

    [Install]
    WantedBy=default.target

Replace `<YOUR-INSTALL-PATH>` with the actual path of `gmcapsuled`. `pip` will install it in a directory on your PATH.

Then you can do the usual:

    systemctl --user daemon-reload
    systemctl --user enable gmcapsule
    systemctl --user start gmcapsule

The log can be viewed via journalctl (or syslog):

    journalctl -xe --user-unit=gmcapsule

## Change log

### v0.5

* Added `processes` to the `[server]` section to configure how many request handler processes are started.
* Extension modules can register new protocols in addition to the built-in Gemini and Titan.
* SIGHUP causes the configuration file to be reloaded and workers to be restarted. The listening socket remains open, so the socket and TLS parameters cannot be changed.
* API change: Extension modules get initialized separately in each worker thread. Instead of a `Capsule`, the extension module `init` method is passed a `Context`. `Capsule` is no longer available as global state.
* API change: `Identity` no longer contains OpenSSL objects for the certificate and public key. Instead, they are provided as serialized in DER format.

### v0.4

* Added built-in module "rewrite" that matches regular expressions against the request path and can rewrite the path or return a custom status for redirection, "Gone" messages, or other exceptional situations.
* Extension module load order is determined after locating all modules from all directories. Previously, the order was local to each directory.
* Added a new configuration section `[priority]` for overriding default module priorities determined from file names. This is useful for changing the priority of the built-in modules.

v0.4.1:

* Rewrite: Request query string can be included in a `status` using the `${QUERY_STRING}` variable.

### v0.3

* Added a shutdown event for custom background workers.
* `Request.query` is None if there is no query string present. Previously, the query string was an empty string in this case. This allows making a distinction between empty and absent query strings.

v0.3.1:

* CGI: Fixed handling of a missing query string.

v0.3.2:

* GitView: Fixed processing of Git commit history when a message contains backslashes.

### v0.2

* Added `[cgi] bin_root` configuration option for automatically and dynamically mapping all executables in a directory tree to URL entry points.
* Minor documentation updates.
* Published on PyPi as "gmcapsule".

v0.2.1:

* Fixed error handling. Exceptions are now caught and the error message is printed.

v0.2.2:

* Reduced required Python version to 3.6 (f-strings).
* Added systemd instructions.

v0.2.3:

* Requests exceeding 1024 bytes should result in an error code and not just be ignored.
* Respond with an error code to malformed UTF-8 in the request.
* Verify that the port number in the request URI matches the server's port.

v0.2.4:

* Fixed an error in the Markdown parser.

v0.2.5:

* Fixed handling of exceptions from request handler, and print a traceback.
* Fixed `importlib` error with Python 3.11.

### v0.1

* Initial public release.