A fault-tolerant, concurrent Gemini protocol server written in Elixir. Built for immortality on the BEAM. Ambrosia is designed for serving high-uptime Capsules on the Geminispace.
Ambrosia is a Gemini server that leverages the Erlang VM's legendary fault tolerance and concurrency to serve your Gemini capsule. It's designed to be simple to deploy, secure by default, and resilient under load. Whether you're running a personal capsule or hosting multiple sites, Ambrosia keeps serving.
- Fault Tolerant: Built on the BEAM VM with supervision trees - if something crashes, it restarts
- Concurrent by Design: Handles a ton of concurrent connections without breaking a sweat
- Docker Ready: Single container deployment with automatic certificate generation
- Monitoring Built-in: Prometheus metrics endpoint for observability
- Minimal Resource Usage: Runs comfortably on a Raspberry Pi hovering about 75-100MB memory
- Gemtext Native: Serves
.gmifiles with proper MIME types - Directory Listings: Auto-generates navigable directory indices
# Create your content directory
mkdir -p gemini certs
# Create docker-compose.yml (see below)
# Add your .gmi files to ./gemini/
# Run it
HOSTNAME=your-domain.com docker-compose up -dBasic docker-compose.yml:
services:
ambrosia:
image: ghcr.io/willc33/ambrosia:latest
ports:
- "1965:1965"
volumes:
- ./gemini:/app/gemini:ro
- ./certs:/certs:ro # Optional: provide your own certs
environment:
- HOSTNAME=your-capsule.com
restart: unless-stoppedThat's it. Ambrosia will generate self-signed certificates if you don't provide them. You are also welcome to use the compose files in the repository
# Prerequisites: Elixir 1.15+, Erlang/OTP 25+
git clone https://codeberg.org/WillC33/ambrosia.git
cd ambrosia
# Install dependencies
mix deps.get
# Generate certificates
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout certs/key.pem -out certs/cert.pem \
-days 365 -subj "/CN=localhost"
# Run in development
HOSTNAME=localhost mix run --no-halt
# Or build a release
MIX_ENV=prod mix release
HOSTNAME=your-domain.com _build/prod/rel/ambrosia/bin/ambrosia startEnvironment variables control Ambrosia's behaviour:
| Variable | Default | Description |
|---|---|---|
HOSTNAME |
(required in prod) | Your capsule's domain name |
GEMINI_PORT |
1965 | Port to listen on |
ROOT_DIR |
/app/gemini | Directory containing your .gmi files |
CERT_FILE |
/certs/cert.pem | Path to TLS certificate |
KEY_FILE |
/certs/key.pem | Path to TLS private key |
MAX_CONNECTIONS |
1000 | Maximum concurrent connections |
REQUEST_TIMEOUT |
10000 | Request timeout in milliseconds |
RATE_LIMIT_REQUESTS |
10 | Requests allowed per window |
RATE_LIMIT_WINDOW_MS |
1000 | Rate limit window duration |
METRICS_ENABLED |
false | Enable internal Prometheus metrics endpoint |
METRICS_PORT |
9568 | Port for metrics endpoint |
Organise your Gemini content like this:
gemini/
├── index.gmi # Homepage
├── about.gmi # About page
├── blog/
│ ├── index.gmi # Blog index
│ ├── 2024-01-01.gmi # Blog posts
│ └── 2024-01-15.gmi
└── page/
├── index.gmi # Whatever else pleases you
└── ambrosia.gmi # Other stuff
Ambrosia automatically:
- Serves
index.gmiorindex.geminifor directories - Generates directory listings when no index exists
- Only serves
.gmiand.geminifiles (by design) - The architecture allows MIME type extension
Enable Prometheus metrics for production monitoring:
environment:
- METRICS_ENABLED=true
- METRICS_PORT=9568
ports:
- "127.0.0.1:9568:9568" # Metrics (localhost only)Available metrics:
- Active connections
- Request duration
- Memory usage
- Process count
- Rate limit hits
Ambrosia takes security seriously:
- Path Traversal Protection: Multiple layers of validation prevent directory escapes
- Rate Limiting: Token bucket algorithm prevents abuse
- TLS Only: It's Gemini. No plaintext connections
- Input Validation: URL length limits and sanitisation
- Resource Limits: Connection caps and timeouts
- Minimal Attack Surface: Only serves Gemtext files
The codebase includes testing against common attack patterns for the file system
Ambrosia includes extensive test coverage:
# Run all tests
mix test
# Run with coverage
mix test --cover
# Security-specific tests
mix test test/file_server_security_test.exsTests cover:
- Path traversal attempts
- Rate limiting
- Concurrent connections
- Request parsing
- File serving
- Directory listings
- Edge cases
Ambrosia uses OTP supervision trees for fault tolerance:
Ambrosia.Supervisor
├── Telemetry (Metrics collection)
├── RateLimiter (Token bucket)
├── ConnectionManager (Connection tracking)
├── Ranch Listener (TCP acceptor pool)
└── MetricsExporter (Prometheus endpoint)
Each connection runs in its own supervised process. If one crashes, others continue serving.
We welcome contributions! Whether it's:
- Bug fixes
- Performance improvements
- Documentation updates
- Feature suggestions
- Security reports
Please open an issue or PR on Codeberg.
Further testing, fixes, and features are definitely needed before this is ready to use
Ambrosia works brilliantly for:
- Personal Capsules: Your blog, wiki, or digital garden
- Project Documentation: Minimalist docs that load instantly
- Community Spaces: Shared capsules for groups
- Archive Mirrors: Resilient content hosting
- Educational Resources: Distraction-free learning materials
- Creative Writing: Fiction, poetry, journaling
The Gemini ecosystem has several excellent servers. This one exists because I love BEAM, not because the other's aren't great:
- Agate (Rust): Excellent performance, minimal dependencies
- Molly Brown (Go): Feature-rich with CGI support
- Jetforce (Python): Great for scripting and extensions
- GLV-1.12556 (C): Lightweight and portable
- Gemserv (Rust): Advanced features like virtual hosting
Choose Ambrosia if you value:
- Erlang's fault tolerance
- Concurrent connection handling
- Simple Docker deployment
- Built-in monitoring
Massive thanks to the Gemini community for creating this wonderful protocol and ecosystem. This project exists because of your collective work towards a better, lighter internet.
Ambrosia follows the Gemini philosophy:
- Content over presentation
- Privacy by default
- Simplicity as a feature
- Technical decisions with moral dimensions
We believe the internet can be different. Gemini proves it.
AGPL-3.0 - If you improve Ambrosia, share those improvements with the community.
In Greek mythology, ambrosia granted immortality to those who consumed it. This server aims for similar resilience - it should run forever, serving your content reliably across time.
Built with love for the small internet.
Find me in Geminispace: gemini://gem.williamcooke.net