Stargate Docker deployment¶
Prerequisites¶
Server Requirements:
Please refer to Recommended Requirements
- Docker will be installed automatically if missing
- Ensure there is an internet connection on the machine where you are installing Stargate services
- Ensure traffic is properly configured to reach the Stargate instance
Step 1: Configure Customer Settings¶
Tip
You can clone our repository with all data and sample configs inside with a command:
If you do not have git installed, you can always get an archive with all files inside. Download it via the following link. Download as ZIP
The installer creates customer-config.sh automatically from the bundled template on first run, so a fresh install needs no manual configuration. If you prefer to create it yourself, copy the template:
You do not need to edit it - every value is either auto-detected or configured later via the dashboard:
| Setting | How it is set |
|---|---|
SERVER_STATIC_IP | Auto-detected from the server's primary network interface. |
CUSTOMER_NAME | Defaults to the system hostname. |
DEPLOYMENT_NAME | Derived from CUSTOMER_NAME (used in log labels and the Alloy hostname). |
Passwords & keys (POSTGRES_PASSWORD, S3_SECRET_KEY, VAULT_TOKEN, WG_PRIVATE_KEY) | Generated securely on first run and saved back to customer-config.sh. |
Mail domains, the mail hostname, S/MIME certificates, and WireGuard peers are all configured at runtime via the dashboard after the stack is up - they are not part of customer-config.sh.
Behind NAT or a floating IP?
Auto-detection uses the IP of the server's primary interface. If your server is reached on a different public or floating IP (common with NAT), set SERVER_STATIC_IP to that public IP in customer-config.sh before installing, so the dashboard and Keycloak login URLs point at the reachable address. Otherwise leave it empty.
Auto-derived settings — leave empty unless you need to override:
| Setting | Derived from | Default |
|---|---|---|
MXENGINE_PUBLIC_ADDRESS | SERVER_STATIC_IP | http://<SERVER_STATIC_IP>:8084 |
S/MIME certificate settings:
| Setting | Description | Default |
|---|---|---|
CERT_CA_IRISAGENT_DOMAIN | CA domain for certificate issuance via WireGuard tunnel | hintest.ch |
Note
WireGuard peer setup is performed at runtime via the dashboard (/installation page). Peer details are configured per deployment after the stack is up - they are not part of customer-config.sh.
WireGuard local settings (typically left at defaults):
| Setting | Default | Description |
|---|---|---|
WG_PRIVATE_KEY | (auto-generated) | Generated by IRISAgent on first run, then saved to customer-config.sh |
WG_LOCAL_IP | SERVER_STATIC_IP | Auto-derived. Only override if you need a different tunnel address. |
WG_INTERFACE_PORT | 19818 | WireGuard tunnel port (both TCP and UDP are exposed) |
WG_TRANSPORT_MODE | tcp | Transport protocol: tcp (default, works through most firewalls) or udp |
Optional settings (have sensible defaults):
| Setting | Default | Description |
|---|---|---|
POSTGRES_PASSWORD | (auto-generated) | Auto-generated 24-character random password if empty |
S3_SECRET_KEY | (auto-generated) | S3 secret key for object storage |
OUTBOUND_SEALER_MX_DOMAIN | hintest.ch | Sealer MX domain for outbound seal delivery |
POLICY_SYNC_REPO_URL | GitHub HIN Stargate policies | Git repo URL for OPA/Rego policy sync |
LOKI_URL | (unset) | Loki endpoint for centralized log shipping (e.g. https://loki.example.com) |
Auto-generated (do not set manually):
VAULT_TOKEN— Generated by Vault during first initialization, saved tocustomer-config.shWG_PRIVATE_KEY— Generated by IRISAgent on first run, saved tocustomer-config.sh
Step 2: Deploy to a Server¶
Tip
You can clone our repository with all data and sample configs inside with a command:
git clone https://github.com/Health-Info-Net-AG/Stargate-deployment.git && \
cd Stargate-deployment-main
If you do not have git installed, you can always get an archive with all files inside and extract it:
Manually copy files to the server
SSH to server
Create customer config from template and fill in required settings (see Step 1)
cp customer-config-prod.example.sh customer-config.sh
nano customer-config.sh # Fill in required settings (see Step 1)
Run installation
Step 3: What Install Does¶
The install script (install.sh) performs the following steps:
- Check dependencies — Detects Docker, Docker Compose, and
jq. If missing, installs them automatically (supports Ubuntu/Debian, RHEL/AlmaLinux/Rocky). - Load and validate
customer-config.sh— Checks required fields (SERVER_STATIC_IP,CUSTOMER_NAME,DEPLOYMENT_NAME). Auto-derives optional fields (MXEngine URL, etc.). - Generate
.envfrom customer config — Auto-generates passwords if not set. - Start all services via Docker Compose (infrastructure + applications).
- Initialize Vault — The
vault-initcontainer initializes, unseals, and creates KV-v2 secret mounts. Optionally writes the WireGuard private key to Vault. - Save Vault keys to
secrets/vault-keys.jsonand update.envwith the root token. The token is also saved tocustomer-config.shfor persistence across VM recreations. - Restart application services to pick up the Vault token.
- Save WireGuard private key to
customer-config.sh— extracted from Vault after IRISAgent generates it. - Set up daily backup cron job (runs at 2:00 AM).
After install completes, the stack is running but no mail domains, S/MIME certificate, or WireGuard peer are set up yet. Continue with Step 4: Onboard via the dashboard.
Step 4: Onboard via the dashboard¶
After installation, complete onboarding through the dashboard at https://<SERVER_STATIC_IP>. The dashboard walks you through three pages in order:
/installation — WireGuard peer setup¶
Performs the nonce/HIN handshake to establish a WireGuard peer connection, and saves the resulting WireGuard configuration to the IRISAgent service.
/onboarding — S/MIME certificate¶
Generates the S/MIME signing key and CSR via the smimekeys service and submits the CSR to the CA over the now-established WireGuard tunnel. (This replaces the previous script-based certificate flow.)
/mail — Mail domains and relay configuration¶
Submits hostname and the list of relay domains to the mtaconf service over its REST API. The daemon applies the configuration to Stalwart without restarting the container.
Adding or changing domains later
Re-open the /mail page in the dashboard, edit the domain list, and submit. The daemon applies the change at runtime - no script invocation, no .env edit, no service restart needed.
Step 5: WireGuard Peer Registration¶
The S/MIME CSR submission on /onboarding will fail if your Stargate instance is not yet registered as a WireGuard peer on the HIN CA side. This is the most common issue during initial setup.
The dashboard's /installation page handles the WireGuard peer registration automatically via the nonce/HIN handshake. If the automatic registration fails, manual registration can be done by providing the following values to HIN:
- WireGuard public key — extract from irisagent logs:
DEPLOYMENT_NAME— from yourcustomer-config.shSERVER_STATIC_IP— the public IP of your Stargate serverWG_INTERFACE_PORT— only if you changed it from the default19818
After peer registration is confirmed:
Re-run the /onboarding page in the dashboard to regenerate the CSR and submit it through the now-up tunnel.
To verify the tunnel before requesting the certificate:
Restart just irisagent
Check for successful WireGuard handshake
Tip
Check your firewall: Port 19818/TCP must be open both directions inbound and outbound on the Stargate server.
Step 6: Post-Onboarding Recommendations¶
Once the certificate is issued and mail is flowing, two configuration items are strongly recommended for any production deployment. Skipping them does not break encryption, but it will degrade your sender reputation, cause "we can't verify the sender" warnings in Outlook/Gmail, and can eventually lead to outbound mail being blocklisted.
Step 6.1 SPF / DKIM / DMARC for sender domains¶
The Stargate sends mail from its own public IP on behalf of your users. Without proper DNS authentication records, recipients will see "we can't verify this sender" warnings and may reject the mail.
For complete instructions on configuring SPF, DKIM, DMARC, and PTR records, see the DNS Setup Guide.
At minimum, for each domain you route through the Stargate:
- SPF: add
ip4:<STARGATE_IP>to the domain's TXT record - DMARC: publish
v=DMARC1; p=noneat_dmarc.<YOUR_DOMAIN> - PTR: set reverse DNS for the Stargate IP to match
MAIL_HOSTNAME
Step 6.2 Relay outbound mail back through your mail platform (recommended for M365 / Exchange Online)¶
By default, after the Stargate signs/encrypts an outbound mail it delivers directly to the recipient's MX. This works, but the connecting IP is your Stargate's IP - and unless that IP has years of warm reputation, it can end up on third-party blocklists (e.g. Barracuda, Abusix), causing intermittent delivery failures.
The recommended pattern is to send the signed mail back through your M365 / Exchange tenant so that the final hop to the internet is Microsoft's well-reputed infrastructure. The Stargate still signs and policy-checks every message; only the last hop changes. This mirrors the original HIN MGW "Send to MX" connector pattern.
Stargate side — per-domain relay¶
Configure per-domain relay through the dashboard's /mail page. Each domain can be mapped to its own M365 / Exchange inbound endpoint; the dashboard sends the mapping to mtaconf's REST API and Stalwart is reconfigured at runtime.
After mxengine signs the mail, Stalwart will hand it back to your tenant on port 25 with TLS instead of delivering directly to the recipient's MX. See Exchange-integration.md for the full per-domain syntax.
M365 / Exchange Online side¶
You essentially recreate the same connector + transport rule set as the old HIN MGW (the original HIN MGW O365 manual is the reference - the same five rules apply). The minimum is:
- Inbound connector - accept mail from the Stargate, identified by TLS certificate (the cert subject must match a domain accepted in your tenant). A self-signed cert on the Stargate will be rejected by this connector - use a valid CA-issued cert (Let's Encrypt is fine).
- Outbound connector "Send to MX" - delivers to the recipient's MX, activated only by transport rule.
- Transport rule
set_header- tags outbound mail with a header likeoutgoing: outgoing_<domain>before it leaves O365 the first time, so the return trip can recognize it. - Transport rule
outgoing_to_mx- matches theoutgoing_<domain>header on mail coming back from the Stargate and routes it via the "Send to MX" connector. - Transport rule
mgw_bypass_antispam- bypasses spam filtering on mail coming back from the Stargate.
mxengine does not strip arbitrary headers, so the outgoing_<domain> tag set by set_header survives the round-trip and triggers outgoing_to_mx correctly.
Why this pattern matters
With the relay-back configuration, the public sender to the internet is Microsoft. Combined with correct SPF/DKIM/DMARC (section 6.1), recipients see a Microsoft IP with spf=pass and dkim=pass aligned to your domain - which is the cleanest reputation profile you can give them.
See Exchange-integration.md for full step-by-step instructions including screenshots.
Subsequent Starts (after reboot)¶
The installer enables a stargate systemd unit, so the stack starts automatically on boot. To start it manually:
This runs start.sh, which:
- Starts infrastructure services
- Unseals Vault using stored keys
- Starts application services
(./scripts/start.sh still works directly if you prefer.)
Stop Services¶
(or ./scripts/stop.sh directly)
This stops containers but preserves all data.
Data Persistence¶
All data is stored in Docker volumes and persists across restarts.
| Service | Volume | Data |
|---|---|---|
| PostgreSQL | postgres_data | All databases (smimekeys, policy, irisagent, mxengine) |
| Vault | vault_data | Encryption keys, secrets, S/MIME keys |
| SeaweedFS | seaweedfs_data | Object storage (messages, attachments) |
| Stalwart | stalwart_data | Mail server state |
Safe Operations (data preserved)¶
Stop and start:
Or using the scripts directly:
Do not use docker compose commands directly
Always use systemctl or the provided scripts (start.sh / stop.sh) to manage the deployment. Running docker compose up, docker compose down, or docker compose restart directly will not unseal Vault, leaving dependent services unable to start. The start.sh script handles the Vault unseal procedure automatically.
Vault Sealing Behavior¶
Vault becomes sealed when its container restarts. This is a security feature.
The start.sh script (and the systemd service) automatically unseal Vault using the keys stored in secrets/vault-keys.json. This is why you must always use the provided scripts or systemd service to manage the stack.
Destructive Operations (data deleted)¶
Warning
These commands DELETE ALL DATA - use with caution!
You can only restore data if you perform backup operations before and save the backup in a safe place.
Danger
Delete everything (volumes, secrets, config)
Or manually remove volumes. The -v flag removes volumes
Scripts Reference¶
| Script | Purpose |
|---|---|
install.sh | First-time installation (Docker, Vault). Domain/cert/peer setup happens in the dashboard afterwards. |
update.sh | Update service images (preserves Vault token, recreates containers) |
start.sh | Start services and unseal Vault |
stop.sh | Stop containers (data preserved) |
backup.sh | Full backup (database, Vault keys, config, certificates) |
restore.sh | Restore from backup archive (works on fresh machine) |
purge.sh | |
health-check.sh | Comprehensive health check of all services (exit 0 = healthy, 1 = failures) |
init-vault.sh | Vault initialization (used by vault-init container, not called directly) |
init-keycloak.sh | Keycloak admin password setup (used by keycloak-init container, not called directly) |
gather-app-versions.sh | Collects app versions from /liveness endpoints for node-exporter (runs in version-collector container) |
Configuration Files¶
| File | Purpose |
|---|---|
customer-config-prod.example.sh | Template for customer settings (copy to customer-config.sh) |
customer-config.sh | Customer-specific settings (created from template, fill in before install) |
.env | Generated environment file (created by install.sh) |
secrets/vault-keys.json | Vault unseal keys and root token (back up securely!) |
secrets/signing-key.csr | Generated CSR for S/MIME certificate |
Support¶
Support
For any questions or issues related to the deployment and operation of the Stargate appliance, please contact HIN support.
Please include relevant information such as the customer name, appliance version, and screenshots/logs where applicable, to help us process your request efficiently.