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.
This commit is contained in:
parent
c193d831ed
commit
0459cb6220
22 changed files with 2296 additions and 406 deletions
107
README.md
107
README.md
|
|
@ -1,6 +1,6 @@
|
|||
# Pollux - A Simple Gemini Server
|
||||
|
||||
Pollux is a lightweight Gemini server for serving static files securely. It supports TLS, hostname validation, and basic directory serving.
|
||||
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
|
||||
|
||||
|
|
@ -16,16 +16,64 @@ cargo build --release
|
|||
|
||||
This produces the `target/release/pollux` binary.
|
||||
|
||||
## Running
|
||||
## 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"
|
||||
bind_host = "0.0.0.0"
|
||||
hostname = "gemini.example.com"
|
||||
bind_host = "0.0.0.0"
|
||||
port = 1965
|
||||
log_level = "info"
|
||||
max_concurrent_requests = 1000
|
||||
|
|
@ -67,16 +115,63 @@ Access with a Gemini client like Lagrange at `gemini://yourdomain.com/`.
|
|||
## 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
|
||||
|
||||
### Certificate Management
|
||||
## 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 integration tests that require Python 3.
|
||||
Run `cargo test` for the full test suite, which includes comprehensive integration tests covering:
|
||||
|
||||
**Note**: Integration tests use Python 3 for Gemini protocol validation. If Python 3 is not available, integration tests will be skipped automatically.
|
||||
- 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.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue