Bichon
A self-hosted webmail client built in Rust.
Bichon is a lightweight, self-hosted webmail application written in Rust. It provides a web interface for reading and managing email, keeping your email access private and independent of third-party webmail providers.
Alternatives considered
Cloud Hosted
| Tool | Open Source | Free Tier | Monthly Cost |
|---|---|---|---|
| Gmail | No | Yes | Free / From $7/seat |
| Outlook Web | No | Yes | Free / From $6/seat |
Self Hosted
| Tool | Open Source | Full Features | Notes |
|---|---|---|---|
| Roundcube | Yes | Yes | Mature PHP webmail |
| Snappymail | Yes | Yes | Lightweight PHP webmail |
Installation
Architecture
- Deployment: Single
bichondeployment in thebichonnamespace - Image:
rustmailer/bichon:0.3.7(digest-pinned) - 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
Schedulebacks up all three Longhorn PVCs to Hetzner S3 via restic
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
Administration
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/talos/bichon/README.md.
Cluster Deployment
Bichon — Talos cluster
Cluster-specific notes only. General product info, "why we use it", and alternatives live in docusaurus/docs/apps/bichon.mdx.
Deviations from defaults
Defaults live in docusaurus/docs/apps/bichon.mdx — document anything this cluster does differently here, with a one-line reason.
- Image:
rustmailer/bichon:1.5.2@sha256:e10a3bdbc5ae9e52f29174d66ccc3dea537ce2353d362f28cb83609c93f82dd3
Rendered manifests (kustomize build)
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kustomize.toolkit.fluxcd.io/force: enabled
labels:
app.kubernetes.io/instance: bichon
app.kubernetes.io/name: bichon
name: bichon
namespace: bichon
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/instance: bichon
app.kubernetes.io/name: bichon
ingress: internal
template:
metadata:
labels:
app.kubernetes.io/instance: bichon
app.kubernetes.io/name: bichon
ingress: internal
spec:
containers:
- envFrom:
- secretRef:
name: bichon
image: rustmailer/bichon:1.5.2@sha256:e10a3bdbc5ae9e52f29174d66ccc3dea537ce2353d362f28cb83609c93f82dd3
name: bichon
ports:
- containerPort: 15630
name: web
protocol: TCP
readinessProbe:
failureThreshold: 1
httpGet:
path: /
port: 15630
initialDelaySeconds: 5
periodSeconds: 3
successThreshold: 1
timeoutSeconds: 2
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
privileged: false
volumeMounts:
- mountPath: /data
name: bichon-data
- mountPath: /index
name: bichon-index
- mountPath: /mails
name: bichon-mails
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