pollux/README.md
Jeena 0459cb6220 feat: Implement virtual hosting for multi-domain Gemini server
- Add hostname-based request routing for multiple capsules per server
- Parse virtual host configs from TOML sections ([hostname])
- Implement per-host certificate and content isolation
- Add comprehensive virtual host testing and validation
- Update docs and examples for multi-host deployments

This enables Pollux to serve multiple Gemini domains from one instance,
providing the foundation for multi-tenant Gemini hosting.
2026-01-22 02:38:09 +00:00

5.4 KiB

Pollux - A Simple Gemini Server

Pollux is a lightweight Gemini server for serving static files securely. It supports virtual hosting, allowing multiple Gemini capsules on a single server instance. Features include TLS encryption, hostname validation, directory serving, and comprehensive security protections.

Requirements

Rust 1.70+ and Cargo.

Building

Clone or download the source, then run:

cargo build --release

This produces the target/release/pollux binary.

Virtual Hosting

Pollux supports virtual hosting, allowing you to serve multiple Gemini capsules from a single server. Each hostname can have its own root directory, certificates, and configuration.

Configuration

Create a config file at /etc/pollux/config.toml or use --config to specify a path:

# Global settings (optional)
bind_host = "0.0.0.0"
port = 1965
log_level = "info"
max_concurrent_requests = 1000

# Virtual host configurations
["example.com"]
root = "/var/gemini/example.com"
cert = "/etc/ssl/example.com.crt"
key = "/etc/ssl/example.com.key"

["blog.example.com"]
root = "/var/gemini/blog"
cert = "/etc/ssl/blog.crt"
key = "/etc/ssl/blog.key"

["another-site.net"]
root = "/var/gemini/another"
cert = "/etc/ssl/another.crt"
key = "/etc/ssl/another.key"
port = 1966  # Optional per-host port override

Features

  • Multiple hostnames on a single server instance
  • Per-host TLS certificates for proper security isolation
  • Automatic content isolation - each host serves only its own files
  • Path security - directory traversal attacks are blocked
  • Index file serving - index.gmi files are served automatically
  • Hostname validation - DNS-compliant hostname checking

Request Routing

  • gemini://example.com/ → serves /var/gemini/example.com/index.gmi
  • gemini://blog.example.com/article.gmi → serves /var/gemini/blog/article.gmi
  • gemini://unknown.com/ → returns status 53 "Proxy request refused"

Single Host Mode (Legacy)

For backward compatibility, you can still use the old single-host format:

root = "/path/to/static/files"
cert = "/path/to/cert.pem"
key = "/path/to/key.pem"
hostname = "gemini.example.com"
bind_host = "0.0.0.0"
port = 1965
log_level = "info"
max_concurrent_requests = 1000

Development Setup

Quick Start with Self-Signed Certs

mkdir -p tmp
openssl req -x509 -newkey rsa:2048 \
  -keyout tmp/key.pem \
  -out tmp/cert.pem \
  -days 365 \
  -nodes \
  -subj "/CN=localhost"

Update config.toml:

cert = "tmp/cert.pem"
key = "tmp/key.pem"

Run the server:

./pollux --config /path/to/config.toml

Access with a Gemini client like Lagrange at gemini://yourdomain.com/.

Development Notes

  • These certificates are for local testing only
  • Browsers will show security warnings with self-signed certs
  • Certificates in the dev/ directory are gitignored for security

Options

  • --config (-C): Path to config file (default /etc/pollux/config.toml)
  • --no-tls: Disable TLS for testing (uses raw TCP connections)
  • --test-processing-delay (debug builds only): Add delay before processing requests (seconds) - for testing rate limiting

Security

Pollux is designed with security as a priority:

  • Path traversal protection - requests like ../../../etc/passwd are blocked
  • TLS encryption - all connections are encrypted with valid certificates
  • Content isolation - virtual hosts cannot access each other's files
  • Request validation - malformed requests are rejected
  • Rate limiting - configurable concurrent request limits prevent abuse

Best Practices

Virtual Hosting Setup

  • Use separate TLS certificates for each hostname when possible
  • Keep host root directories separate and properly permissioned
  • Use DNS-compliant hostnames (no underscores, proper formatting)
  • Monitor logs for unknown hostname attempts

Certificate Management

  • Never commit certificate files to version control
  • Use development certificates only for local testing
  • Production certificates should be obtained via Let's Encrypt or your CA
  • Rotate certificates regularly and restart the server

File Organization

  • Create index.gmi files in directories for automatic serving
  • Use .gmi extension for Gemini text files
  • Store certificates outside web-accessible directories
  • Use proper file permissions (readable by server user only)

Limitations

  • No dynamic content - Pollux serves only static files
  • Single certificate per server - All hosts currently share the same TLS certificate (can be enhanced)
  • No CGI support - No server-side processing or scripting
  • Memory usage - All host configurations are loaded into memory
  • No HTTP support - Gemini protocol only

Examples

The examples/ directory contains sample configuration files:

  • virtual-hosting.toml - Multi-host setup with different certificates
  • single-host.toml - Legacy single-host configuration
  • development.toml - Local development with self-signed certificates

Testing

Run cargo test for the full test suite, which includes comprehensive integration tests covering:

  • Virtual hosting with multiple hostnames
  • TLS certificate validation
  • Path security and isolation
  • Concurrent request handling
  • Performance validation

Note: Some integration tests use Python 3 for Gemini protocol validation. If Python 3 is not available, certain tests will be skipped automatically.