Modern Gemini protocol server and client implementation using asyncio
Project description
Nauyaca - Gemini Protocol Server & Client
A modern, high-performance implementation of the Gemini protocol in Python. Nauyaca (pronounced "now-YAH-kah", meaning "serpent" in Nahuatl) uses asyncio's low-level Protocol/Transport pattern for efficient, non-blocking network I/O with both server and client capabilities.
Key Features
- High Performance - asyncio Protocol/Transport pattern for maximum efficiency
- Security First - Mandatory TLS 1.2+, TOFU certificate validation, rate limiting, and access control
- Production Ready - TOML configuration, middleware system, and systemd integration
- Developer Friendly - Full type hints, comprehensive tests, and modern tooling with
uv
Quick Start
Installation
# As a CLI tool (recommended)
uv tool install nauyaca
# As a library
uv add nauyaca
# From source (for development)
git clone https://github.com/alanbato/nauyaca.git
cd nauyaca && uv sync
Run a Server
# Serve content from a directory
nauyaca serve ./capsule
# With configuration file
nauyaca serve --config config.toml
# With hot-reload for development
nauyaca serve ./capsule --reload
Fetch Content
# Get a Gemini resource
nauyaca get gemini://geminiprotocol.net/
# With verbose output
nauyaca get gemini://geminiprotocol.net/ --verbose
Use as a Library
import asyncio
from nauyaca.client import GeminiClient
async def main():
async with GeminiClient() as client:
response = await client.get("gemini://geminiprotocol.net/")
if response.is_success():
print(response.body)
elif response.is_redirect():
print(f"Redirect to: {response.redirect_url}")
else:
print(f"Error {response.status}: {response.meta}")
asyncio.run(main())
Advanced Features
Location-Based Routing
Nauyaca supports flexible routing with multiple handlers per server. Configure different URL paths to use different handlers (static files, proxy, etc.):
# Proxy API requests to backend server
[[locations]]
prefix = "/api/"
handler = "proxy"
upstream = "gemini://backend.example.com:1965"
strip_prefix = true # /api/resource → /resource on backend
timeout = 30
# Serve static content for everything else
[[locations]]
prefix = "/"
handler = "static"
document_root = "./capsule"
Reverse Proxy
Use Nauyaca as a reverse proxy to aggregate multiple Gemini capsules:
# Forward blog requests to blog server
[[locations]]
prefix = "/blog/"
handler = "proxy"
upstream = "gemini://blog.example.com"
strip_prefix = true
# Forward wiki requests to wiki server
[[locations]]
prefix = "/wiki/"
handler = "proxy"
upstream = "gemini://wiki.example.com"
strip_prefix = true
# Serve homepage from local files
[[locations]]
prefix = "/"
handler = "static"
document_root = "./homepage"
See config.example.toml for more configuration examples.
Documentation
| Section | Description |
|---|---|
| Installation | Setup and requirements |
| Quick Start | Get running in 5 minutes |
| Tutorials | Step-by-step guides |
| How-to Guides | Task-oriented recipes |
| Reference | CLI, configuration, API |
| Explanation | Architecture and concepts |
Contributing
# Setup
git clone https://github.com/alanbato/nauyaca.git
cd nauyaca && uv sync
# Test
uv run pytest
# Lint & Type Check
uv run ruff check src/ tests/
uv run mypy src/
See CONTRIBUTING.md for guidelines.
License
MIT License - see LICENSE for details.
Resources
- Gemini Protocol - Official protocol website
- SECURITY.md - Security documentation and vulnerability reporting
- GitHub Issues - Bug reports
- GitHub Discussions - Questions and ideas
Acknowledgments
- Solderpunk for creating the Gemini protocol
- The Gemini community for feedback and inspiration
Status: Active development (pre-1.0). Core protocol and security features are stable.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nauyaca-0.11.0.tar.gz.
File metadata
- Download URL: nauyaca-0.11.0.tar.gz
- Upload date:
- Size: 49.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3d844bf2631dc9b5f2b959bf594262025a29b2ce1f42b8f7f9b05ac15210d719
|
|
| MD5 |
57335c6fa255e6545a266e7cf3124630
|
|
| BLAKE2b-256 |
8cbec672ddfab03a1deeb92594fb0c429d87a0f0dbc8c0d591fe2ac902ebab28
|
Provenance
The following attestation bundles were made for nauyaca-0.11.0.tar.gz:
Publisher:
release-pypi.yml on alanbato/nauyaca
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nauyaca-0.11.0.tar.gz -
Subject digest:
3d844bf2631dc9b5f2b959bf594262025a29b2ce1f42b8f7f9b05ac15210d719 - Sigstore transparency entry: 963893148
- Sigstore integration time:
-
Permalink:
alanbato/nauyaca@f3498c123ba44adeb81f6bec5045eaa6864e493f -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/alanbato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@f3498c123ba44adeb81f6bec5045eaa6864e493f -
Trigger Event:
push
-
Statement type:
File details
Details for the file nauyaca-0.11.0-py3-none-any.whl.
File metadata
- Download URL: nauyaca-0.11.0-py3-none-any.whl
- Upload date:
- Size: 62.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d35d49aba9984593ecdc63c8e30750cc517f11670ba30793a7289162560b41df
|
|
| MD5 |
3cf076f670d4fa863730f4dd7eb59864
|
|
| BLAKE2b-256 |
ab4587a6b73ec4f75b5c281662c048093eee20695c8f88f124da6c69c9689da8
|
Provenance
The following attestation bundles were made for nauyaca-0.11.0-py3-none-any.whl:
Publisher:
release-pypi.yml on alanbato/nauyaca
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
nauyaca-0.11.0-py3-none-any.whl -
Subject digest:
d35d49aba9984593ecdc63c8e30750cc517f11670ba30793a7289162560b41df - Sigstore transparency entry: 963893252
- Sigstore integration time:
-
Permalink:
alanbato/nauyaca@f3498c123ba44adeb81f6bec5045eaa6864e493f -
Branch / Tag:
refs/tags/v0.11.0 - Owner: https://github.com/alanbato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release-pypi.yml@f3498c123ba44adeb81f6bec5045eaa6864e493f -
Trigger Event:
push
-
Statement type: