<img width="200" height="175" alt="Bichon Logo" src="https://github.com/user-attachments/assets/06dc3b67-7d55-4a93-a3de-8b90951c575b" />
A self-hosted email archiving server built in Rust. Download emails from IMAP accounts, builds a full-text search index, and serves a REST API with an embedded WebUI. Purpose-built for long-term preservation, unified cross-account search, and programmatic access to archived email.
▶ Click to watch the demo
[!NOTE] Bichon is an archiver, not an email client. It does not send, compose, forward, or reply to emails. Its optional SMTP server is for receiving emails only.
/api-docs (Swagger UI, ReDoc, Scalar). All endpoints documented with request/response schemas.bichon-cli.# Pull the image
docker pull rustmailer/bichon:latest
# Create data directory
mkdir -p ./bichon-data
# Run container
docker run -d \
--name bichon \
-p 15630:15630 \
-v $(pwd)/bichon-data:/data \
--user 1000:1000 \
-e BICHON_ROOT_DIR=/data \
-e BICHON_ENCRYPT_PASSWORD=your-secure-password-here \
rustmailer/bichon:latest
Open http://localhost:15630 in your browser.
[!IMPORTANT] Default login: username
admin, passwordadmin@bichon. Change this immediately via Settings → Profile.
services:
bichon:
image: rustmailer/bichon:latest
container_name: bichon
ports:
- "15630:15630"
volumes:
- ./bichon-data:/data
user: "1000:1000"
environment:
BICHON_ROOT_DIR: /data
BICHON_ENCRYPT_PASSWORD: your-secure-password-here
BICHON_LOG_LEVEL: info
Download from the Releases page:
| Platform | Archive |
|---|---|
| Linux (GNU) | bichon-x.x.x-x86_64-unknown-linux-gnu.tar.gz |
| Linux (MUSL) | bichon-x.x.x-x86_64-unknown-linux-musl.tar.gz |
| macOS | bichon-x.x.x-x86_64-apple-darwin.tar.gz |
| Windows | bichon-x.x.x-x86_64-pc-windows-msvc.zip |
# Linux / macOS
./bichon --bichon-root-dir /path/to/data --bichon-encrypt-password your-password
# Windows
.\bichon.exe --bichon-root-dir E:\bichon-data --bichon-encrypt-password your-password
--bichon-root-dir must be an absolute path. All Bichon data lives under this directory.
Prerequisites: Rust (latest stable), Node.js 20+, pnpm
git clone https://github.com/rustmailer/bichon.git
cd bichon
# Build the WebUI (required before building the server)
cd web && pnpm install && pnpm run build && cd ..
# Build and run
export BICHON_ENCRYPT_PASSWORD=dev-password
cargo run -- --bichon-root-dir /tmp/bichon-data
For frontend development:
cd web && pnpm run dev # Vite dev server with API proxy to Rust backend
[!TIP] The WebUI must be built at least once (
pnpm run build) for the server to serve the frontend. In dev mode (pnpm run dev), Vite proxies API calls to the Rust server automatically.
All settings accept both CLI flags (--bichon-http-port) and environment variables (BICHON_HTTP_PORT). CLI flags take precedence over environment variables.
| Variable | CLI Flag | Description |
|---|---|---|
BICHON_ROOT_DIR |
--bichon-root-dir |
Required. Absolute path for all persistent data |
BICHON_ENCRYPT_PASSWORD |
--bichon-encrypt-password |
Password used to encrypt stored credentials (IMAP passwords, OAuth tokens) |
BICHON_ENCRYPT_PASSWORD_FILE |
--bichon-encrypt-password-file |
Alternative: read the encryption password from a file |
[!NOTE] If both password options are set, the direct value takes precedence over the file.
| Variable | Default | Description |
|---|---|---|
BICHON_HTTP_PORT |
15630 |
HTTP server port |
BICHON_BIND_IP |
0.0.0.0 |
IP address to bind to (IPv4 or IPv6) |
BICHON_PUBLIC_URL |
http://localhost:15630 |
Public-facing URL used in OAuth redirects and docs |
BICHON_BASE_URL |
/ |
Base path for WebUI when behind a reverse proxy (e.g. /bichon) |
BICHON_WEBUI_TOKEN_EXPIRATION_HOURS |
168 |
Access token lifetime in hours (default 7 days) |
BICHON_HTTP_COMPRESSION_ENABLED |
true |
Enable gzip/brotli/zstd response compression |
| Variable | Default | Description |
|---|---|---|
BICHON_LOG_LEVEL |
info |
Log level: trace, debug, info, warn, error |
BICHON_ANSI_LOGS |
true |
Colorized terminal output |
BICHON_JSON_LOGS |
false |
JSON-formatted logs for log aggregators |
BICHON_LOG_TO_FILE |
false |
Persist logs to files under root dir |
BICHON_MAX_SERVER_LOG_FILES |
5 |
Max log files to retain |
| Variable | Default | Description |
|---|---|---|
BICHON_CORS_ORIGINS |
(allow all) | Comma-separated list of allowed origins: http://192.168.1.16:15630,http://myserver.local:15630 |
BICHON_CORS_MAX_AGE |
86400 |
Cache duration for CORS preflight in seconds |
[!WARNING] If
BICHON_CORS_ORIGINSis not set, all origins are allowed. If you set it, only exact matches pass. Wildcards (*) are not supported. Do not add trailing slashes. When using Docker, avoid wrapping the value in quotes.
| Variable | Default | Description |
|---|---|---|
BICHON_ENABLE_REST_HTTPS |
false |
Serve the API over HTTPS (requires valid certificate) |
| Variable | Default | Description |
|---|---|---|
BICHON_ENABLE_SMTP |
false |
Enable the embedded SMTP receiver |
BICHON_SMTP_PORT |
2525 |
SMTP listening port |
BICHON_SMTP_ENCRYPTION |
starttls |
Encryption mode: none, starttls, or tls |
BICHON_SMTP_AUTH_REQUIRED |
true |
Require authentication for SMTP connections |
BICHON_SMTP_TLS_KEY_PATH |
— | Absolute path to SMTP TLS private key |
BICHON_SMTP_TLS_CERT_PATH |
— | Absolute path to SMTP TLS certificate chain |
| Variable | Default | Description |
|---|---|---|
BICHON_INDEX_DIR |
{root}/bichon-indices |
Tantivy full-text index directory |
BICHON_DATA_DIR |
{root}/bichon-storage |
Fjall blob storage directory |
[!TIP] Place
BICHON_INDEX_DIRon fast SSD storage for responsive search, andBICHON_DATA_DIRon high-capacity HDD for cost-effective blob storage.[!IMPORTANT] Bichon does NOT support writing data directly to a network file system (NFS, CIFS/SMB, etc.). All directories —
BICHON_ROOT_DIR,BICHON_DATA_DIR, andBICHON_INDEX_DIR— must reside on a local file system; otherwise, data corruption may occur.
| Variable | Default | Description |
|---|---|---|
BICHON_SYNC_CONCURRENCY |
num_cpus × 2 |
Max concurrent account sync tasks |
BICHON_METADATA_CACHE_SIZE |
134217728 (128 MB) |
Metadata DB cache in bytes |
BICHON_ENVELOPE_CACHE_SIZE |
134217728 (128 MB) |
Envelope index cache in bytes |
POST /api/login with username + password returns a JWT access token/api/v1/* endpoints require Authorization: Bearer <token>BICHON_WEBUI_TOKEN_EXPIRATION_HOURS, default 7 days)On
$ claude mcp add bichon \
-- python -m otcore.mcp_server <graph>