Configuration Reference¶
This page documents all configuration options for the Nauyaca Gemini server. Configuration can be provided via TOML files using the --config flag, with CLI arguments overriding file-based settings.
Configuration File Format¶
Nauyaca uses TOML (Tom's Obvious Minimal Language) for configuration files. TOML is a minimal, easy-to-read configuration format with clear semantics.
# Start server with configuration file
nauyaca serve --config config.toml
# Override specific settings via CLI
nauyaca serve --config config.toml --port 8080 --host 0.0.0.0
Configuration Examples
See config.minimal.toml for the simplest working configuration, or config.example.toml for a complete configuration with all available options.
[server] Section¶
Core server settings including network binding, TLS configuration, and content serving.
| Option | Type | Default | Description |
|---|---|---|---|
host |
string | "localhost" |
Host address to bind to. Use "0.0.0.0" to bind to all interfaces, "localhost" for local-only access. |
port |
integer | 1965 |
TCP port to listen on. Standard Gemini port is 1965. Valid range: 1-65535. |
document_root |
string | (required) | Path to directory containing files to serve. Can be relative or absolute. Must exist and be a directory. |
certfile |
string | null |
Path to TLS certificate file (PEM format). If omitted, a self-signed certificate will be auto-generated for testing. |
keyfile |
string | null |
Path to TLS private key file (PEM format). Must be provided together with certfile. |
max_file_size |
integer | 104857600 |
Maximum file size to serve in bytes. Default is 100 MiB (104857600 bytes). Gemini is not designed for large file transfers. |
require_client_cert |
boolean | false |
Request client certificates using PyOpenSSL. When true, the server can accept any self-signed client certificate. Use with [[certificate_auth.paths]] rules to enforce authorization. |
Production TLS Certificates
Auto-generated self-signed certificates are only suitable for testing. For production deployments, generate proper certificates using tools like agate-cert or OpenSSL.
Certificate and Key Pairing
Both certfile and keyfile must be provided together, or both must be omitted (for auto-generation).
Example¶
[server]
host = "0.0.0.0"
port = 1965
document_root = "/var/gemini/capsule"
certfile = "/etc/nauyaca/cert.pem"
keyfile = "/etc/nauyaca/key.pem"
max_file_size = 52428800 # 50 MiB
CLI Overrides¶
| TOML Option | CLI Flag | Example |
|---|---|---|
host |
--host, -h |
--host 0.0.0.0 |
port |
--port, -p |
--port 8080 |
document_root |
First positional argument | nauyaca serve ./capsule |
certfile |
--cert |
--cert cert.pem |
keyfile |
--key |
--key key.pem |
max_file_size |
--max-file-size |
--max-file-size 52428800 |
[rate_limit] Section¶
Token bucket rate limiting to protect against DoS attacks. Limits the number of requests per IP address.
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | true |
Enable or disable rate limiting. Set to false to completely disable rate limiting. |
capacity |
integer | 10 |
Maximum number of tokens (requests) allowed in a burst. This is the initial bucket size. |
refill_rate |
float | 1.0 |
Rate at which tokens are added to the bucket per second. This controls the sustained request rate. For example, 1.0 = 1 request/second, 2.0 = 2 requests/second. |
retry_after |
integer | 30 |
Number of seconds the client should wait when rate limited. Sent in the status 44 (SLOW DOWN) response meta field. |
Token Bucket Algorithm
Each IP address gets a token bucket. Requests consume one token. When the bucket is empty, requests are rejected with status 44 (SLOW DOWN). Tokens refill at the configured rate up to the maximum capacity.
Rate Limiting Behavior¶
- Initial burst: Clients can make up to
capacityrequests immediately - Sustained rate: After the initial burst, clients are limited to
refill_raterequests per second - Rate limit response: Status
44 SLOW DOWNwithretry_afterseconds in the meta field - Automatic cleanup: Rate limit state for inactive IPs is cleaned up automatically
Example¶
[rate_limit]
enabled = true
capacity = 20
refill_rate = 2.0 # Allow 2 requests per second sustained
retry_after = 60 # Tell clients to wait 60 seconds when rate limited
CLI Overrides¶
Rate limiting cannot be fully configured via CLI. Use a configuration file for fine-grained control. The --config flag allows loading these settings from TOML.
[access_control] Section¶
IP-based access control with support for CIDR notation. Allows creating allowlists (whitelists) and denylists (blacklists).
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | true |
Enable or disable access control. Set to false to completely disable IP-based access control even if lists are configured. |
allow_list |
array of strings | null |
List of allowed IP addresses/networks in CIDR notation. If set, only these IPs can connect (whitelist mode). |
deny_list |
array of strings | null |
List of denied IP addresses/networks in CIDR notation. These IPs are blocked from connecting (blacklist mode). |
default_allow |
boolean | true |
Default policy when an IP is not in any list. true = allow all unlisted IPs, false = deny all unlisted IPs. |
CIDR Notation
Both lists support CIDR notation for network ranges:
192.168.1.0/24- entire subnet (192.168.1.0 - 192.168.1.255)10.0.0.5- single IP address (equivalent to10.0.0.5/32)127.0.0.0/8- localhost range
Access Control Modes¶
Whitelist Mode (allow only specific IPs):
Blacklist Mode (block specific IPs):
Localhost Only:
Local Network Only:
Decision Logic¶
- If IP is in
deny_list→ Reject (status 53 PROXY REQUEST REFUSED) - If IP is in
allow_list→ Allow - Otherwise → Use
default_allowsetting
Example¶
[access_control]
# Block known abusive networks
deny_list = [
"198.51.100.0/24",
"203.0.113.0/24"
]
# Allow everyone else
default_allow = true
CLI Overrides¶
Access control cannot be configured via CLI arguments. Use a configuration file to set up IP-based access control.
[[certificate_auth.paths]] Section¶
Path-based client certificate authentication following Gemini best practices. Certificates are activated for specific URL prefixes rather than globally, allowing public and authenticated content to coexist on the same server.
Array of Tables
[[certificate_auth.paths]] is a TOML "array of tables". Each [[certificate_auth.paths]] entry defines one path rule. Rules are checked in order - the first matching rule applies.
| Option | Type | Default | Description |
|---|---|---|---|
prefix |
string | (required) | URL path prefix to match (e.g., "/app/", "/admin/"). Must start with /. |
require_cert |
boolean | false |
Whether a client certificate is required for this path. If true and no cert is provided, returns status 60 (CLIENT CERTIFICATE REQUIRED). |
allowed_fingerprints |
array of strings | null |
List of allowed certificate fingerprints (SHA-256, format: "sha256:..."). If set, only certificates matching these fingerprints are accepted. If null, any valid certificate is accepted. |
Certificate Fingerprints¶
Certificate fingerprints are SHA-256 hashes in the format:
To get a certificate's fingerprint:
Matching Rules¶
- Rules are evaluated in the order they appear in the configuration file
- The first matching prefix applies to the request
- If no rule matches, the request is allowed without certificate requirements
- Longer prefixes should generally come before shorter ones for proper precedence
Response Codes¶
- 60 CLIENT CERTIFICATE REQUIRED: No certificate provided but
require_cert = true - 61 CERTIFICATE NOT AUTHORISED: Certificate provided but not in
allowed_fingerprintslist - 62 CERTIFICATE NOT VALID: Certificate is present but invalid (expired, malformed, etc.)
Examples¶
Require any certificate for /app/ paths:
Require specific certificates for /admin/ paths:
[[certificate_auth.paths]]
prefix = "/admin/"
require_cert = true
allowed_fingerprints = [
"sha256:a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456",
"sha256:1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
]
Mixed public and authenticated content:
# Public area - no cert needed (must come before /app/ rule!)
[[certificate_auth.paths]]
prefix = "/app/public/"
require_cert = false
# Main app - any cert accepted
[[certificate_auth.paths]]
prefix = "/app/"
require_cert = true
# Admin area - specific certs only
[[certificate_auth.paths]]
prefix = "/admin/"
require_cert = true
allowed_fingerprints = ["sha256:admin-cert-fingerprint-here"]
Rule Order Matters
In the example above, /app/public/ must come before /app/ because rules are evaluated in order. If /app/ came first, it would match /app/public/ requests and require a certificate.
CLI Overrides¶
| TOML Option | CLI Flag | Example |
|---|---|---|
| Basic cert requirement | --require-client-cert |
Requires client cert for all paths |
CLI Limitation
The --require-client-cert flag applies globally to all paths and does not support fingerprint restrictions. For fine-grained path-based authentication, use a TOML configuration file.
[titan] Section¶
Titan is Gemini's companion upload protocol. This section configures server-side upload handling.
Disabled by Default
Titan uploads are disabled by default for security. Only enable if you need upload functionality.
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | false |
Enable Titan upload support. When false, all Titan requests are rejected. |
upload_dir |
string | (required if enabled) | Directory for storing uploaded files. Must be different from document_root for security. Created automatically if it doesn't exist. |
max_upload_size |
integer | 10485760 |
Maximum upload size in bytes. Default is 10 MiB (10485760 bytes). Uploads exceeding this limit are rejected with status 50. |
allowed_mime_types |
array of strings | null |
List of allowed MIME types. If null, all types are accepted. Uploads with disallowed types are rejected with status 59. |
auth_tokens |
array of strings | null |
List of valid authentication tokens. If null, no authentication is required (not recommended for public servers). Invalid/missing tokens result in status 60. |
enable_delete |
boolean | false |
Allow delete operations via zero-byte uploads. When false, delete requests are rejected with status 50. |
Security Considerations¶
- Separate upload directory: Keep
upload_dirseparate fromdocument_rootto prevent overwrites - Authentication: Always use
auth_tokenson public servers - Size limits: Set appropriate
max_upload_sizeto prevent abuse - MIME filtering: Restrict
allowed_mime_typesto expected content types - Delete operations: Only enable
enable_deleteif you need this functionality
Example Configurations¶
Wiki with editing:
[titan]
enabled = true
upload_dir = "./wiki-content"
max_upload_size = 1048576 # 1 MiB
allowed_mime_types = ["text/gemini", "text/plain"]
auth_tokens = ["editor-token-abc123"]
enable_delete = true
Image gallery:
[titan]
enabled = true
upload_dir = "./gallery"
max_upload_size = 5242880 # 5 MiB
allowed_mime_types = ["image/png", "image/jpeg", "image/gif"]
auth_tokens = ["gallery-upload-token"]
enable_delete = false
CLI Overrides¶
Titan configuration cannot be set via CLI arguments. Use a configuration file to enable and configure Titan uploads.
[logging] Section¶
Privacy-preserving logging configuration.
| Option | Type | Default | Description |
|---|---|---|---|
hash_ips |
boolean | true |
Hash client IP addresses in logs using SHA-256. When enabled, IP addresses are replaced with hashes like ip:abc123.... This allows abuse detection while protecting user privacy. |
Privacy by Default
IP hashing is enabled by default to protect user privacy. Hashed IPs can still be used to detect patterns of abuse (same hash = same IP) without storing raw IP addresses.
Example¶
CLI Overrides¶
| TOML Option | CLI Flag | Example |
|---|---|---|
hash_ips |
--hash-ips / --no-hash-ips |
--no-hash-ips to disable hashing |
Additional Logging Options (CLI Only)¶
The following logging options are only available via CLI flags, not in TOML configuration:
| CLI Flag | Default | Description |
|---|---|---|
--log-level, -l |
INFO |
Logging level: DEBUG, INFO, WARNING, ERROR |
--log-file |
stdout | Path to log file. If not specified, logs to stdout |
--json-logs |
false |
Output logs in JSON format (useful for log aggregation systems) |
Complete Configuration Example¶
This example shows all available configuration options:
# Nauyaca Gemini Server Configuration
[server]
host = "0.0.0.0"
port = 1965
document_root = "/var/gemini/capsule"
certfile = "/etc/nauyaca/cert.pem"
keyfile = "/etc/nauyaca/key.pem"
max_file_size = 104857600 # 100 MiB
[rate_limit]
enabled = true
capacity = 10
refill_rate = 1.0
retry_after = 30
[access_control]
enabled = true
# Allow local network and specific remote IPs
allow_list = [
"127.0.0.0/8",
"192.168.0.0/16",
"203.0.113.42"
]
# Block known bad actors
deny_list = ["198.51.100.0/24"]
default_allow = false
# Path-based certificate authentication
[[certificate_auth.paths]]
prefix = "/app/public/"
require_cert = false
[[certificate_auth.paths]]
prefix = "/app/"
require_cert = true
[[certificate_auth.paths]]
prefix = "/admin/"
require_cert = true
allowed_fingerprints = [
"sha256:a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef123456"
]
[logging]
hash_ips = true
# Titan upload support (optional)
[titan]
enabled = true
upload_dir = "/var/gemini/uploads"
max_upload_size = 10485760 # 10 MiB
allowed_mime_types = ["text/gemini", "text/plain"]
auth_tokens = ["upload-token-abc123"]
enable_delete = false
Minimal Configuration Example¶
The simplest working configuration requires only the document root:
This uses defaults for everything else:
- Host:
localhost(local access only) - Port:
1965(standard Gemini port) - TLS: Auto-generated self-signed certificate
- Rate limiting: Enabled with default settings
- Access control: Allow all
- Logging: IP hashing enabled
Configuration Validation¶
When loading a configuration file, Nauyaca validates:
- File existence: Config file and referenced paths (document_root, certfile, keyfile) must exist
- Port range: Port must be between 1 and 65535
- Directory checks:
document_rootmust be a directory, not a file - Certificate pairing: Both
certfileandkeyfilemust be provided together - TOML syntax: File must be valid TOML format
Validation errors are reported clearly with helpful error messages indicating what went wrong.
See Also¶
- How-to: Server Configuration - Step-by-step configuration guide
- Security Features - Understanding security features
- CLI Reference - Complete CLI command reference