Bichon on Ubuntu 24.04 on Azure User Guide
Overview
Bichon is a self hosted email archiving server written in Rust. It downloads mail from your IMAP accounts, builds a full text search index over subjects, bodies, participants and attachments, and serves the whole archive through a REST API and an embedded web interface. It is built for long term preservation and retrieval rather than day to day mail: it archives, indexes, deduplicates and searches, but it never sends or replies. The cloudimg image serves Bichon 2.0.2 on a hardened, fully patched Ubuntu 24.04 LTS base, with the archive itself on a dedicated Azure data disk so your mail store grows independently of the operating system disk.
The image is secure by default. Bichon upstream creates a built in administrator with a published default password the first time it starts. This image never ships that state: the archive store is empty at capture, so there is no user database in the image at all. On the first boot of every VM a one shot service generates a data encryption key and an administrator password that are unique to that machine, completes the bootstrap on the loopback interface only, and replaces the upstream default before the public listener is ever started. The default password has never been reachable on your VM. Backed by 24/7 cloudimg support.
What is included:
- Bichon 2.0.2, the official upstream release binaries, shipped unmodified and managed by systemd
- The REST API and embedded web interface on
:15630 - A per VM administrator password and a per VM data encryption key, both generated at first boot
- Three embedded storage layers with no external database: a Tantivy full text index, a compressed blob store and an embedded metadata store
- Multi account IMAP archiving with password and OAuth 2.0 authentication, and incremental delta downloads
- Full text search across subject, body, sender, recipients and attachment properties, with faceted filters and thread grouping
- Import from EML, MBOX, Thunderbird profiles and Outlook PST files
- Multi user access control with five built in roles and account level isolation
- Interactive OpenAPI documentation at
/api-docs/swagger - A dedicated Azure data disk at
/var/lib/bichonfor the whole archive bichon.serviceas an enabled systemd unit- 24/7 cloudimg support
Bichon is an independent open source project licensed under the GNU Affero General Public License v3.0. cloudimg is not affiliated with the Bichon project or rustmailer. The licence text and a pointer to the corresponding source ship in /usr/share/doc/bichon/.
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a sensible starting point; size up if you archive many accounts concurrently or index a large historic mailbox. NSG inbound: allow 22/tcp from your management network and 15630/tcp for the web interface. Restrict 15630/tcp to trusted networks in production, since it exposes your entire mail archive. Size the data disk for the mail you intend to keep: Bichon compresses bodies and attachments and stores identical content once, so the archive is usually smaller than the source mailboxes.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Bichon by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22). Review the dedicated data disk on the Disks tab, then Review + create then Create. After the VM is created, add an NSG rule for 15630/tcp scoped to the networks that should reach the archive.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name bichon \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Then open the web interface port:
az vm open-port --resource-group <your-rg> --name bichon --port 15630 --priority 900
Step 3 - Confirm the service is running
SSH in as azureuser and confirm Bichon is active. The server listens on port 15630 and serves both the REST API and the web interface from that one port.
systemctl is-active bichon bichon-firstboot
sudo ss -tlnp | grep ':15630 ' | awk '{print $1, $4}'
findmnt -no SOURCE,TARGET,FSTYPE /var/lib/bichon
curl -s http://127.0.0.1:15630/api/status | jq .
The status endpoint is public and unauthenticated, so it is a convenient health check for a load balancer or a monitoring probe. It reports the running version and how long the server has been up:
{
"uptime_ms": 618664,
"timeago": "10 minutes ago",
"timezone": "+00:00",
"version": "2.0.2"
}

Step 4 - Read your per VM administrator password
Every VM generates its own administrator password on first boot and writes it to a root only file. Nothing is shared between deployments, and the password is not known to cloudimg. Read it with sudo:
sudo cat /root/bichon-credentials.txt
The file records the web interface URL, the administrator username, and the password that first boot generated for this machine:
BICHON_URL=http://10.0.0.14:15630/
bichon.admin.username=admin
bichon.admin.password=<unique to your VM>
You can prove from the command line that the password in that file signs in, and that the published upstream default does not. First, the per VM password:
BICHON_PW=$(sudo grep '^bichon.admin.password=' /root/bichon-credentials.txt | cut -d= -f2-)
curl -s -X POST -H 'Content-Type: application/json' \
-d "{\"username\":\"admin\",\"password\":\"$BICHON_PW\"}" \
http://127.0.0.1:15630/api/login | jq '{success, signed_in: (.access_token != null)}'
{
"success": true,
"signed_in": true
}
Now the upstream default, which this image rotates away before the public listener ever starts:
curl -s -X POST -H 'Content-Type: application/json' \
-d '{"username":"admin","password":"admin@bichon"}' \
http://127.0.0.1:15630/api/login | jq '{success, error_message}'
{
"success": false,
"error_message": "Incorrect password."
}

Step 5 - Sign in to the web interface
Browse to http://<vm-public-ip>:15630/. Bichon opens on its sign in page: there is no anonymous access to any part of the archive. Sign in as admin with the password from Step 4. Change it to one of your own straight away under Settings then Profile.

Step 6 - The archive dashboard
The dashboard is the landing page after sign in. It reports how many mail accounts are connected, how many messages and attachments are archived, and how much disk the compressed blob store and the search index are using. Below that it charts message volume over time and the share of mail carrying attachments, and lists your top senders, largest messages, largest attachments and busiest accounts.

Step 7 - Connect a mailbox to archive
Open Email Accounts from the left navigation. Choose IMAP account to archive a live mailbox: enter the address, the IMAP host and port, the encryption mode, and either a password or OAuth 2.0. Bichon can discover most provider settings from the email domain. Set a download interval or a cron schedule, and optionally scope the download by date range or by folder so you only archive what you need. Choose Local account instead if you want a container for imported mail with no IMAP server behind it.
Bichon downloads incrementally after the first pass, fetching only new messages by UID, and it detects UIDVALIDITY changes and rebuilds its cache automatically.

Step 8 - Import existing mail
Existing archives can be loaded straight in. From the web interface open Import and upload .eml or .mbox files into an account and folder. For larger or scripted migrations use the bundled command line tool, which also handles Thunderbird profiles, Outlook PST files and export back to MBOX:
/usr/local/bin/bichon-cli --version
The tool writes a config.toml on first run holding your server URL and an API token, which you create under Settings then API tokens. All parsing, indexing, deduplication and storage happen server side.
Step 9 - Search the archive
Open Search. Type a term and Bichon queries the full text index across subjects, bodies, participants and attachment properties, returning matches with the sender, recipient, folder, size, attachment count and date. Narrow results with the account, mailbox, contact and tag filters, or open Advanced for date ranges, size ranges, attachment presence and file type. Select a result to read the message, view the whole conversation thread, download the original EML, or restore it back to an IMAP mailbox.

Step 10 - Verify the stack
Confirm the shipped version, that the unit is enabled for reboots, that the API answers, and the dedicated data disk mount:
/usr/local/bin/bichon-cli --version
systemctl is-enabled bichon
curl -s -o /dev/null -w 'GET /api/status -> HTTP %{http_code}\n' http://127.0.0.1:15630/api/status
df -h /var/lib/bichon | tail -1

Step 11 - Where your mail is stored
The entire archive lives on a dedicated Azure data disk mounted at /var/lib/bichon, separate from the operating system disk. This disk is captured into the image and re provisioned on every VM, and you can snapshot and resize it independently as the archive grows.
sudo ls /var/lib/bichon
Three storage layers sit under that mount: bichon-indices is the Tantivy full text index, bichon-storage is the compressed blob store holding message bodies and attachments, and memdb holds relational metadata. Identical bodies and attachments are stored once and referenced by content hash, so duplicated mail across accounts costs very little extra space.
df -h /var/lib/bichon | tail -1
To back the archive up, snapshot the data disk and keep a copy of /etc/bichon/encrypt.key with it. That key encrypts the stored IMAP passwords and OAuth tokens, it is unique to this VM, and without it a restored archive cannot reconnect to your mail accounts.
Step 12 - Explore the API
Every feature of the web interface is available over the REST API, documented interactively on the VM itself. Browse to http://<vm-public-ip>:15630/api-docs/swagger for Swagger UI, or /api-docs/redoc and /api-docs/scalar for alternative renderings, and /api-docs/spec.json for the raw OpenAPI 3.0 document. Endpoints under /api/v1/ take an Authorization: Bearer header. Create long lived tokens for automation under Settings then API tokens so scripts never need the administrator password.
Security notes
- The web interface and the API share port 15630. Restrict
15630/tcpin the NSG to trusted networks, and consider fronting it with your own TLS terminating proxy or reaching it over a VPN. The archive contains the full text of your mail. - No known credential ships in the image. The archive store is empty at capture, so the image contains no user database at all. First boot generates the administrator password and the data encryption key for that VM alone, completes the bootstrap on the loopback interface, and replaces the upstream default before the public listener starts.
/root/bichon-credentials.txtis0600 root:rootand/etc/bichon/encrypt.keyis0400and owned by the service account. Change the administrator password to one of your own under Settings then Profile, and give each person their own account and role rather than sharing the administrator.- Bichon runs as the unprivileged
bichonsystem account under systemd, withNoNewPrivileges, a private/tmp, a read only system tree and write access limited to the archive disk. - Use the built in roles to limit access. Managers, members and per account viewers can be scoped to individual mailboxes, which matters when an archive spans several teams.
- Keep the VM patched. The image ships fully patched with unattended security upgrades enabled.
Support
cloudimg images come with 24/7 support. If you have any questions about this Bichon image or need help with your deployment, contact us through the cloudimg website.