Storage Azure

Bichon on Ubuntu 24.04 on Azure User Guide

| Product: Bichon on Ubuntu 24.04 LTS on Azure

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/bichon for the whole archive
  • bichon.service as 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"
}

The bichon and bichon-firstboot services reported active, the server listening on port 15630, and the public status endpoint returning the running Bichon 2.0.2 version

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."
}

The per VM credentials file with its root only permissions, and the upstream default password admin@bichon being rejected by the login endpoint on this image

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.

The Bichon sign in page, the authenticated front door to the archive - the image ships with no anonymous access and a password unique to each VM

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.

The Bichon dashboard showing a live archive: connected accounts, archived message and attachment counts, storage and index usage, the message volume chart, the attachment ratio, and the top senders and largest messages tables

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.

The Bichon Email Accounts page listing an archive account, with the IMAP account and Local account actions used to connect a mailbox

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.

Bichon full text search returning eighteen archived messages for a query, showing sender, recipient, subject, attachment count, size and date for every hit

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

The shipped Bichon 2.0.2 version, the dedicated ext4 archive disk and its free space, the three embedded storage layers, and the licence and upstream source notice

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/tcp in 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.txt is 0600 root:root and /etc/bichon/encrypt.key is 0400 and 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 bichon system account under systemd, with NoNewPrivileges, 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.