Installation & setup
This page takes you from an empty server to a working gateway with your first organization and domain. Read Go-live before you change any MX record.
1. Requirements
| Item | Requirement |
|---|---|
| Operating system | Ubuntu Server 24.04 LTS, freshly installed, nothing else listening on ports 25, 80, 443, 5432. |
| Size | 2+ vCPU, 4 GB RAM minimum (8 GB recommended - ClamAV alone uses ~1.5 GB), 40 GB+ disk for the quarantine store. |
| Access | SSH with an account that can use sudo. |
| Outbound | TCP 25 (delivery to the internet), UDP/TCP 53 (its own DNS resolution - Spamhaus refuses big public resolvers), TCP 443 (updates, ClamAV signatures, Microsoft/Google APIs). |
| AI host (optional) | An Ollama server reachable on TCP 11434 from the gateway. |
| Inbound (at go-live) | TCP 25 from the internet (MX) and TCP 443 for the console and digest links. |
2. Install
Copy the release to the server and run the installer as root. It is idempotent: running it again upgrades in place and keeps your data and settings.
tar xzf obsidian.tar.gz && cd obsidian
sudo OBSIDIAN_HOSTNAME=mx1.example.com \
OBSIDIAN_PUBLIC_URL=https://mx1.example.com \
bash deploy/install.sh
- OBSIDIAN_HOSTNAME
- The gateway's public host name (becomes the MX target and Postfix host name). Defaults to the server's
hostname -f. You can change it later in Settings › General. - OBSIDIAN_PUBLIC_URL
- The address people use to open the console. It is written into digest release links and sign-in links, so it must be reachable by your users. Stored in
/etc/obsidian/obsidian.toml.
What the installer sets up:
- Postfix with postscreen on port 25, the scanning milter, and a local-only re-injection port (10026) for released mail.
- PostgreSQL database
obsidianwith a random password. - ClamAV daemon, signature updates, and Sanesecurity signatures (clamav-unofficial-sigs).
- unbound on 127.0.0.1:5335 as the system resolver, so Spamhaus sees your own IP.
- nginx serving the console over HTTPS with a temporary self-signed certificate.
- Three services:
obsidian-milter(scans mail),obsidian-worker(AI reviews, digests, connectors, clean-up),obsidian-web(this console). /etc/obsidian/obsidian.toml- database password, session secret, data key and a one-time setup token.
data_key decrypts stored connector secrets and DKIM keys. Without it, restored databases cannot use their connectors.At the end the installer prints the status of every service. All should read active. Check again any time on System health.
3. Create the MSP administrator
- Read the setup token on the server:
sudo cat /etc/obsidian/setup-token - Open
https://<server>/setup. Your browser will warn about the temporary certificate - that is expected until you install a real one. - Enter the setup token, your email, name and a password of at least 12 characters, then Create administrator.
The setup page only works while no account exists; afterwards it redirects to sign-in. Lost the password? On the server: sudo -u obsidian env OBSIDIAN_CONFIG=/etc/obsidian/obsidian.toml /opt/obsidian/venv/bin/obsidian-admin create-admin you@example.com resets it.
4. Platform settings
Open Settings (every option explained) and fill in at least:
- General › Gateway hostname - the FQDN your MX records will point to.
- General › Gateway public IPs - so setup instructions show the right addresses.
- General › Time zone.
- Spamhaus › Data Query Service key - required for commercial use and for the ZRD and HBL lists. Register at Spamhaus for a DQS key; until then the free public mirrors are used.
- AI analysis - check the Ollama endpoint and model name, then System health › Test AI model.
- Quarantine digests - hours and From address.
- TLS certificate - request a Let's Encrypt certificate (how). With Cloudflare DNS this works before the server is reachable from the internet.
Set the console's public address once you have its name: re-run the installer with OBSIDIAN_PUBLIC_URL=https://portal.example.com (or edit public_url in /etc/obsidian/obsidian.toml and restart the obsidian services) so digest and sign-in links use it.
5. Add an organization
Organizations › Add organization. Choose the mail platform - it pre-fills where clean mail is delivered and tailors every setup instruction. See Organizations.
6. Add its domains
On the organization page, Add domain. For Microsoft 365 the delivery host is filled in automatically (domain-com.mail.protection.outlook.com); for Google it is aspmx.l.google.com; for Exchange enter the server's address. Open the domain and click Test delivery host - you want "STARTTLS offered". Details: Domains & mail routing.
7. Connect the mail platform (recommended)
Add an API connector on the organization page: Microsoft 365, Google Workspace or Exchange. It syncs users and aliases (needed for recipient checks, personal quarantines and VIP protection), enables sign-in with work accounts, clawback, and optional API-mode scanning. Follow API connectors, then Test connection and Sync users.
8. Mark your VIPs
On Users, open each executive / finance approver and tick VIP. External mail using their display name is then flagged as impersonation.
9. Test before go-live
- Test a message: upload a few real .eml files (a newsletter, a phishing sample, an internal email) and read the verdicts. See Test a message.
- Optionally run API mode on a pilot mailbox for a few days and watch Message trace.
- Tune Policies and allow lists for partners that fail authentication.
Then continue with the Go-live checklist.
Upgrading
Re-run deploy/install.sh from the new release (or python deploy/deploy_once.py from the development workstation, which uploads and installs in one SSH session). The installer runs as a background systemd unit (obsidian-install, log in /var/log/obsidian-install.log), so a dropped SSH connection cannot interrupt it. Mail is only paused for the few seconds the services restart; senders retry automatically.
Backups
- Database:
sudo -u postgres pg_dump obsidian | gzip > obsidian-$(date +%F).sql.gz - Configuration:
/etc/obsidian/(includes the data key and TLS links) - Quarantine store:
/var/lib/obsidian/store/(gzip-compressed messages)