Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

mail-grpc: the chain gateway

Standard port(s): gRPC 50051, health 8193 (both in-code defaults, loopback-bound).

The gRPC gateway other servers use to reach Solana — it implements the SolanaMail service (ResolveAlias, GetFrombox, SendMail, GetMailbox, GetMailboxKey, DeleteMail). MX/ mail servers call this instead of talking to Solana directly.

When you need it: always, in any deployment where mail should actually reach the chain — without it, sithbitd runs with its chain pipeline disabled.

Network posture: the gRPC surface carries no TLS or authentication — anyone who can reach the port can sign with the gateway’s keypair. Bind it to loopback or a private interface only, never a public address. Why the gateway is a separate private service at all (and what would change that) is recorded in the topology design note.

Quickstart:

cargo run -p mail-grpc

Config file mail_grpc.toml, or point MAIL_GRPC_CONFIG at an alternate path — the same layered TOML/env mechanism as every other SithBit binary (in-code default → TOML → ./.env./.env.$APP_ENV → environment; MAIL_GRPC_* variables override individual settings, e.g. MAIL_GRPC_BIND_ADDR or MAIL_GRPC_ALIAS_INDEX__DATABASE). An empty or missing config file is a runnable dev gateway: it binds 127.0.0.1:50051 — the private-network posture above is the default the code enforces now, not a convention — and resolves the chain endpoint and the signing keypair from the operator’s Solana CLI config (~/.config/solana/cli/config.yml; a missing file means the stock CLI defaults, i.e. mainnet-beta), exactly like the sithbit CLI, so solana config set governs a zero-config gateway. As with the CLI, a bare JSON_RPC_URL environment variable overrides the endpoint (it wins over a configured json_rpc_url), which is handy for pointing a gateway at a local validator without editing config. The annotated mail_grpc/mail_grpc.example.toml documents every key with its default; the Configuration reference has the key/default table.

Migration (clean break): mail-grpc no longer reads its legacy environment-only configuration. GRPC_SERVER_ADDRESS, DEFAULT_KEYPAIR (and DEFAULT_KEYPAIR_VAULT_URI / DEFAULT_KEYPAIR_SECRET_NAME), ALIAS_INDEX_DB, ALIAS_INDEX_POLL_SECONDS, ALIAS_CACHE_SECONDS, and HEALTH_BIND are all ignored. The one legacy name still honored is JSON_RPC_URL (bare, un-prefixed), for parity with the sithbit CLI and the standard Solana convention — it overrides the configured json_rpc_url. In particular, there is no keypair-content-in-an-environment-variable shape anymore: DEFAULT_KEYPAIR used to hold the raw JSON keypair array itself, while the TOML keypair names a key source — a keypair file path, or a cloud secret-manager secret. The nearest env-var equivalent is MAIL_GRPC_KEYPAIR=/path/to/id.json.

Signing keypair: a file or a cloud secret manager

keypair is a key source like the workspace’s other file-loaded secrets. A bare string is a Solana keypair file; the table form fetches the keypair from a cloud secret manager instead — the secret’s value holds exactly what the file would, the raw JSON keypair array. Authentication is each cloud’s ambient chain (Azure managed identity, the AWS credential chain, Google ADC): no new auth to configure, and no key material in the config file — only the secret’s coordinates.

keypair = "signer.json"
keypair = { kind = "akv", vault_uri = "https://<vault>.vault.azure.net/",
            secret_name = "signer" }
keypair = { kind = "asm", secret_id = "sithbit/signer" }
keypair = { kind = "gsm", project = "my-project", secret = "signer" }

Unset (the default), the keypair comes from the Solana CLI config’s keypair_path~/.config/solana/id.json unless solana config set moved it.

mail-grpc also runs the alias indexer that backs Aliases’s ListAliases lookups ([alias_index]; an explicitly empty database disables it). See the Configuration reference for the full key/default table.