{"id":49896429,"url":"https://github.com/0kaba0hub/yarilo","last_synced_at":"2026-06-13T13:02:14.334Z","repository":{"id":357434465,"uuid":"1236926430","full_name":"0kaba0hub/yarilo","owner":"0kaba0hub","description":"Yarilo — IMAP/SMTP mail server written in Go","archived":false,"fork":false,"pushed_at":"2026-05-30T07:49:13.000Z","size":7662,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-30T09:22:56.847Z","etag":null,"topics":["dovecot","go","golang","helm","imap","imap4","kubernetes","mail-server","maildir"],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/0kaba0hub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-12T17:52:31.000Z","updated_at":"2026-05-30T07:46:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/0kaba0hub/yarilo","commit_stats":null,"previous_names":["0kaba0hub/yarilo"],"tags_count":44,"template":false,"template_full_name":null,"purl":"pkg:github/0kaba0hub/yarilo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0kaba0hub%2Fyarilo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0kaba0hub%2Fyarilo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0kaba0hub%2Fyarilo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0kaba0hub%2Fyarilo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/0kaba0hub","download_url":"https://codeload.github.com/0kaba0hub/yarilo/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/0kaba0hub%2Fyarilo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33771629,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-01T02:00:06.963Z","response_time":115,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dovecot","go","golang","helm","imap","imap4","kubernetes","mail-server","maildir"],"created_at":"2026-05-16T00:10:23.473Z","updated_at":"2026-06-13T13:02:14.315Z","avatar_url":"https://github.com/0kaba0hub.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# yarilo\n\n\u003ctable\u003e\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"https://raw.githubusercontent.com/0kaba0hub/yarilo/main/docs/icon.svg\" width=\"180\" alt=\"yarilo logo\"/\u003e\u003c/td\u003e\n\u003ctd\u003e\n\nProduction-grade IMAP/Submission/LMTP/JMAP mail server written in Go.\nThree-tier cluster (proxy → director → backend), pluggable storage (Maildir / dbox / mdbox / S3), Sieve filtering, full Dovecot 2.3 protocol compatibility.\n\n[![CI](https://github.com/0kaba0hub/yarilo/actions/workflows/ci.yml/badge.svg)](https://github.com/0kaba0hub/yarilo/actions/workflows/ci.yml)\n[![Go 1.26](https://img.shields.io/badge/Go-1.26-00ADD8?logo=go\u0026logoColor=white)](https://go.dev/)\n[![Platform](https://img.shields.io/badge/platform-linux%2Famd64-blue)](https://github.com/0kaba0hub/yarilo)\n[![License: GPL v3](https://img.shields.io/badge/license-GPLv3-blue.svg)](LICENSE)\n[![Status: pre-alpha](https://img.shields.io/badge/status-pre--alpha-orange)](PLAN.md)\n\n\u003c/td\u003e\n\u003c/tr\u003e\u003c/table\u003e\n\n---\n\n## Architecture\n\nYarilo is a single binary that runs in one of three roles (`mode: proxy | director | backend`).\n\n```\n  Internet\n     |\n     | IMAP / IMAPs / SUBMISSION / POP3 / JMAP\n     v\n+------------------+     +------------------+\n|     PROXY        |     |     PROXY        |  ...N\n|                  |     |                  |\n| TLS termination  |     | TLS termination  |\n| Auth (passdb)    |     | Auth (passdb)    |\n| Route lookup     |     | Route lookup     |\n+--------+---------+     +--------+---------+\n         |  TAB-delimited protocol           |\n         v                                   v\n+------------------------------------------------+\n|                  DIRECTOR                      |\n|                                                |\n| Consistent hashing: user@domain -\u003e backend     |\n| Sticky sessions (one user = one backend)       |\n| Backend registry + health checks              |\n| Failover: reassign on node failure             |\n+--------+----------+----------+----------------+\n         |          |          |\n         v          v          v\n  +----------+ +----------+ +----------+\n  | BACKEND  | | BACKEND  | | BACKEND  |  ...N\n  |          | |          | |          |\n  | IMAP     | | IMAP     | | IMAP     |\n  | POP3     | | POP3     | | POP3     |\n  | JMAP     | | JMAP     | | JMAP     |\n  | Sub/LMTP | | Sub/LMTP | | Sub/LMTP |\n  | Sieve    | | Sieve    | | Sieve    |\n  | Quota    | | Quota    | | Quota    |\n  | ACL      | | ACL      | | ACL      |\n  +----+-----+ +----+-----+ +----+-----+\n       |             |            |\n       v             v            v\n  +-----------+ +-----------+ +-----------+\n  | Mailbox   | | Mailbox   | | Mailbox   |\n  | + Index   | | + Index   | | + Index   |\n  +-----------+ +-----------+ +-----------+\n       |                            |\n       v                            v\n  [Maildir/dbox/mdbox]          [obox -\u003e S3]\n  [FileIndex / SQLite]          [Cassandra]\n```\n\n**Proxy** — accepts client connections, terminates TLS (SNI per-domain), authenticates via passdb, queries Director for routing, forwards the raw TCP stream to the target backend. Stateless; scale horizontally without limits.\n\n**Director** — consistent-hashing ring (MD5, 100 vhosts/backend). One user always lands on the same backend. Detects failures and reassigns. All intra-cluster traffic uses the TAB-delimited yarilo-director protocol (see [INTERNALS.md](INTERNALS.md) §2).\n\n**Backend** — full mail server: IMAP, POP3, JMAP, Submission, LMTP, ManageSieve, Sieve execution engine, Quota, ACL, FTS. Speaks natively to the mailbox + index layer.\n\n---\n\n## Protocol support\n\n| Protocol | Standard | Extensions |\n|:---|:---|:---|\n| IMAP4rev2 | RFC 9051 | IDLE, MOVE, CONDSTORE, UNSELECT, NAMESPACE, QUOTA, ACL, BINARY, UIDPLUS, SORT, THREAD, ESEARCH, NOTIFY, QRESYNC, URLAUTH, SPECIAL-USE |\n| Submission | RFC 6409 | STARTTLS, AUTH PLAIN, SIZE, PIPELINING, relay to upstream MTA, ALPN matching, configurable `Received:` header |\n| LMTP | RFC 2033 | per-recipient status codes, proxy/director mode, HAProxy, XCLIENT (incl. `DESTADDR`/`DESTPORT`), STARTTLS, Delivered-To header, per-user concurrency limit, client workarounds |\n| POP3 | RFC 1939 | STLS, UIDL, CAPA, XCLIENT |\n| JMAP | RFC 8620, RFC 8621 | HTTP dispatch, WebSocket push (RFC 8887) |\n| ManageSieve | RFC 5804 | full Sieve script management |\n| Sieve | RFC 5228 | fileinto, reject, vacation, notify, include, variables, date, relational, imap4flags, editheader, extlists, vnd.dovecot.* |\n| SASL | — | PLAIN, LOGIN, GSSAPI, SCRAM-SHA-256, XOAUTH2, OAUTHBEARER |\n| TLS | — | SNI, per-domain context reload |\n\n---\n\n## Storage\n\n| Layer | Backend | Notes |\n|:---|:---|:---|\n| Mailbox | Maildir | one file per message, local FS |\n| Mailbox | dbox (sdbox) | single-file dbox, local FS |\n| Mailbox | mdbox | multi-message dbox, local FS |\n| Mailbox | obox | S3-compatible object storage via minio-go |\n| Index | FileIndex | custom binary format (`.index` / `.index.log` / `.index.cache`) alongside mailbox |\n| Index | SQLite | dev / small deployments |\n| Index | Cassandra | multi-node / large scale |\n| FTS | built-in tokenizer | snowball stemmer + ICU normalizer |\n| FTS | Solr | HTTP XML bridge |\n\n---\n\n## Deployment modes\n\n| Mode | Process layout | Use case |\n|:---|:---|:---|\n| Single node | proxy + director + backend in one process | dev / small server |\n| Multi-node | separate proxy / director / backend | production |\n| Cloud | proxy + director + backend (obox + Cassandra) | large scale |\n\n---\n\n## Cluster components\n\n| Component | Role | Status |\n|:---|:---|:---|\n| yarilo-auth | passdb chain, auth cache, SASL dispatch — TCP+mTLS | ✅ v1.0.0 |\n| yarilo-director | consistent hashing, sticky sessions, failover | planned |\n| yarilo-anvil | connection rate limiting + penalty algorithm | planned |\n| yarilo-locks | cross-process write coordination — embedded (standalone) / remote Redis-backed (backend per tag) | planned |\n| yarilo-dict | Redis / SQLite key-value abstraction | planned |\n| yarilo-admin | control socket (kick, reload, stats) | planned |\n| yarilo-stats | per-user / per-domain connection metrics | planned |\n| imap-hibernate | idle IMAP connection parking via FD-passing | planned |\n| yarilo-indexer | background FTS indexing service | planned |\n\nAll intra-cluster protocols are TAB-delimited text with LF termination and a version handshake.\nFull wire-format specification: [INTERNALS.md](INTERNALS.md).\n\n---\n\n## Quick start (single-node)\n\n```yaml\n# yarilo.yaml\nmode: single   # proxy | director | backend | single\n\ngeneral:\n  ssl:\n    tls_cert: /etc/ssl/yarilo/cert.pem\n    tls_key:  /etc/ssl/yarilo/key.pem\n  haproxy:\n    trusted_nets: [\"127.0.0.1/32\", \"10.0.0.0/8\"]\n    timeout: 3\n  xclient:\n    trusted_nets: [\"127.0.0.1/32\", \"10.0.0.0/8\"]\n  limits:\n    mail_max_userip_connections: 10\n\nservices:\n  imaps:\n    enabled: true\n    port: 993\n    ssl_mode: ssl\n  imap:\n    enabled: true\n    port: 143\n    ssl_mode: starttls\n    disable_plaintext_auth: true\n  submission:\n    enabled: true\n    port: 587\n    ssl_mode: starttls\n    disable_plaintext_auth: true\n  lmtp:\n    enabled: true\n    port: 24\n    ssl_mode: no\n    xclient_protocol: true\n\nprotocol:\n  imap:\n    imap_idle_notify_interval: 120\n    imap_max_line_length: 65536\n    imap_id_send: \"name *\"\n    acl:\n      # RFC 4314 server-side ACL (GETACL/SETACL/DELETEACL/MYRIGHTS/LISTRIGHTS).\n      # Storage = per-mailbox `yarilo-acl` file next to `yarilo.index*`.\n      # When false, ACL commands return NO; the capability is still\n      # advertised because go-imap detects it via interface assertion.\n      enabled: false\n  submission:\n    hostname: mail.example.com\n    max_message_size: 41943040\n    recipient_delimiter: \"+\"\n\nauth:\n  passdb:\n    - driver: postgres\n      dsn: \"${DB_URL}\"\n\n# yarilo-auth standalone process (multi-process mode).\n# Listen address and mTLS cert paths used by the yarilo-auth binary.\nauth_service:\n  listen: \":9100\"\n  # master_listen — Dovecot-style master protocol for password-less\n  # userdb lookups (USER / LIST). Consumed by yarilo-backend-api admin\n  # endpoints and CLI tooling. Empty disables.\n  master_listen: \":9102\"\n  mtls:\n    cert: /etc/yarilo/tls/tls.crt\n    key:  /etc/yarilo/tls/tls.key\n    ca:   /etc/yarilo/tls/ca.crt\n  shutdown:\n    session_grace_period: 30  # seconds to drain sessions on SIGTERM\n    kill_timeout: 5           # seconds before forced exit\n\nstorage:\n  mailbox: maildir\n  maildir_root: /var/mail/vhosts\n  mail_home_template: \"%d/%n\"   # %d=domain %n=local %u=full email\n\nlog:\n  level: info\n```\n\n```sh\nyarilo -config yarilo.yaml\n```\n\nSet `LOG_LEVEL=debug` to enable verbose protocol tracing without restarting.\n\n---\n\n## Mailbox backends\n\n| Value | Format | Description |\n|:---|:---|:---|\n| `maildir` | Maildir | one file per message, `cur/` + `new/` + `tmp/` |\n| `dbox` | sdbox | one file per message in dbox wire format (GUID + metadata embedded) |\n| `mdbox` | mdbox | multiple messages per `m.\u003cid\u003e` file, higher density |\n\n```sh\nyarilo-migrate \\\n  --from /var/mail/vhosts \\\n  --to   /var/mail/dbox \\\n  --format dbox   # or mdbox; --dry-run to preview\n```\n\n---\n\n## Documentation\n\n| Document | Contents |\n|:---|:---|\n| [PLAN.md](PLAN.md) | Implementation plan, phases, library strategy, timelines |\n| [INTERNALS.md](INTERNALS.md) | Wire-format specs for all internal protocols (33 sections) |\n| [docs/GENERAL.md](docs/GENERAL.md) | `general`: shared SSL, HAProxy, XClient, connection limits |\n| [docs/SERVICES.md](docs/SERVICES.md) | `services`: per-listener config for all 7 listeners |\n| [docs/IMAP.md](docs/IMAP.md) | `protocol.imap`: IDLE interval, line length, ID, logout format |\n| [docs/NAMESPACE.md](docs/NAMESPACE.md) | IMAP namespaces (RFC 2342 / 9051 §6.3.10): personal / shared / other_users config, separator semantics, phase roadmap (NS-1a wire → NS-1b storage routing → ACL → NS-3 cross-pod) |\n| [docs/SUBMISSION.md](docs/SUBMISSION.md) | `protocol.submission`: hostname, size limits, relay |\n| [docs/LMTP.md](docs/LMTP.md) | `protocol.lmtp`: local delivery, proxy/director mode, HAProxy, XCLIENT, TLS, headers |\n| [docs/POP3.md](docs/POP3.md) | `protocol.pop3`: UIDL format, soft-delete, migration |\n| [docs/JMAP.md](docs/JMAP.md) | JMAP (planned, Phase 5) |\n| [INSTALL.md](INSTALL.md) | End-to-end Kubernetes deploy with cert-manager + Let's Encrypt |\n| [docs/AUTH.md](docs/AUTH.md) | `auth.passdb`: SQL backends (SQLite/MySQL/Postgres), password schemes |\n| [docs/SMOKE.md](docs/SMOKE.md) | End-to-end smoke test: AUTH → LMTP → IMAPS/POP3S read |\n| [docs/DIRECTOR.md](docs/DIRECTOR.md) | `director_service`: ring config, peers, HAProxy, XCLIENT, mTLS, Helm values |\n| [docs/MONITOR.md](docs/MONITOR.md) | `yarilo-monitor` sidecar: backend health probes, tag credentials, Helm values, Prometheus metrics |\n| [docs/DIRECTOR-API.md](docs/DIRECTOR-API.md) | Director HTTP admin API (ring / backends / users / peers): auth, IP whitelist, endpoints |\n| [docs/BACKEND-API.md](docs/BACKEND-API.md) | Backend-plane HTTP admin API (`yarilo-backend-api` on `:9105`): `/api/backend/\u003cservice\u003e/...` — dict surface today; ACL / quota / folder / user / mailbox in subsequent phases |\n| [docs/YARILO-ADMIN.md](docs/YARILO-ADMIN.md) | `yarilo-admin` CLI: two top-level planes (`director`, `backend`), commands, flags, env vars, usage examples |\n| [docs/DICT.md](docs/DICT.md) | `pkg/dict` KV-store abstraction: drivers (file/redis/sql/memory/fail), YAML schema, `yarilo-admin dict` CLI |\n\n---\n\n## License\n\nGNU General Public License v3.0 — see [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0kaba0hub%2Fyarilo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F0kaba0hub%2Fyarilo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F0kaba0hub%2Fyarilo/lists"}