Sula: A Gemini protocol server written in Scryer Prolog

Hacker News Top Tools

Summary

Sula is a Gemini protocol server written in Scryer Prolog, featuring TLS via rustls, content negotiation, and graceful shutdown, but requires a patched Scryer Prolog build.

No content available
Original Article
View Cached Full Text

Cached at: 08/05/26, 07:56 PM

# Sula Source: [https://sagredo.dev/projects/sula/](https://sagredo.dev/projects/sula/) > `/'su\.la/`for the suffix of capsule in Spanish, Cápsula\. ![sula logo](https://sagredo.dev/img/sula.png) [Git](https://git.sagredo.dev/?p=sula.git;a=summary) A[Gemini](https://geminiprotocol.net/)protocol server written in[Scryer Prolog](https://www.scryer.pl/)\. ## Requirements sula depends on a patched Scryer Prolog which can be found[here](https://git.sagredo.dev/scryer-prolog)\(branch`js/fixes`\)\. The required patches are: - A native`'$copy\_stream'/2`builtin used for streaming binary file bodies to TLS clients without materialising the contents on the Prolog heap\. - A fix to`library\(pio\)`’s`buffer\_prepare\_for\_n/5`so that lazy reads from process pipes \(and other streams whose`at\_end\_of\_stream/1`never reports true\) terminate on EOF instead of spinning\. - A non\-blocking poll loop in`socket\_server\_accept/4`that checks Scryer’s`INTERRUPT`flag, so`SIGINT`becomes a catchable`'$interrupt\_thrown'`exception instead of being trapped behind a blocking syscall\. - A port to`rustls`\. - A modification of`tls\_server\_negotiate`to include the optional client certificate\. Build and install the patched Scryer: ``` git clone https://git.sagredo.dev/scryer-prolog -b js/fixes cd scryer-prolog cargo install --path . ``` `openssl\(1\)`must also be on`PATH`— it’s invoked at startup to read the`CN`from the configured identity certificate and verify it matches the configured hostname\. ## Running ``` ./sula.pl --addr HOST:PORT --hostname NAME --content DIR --certs DIR ``` `sula\.pl`is a polyglot script: bash detects`scryer\-prolog`on`PATH`and execs it with`sula:run, halt`as the entry goal\. Example: ``` ./sula.pl \ --addr 127.0.0.1:1965 \ --hostname gmi.example.dev \ --content ./site \ --certs . ``` ### CLI options All options accept any order\. Anything unrecognised is silently dropped\. OptionMeaningDefault`\-\-addr HOST:PORT`Bind address and port for the listening socket`127\.0\.0\.1:1965``\-\-hostname NAME`Expected`CN`of the certificate\. Startup aborts on mismatch`localhost``\-\-content DIR`Root directory for served files`\./site``\-\-certs DIR`Directory containing`cert\.pem`and`key\.pem``\.`### Stopping the server `Ctrl\+C`triggers a clean shutdown: the listening socket is closed, the top\-level catch logs`Shutting down`, and the process exits 0\. ## Features - TLS via`rustls`, PKCS\#12 identity files\. - Hostname verification: at startup,`cert\_is\_for\_hostname/2`shells out to`openssl x509`and asserts the cert’s`CN`matches`\-\-hostname`\. - Content negotiation by extension via`mime/2`, populated at startup from`/etc/mime\.types`\(parsed by a DCG in`mime\.pl`\)\.`text/gemini`is added for`\.gmi`\. - Text responses sent via`format/3`; binary responses streamed in native code through`copy\_stream/2`\(file → TLS socket, no Prolog heap traffic\)\. - Per\-connection error handling: TLS handshake failures and mid\-stream client disconnects are logged and the loop continues\. Other errors re\-throw and surface at the top level\. - Graceful shutdown on`SIGINT`via the patched Scryer`socket\_server\_accept/4`\. ## Layout ``` sula.pl Polyglot launcher + main sula module (run/0, request loop). config.pl CLI parsing (DCG) and config accessors (cert/1, addr/1, ...). cert.pl Certificate loading + hostname-vs-CN check. mime.pl /etc/mime.types parser (DCG) and mime/2 facts. request.pl Request line reader. gemini_uri.pl Gemini URI DCG (gemini://host[:port]/path[?query]). ip.pl IP address recognition (rejected as Gemini hosts). response.pl Response status code DCG. log.pl Tagged log_msg/3. banner.pl Reads banner.txt and emits it line-by-line via display_banner/1. ``` ## Planned features - Use key and cert instead of identity\.p12 - Client certificates - Load configuration from a configuration file - Save and load users - Run CGI scripts - All status codes - Rate limiting - Virtual hosting - File logging - Multi\-threading or kind of? - Hot reload?

Similar Articles

yserver: A modern X11 server written from scratch in Rust

Lobsters Hottest

yserver is a modern X11 server written from scratch in Rust, capable of running full desktop environments like MATE, XFCE, and Cinnamon while dropping legacy baggage. It supports many X extensions and has been tested on various hardware.

alireza0/s-ui

GitHub Trending (daily)

S-UI is an advanced web panel built on SagerNet/Sing-Box for managing multi-protocol proxy configurations with features like traffic routing, subscription links, and multi-language support.