Troubleshooting
Symptoms, causes and fixes for the problems you are most likely to meet. Start with System health - it answers most of these at a glance.
Mail is not arriving at all
- Is it reaching the gateway? Search Message trace for the sender. Nothing? Check the MX record, the firewall forward of TCP 25, and
journalctl -u postfix@- -fwhile sending a test. Senders on Spamhaus ZEN are dropped by postscreen and never appear in the trace. - In the trace as delivered, but not in the mailbox? Look at System health › Postfix queue: a deferred reason like "TLS is required" or "connection refused" means the delivery host is wrong or refuses the gateway. Run Test delivery host on the domain; for M365 check the inbound connector's IP restriction includes the gateway.
- Held for AI? Filter Quarantine by status "Held for AI". If items stay there, the model host is unreachable - see below.
Senders get "451 Temporary ... try again later"
- obsidian-milter is not running - Postfix refuses temporarily rather than deliver unscanned.
sudo systemctl status obsidian-milterand its journal. - ClamAV is down and clamav.fail_action is tempfail. Restart
clamav-daemon; after an upgrade it can take a minute to load signatures. - "Temporary lookup failure" - a Postfix table is missing; run System health › Rebuild Postfix maps (and
sudo newaliasesfor local addresses).
Spamhaus shows 127.255.255.254 or never lists anything
Spamhaus is refusing queries because they arrive through a public resolver. The gateway must resolve through its own unbound (127.0.0.1:5335): systemctl status unbound; dig -p 5335 @127.0.0.1 2.0.0.127.zen.spamhaus.org should answer 127.0.0.x. Re-running the installer repairs the configuration. 127.255.255.255 means you exceeded the public mirrors' free limit - enter a DQS key.
The AI never reviews anything, or is very slow
- System health › AI model says unavailable: check the endpoint, that the gateway can reach TCP 11434 on the model host (firewall), and that the model name matches
ollama list. - "Not loaded": the first request after the model host restarts loads the model (can take a minute or two on CPU).
- Many held messages: lower the load - raise the policies' "Ask the model from score", reduce
llm.max_body_chars, or use async mode. - The AI is only asked about grey-zone, BEC-looking, VIP-name and first-time-sender-with-links mail - clear spam and clean mail skip it by design. The "ai" stage on a message page says why it was skipped.
Legitimate mail is quarantined
- Open the message and read Why. Authentication failures (SPF_FAIL, DMARC_FAIL_*) are the most common cause - the sender's DNS is wrong. Tell them; meanwhile allow-list the sender or domain.
- Release it and click Not spam so Bayes learns.
- If a whole category is too strict, adjust the policy thresholds for that organization.
Your own servers' mail is quarantined as phishing
Cron output, application alerts or scan-to-email from your LAN, flagged SPOOF_INTERNAL_DOMAIN + SPF/DMARC failures: add the LAN range to Settings › Mail flow › Trusted internal networks, then release the held copies.
Spam is getting through
- Open it in Message trace (search the subject) and check its score and rules.
- Report spam - after 50 of each kind Bayes starts contributing.
- Block the sender / domain if it is a persistent source.
- Enter a Spamhaus DQS key if you have not (enables ZRD and HBL, which catch new campaigns).
- Lower the quarantine threshold for the affected organization.
Outbound mail rejected with "Relaying denied"
- The sending server is not in Outbound relay clients, or the domain has "Allow outbound relay" off.
- The domain has a relay key and the message lacks the correct
X-Obsidian-Relay-Keyheader - check the platform's transport rule has the current key.
Users cannot release a message
It is admin-only (virus, malware, phishing) or its verdict is not in the policy's "Users may release their own" list. Release it from the admin console if appropriate.
Digest links say "expired" or do nothing
Links last 7 days and need the confirmation click. If links point to the wrong address, fix public_url in /etc/obsidian/obsidian.toml and restart the services. Digests not arriving at all: check Settings › Quarantine digests is on, the user's "Send quarantine digests" is ticked, and that the digest From address is not blocked by the tenant.
Certificate request fails
- The full certbot log is under Settings › TLS certificate › Last request.
- Cloudflare "Invalid request headers" / 403: the token is wrong or lacks Zone › DNS › Edit on that zone.
- "No TXT record found" / DNS problem: the name is not in a zone the token can edit, or the zone's nameservers are not Cloudflare.
- HTTP method "Connection refused / Timeout": the name does not resolve to the gateway's public IP, or TCP 80 is not forwarded.
- "too many certificates already issued": Let's Encrypt rate limit - use staging while testing and wait before retrying.
- Browsers still show the old certificate: hard-refresh; check System health shows the new expiry.
Sign-in problems
- "Account temporarily locked": wait the lockout time or have an administrator save the user record (clears it).
- Lost two-factor device: an administrator ticks Reset two-factor on the user.
- "is not a protected mailbox" after Microsoft/Google sign-in: the account is not a user in Obsidian - run the connector's user sync.
- Locked-out MSP administrator:
obsidian-admin create-admin you@example.comon the server resets and unlocks. - "Security token expired": the page was open too long; reload and try again.
Connector errors
- M365 401 / invalid_client: client secret expired or wrong - create a new one.
- M365 403: admin consent not granted for Mail.ReadWrite / User.Read.All.
- Google unauthorized_client: domain-wide delegation scopes missing or mistyped.
- Exchange ErrorImpersonateUserDenied: the service account lacks the ApplicationImpersonation role.