No description
  • Python 71.6%
  • HTML 26.7%
  • Shell 1.5%
  • Mako 0.2%
Find a file
2026-04-13 20:09:06 +00:00
.config Adding Managment of TLS 2026-04-13 20:09:06 +00:00
alembic Add integration tests and fix Alembic to use app DATABASE_URL 2026-04-10 23:53:11 +00:00
deploy Adding Managment of TLS 2026-04-13 20:09:06 +00:00
src/chaskiadmin Adding Managment of TLS 2026-04-13 20:09:06 +00:00
tests Adding Managment of TLS 2026-04-13 20:09:06 +00:00
.gitignore Rewrite test suite for 95% coverage and fix broken tests 2026-04-10 21:30:32 +00:00
alembic.ini initial commit 2026-04-10 00:44:11 -03:00
CLAUDE.md initial commit 2026-04-10 00:44:11 -03:00
install.sh Adding Managment of TLS 2026-04-13 20:09:06 +00:00
pyproject.toml Adding Managment of TLS 2026-04-13 20:09:06 +00:00
README.md Adding Managment of TLS 2026-04-13 20:09:06 +00:00

ChaskiAdmin

Multi-tenant middleware for Stalwart Mail Server. Adds tenant isolation, OIDC authentication, and domain-scoped administration without forking Stalwart or requiring an Enterprise license.

Architecture

Tenant Admin --> ChaskiAdmin (FastAPI) --> Stalwart Admin API
                      |
                 PostgreSQL          Zitadel (sso.pop.coop)

ChaskiAdmin sits between tenant admins and Stalwart's management API. It maintains a tenant registry in PostgreSQL and filters all Stalwart API responses to only show resources belonging to the authenticated tenant.

Quick Start

# Clone and set up virtualenv
git clone https://git.pop.coop/pop/chaski-manager.git
cd chaski-manager
uv venv .venv
uv pip install -e ".[dev]"

# Configure
cp .config/settings.env.example .config/settings.env
# Edit .config/settings.env with your credentials

# Run migrations
.venv/bin/python -m alembic upgrade head

# Start the server
.venv/bin/python -m chaskiadmin.main

The admin UI is served at the root URL (default: https://admin.autonomia.lat).

Configuration

All configuration via environment variables in .config/settings.env:

Variable Default Description
DATABASE_URL postgresql+asyncpg://... PostgreSQL connection string
DB_POOL_SIZE 10 Connection pool size
DB_MAX_OVERFLOW 20 Max overflow connections
STALWART_API_URL https://mail.autonomia.lat/api Stalwart admin API URL
STALWART_ADMIN_USER admin Stalwart admin username
STALWART_ADMIN_PASSWORD Stalwart admin password
OIDC_ISSUER https://sso.pop.coop Zitadel OIDC issuer
OIDC_CLIENT_ID OIDC client ID
OIDC_CLIENT_SECRET OIDC client secret
OIDC_REDIRECT_URI https://admin.autonomia.lat/auth/callback OAuth callback URL
SUPER_ADMIN_DOMAINS pop.coop Comma-separated super-admin email domains
APP_HOST :: Bind address (IPv6-first)
APP_PORT 8000 Bind port
APP_BASE_URL https://admin.autonomia.lat Public URL
SECRET_KEY (auto-generated) Session signing key
DOCS_ENABLED false Enable /docs and /redoc
LOG_LEVEL INFO Logging level
LOG_JSON true Structured JSON logging

API

All endpoints prefixed with /api/v1/. Authentication required via Bearer token or session cookie.

Tenant Management (super-admin only)

  • POST /tenants -- Create tenant
  • GET /tenants -- List tenants (paginated: ?limit=100&offset=0)
  • GET /tenants/{id} -- Get tenant details
  • PATCH /tenants/{id} -- Update tenant
  • DELETE /tenants/{id} -- Deactivate tenant
  • POST /tenants/{id}/domains -- Add domain (auto-generates DKIM keys)
  • DELETE /tenants/{id}/domains/{domain} -- Remove domain
  • POST /tenants/{id}/admins -- Add tenant admin
  • DELETE /tenants/{id}/admins/{email} -- Remove admin

Account Management (tenant-scoped)

  • GET /accounts -- List accounts (paginated)
  • POST /accounts -- Create account
  • GET /accounts/{email} -- Get account
  • PATCH /accounts/{email} -- Update account
  • DELETE /accounts/{email} -- Delete account

Group Management (tenant-scoped)

  • GET /groups -- List groups (paginated)
  • POST /groups -- Create group
  • PATCH /groups/{name} -- Update group
  • DELETE /groups/{name} -- Delete group

Domains (tenant-scoped)

  • GET /domains -- List tenant's domains
  • GET /domains/{domain}/dns -- Full DNS record check (MX, SPF, DKIM, DMARC, CNAME)
  • PATCH /domains/{domain}/hosts -- Set custom webmail/imap/smtp hostnames

Stats & Monitoring (tenant-scoped)

  • GET /stats -- Usage stats (accounts, storage, quota)
  • GET /stats/queue -- Mail queue
  • GET /stats/rate-limit -- Rate limit status

Audit (tenant-scoped)

  • GET /audit -- Audit log (paginated)

Health

  • GET /health -- DB connectivity check (returns 503 if degraded)

Testing

# Unit tests (212 tests, 94% coverage)
.venv/bin/python -m pytest

# With coverage report
.venv/bin/python -m pytest --cov=src/chaskiadmin --cov-report=term-missing

# Integration tests against real Stalwart (requires env vars)
.venv/bin/python -m pytest -m integration

# Dependency security audit
.venv/bin/pip-audit

Deployment

systemd

sudo cp deploy/chaskiadmin.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now chaskiadmin

The service runs as the chaskiadmin user with systemd security hardening (NoNewPrivileges, ProtectSystem=strict, PrivateTmp, etc).

Migrations

# Apply pending migrations
.venv/bin/python -m alembic upgrade head

# Check current state
.venv/bin/python -m alembic current

Security

  • OIDC authentication via Zitadel
  • Tenant isolation enforced at the middleware layer
  • Security headers: CSP, HSTS, X-Frame-Options, X-Content-Type-Options
  • Trusted host validation
  • Per-tenant rate limiting (HTTP 429)
  • Session cookies: HttpOnly, Secure, SameSite=Lax
  • API docs disabled by default in production
  • All inputs validated via Pydantic v2
  • SQL injection protected via SQLAlchemy ORM

Tech Stack

  • Python 3.12+ / FastAPI / uvicorn
  • SQLAlchemy 2.0 (async) + asyncpg + Alembic
  • httpx (async Stalwart API client)
  • authlib (OIDC/JWT)
  • dnspython + cryptography (DNS checker, DKIM)

License

Internal -- POP Coop