Skip to main content

Bichon

A self-hosted email archiver with a web UI, built in Rust.

Bichon is a lightweight email archiver written in Rust. It pulls mail from IMAP accounts, stores and indexes it, and offers a web UI for search and browsing. It is an archive that stays readable independent of the mail provider, not a mail client: it does not send mail.

Alternatives considered​

Cloud Hosted

ToolOpen SourceFree TierMonthly Cost
GmailNoYesFree / From $7/seat
Outlook WebNoYesFree / From $6/seat

Self Hosted

ToolOpen SourceFull FeaturesNotes
PilerYesYesMature archiver fed over SMTP; heavier to run
Open ArchiverYesYesIMAP, Google Workspace and Microsoft 365 ingestion
Mail-ArchiverYesYesIMAP archiver on .NET and PostgreSQL

Installation​

Architecture​

  • Deployment: Single bichon deployment in the bichon namespace
  • Image: rustmailer/bichon, digest-pinned via Renovate
  • Storage: Three Longhorn PVCs — bichon (app data), index (search index), mails (mail storage)
  • Networking: ClusterIP service, HTTPRoute via internal gateway

Security​

  • Runs as runAsUser: 1000, runAsNonRoot: true, allowPrivilegeEscalation: false, capabilities dropped
  • Longhorn PVCs encrypted at rest via SOPS-managed keys

Updates​

Managed by Renovate. Image is digest-pinned.

Data Management​

  • PVCs: bichon (app data), index (search index), mails (mail storage) — all Longhorn-encrypted
  • Backups: k8up Schedules to Hetzner and Backblaze via restic, covering all three Longhorn PVCs

User Management​

No OIDC or external auth configured. Access controlled by application-level authentication.

Configuration Management​

  • BICHON_DATA_DIR, BICHON_INDEX_DIR, BICHON_ROOT_DIR, and encryption password from SOPS-encrypted secret

Usage​

Access the web UI to read, compose, and organize email. The search index enables full-text search across stored mail. All mail data is persisted in the encrypted Longhorn volumes on-cluster.

Cluster-specific deviations from the above live in the per-cluster README — see k8s/apps/bichon/talos/README.md.

Cluster Deployment​

Bichon — Talos cluster

Kubernetes Metadata
  • Image: rustmailer/bichon:2.1.1@sha256:81aeb6d331bbef407df9f927b355398ea87ec5099a0b15a062cd62a6e7cb402e
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app.kubernetes.io/name: bichon
name: bichon
namespace: bichon
spec:
replicas: 1
revisionHistoryLimit: 2
selector:
matchLabels:
app.kubernetes.io/name: bichon
strategy:
type: Recreate
template:
metadata:
labels:
app.kubernetes.io/name: bichon
spec:
automountServiceAccountToken: false
containers:
- envFrom:
- secretRef:
name: bichon
image: rustmailer/bichon:2.1.1@sha256:81aeb6d331bbef407df9f927b355398ea87ec5099a0b15a062cd62a6e7cb402e
name: bichon
ports:
- containerPort: 15630
name: web
protocol: TCP
readinessProbe:
failureThreshold: 1
httpGet:
path: /
port: 15630
initialDelaySeconds: 5
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 2
resources:
limits:
memory: 2Gi
requests:
cpu: 25m
memory: 1Gi
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
volumeMounts:
- mountPath: /data
name: bichon-data
- mountPath: /index
name: bichon-index
- mountPath: /mails
name: bichon-mails
priorityClassName: tier-2
securityContext:
fsGroup: 1000
fsGroupChangePolicy: OnRootMismatch
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
volumes:
- name: bichon-data
persistentVolumeClaim:
claimName: bichon
- name: bichon-index
persistentVolumeClaim:
claimName: index
- name: bichon-mails
persistentVolumeClaim:
claimName: mails