Releases
Every tagged release on GitHub appears here automatically. We use semantic date-stamped tags (`v260120` = 2026-01-20) for predictable cadence and so you can correlate releases with the changelog at a glance.
Hermes SEG v260723 — quarantine notifier flood fix
Hermes SEG v260723
> ## Upgrade impact: low — no manual step required
>
> This is a small patch on top of v260722. It ships a
> code-only fix to the quarantine notifier — no schema change, no new
> container or image, no Console Settings / nginx regeneration. The update
> orchestrator deploys the new file and advances build_no automatically.
This release follows v260722.
Fixes
Quarantine notifier no longer floods the queue after a migration/restore (#287)
The near-real-time quarantine notifier (schedule/quarantine_notify.cfm, #180)
runs every 60s and selected messages to notify about using only
msgrcpt.notification_sent = 0 — it had no age filter. Because that column is
a Docker-era addition the legacy database predates, the v260722 legacy→Docker
migration's additive schema-forward added it DEFAULT 0, stamping every restored
historical quarantine row as "never notified." The notifier then treated the
entire quarantine history as brand-new and drained it at 100/min — observed as
49,000+ [Quarantine Notice] messages piling up in the queue. (The v260722
outbound-delivery pause contained the blast so nothing left the box, but the queue
still filled.)
Fixed in two layers so the whole class of bug is closed, not just this migration:
- Systemic backstop —
schedule/quarantine_notify.cfmgained a 7-day recency
guard (msgs.time_num, using the existing msgs_idx_time_num index). The
notifier can no longer notify on messages older than the window regardless of
the flag, so any path that reintroduces old msgrcpt rows at 0 (cross-host
restore/DR rehost, manual DB import, a future migration build) can never flood.
- Fix at the source —
scripts/migrate_legacy_to_docker.shnow marks restored
historical quarantine as already-handled (notification_sent = 1) right after the
schema-forward step, so a fresh migration never generates the backlog in the first
place. Idempotent; warns rather than aborts on failure.
Trade-off of the recency guard: if the notifier (or the box) is down longer than the
window, quarantines that age past 7 days are silently skipped — acceptable for a
courtesy notice.
Already-flooded box? Mark the history handled and clear the stale queue:
docker exec -i hermes_db_server mariadb -u root hermes \
-e "UPDATE msgrcpt SET notification_sent = 1 WHERE ds IN ('B','D') AND notification_sent = 0;"
Confirm the queue is the quarantine notices, then delete ONLY those (by postmaster
sender — NOT postsuper -d ALL):
docker exec hermes_postfix_dkim postqueue -p | head
Upgrading
1. Update the code. Git-based (e.g. Test): git fetch && git reset --hard v260723,
or run the standard orchestrator (scripts/system_update_docker.sh v260723).
2. No schema change — updates/v260723/sql/schema_updates.sql only advances
build_no (the orchestrator's version stamp). The notifier fix takes effect as
soon as the new .cfm is in place.
3. Verify: Mail Queue still shows the Outbound Delivery card; the every-60s
quarantine notifier no longer regenerates notices for old quarantined mail.
---
Issue: #287
(related: #180,
#150). For how
Hermes is released and upgraded, see
docs/install/release-and-update-methodology.md.
Hermes SEG v260722 — Pause Outbound Delivery + migration hardening
Hermes SEG v260722
> ## Upgrade impact: low — no manual step required
>
> This release adds a small, idempotent schema change (the Pause Outbound
> Delivery control) that the update orchestrator applies automatically. There is
> no Console Settings / nginx regeneration step and no new container or image.
> Existing installs upgrade with the normal command and are done.
This release follows v260630.
What's new
Pause / Resume Outbound Delivery (Mail Queue)
The Mail Queue page gains an Outbound Delivery card showing ACTIVE or
PAUSED, with Pause / Resume buttons. Pausing holds all outbound mail in
the queue; resuming releases the hold and flushes the queue.
- The hold is a first-class
defer_transportsparameters directive (not a bare
postconf), so it survives every subsequent Save & Apply — including the SPF/
DKIM/DMARC saves — instead of being silently un-paused by the next config render.
- Default is normal delivery (
enabled=0); existing behavior is unchanged until
an administrator explicitly pauses.
Fixes
Legacy → Docker migration hardening (#150)
scripts/migrate_legacy_to_docker.sh was hardened extensively against real
build-240815 backups. Each of these was a live failure found by running the
migration end-to-end:
- Safe-cutover hold — a freshly migrated box now comes up with outbound
HELD, so it cannot blast the restored quarantine's stale notifications to real
recipients. A completion banner and a Release Outbound Delivery checklist step
make the hold explicit. (This is the migration side of the Pause control above.)
- Postfix directives resolved after restore — backfills
parameters.parent_name
and merges in the baseline parameters seed rows the legacy DB predates, so
SPF/DKIM/DMARC Save & Apply no longer fails with bad numerical configuration.
- Mail flows after restore — compiles the postfix
hash:maps the live config
references (was smtpd-451-rejecting every message) and chowns the restored
quarantine to the container's amavis uid (was deferring on Permission denied).
- Strict-mode safe & fail-loud — the schema-forward step runs cleanly under
MariaDB 11.4 strict sql_mode and reports a clear error instead of aborting
silently on failure.
DKIM key generation on fresh installs (#285)
Fresh installs of v260612 / v260628 / v260630 failed to generate DKIM keys
(opendkim-genkey … chdir(): No such file) because dkim/keys/ was absent in a
fresh clone. Fixed for fresh clones, fresh installs, and already-deployed hosts.
Postfix master.cf re-injection (public snapshot drift)
The public repo's master.cf snapshot predated #232 (loopback-bound :10026,
no_milters), which broke CipherMail cross-container re-injection and disabled
post-MIME-rebuild DKIM re-signing on fresh installs / migrations. Restored to the
#232 design (matches production). Installs built before the public repo already
had the correct file and are unaffected.
Repository / tooling
- Removed hardcoded install-root paths repo-wide (scripts self-locate; admin pages
use the live Docker directory), so installs rooted at any path work — including two
admin pages that had printed a wrong path in copy-pasteable instructions.
- Added a pre-commit guard (Layer 4) that blocks hardcoded install roots in staged
code, plus a fresh-install smoke-test path fix (#284).
Upgrading
1. Update the code. Git-based (e.g. Test): git fetch && git reset --hard v260722,
or run the standard orchestrator (scripts/system_update_docker.sh v260722).
2. Schema applies automatically — updates/v260722/sql/schema_updates.sql adds the
defer_transports directive rows (idempotent) and advances build_no.
3. Verify: Mail Queue → the Outbound Delivery card shows ACTIVE.
---
Issues: #150,
#284,
#285. For how Hermes
is released and upgraded, see
docs/install/release-and-update-methodology.md.
Hermes SEG v260630
Hermes SEG v260630
> ## ⚠️ ACTION REQUIRED AFTER UPGRADING
>
> This release adds a public landing page at the console root (/) and moves
> the login portal to /auth. These changes live in the nginx templates, so
> existing installs must regenerate their nginx configuration to activate them.
>
> ➜ After upgrading, an administrator must open
> System → Console Settings and click _Save & Apply Settings_ once.
> No fields need to change — saving re-renders both nginx configs from the updated
> templates and reloads nginx.
>
> Nothing breaks if you skip it — the console keeps its current behavior — but
> the new landing page and login routing will not appear until you do.
>
> Behavioral change once regenerated: visiting the bare console URL
> (https://<your-host>/) now shows a landing page with links to the User and
> Admin consoles, instead of going straight to the Authelia login. The login screen
> moves to /auth. Direct links to /admin, /users, /nc/, /ciphermail, etc.
> are unchanged and continue to work exactly as before.
This release follows v260628.
What's new
Public landing page at the console root (#283)
Browsing the bare console hostname now lands on a clean splash page instead of an
immediate login prompt:
- User Console is the prominent call-to-action — for mailbox and relay users
to review quarantined mail, manage their account & security, and (mailbox users)
access webmail.
- Admin Console is a deliberately secondary link for administrators.
Login is functionally unchanged — it simply moves to /auth so the root URL can host
the landing page. Every existing entry point (/admin, /users, /nc/, /ciphermail)
behaves exactly as before.
Friendlier direct /nc/ (webmail) access
Typing the Nextcloud URL (/nc/) directly while logged out previously dead-ended on a
Nextcloud "Page not found" (a known OIDC URL-mangling quirk when the session cookie
isn't primed first). Cold /nc/ visits are now routed to the User Console, where the
Webmail link opens Nextcloud cleanly via the normal primed flow.
Upgrading
This release ships no schema changes and no new containers — but it does
require the nginx regeneration step from the top of this document.
1. Update the code. Git-based (e.g. Test): git fetch && git reset --hard <tag>,
or run the standard orchestrator (scripts/system_update_docker.sh).
2. Regenerate nginx (required): System → Console Settings → Save & Apply. This re-renders
Settingshermes-ssl.conf + auth.conf from the updated
templates and reloads nginx.
3. Verify: https://<host>/ → landing page · /admin + /users → /auth login ·
/nc/ (logged out) → User Console.
> Why a manual step? Hermes renders its live nginx config from templates via the
> Console Settings / host-configuration flow; routine upgrades do not currently
> re-render it automatically. A future release will fold this into the post-upgrade
> hook (schedule/post_upgrade.cfm) so the step becomes automatic.
---
Issue: #283. For how Hermes is released and upgraded, see
docs/install/release-and-update-methodology.md.
Hermes SEG v260628 — Let's Encrypt in Community Edition
Hermes SEG v260628
> Maintenance + feature release. Headline change: Let's Encrypt / ACME
> certificate management is now available in Community Edition — automated
> issuance and renewal are no longer Pro-gated. Plus documentation refinements
> and a published project changelog. No schema changes; no mandatory action for
> existing installs.
This release follows v260612, the initial public Docker
release. It is a small, low-risk update — primarily an edition-gating change for
Let's Encrypt and a batch of documentation improvements.
What's new
Let's Encrypt / ACME is now Community (#282)
The entire Let's Encrypt / ACME certificate gate has moved to all editions:
- System Certificates → Request ACME Certificate — issue and auto-renew a free
Let's Encrypt certificate for the console / mail host. Previously Pro-only.
- Email Server → Domains → Auto-managed (Let's Encrypt) — per-mailbox-domain
SAN certificates with automatic DNS/IP validation, issuance, and renewal.
Previously Pro-only.
Free, automated TLS is table-stakes for a self-hosted mail platform, so it now ships
to everyone. The certbot engine, SAN validator, and SMTP-SNI generator all run on
Community. The manual CSR + import path remains for those who prefer a commercial CA.
Existing Pro installations are unaffected — they already had this functionality;
nothing is removed or downgraded.
Documentation & housekeeping
- Added
CHANGELOG.mdin Keep a Changelog format. - README refinements: corrected container count, refreshed hero descriptor and the
Link Guard row, removed the Pro pricing badge.
- Get-started guide: added admin-email review, Antispam Maintenance (Pyzor / Razor /
Bayes), Barracuda registration, and CipherMail console-password steps.
- Fixed the System Users edit-modal Access-Control-Policy documentation link.
Upgrading
This is a drop-in update — there are no schema changes and no new containers.
- Docker (git-based, e.g. Test):
git fetch && git reset --hard <tag>then redeploy
the web files, or run the standard update orchestrator
(scripts/system_update_docker.sh).
- Pro Edition: the Pro template fingerprint changed in this release (two
fingerprinted templates were edited for the ACME gating). The validation server's
manifest for v260628 has been published, so upgrading Pro boxes validate normally —
no action required. Boxes that stay on v260612 also continue to validate against
their existing manifest.
Edition matrix (certificates)
| Capability | Community | Pro |
| --- | :---: | :---: |
| Import 3rd-party certificate / Generate CSR | ✅ | ✅ |
| Request ACME (Let's Encrypt) — console cert | ✅ (new) | ✅ |
| Auto-managed SAN certs per mailbox domain | ✅ (new) | ✅ |
---
Issue: #282.
For how Hermes is released and upgraded, see
docs/install/release-and-update-methodology.md.
Hermes SEG v260612 — Initial Public Docker Release
Hermes SEG v260612 — Initial Public Docker Release
> Early-adopter release. v260612 is the first public release of Hermes SEG's
> Docker era — feature-complete and validated end-to-end on our DEV and Test
> environments. If you run a production gateway, stand v260612 up in parallel and
> put it through your own acceptance tests before cutting over — send and receive
> mail through it, exercise your relay flows, quarantine release, DKIM/SPF/DMARC
> alignment, and your backup/restore plan. Field feedback from early adopters
> directly shapes the next release.
This is the first tagged public release of Hermes SEG as a Docker product. Hermes
shipped for years as a bare-metal Ubuntu install — a custom installer, host-level
Postfix / Amavis / Dovecot / Lucee / OpenLDAP, host-managed systemd services.
v260612 marks the Dockerized rewrite as a coherent, shipping product: a 19-container
stack orchestrated by Docker Compose, a five-tier storage topology, a single-command
update orchestrator, Authelia SSO across the admin console + user portal + Nextcloud,
time-of-click link protection, Docker-aware backup / disaster-recovery tooling, and a
release pipeline built on GitHub Releases and ghcr.io.
This release is fresh-install only — legacy-to-Docker migration tooling exists in
skeletal form but is not yet end-to-end Docker-aware (see Migrating from legacy).
Summary
- Early-adopter release — feature-complete and validated on our infrastructure;
exercise your real mail flow in parallel before cutting a production gateway over.
- Full Docker stack: 19 containers, single
docker compose up -d, all services run
in containers (no host-level mail stack). Replaces the legacy bare-metal installer.
- Time-of-click Link Guard (Pro): inbound links are rewritten through a Hermes
redirect and checked for reputation at click time — closing the gap where a link
is weaponized after delivery.
- Docker-aware backup, disaster recovery & re-host: hot backups, cross-host restore
with storage-topology remap and credential reconciliation, and a host-identity rewire.
- Five-tier storage topology: Config / Data / Archive / Vmail / Nextcloud, each
independently mountable so you put each tier on the right kind of disk.
- Single-command update orchestrator:
scripts/system_update_docker.shruns a
5-phase pipeline (git pull → image pull → per-release artifacts → finalize →
post-upgrade hook), auto-resolves the latest tag via the GitHub Releases API, and
auto-runs occ upgrade + rehydrates Nextcloud apps on NCVERSION bumps.
- Authelia SSO: unified MFA (TOTP / WebAuthn / Duo Push) across admin console, user
portal, and Nextcloud (via OIDC).
- Nextcloud integrated: webmail, file sync, calendars (CalDAV), and contacts
(CardDAV) ship with the stack, pre-provisioned on first OIDC login.
- GitHub-distributed: images at
ghcr.io/deeztek/hermes-<service>:<tag>; releases on
GitHub; code on GitLab for dev.
---
What's included
Link Guard — time-of-click safe links (Pro Edition)
Inbound email links are rewritten to route through a Hermes-hosted redirect, and the
destination's reputation is checked at the moment the user clicks — closing the gap
where a link is weaponized after delivery.
- Dedicated container
hermes_linkguard(self-contained Python service) runs in the
compose stack. The body milter rewrites links to a UI-configured base URL pointing at
the in-stack /lg/ endpoint. (Running the container off-box on a separate host is
deferred to a later release.)
- Layered verdict pipeline: heuristics (lookalike / punycode / IP-literal /
@/
URL-shortener / excess-subdomain) + open-redirect detection + free local feeds
(URLhaus, OpenPhish) + an operator-managed list of abused cloud-storage / redirector
hosts + optional Google Safe Browsing / VirusTotal + optional guarded
redirect-chain following — each reputation source individually enabled/disabled from
one toggle list, behind a verdict cache.
- Admin-configured per-tier actions: clean → redirect; suspicious → warn / allow /
block; malicious → block / block-with-override / warn.
- Protected-domain picker: choose from the recipient domains the box actually hosts
(or _default for all); URL allow/block rules with input validation.
- Outbound restoration (default ON): when a user replies to or forwards a protected
message, the wrappers are unwrapped on the way out, so external recipients get clean
original links.
- Rotatable HMAC signing key with a current+previous overlap window, so links already
in mailboxes keep working through a rotation.
- Every link is protected regardless of length — rewritten links use a compact
server-side reference, so no link is skipped for being too long.
- Diagnostics in the admin UI: a Check a URL tool shows the verdict, which layer
decided it, and the resolved host; a Recent activity view lists recent click
evaluations (host only, for privacy).
- New Pro-gated admin page: Email Policies → Link Guard.
Mail flow
- Outbound disclaimers (Pro): per-domain / per-address disclaimer templates, applied
by the dedicated hermes_body_milter Python container in the Postfix milter chain.
- Personal signatures (Community): rich-HTML per-user signatures with a Quill editor,
template gallery, tables, and social-media icons, rendered on every outbound message.
- Organizational signatures (Pro): admin-managed per-domain signature templates with
placeholder substitution (name / title / phone / email / department / org).
- External Sender Banner (Community): inbound mail from outside the org gets a visual
banner injected by hermes_body_milter.
- CID inline image support in body modifiers: signatures and disclaimers can embed
inline images that survive multipart/related wrapping and DKIM signing.
- OpenARC integration:
hermes_openarcdoes ARC chain signing on outbound and
verification on inbound for forwarding-trust preservation.
- Multi-instance OpenDKIM: separate signer and verifier instances so outbound-sign and
inbound-verify behave independently without config bleed.
Mailbox hosting
- Email Server section — Domains / Mailboxes / Aliases / Mailbox Rules with a full
admin UI on top of Dovecot 2.4.
- Dovecot 2.4 custom Ubuntu-based image, replacing 2.3.x (breaking config/plugin/ACL
changes absorbed).
- Shared mailboxes + user-managed folder sharing (Dovecot ACL / vfile), admin and user
UIs, Rebuild ACL Files action.
- Sieve rules: admin global rules + per-user filters, on an isolated
dovecot_sieve
volume.
- Vacation auto-reply with per-user date scoping and per-mailbox timezone.
- BCC Maps UI: sender-BCC and recipient-BCC management.
- Mobile device setup wizard: "Set Up Your Devices" walkthroughs, signed iOS
.mobileconfig (IMAP/SMTP/CalDAV/CardDAV), QR-gated download.
- App Passwords: unified credential system for Dovecot IMAP/SMTP + Nextcloud DAV.
- Email autoconfiguration: autodiscover + autoconfig endpoints from SNI certificates;
CalDAV/CardDAV autodiscovery.
Nextcloud integration
- Webmail + Files + Calendar + Contacts out of the box, SSO via Authelia OIDC.
user_oidc-based integration with a pre-provisioning pipeline that creates NC
accounts on first login, plus NC Mail profiles so users land in working webmail.
- External Sites integration: a "User Console" link in the NC top menu points back to
the Hermes user portal, kept in sync with console-hostname changes.
- Vendor-driven version management:
NCVERSIONis Hermes-release-managed; each bump
ships only after passing the NC integration check on a Test box.
- Maintenance Mode card in System Settings for NC-native admin access (local
username/password + TOTP) independent of SSO.
Operations: backup, disaster recovery & upgrades
- Docker-aware backup & restore: hot (zero-downtime) backups, scoped/slim storage
tiers, a directory-style backup format, streamed restore, disk-space pre-checks, and
email notifications (--notify-email, --notify-on-success).
- Cross-host disaster recovery + re-host: restore a backup onto fresh hardware —
system_restore.sh auto-remaps the storage topology when it differs from the source,
reconciles per-service DB credentials (including Nextcloud's config.php) to the
target host's own creds/, and detects a cross-host restore and offers to run
system_rehost.sh, which rewires host identity (console hostname, regenerated service
configs, Nextcloud OIDC discovery + end-session URLs). A version-match gate guards
against accidental cross-version restores. After any restore, follow the
Post-Restore Steps.
- Self-healing update orchestrator:
system_update_docker.shself-heals tracked-file
runtime/restore drift (saves a recovery patch, then git checkout -f) instead of
refusing, has a pre-container pre-scripts/ hook + self-re-exec, and only restarts what
changed.
- Let's Encrypt cert store in backups: ACME certs (
config/certbot/conf/,
symlink-preserving) survive a cross-host restore; the nginx vhost generator falls back
to the bootstrap cert when a domain's LE cert isn't present, so a config regen can't
emit a missing-cert path and crash nginx.
Security & administration
- Authelia SSO with an LDAP backend; TOTP / WebAuthn / Duo Push across console,
portal, and Nextcloud.
- Per-domain MFA enforcement with per-mailbox override; app passwords for clients that
can't do MFA.
- Pro Edition licensing: Pro features require a valid license to remain active; if a
license expires or is revoked, Pro functionality is disabled until restored, and free
(Community) functionality is unaffected. Validation hits validate.hermesseg.io over
HTTPS and is cached locally so Pro stays available during brief network outages.
- Content filtering: Amavis + SpamAssassin + ClamAV, custom message rules, per-rule
score overrides, custom file-type rules, quarantine + release.
- Encryption: CipherMail-based S/MIME + PGP, PDF encryption / portal reply.
---
Editions: Community vs Pro
Community Edition is fully functional and needs no license. Pro Edition unlocks seven
advanced features:
| Pro Feature | What it does |
|---|---|
| Let's Encrypt (ACME) automation | Automated issuance + renewal of free Let's Encrypt certs for the console and per-domain. Community can still request/use LE certs manually. |
| Email disclaimers | Per-domain outbound disclaimer templates at the milter level. |
| Organizational signatures | Centrally-managed per-domain employee signatures with placeholder substitution. Community has Personal Signatures (per-user) only. |
| Intrusion Prevention (IPS) | Web UI for Fail2ban jails, ban thresholds, whitelists, and a real-time view of active bans. The hermes_fail2ban container runs on all editions; Pro gates the UI + which jails are active. |
| Console firewall | Web UI for the host firewall protecting the admin console (port allowlisting, source-IP restriction). |
| LDAP RemoteAuth | Per-domain pass-through authentication to external LDAP / Active Directory; auto-provisions mailboxes on first successful login; supports STARTTLS and LDAPS. |
| Link Guard (safe links) | Time-of-click URL protection for inbound mail (see above). |
---
Installing
sudo git clone https://github.com/deeztek/Hermes-Secure-Email-Gateway.git
cd Hermes-Secure-Email-Gateway
sudo ./scripts/install_hermes_docker.sh
The installer runs in a single session, 10–30 minutes (mostly image downloads). It will:
1. Display the Pro EULA and ask for acceptance.
2. Prompt for mail server hostname (FQDN), console address, host IP, upstream DNS
forwarders, and the four storage mount paths.
3. Generate all secrets and per-service config files (LDAP secrets, DB passwords, Authelia
session keys, OIDC keypair, self-signed bootstrap cert, Docker secret files).
4. Write DATA_MOUNT / ARCHIVE_MOUNT / VMAIL_MOUNT / FILES_MOUNT into .env.
5. Run docker compose up -d --build to pull images and start the stack.
6. Initialize all databases (Hermes, Authelia, Nextcloud, OpenDMARC, CipherMail, Syslog),
populate the LDAP base structure, create the initial admin user, and pre-provision the
Nextcloud admin.
7. Print an installation summary with the admin console URL and one-time admin credentials.
The installer is idempotent — re-running it on an already-installed system skips
completed work via state guards. Run --help for the full flag list.
After install you have:
- Admin Console:
https://<console-host>/admin/ - User Portal:
https://<console-host>/users/ - Nextcloud:
https://<console-host>/nc/
The bootstrap admin lands you in a working console, but mail won't flow until you
complete the minimum first-run config in
docs/install/get-started-docker.md — first domain,
relay networks, first recipient or mailbox, DNS records. The dashboard surfaces two nudges
(Placeholder hostname, Self-signed cert) that auto-clear when satisfied.
Configuring Link Guard (optional, Pro)
Link Guard is dormant until enabled — safe to install ahead of configuring it.
1. Email Policies → Link Guard (Pro Edition).
2. Set the Redirect base URL (e.g. https://<console-host>/lg/).
3. Add protected recipient domains (or _default for all).
4. Choose per-tier actions; toggle reputation sources (URLhaus/OpenPhish free;
Google Safe Browsing / VirusTotal need API keys); optionally add URL allow/block
rules.
5. Enable Link Guard and Save & Reload. The first save generates the signing keys
and pushes config to the milter and the container.
6. Send a test inbound message and confirm links resolve correctly at click time.
---
System requirements
| Resource | Requirement |
|---|---|
| CPU | 4 vCPUs minimum; more for higher mail volume |
| RAM | 8 GB minimum, 16 GB+ recommended for production |
| Disk | See below |
Hermes splits storage across five independent tiers, so disk sizing depends on your
layout:
- Production (each tier on its own disk): ~120 GB for the OS / Config disk (OS, Docker
engine, the full Hermes image set + running containers, the repo, install/service logs),
plus a dedicated disk per data tier — Data, Archive, Vmail, Nextcloud —
each sized to your mail and file storage needs. The tiers have deliberately different I/O
and growth profiles, so isolating them lets you match disk to workload and expand each
independently.
- Small or test (everything on one disk): point Archive, Vmail, and Nextcloud at the
same path as Data; ~275 GB total (thin-provisioned) is a comfortable starting point.
See docs/install/storage-topology.md for the
canonical reference.
| Tier | Default path | Contents | Profile |
|---|---|---|---|
| 1. Config | install root (implicit) | Repo working tree, config/ subtrees, secrets, .env | Fast SSD, modest size |
| 2. Data | /mnt/data | All databases, Amavis state, ClamAV signatures, Lucee home, Sieve scripts, all logs, OpenDMARC, Postfix queue | Fast SSD; DB growth + log retention |
| 3. Archive | /mnt/archive | Amavis quarantine archive | Cheap bulk; retention × inflow |
| 4. Vmail | /mnt/vmail | Dovecot mailboxes | Cheap bulk; users × quota |
| 5. Nextcloud | /mnt/files | Nextcloud app + user files + NC Redis cache | Cheap bulk; user file storage |
---
Migrating from legacy
Honest status: a skeletal migration script exists at
scripts/migrate_legacy_to_docker.sh (restores
legacy DBs into the Docker MariaDB, creates the Docker-only DBs, copies legacy config
trees). It does not yet auto-detect the legacy 3-tier storage layout or migrate
Authelia users to LDAP automatically. Recommendation: treat v260612 as fresh-install
only. If you run a production legacy install, run a parallel Docker install on a second
host and evaluate before cutting over by hand. The legacy bare-metal system_backup.sh /
system_restore.sh scripts are not safe to run against a Docker install.
Known limitations / things you'll want to know
- Post-upgrade browser hard-refresh. After an upgrade that bumps
NCVERSIONor changes
admin web assets, hard-refresh open admin/Nextcloud tabs (Ctrl-Shift-R / Cmd-Shift-R) —
the browser often serves the pre-upgrade CSS/JS bundle.
- No CLI recovery path for admin lockout yet. If you misconfigure the console hostname
or host IP and lock yourself out of the admin UI, recover from a hypervisor/VM snapshot;
a menu-driven scripts/hermes-cli.sh recovery tool is planned for a future release.
- Docker subnet is pinned.
IPV4SUBNET(default172.16.32) is referenced across 15+
config files; do not change it after install — there is no current template path to
propagate the change everywhere. Dynamic subnet support is on the backlog.
- Vendored CipherMail binary. The vendored CipherMail
.deb/.tar.xzfiles exceed
GitHub's 50 MB size-warning threshold. Functional, flagged for cleanup.
- Nextcloud admin via Maintenance Mode. NC admin tasks needing local-NC auth go through
System → Settings → Nextcloud Maintenance Mode, not the SSO path.
Repository / distribution
- Code: GitLab —
https://gitlab.deeztek.com/dedwards/hermes-seg-docker-gl.git - Distribution: GitHub —
https://github.com/deeztek/Hermes-Secure-Email-Gateway - Container images: GitHub Container Registry —
ghcr.io/deeztek/hermes-<service>:<tag> - Issues + Releases: GitHub
- Documentation: docs.deeztek.com
See docs/install/release-and-update-methodology.md
for the full release/upgrade methodology.
---
Welcome to the Docker era of Hermes SEG.
Hermes SEG build-240815
Historical pre-Docker release (Ubuntu bare-metal lineage), originally released 2024-09-30. Browse this point in the project's history on the legacy branch. _Backfilled; GitHub stamps the publish date as today._
Hermes SEG build-231130
Historical pre-Docker release (Ubuntu bare-metal lineage), originally released 2024-08-16. Browse this point in the project's history on the legacy branch. _Backfilled; GitHub stamps the publish date as today._
Hermes SEG build-221211
Historical pre-Docker release (Ubuntu bare-metal lineage), originally released 2023-05-20. Browse this point in the project's history on the legacy branch. _Backfilled; GitHub stamps the publish date as today._
Hermes SEG build-220410
Historical pre-Docker release (Ubuntu bare-metal lineage), originally released 2022-06-05. Browse this point in the project's history on the legacy branch. _Backfilled; GitHub stamps the publish date as today._
Hermes SEG build-220203
Historical pre-Docker release (Ubuntu bare-metal lineage), originally released 2022-04-03. Browse this point in the project's history on the legacy branch. _Backfilled; GitHub stamps the publish date as today._
