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

177 lines
5.4 KiB
Markdown

# 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:
```bash
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:
```toml
# 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:
```toml
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
```bash
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`:
```toml
cert = "tmp/cert.pem"
key = "tmp/key.pem"
```
Run the server:
```bash
./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.