Skip to content

Hosting: offboarding a tenant#

This documentation applies to Piler enterprise edition 2.2.5+

Revision #2

Publication date: 2026-OCT-27

When a customer leaves: hand over their archive, then delete their data. Agree on both in your contract, e.g. how long the archive is kept after the end of the contract, and in what format it's handed over.

1. Export the archive#

pilerexport writes the emails as EML files, or a ZIP of them. Exporting a whole tenant means the range of its metadata ids. Multi-node: every worker has its own emails and its own id range, so export on every worker.

On each worker (or the single node):

# The tenant's id range on this node
docker compose exec piler sh -c \
   'mariadb --defaults-file=/etc/piler/.my.cnf -N customer1 -e "SELECT MIN(id), MAX(id) FROM metadata"'

# Export it (the export reads the emails from S3 or the store)
docker compose exec piler pilerexport -tenantid customer1 \
   -start <min id> -stop <max id> -zip /var/piler/tmp/customer1-worker0.zip -progress

docker compose cp piler:/var/piler/tmp/customer1-worker0.zip .
docker compose exec piler rm /var/piler/tmp/customer1-worker0.zip

Check the free space of /var/piler/tmp first: the ZIP is about the original size of the archive. Hand the files over the way your contract says, e.g. a download link with an expiry, and then delete your copies.

Users may also export their own search results from the UI, and auditors can produce an eDiscovery export with a chain of custody, if the customer needs one for a legal matter.

2. Stop the email#

  • Have the customer remove the journaling rule, or block their mail servers at port 25.
  • Remove the tenant's router from Traefik and its DNS record.

3. Delete the data#

Removing the tenant in Admin > Tenant only removes its settings: the archive stays until you delete it. Do this once the export has been handed over and the agreed retention after the contract has passed. It can't be undone; your backups keep the data until they expire.

The purge-tenant.sh script does the steps below on a node, with safety checks: it refuses while a legal hold is open (also the master's, on a worker), or while the email still arrives, and without --execute it only shows what it would delete. Run it on every node, the workers first, then the master.

By hand: on every node (the master and each worker, or the single node), in its piler container:

T=customer1

# The tenant's database
mariadb --defaults-file=/etc/piler/.my.cnf-root -e "DROP DATABASE \`$T\`"

# Its Manticore tables. List them by name: a pattern like 'customer1%'
# would also match a tenant named customer10.
for s in "" _tag1 _note1 _cat1 _audit _embeddings _teams_messages _slack_messages; do
   echo "DROP TABLE IF EXISTS ${T}${s};"
done | mariadb -h manticore -P9306

# Its directories (the store is empty with S3 storage)
rm -rf /var/piler/store/*/$T /var/piler/astore/*/$T

Then:

  • Remove the tenant in Admin > Tenant on the master, and on every worker through its piler-ui (or DELETE FROM piler.tenant_settings WHERE tenant_id='customer1' on each node's database).
  • With S3 storage, delete the bucket S3_BUCKET_PREFIX + tenant id and its objects.
  • Remove the tenant from your monitoring and billing.

The _audit table holds who accessed the archive. If your compliance rules require keeping the access log after the contract, export it before dropping it (Audit > Export as an auditor, or a SELECT on the table).