Skip to main content

Modern Gemini protocol server and client implementation using asyncio

Project description

Nauyaca - Gemini Protocol Server & Client

Python 3.14+ License: MIT Code style: Ruff Type checked: mypy

A modern, high-performance implementation of the Gemini protocol in Python using asyncio, providing both server and client capabilities.

โœจ Why Nauyaca?

Nauyaca (pronounced "now-YAH-kah", meaning "serpent" in Nahuatl) brings modern Python async capabilities to the Gemini protocol:

  • ๐Ÿš€ High Performance: Uses asyncio's low-level Protocol/Transport pattern for maximum efficiency
  • ๐Ÿ”’ Security First: TOFU certificate validation, rate limiting, and access control built-in
  • โš™๏ธ Production Ready: Comprehensive configuration, middleware system, and systemd integration
  • ๐Ÿ› ๏ธ Developer Friendly: Full type hints, extensive tests, and powered by uv for fast dependency management
  • ๐Ÿ“š Well Documented: Clear architecture docs, security guidelines, and API examples

๐Ÿ“‹ Table of Contents

๐Ÿ“– Project Overview

What is Gemini?

The Gemini protocol is a modern, privacy-focused alternative to HTTP and the web. It aims to be:

  • Simple: Easier to implement than HTTP, harder to extend (by design)
  • Privacy-focused: No cookies, no tracking, no JavaScript
  • Secure: TLS is mandatory, not optional
  • Lightweight: Text-focused content with minimal formatting
  • User-centric: Readers control how content is displayed

Think of it as a modern take on Gopher, sitting comfortably between the complexity of the web and the simplicity of plain text.

About Nauyaca

This project implements the Gemini protocol with a focus on performance and security. Unlike typical implementations, Nauyaca uses Python's low-level asyncio Protocol/Transport pattern for efficient, non-blocking network I/O with fine-grained control over connection handling.

Goals

  • โœ… Implement a production-ready Gemini server
  • โœ… Implement a full-featured Gemini client
  • โœ… Support all Gemini protocol features (TLS, client certs, TOFU, etc.)
  • โœ… Provide clean, maintainable, well-documented code
  • โœ… Include comprehensive test coverage
  • โœ… Offer both library and CLI interfaces

Project Status

Current Phase: Security Hardening & Integration Testing

Feature Status
Core Protocol Implementation โœ… Complete
TLS 1.2+ Support โœ… Complete
Server Configuration (TOML) โœ… Complete
TOFU Certificate Validation โœ… Complete
Rate Limiting & DoS Protection โœ… Complete
IP-based Access Control โœ… Complete
Client Session Management โœ… Complete
Security Documentation โœ… Complete
Integration Testing ๐Ÿšง In Progress
CLI Interface ๐Ÿšง In Progress
Static File Serving ๐Ÿ“‹ Planned
Content Type Detection ๐Ÿ“‹ Planned

The core protocol and security features are production-ready. CLI and content serving features are being actively developed.

๐Ÿ›  Technology Stack

  • Python 3.11+ - Modern Python features and performance
  • asyncio - Asynchronous I/O using Protocol/Transport pattern
  • ssl - TLS 1.2+ encryption with custom certificate validation
  • uv - Fast, modern Python package manager for development
  • pytest-asyncio - Async test support and fixtures
  • typer - CLI interface with rich terminal output
  • cryptography - Certificate handling and TOFU implementation
  • tomllib - TOML configuration file parsing

๐Ÿ— Project Structure

nauyaca/
โ”œโ”€โ”€ README.md
โ”œโ”€โ”€ SECURITY.md              # Security documentation
โ”œโ”€โ”€ CONTRIBUTING.md          # Contribution guidelines
โ”œโ”€โ”€ CODE_OF_CONDUCT.md       # Code of conduct
โ”œโ”€โ”€ pyproject.toml           # Project metadata and dependencies (managed by uv)
โ”œโ”€โ”€ uv.lock                  # Dependency lock file
โ”œโ”€โ”€ config.example.toml      # Full configuration example
โ”œโ”€โ”€ config.minimal.toml      # Minimal configuration example
โ”‚
โ”œโ”€โ”€ src/
โ”‚   โ””โ”€โ”€ nauyaca/
โ”‚       โ”œโ”€โ”€ __init__.py
โ”‚       โ”œโ”€โ”€ __main__.py      # CLI entry point
โ”‚       โ”‚
โ”‚       โ”œโ”€โ”€ protocol/
โ”‚       โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚       โ”‚   โ”œโ”€โ”€ constants.py      # Status codes, MIME types, etc.
โ”‚       โ”‚   โ”œโ”€โ”€ request.py        # Request parsing
โ”‚       โ”‚   โ”œโ”€โ”€ response.py       # Response building
โ”‚       โ”‚   โ””โ”€โ”€ status.py         # Status code utilities
โ”‚       โ”‚
โ”‚       โ”œโ”€โ”€ server/
โ”‚       โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚       โ”‚   โ”œโ”€โ”€ protocol.py       # Server protocol implementation
โ”‚       โ”‚   โ”œโ”€โ”€ handler.py        # Request handler
โ”‚       โ”‚   โ”œโ”€โ”€ router.py         # URL routing
โ”‚       โ”‚   โ”œโ”€โ”€ config.py         # Server configuration
โ”‚       โ”‚   โ””โ”€โ”€ middleware.py     # Rate limiting, access control
โ”‚       โ”‚
โ”‚       โ”œโ”€โ”€ client/
โ”‚       โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚       โ”‚   โ”œโ”€โ”€ protocol.py       # Client protocol implementation
โ”‚       โ”‚   โ””โ”€โ”€ session.py        # High-level client API
โ”‚       โ”‚
โ”‚       โ”œโ”€โ”€ security/
โ”‚       โ”‚   โ”œโ”€โ”€ __init__.py
โ”‚       โ”‚   โ”œโ”€โ”€ tls.py            # TLS context creation
โ”‚       โ”‚   โ”œโ”€โ”€ certificates.py   # Cert generation and management
โ”‚       โ”‚   โ””โ”€โ”€ tofu.py           # TOFU database
โ”‚       โ”‚
โ”‚       โ””โ”€โ”€ utils/
โ”‚           โ”œโ”€โ”€ __init__.py
โ”‚           โ””โ”€โ”€ url.py            # URL parsing/validation
โ”‚
โ”œโ”€โ”€ tests/
โ”‚   โ”œโ”€โ”€ conftest.py              # Pytest fixtures
โ”‚   โ”œโ”€โ”€ test_protocol/
โ”‚   โ”œโ”€โ”€ test_server/
โ”‚   โ”œโ”€โ”€ test_client/
โ”‚   โ”œโ”€โ”€ test_security/
โ”‚   โ””โ”€โ”€ test_integration/
โ”‚
โ”œโ”€โ”€ docs/
โ”‚   โ””โ”€โ”€ gemini_protocol/         # Gemini protocol reference docs
โ”‚       โ””โ”€โ”€ gemtext.txt
โ”‚
โ””โ”€โ”€ capsule/                     # Example Gemini capsule content directory

๐Ÿš€ Quick Start

Prerequisites

  • Python 3.14 or higher
  • uv - Fast Python package manager (recommended)
    # Install uv if you haven't already
    curl -LsSf https://astral.sh/uv/install.sh | sh
    

Installation

Option 1: Standalone CLI tool (recommended for general use)

uv tool install nauyaca

Option 2: As a library (for development or embedding in your project)

# Add to existing project
uv add nauyaca

# Or start a new project
uv init my-gemini-project
cd my-gemini-project
uv add nauyaca

Option 3: From source (for development)

git clone https://github.com/alanbato/nauyaca.git
cd nauyaca
uv sync

Running the Server

# Minimal - serve current directory (uses auto-generated cert)
nauyaca serve ./capsule

# With custom host/port
nauyaca serve ./capsule --host 0.0.0.0 --port 1965

# With configuration file
nauyaca serve --config config.toml

# With TLS certificates
nauyaca serve ./capsule --cert cert.pem --key key.pem

Generate SSL Certificates

# Generate self-signed certificate for testing
nauyaca cert generate --hostname localhost --output ./certs

# For production (with proper hostname)
nauyaca cert generate --hostname gemini.example.com --days 365

Using the Client

# Get a resource
nauyaca get gemini://geminiprotocol.net/

# Get with verbose output showing response headers
nauyaca get gemini://geminiprotocol.net/ --verbose

# Manage TOFU database
nauyaca tofu list
nauyaca tofu trust geminiprotocol.net
nauyaca tofu export backup.toml
nauyaca tofu import backup.toml
nauyaca tofu revoke example.com

As a Library

import asyncio
from nauyaca.client import GeminiClient

async def main():
    # Simple fetch with TOFU validation
    async with GeminiClient() as client:
        response = await client.get("gemini://geminiprotocol.net/")

        if response.is_success():
            print(f"Content-Type: {response.meta}")
            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())

Development Standards

This project follows modern Python best practices:

  • PEP 8 style guide compliance
  • Ruff for linting and code formatting (replaces Black, isort, flake8)
  • mypy for strict type checking
  • pytest for comprehensive testing with async support
  • uv for fast, reliable dependency management

Running Tests

# Run all tests
uv run pytest

# Run with coverage report
uv run pytest --cov=src/nauyaca --cov-report=html

# Run specific test file
uv run pytest tests/test_protocol/test_request.py

# Run specific test function
uv run pytest tests/test_server/test_handler.py::test_static_file_serving

# Run with verbose output
uv run pytest -v

# Run only unit tests (fast)
uv run pytest -m unit

# Run only integration tests
uv run pytest -m integration

# Watch mode (requires pytest-watch)
uv run ptw

๐Ÿ“– Core Features

Server Features

  • Protocol Implementation

    • TLS 1.2+ encryption (mandatory)
    • Complete status code support (1x-6x)
    • Request URL parsing and validation
    • Response header generation
  • Content Serving

    • Static file serving
    • Directory listings
    • MIME type detection
    • Gemtext rendering
    • CGI script support
    • Virtual hosting
  • Security

    • Client certificate support (status 6x)
    • Certificate-based authentication
    • Rate limiting
    • Access control lists
    • Path traversal protection
  • Features

    • URL rewriting and routing
    • Logging and monitoring
    • Graceful shutdown
    • Hot reload (development mode)
    • Custom error pages

Client Features

  • Protocol Implementation

    • TLS connection handling
    • Request sending
    • Response parsing
    • Redirect following
  • Security

    • TOFU certificate validation
    • Certificate pinning
    • Client certificate support
    • Known hosts database
  • Features

    • Async/await API
    • Connection pooling
    • Response caching
    • Timeout handling
    • Retry logic
    • CLI interface

๐Ÿ”ง Configuration

Server Configuration

The server supports TOML configuration files for persistent settings. Command-line arguments override config file values.

Minimal Configuration

Create a config.toml file with just the essentials:

[server]
# Required: Path to your gemini content
document_root = "./capsule"

# All other settings use sensible defaults:
# - host: localhost
# - port: 1965
# - TLS: auto-generated self-signed certificate (for testing only!)
# - Rate limiting: enabled with default limits
# - Access control: allow all

Full Configuration Example

For production deployments, use a complete configuration:

[server]
host = "0.0.0.0"
port = 1965
document_root = "./capsule"
certfile = "./certs/cert.pem"
keyfile = "./certs/key.pem"

[rate_limit]
enabled = true
capacity = 10           # Max burst size (requests)
refill_rate = 1.0      # Requests per second
retry_after = 30       # Seconds to wait when limited

[access_control]
# IP-based access control (supports CIDR notation)
allow_list = ["192.168.1.0/24", "10.0.0.1"]
deny_list = ["203.0.113.0/24"]
default_allow = true   # Default policy when no lists match

Using Configuration Files

# Load configuration from file
nauyaca serve --config config.toml

# Override specific settings
nauyaca serve --config config.toml --host 0.0.0.0 --port 11965

# Without config file (all settings from CLI)
nauyaca serve ./capsule --host localhost --port 1965

Client Configuration

The client uses TOFU (Trust-On-First-Use) certificate validation with a local database:

# TOFU database location
~/.nauyaca/known_hosts.db

# List known hosts
nauyaca tofu list

# Export known hosts for backup
nauyaca tofu export backup.toml

# Import known hosts
nauyaca tofu import backup.toml

# Revoke trust for a host
nauyaca tofu revoke example.com

# Manually trust a host (connects and retrieves certificate)
nauyaca tofu trust example.com

๐Ÿ› Architecture

Key Design Decisions

  1. asyncio Protocol Pattern: Low-level control, high performance
  2. Plugin Architecture: Extensible handler system
  3. TOFU by Default: Privacy-focused certificate validation
  4. Stateless: Each request is independent (no sessions)
  5. Type Hints: Full typing for better IDE support and error catching

๐Ÿงช Testing

Nauyaca has comprehensive test coverage across multiple layers:

Test Organization

  • Unit Tests (@pytest.mark.unit)

    • Test individual components in isolation
    • Mock external dependencies
    • Fast execution for rapid development feedback
  • Integration Tests (@pytest.mark.integration)

    • Test component interactions
    • Real network connections (localhost only)
    • TLS handshake validation
  • Security Tests

    • TOFU certificate validation
    • Rate limiting behavior
    • Access control enforcement
    • Path traversal protection

Test Coverage

Current test coverage focuses on:

  • โœ… Protocol parsing and validation
  • โœ… TLS configuration and certificate handling
  • โœ… TOFU database operations (store, verify, export, import)
  • โœ… Server middleware (rate limiting, access control)
  • โœ… Configuration loading and validation
  • ๐Ÿšง End-to-end client/server integration (in progress)

Run uv run pytest --cov=src/nauyaca --cov-report=html to generate a detailed coverage report.

๐Ÿ“š API Examples

Using Nauyaca as a Library

import asyncio
from nauyaca.client import GeminiClient

async def main():
    # Create client with TOFU validation enabled (default)
    async with GeminiClient() as client:
        # Simple GET request
        response = await client.get("gemini://geminiprotocol.net/")

        # Check response status
        if response.is_success():
            print(f"Content-Type: {response.meta}")
            print(response.body)
        elif response.is_redirect():
            print(f"Redirect to: {response.redirect_url}")
        elif 10 <= response.status < 20:
            # Input required (status 1x)
            print(f"Input requested: {response.meta}")
        else:
            print(f"Error {response.status}: {response.meta}")

asyncio.run(main())

Advanced Configuration

from nauyaca.client import GeminiClient

# Custom timeout and redirect settings
async with GeminiClient(timeout=60, max_redirects=3) as client:
    response = await client.get("gemini://geminiprotocol.net/")

# Disable redirect following
async with GeminiClient() as client:
    response = await client.get(
        "gemini://geminiprotocol.net/",
        follow_redirects=False
    )

For more advanced usage, see the integration tests which demonstrate server and client usage patterns.

๐Ÿ”’ Security Features

Nauyaca implements multiple layers of security to protect both servers and clients. See SECURITY.md for complete security documentation.

TLS Security

Mandatory TLS 1.2+

  • All Gemini connections require TLS 1.2 or higher
  • No plaintext fallback - non-TLS connections rejected
  • Strong cipher suites enforced by default
  • Self-signed certificates supported (TOFU model)
# Automatic strong TLS configuration
ssl_context.minimum_version = ssl.TLSVersion.TLSv1_2

TOFU (Trust-On-First-Use) Certificate Validation

How TOFU Works:

  1. First Connection: Accept certificate, store SHA-256 fingerprint
  2. Subsequent Connections: Verify certificate matches stored fingerprint
  3. Certificate Change: Prompt user for confirmation (may be renewal or MITM attack)

TOFU Management:

# List all known hosts with fingerprints
nauyaca tofu list

# Export for backup/sharing
nauyaca tofu export backup.toml

# Import from backup
nauyaca tofu import backup.toml

# Revoke trust for compromised host
nauyaca tofu revoke example.com

# Manually trust a certificate (connects and retrieves it)
nauyaca tofu trust example.com

Storage: Certificates stored in ~/.nauyaca/known_hosts.db (SQLite database)

Rate Limiting & DoS Protection

Token Bucket Algorithm

  • Industry-standard rate limiting per client IP
  • Configurable capacity (burst size) and refill rate
  • Automatic cleanup of idle rate limiters (memory efficient)
  • Returns status 44 SLOW DOWN when limits exceeded

Configuration:

[rate_limit]
enabled = true
capacity = 10           # Max burst size
refill_rate = 1.0      # Requests per second
retry_after = 30       # Seconds to wait when limited

Example Rate Limits:

  • Personal capsule: capacity=5, refill_rate=0.5 (restrictive)
  • Public server: capacity=20, refill_rate=2.0 (generous)
  • High-traffic: capacity=50, refill_rate=5.0 (very generous)

IP-based Access Control

Allow/Deny Lists with CIDR Support

  • Individual IPs: 10.0.0.1
  • IPv4 networks: 192.168.1.0/24
  • IPv6 networks: 2001:db8::/32
  • Configurable default policy (allow or deny)

Configuration:

[access_control]
allow_list = ["192.168.1.0/24", "10.0.0.1"]  # Whitelist
deny_list = ["203.0.113.0/24"]               # Blacklist
default_allow = true                          # Default policy

Processing Order:

  1. Check deny list โ†’ reject if match
  2. Check allow list โ†’ accept if match
  3. Apply default policy

Use Cases:

  • Private capsule: Set default_allow = false, add trusted IPs to allow_list
  • Public server: Set default_allow = true, add abusive IPs to deny_list

Request Validation & Protection

Size Limits:

  • Maximum request size: 1024 bytes (per Gemini spec)
  • Oversized requests receive status 59 BAD REQUEST

Timeout Protection:

  • Default request timeout: 30 seconds
  • Slow clients receive status 40 TIMEOUT
  • Prevents slow-loris attacks

Path Traversal Protection:

# All file paths canonicalized and validated
safe_path = (root / requested_path).resolve()
if not safe_path.is_relative_to(root):
    return Response(status=51, meta='Not found')  # Never expose path info

Client Certificate Support

Mutual TLS (mTLS):

  • Server can request client certificates for authentication
  • Status codes 60-62 for certificate-based access control
  • Certificate fingerprint validation

Generate Client Certificate:

nauyaca cert generate-client --name "My Identity"

Security Best Practices

For Server Operators:

  • Use proper certificates (CA-signed or self-signed with TOFU)
  • Keep private keys secure (file mode 0600)
  • Enable rate limiting appropriate to your traffic
  • Use whitelist mode for private capsules
  • Monitor logs for suspicious activity
  • Keep document root clean of sensitive files

For Client Users:

  • Verify certificate fingerprints on first connection
  • Be suspicious of unexpected certificate changes
  • Keep TOFU database backed up
  • Use separate certificates for different identities
  • Check redirect destinations before following

Important: See SECURITY.md for:

  • Complete security documentation
  • Vulnerability reporting process
  • Known limitations
  • Deployment guidelines
  • Compliance information

๐Ÿš€ Deployment

Systemd Service Example

For production deployments on Linux systems with systemd:

[Unit]
Description=Nauyaca Gemini Protocol Server
After=network.target

[Service]
Type=simple
User=nauyaca
Group=nauyaca
WorkingDirectory=/opt/nauyaca
ExecStart=/usr/local/bin/nauyaca serve --config /etc/nauyaca/config.toml
Restart=always
RestartSec=10

# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/nauyaca/capsule

[Install]
WantedBy=multi-user.target

Save this as /etc/systemd/system/nauyaca.service, then:

# Enable and start the service
sudo systemctl enable nauyaca
sudo systemctl start nauyaca

# Check status
sudo systemctl status nauyaca

# View logs
sudo journalctl -u nauyaca -f

๐Ÿค Contributing

We welcome contributions! Follow these steps to get started.

Development Setup

# Clone the repository
git clone https://github.com/alanbato/nauyaca.git
cd nauyaca

# Install dependencies with uv
uv sync

# Run tests to verify setup
uv run pytest

# Run linting
uv run ruff check src/ tests/

# Run type checking
uv run mypy src/

Development Workflow

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Make your changes
  4. Write/update tests
  5. Ensure tests pass: uv run pytest
  6. Run linting: uv run ruff check src/ tests/
  7. Run type checking: uv run mypy src/
  8. Commit changes (git commit -m 'Add amazing feature')
  9. Push to branch (git push origin feature/amazing-feature)
  10. Open a Pull Request

Commit Convention

Follow Conventional Commits:

feat: Add client certificate support
fix: Handle edge case in URL parsing
docs: Update API reference
test: Add integration tests for server
refactor: Simplify protocol parsing logic

๐Ÿ“„ License

MIT License - see LICENSE file for details

๐Ÿ”— Resources

Gemini Protocol

Python & Asyncio

Nauyaca Documentation

๐Ÿ’ฌ Support & Community

Getting Help

  1. Check the documentation (SECURITY.md, CONTRIBUTING.md)
  2. Search existing GitHub Issues
  3. Ask questions in GitHub Discussions
  4. Review the integration tests for usage examples

๐Ÿ—บ๏ธ Roadmap

Version 0.2.0 (Current)

  • โœ… Core protocol implementation
  • โœ… Security features (TOFU, rate limiting, access control)
  • โœ… Configuration system
  • ๐Ÿšง Integration testing
  • ๐Ÿšง CLI interface completion

Version 0.3.0 (Next)

  • Static file serving
  • Content type detection
  • Directory listings
  • Error page templates
  • Performance optimization

Version 1.0.0 (Stable)

  • Production-ready release
  • Stable API
  • Complete documentation
  • Performance benchmarks
  • Migration guides

๐Ÿ™ Acknowledgments

  • Solderpunk for creating the Gemini protocol
  • The Gemini community for feedback and inspiration
  • Contributors and testers who help improve Nauyaca

Development Status: This project is in active development (pre-1.0). Core protocol and security features are stable, but the high-level API may change based on community feedback.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

nauyaca-0.2.0.tar.gz (43.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

nauyaca-0.2.0-py3-none-any.whl (54.8 kB view details)

Uploaded Python 3

File details

Details for the file nauyaca-0.2.0.tar.gz.

File metadata

  • Download URL: nauyaca-0.2.0.tar.gz
  • Upload date:
  • Size: 43.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nauyaca-0.2.0.tar.gz
Algorithm Hash digest
SHA256 5c29f67bab24c3f31bfbbb66de4c1881946679f8b0684dadf90f35066436f7bf
MD5 8ff255606adf44d3318d8fa2af81d43d
BLAKE2b-256 dca242d0b744e7a61a6b983d66031e8019f562bf6e47a1cb8cd0234089b24446

See more details on using hashes here.

Provenance

The following attestation bundles were made for nauyaca-0.2.0.tar.gz:

Publisher: release-pypi.yml on alanbato/nauyaca

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file nauyaca-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: nauyaca-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 54.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for nauyaca-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d4716ac85fe38c3e2cf9e71301d39cee0ee83127ed37cc7d7b9329714c885aab
MD5 020e74585fcd77a0717f8aed3ab0bc10
BLAKE2b-256 9ec25d69434df85b3321a0c28553bbbc63989e8cb5a94b1eaf650850983c7795

See more details on using hashes here.

Provenance

The following attestation bundles were made for nauyaca-0.2.0-py3-none-any.whl:

Publisher: release-pypi.yml on alanbato/nauyaca

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page