corso/website/blog/2023-07-24-multi-tenant-backup-with-corso.md
Niraj Tolia 6880064c64
First draft of a community-contributed blog post on multi-tenant backup (#3885)
- Minor edits made for clarity and to pass the linter
- Added image

---

#### Does this PR need a docs update or release note?

- [x]  No
2023-07-22 01:04:18 +00:00

176 lines
6.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
slug: multi-tenant-backup-with-corso
title: "Using Corso to Build a Self-Hosted Multi-Tenant Office 365 Backup Solution"
description: ""
authors:
- name: meuchels
title: Corso Community Member, IT Lead
url: https://github.com/meuchels
image_url: https://avatars.githubusercontent.com/u/77171293?v=4
tags: [corso, microsoft 365, backups, msp, multi-tenant]
date: 2023-07-24
image: ./images/data-center.jpg
---
![A woman engineer holding a laptop in front of a data center](./images/data-center.jpg)
This community-contributed blog post shows how MSPs in the community are using Corso to build out a multi-tenant backup
solution for their Microsoft 365 customers. If you have questions, come find the author (or us) on
[Discord](https://www.alcion.ai/discord).
<!-- truncate -->
First of all, I offer a fully managed backup solution. My clients have no access to the backup software or the data. I
require them to request recovery in a ticket. For my use case I have a self-hosted instance of MinIO that I won't be
going over but there is [another blog post on it](./2023-2-4-where-to-store-corso.md#local-s3-testing). I will show the
layout and an example of how to backup emails using the exchange option in Corso.
## Organizing the file structure on your storage
I wanted my S3 bucket to be laid out in the following fashion utilizing 1 bucket with prefixes for the tenants. For now,
all I did is create a bucket with access to a user for corso. While it's possible to use a single bucket and use prefix
paths per tenant within it, I didn't do that in my setup. The will be generated later with the backup initialization.
```bash
BUCKET
tenant1-exchange
tenant1-onedrive
tenant1-sharepoint
tenant2-exchange
tenant2-onedrive
tenant2-sharepoint
```
If I dont backup a particular service for a client, it will be clear by looking at whether the bucket exists or not.
I have a short name for each tenant to differentiate them.
## The backup compute server layout
I utilize Ubuntu Server for this task. In my setup, everything is done as the root user. I have put the corso
executable in `/opt/corso/` and will be building everything under there. Here is the folder layout before I go into
usage.
```bash
# For logs
/opt/corso/logs
# For config files
/opt/corso/toml
# Root of the scripts folder
/opt/corso/scripts
# For building out the environment loaders
/opt/corso/scripts/environments
# For building out the backup scripts
/opt/corso/scripts/back-available
# For adding a link to the backups that will be run
/opt/corso/scripts/back-active
```
## The environment files
For [configuration](../../docs/setup/configuration/), create an environment file
`/opt/corso/scripts/environments/blank-exchange` with the following content for a template. You can copy this template
to `<tenantshortname>-exchange` in the same folder to setup your client exchange backup environment.
```bash
#####################################
#EDIT THIS SECTION TO MEET YOUR NEEDS
#####################################
# this is a shortname for your tenant to setup storage
export tenantshortname=""
# this is your tenant info from the app setup on O365
export AZURE_TENANT_ID=""
export AZURE_CLIENT_ID=""
export AZURE_CLIENT_SECRET=""
# this is your credentials for your s3 storage
export AWS_ACCESS_KEY_ID="<S3-STORAGE-USERNAME>"
export AWS_SECRET_ACCESS_KEY="<S3-STORAGE-PASSWORD"
# this sets your encryption key for your backups
export CORSO_PASSPHRASE="<ENCRYPTION-PASSWORD>"
# this is your s3 storage endpoint
export s3endpoint="<YOUR-S3-STORAGE-SERVER>"
export bucket="<YOUR-BUCKET>"
####################################
#END EDIT
####################################
export configfile=/opt/corso/toml/${tenantshortname}-exchange.toml
```
## The backup scripts
Create a backup script `/opt/corso/scripts/back-available/blank-exchange` with the following content for an exchange
backup template. This can be copied to `tenantshortname-exchange` in the same directory for creating the backup script.
```bash
#!/bin/bash
##############Begin Edit###
# change blank to tenant short name
source /opt/corso/scripts/environments/blank-exchange
##############End Edit###
# create runtime variables
logfilename="/opt/corso/log/${tenantshortname}-exchange/$(date +'%Y-%m-%d-%H%M%S').log" runcorso="/opt/corso/corso"
# init bucket
$runcorso repo init s3 --bucket $bucket --prefix ${tenantshortname}_exchange --endpoint $s3endpoint \
--log-file $logfilename --config-file $configfile --hide-progress
$runcorso repo connect s3 --bucket $bucket --log-file $logfilename --config-file $configfile --hide- progress
# run Backup
$runcorso backup create exchange --mailbox '*' --log-file $logfilename --config-file $configfile --hide- progress
```
Use this folder for a working directory and create a symbolic link to the scripts that you want to activate in `/opt/corso/scripts/back-active/`.
## The backup runner
To fire it all off, I have a `backuprunner.sh` script that cycles through the `/opt/corso/scripts/back-active` folder
and is scheduled with a `cron` job to run at your interval. You can put it wherever you want but I put it in the scripts
folder as well so I know where everything is. Add your email address. This relies on the Linux mail package, you will
have to accept the email from it.
```bash
#!/bin/bash
# Directory containing the scripts
script_directory="/opt/corso/scripts/back-active"
# Email configuration
recipient="<YOUR-EMAIL-ADDRESS>"
subject_prefix="Backup Job: "
# Iterate over all scripts in the directory
for script_file in "$script_directory"/*; do
# Run the script and capture the output
output=$("$script_file")
# Prepare email subject
script_name=$(basename "$script_file")
subject="$subject_prefix$script_name"
# Send an email with the script output
echo "$output" | mail -s "$subject" "$recipient"
done
```
Once your backups have completed, you can load the environments using the command
`source /opt/corso/scripts/environments/tenant-exchange` to load the variables and access the backups of that tenant. Be
sure to specify the `config-file` flag.
```bash
source /opt/corso/scripts/environments/tenant-exchange
/opt/corso/corso backup list exchange --config-file $configfile
```
Dont forget to backup your /opt/corso folder once in a while to save your scripts!