Skip to content

SilentSuite Bridge ​

SilentSuite Bridge is a local daemon that translates between CalDAV/CardDAV and the Etebase protocol. It runs on your machine and provides local DAV endpoints for supported desktop integrations, including Thunderbird, Calendar and Contacts on macOS, GNOME Calendar and Evolution, KDE Kontact, and Outlook on Windows.

How It Works ​

Your App (CalDAV/CardDAV)
        |
http://localhost:37358/
        |
SilentSuite Bridge (local)
        | (encrypted)
SilentSuite Server

Local-only bridge

Keep the bridge bound to your local machine unless you fully understand the risk: DAV clients can access decrypted local calendar, contact, and task data through the bridge.

The bridge handles encryption/decryption locally. Your data is still end-to-end encrypted -- the bridge just presents it as standard CalDAV/CardDAV to your apps.

Supported data types:

  • Calendars (CalDAV / VEVENT)
  • Tasks (CalDAV / VTODO)
  • Contacts (CardDAV / VCARD)

The bridge exposes every SilentSuite calendar, task list, and address book as its own DAV collection, so compatible clients can select the destination collection for new events, tasks, and contacts.

Install ​

Linux ​

Follow the Linux desktop bridge guide for the stable installer, first-time setup, systemd auto-start, troubleshooting, and uninstall instructions.

Windows ​

Download the current Windows bridge binary directly:

Save the file in Downloads. You can either keep the release file name or rename it to silentsuite-bridge.exe, then run it from an already-open PowerShell or Windows Terminal window so any first-run errors stay visible:

powershell
cd $env:USERPROFILE\Downloads
.\silentsuite-bridge-windows-x86_64.exe --version
.\silentsuite-bridge-windows-x86_64.exe --login

If you renamed the file, use ./silentsuite-bridge.exe instead.

If Windows SmartScreen appears, choose More info and only continue if the publisher/file name matches the SilentSuite release you downloaded.

Installer Status ​

Bridge installer scripts are being hardened. If you use a PowerShell installer command, run it from an already-open PowerShell or Windows Terminal window, not from the Run dialog or by double-clicking a .ps1 file.

WARNING

Do not run installer commands from the public dev branch. Those scripts may contain unreleased changes and are not part of the stable docs flow.

If a PowerShell window closes before you can read the error, reopen PowerShell and run the diagnostic form instead. It downloads the installer to a temporary file and runs it with -File, so failures stay visible and are also written to %LOCALAPPDATA%\SilentSuite\install.log.

powershell
irm https://raw.githubusercontent.com/silent-suite/silentsuite/main/bridge/install.ps1 -OutFile $env:TEMP\silentsuite-bridge-install.ps1
powershell -ExecutionPolicy Bypass -File $env:TEMP\silentsuite-bridge-install.ps1

All downloads are also available from the GitHub releases page.

First-Time Setup ​

1. Start The Bridge And Log In ​

After installation, run:

bash
silentsuite-bridge

This starts the local bridge and opens the dashboard at http://localhost:37358/. If your browser does not open automatically, open that URL yourself. Enter your account email and password in the dashboard setup form; the bridge authenticates with the server, stores your session locally, and starts syncing.

silentsuite-bridge --login is still available as a fallback or advanced path. Running it adds another account or re-authenticates the same account; it does not remove accounts that are already configured.

2. Note Your Connection URLs ​

After successful login, the dashboard shows your CalDAV/CardDAV URLs:

FieldValue
CalDAV URLhttp://localhost:37358/your@email.com/
CardDAV URLhttp://localhost:37358/your@email.com/
UsernameYour account email
PasswordYour account password

You can always find these URLs by:

  • Opening the dashboard at http://localhost:37358/
  • Using the system tray menu account entries (Copy CalDAV URL / Copy CardDAV URL)

macOS Apple Internet Accounts HTTPS setup ​

Most DAV clients can use the default local HTTP bridge URL. macOS Apple Internet Accounts is stricter: use Advanced setup with Use SSL checked and a trusted localhost certificate.

On the Mac that runs the bridge:

bash
silentsuite-bridge --setup-macos-apple-accounts

Then trust the generated localhost certificate in Keychain Access with Trust > Secure Sockets Layer (SSL) set to Always Trust, restart the bridge, and use the https:// DAV URLs shown in the dashboard.

HTTPS is all-or-nothing for one bridge profile

Enabling bridge SSL switches every configured listener (loopback and remote) from HTTP to HTTPS. Existing Thunderbird, Evolution, or KDE clients configured with http://localhost:37358/ must be updated to the dashboard's https:// URL and may need to trust the same localhost certificate. Running simultaneous HTTP and HTTPS listeners is not part of this bridge mode. For a remote listener, the remote IP or hostname must also be in the certificate's SANs (see the Remote DAV Access section).

For detailed Apple setup fields and troubleshooting, see macOS Calendar & Contacts.

Remote DAV Access (Tailscale / Private Networks) ​

The Bridge listens on the addresses you configure in SILENTSUITE_SERVER_HOSTS (as a comma-separated host:port list). Each entry is a requested listener; only the entries that actually bind become bound listeners you can dial. The dashboard Network card and the /.web/api/status JSON show both lists so you can tell requested-but-unbound entries from real endpoints.

When you start the Bridge from a terminal it also prints the requested list and one Listening: or Listener not bound: line per address. Under the launchd agent, the systemd user service, or any redirected output, stdout is a persistent log rather than an operator terminal, so those lines carry only the listener kind and outcome and no address, hostname or port. Set SILENTSUITE_LISTENER_DETAIL=1 to print the addresses there anyway, or read them from the tray menu or the Network card.

Loopback is special ​

The unauthenticated Bridge dashboard is served only on a listener whose bound address is a numeric loopback literal (127.0.0.1 or ::1). The dashboard gate checks three bridge-owned facts stamped into every request: the bound listener address, the accepted local socket address, and the peer address. All three must be loopback. A 0.0.0.0 / :: wildcard bind is never treated as loopback even for a connection from 127.0.0.1, because the bound address is the wildcard, not a loopback literal. The dashboard is therefore denied on wildcard and remote listeners regardless of where the request originates — there is no "local connection" exception for the dashboard. To use the dashboard, run the Bridge with a loopback entry and open it from the Bridge host.

DAV endpoints have no such restriction: any bound listener (loopback, wildcard, or remote) serves CalDAV/CardDAV to clients that can reach it. A wildcard bind (0.0.0.0 / ::) serves DAV on every interface, but it is not a dialable client URL itself — clients reach it via the host's actual IP address. This is how a remote private-network bind is meant to be used.

To keep the dashboard usable on the Bridge host while exposing DAV to a private network, configure both a loopback and a remote entry in SILENTSUITE_SERVER_HOSTS:

bash
SILENTSUITE_SERVER_HOSTS=127.0.0.1:37358,100.64.10.20:37358 \
SILENTSUITE_ALLOW_REMOTE=1 silentsuite-bridge

The loopback entry serves the dashboard and DAV on the Bridge host; the remote entry serves DAV only to the private network. The dashboard URL and the per-account DAV URLs the tray shows always prefer the bound loopback listener, so copying a DAV URL gives you the safe local endpoint by default. A remote-only bind (no loopback entry) makes the tray show the bound remote literal with its configured port for DAV — never a wildcard, never an unbound LISTEN_ADDRESS:LISTEN_PORT. The dashboard itself is not served on a remote-only bind, so its Network card is only visible when a loopback listener is also configured and you open the dashboard from the Bridge host.

Remote DAV clients ​

127.0.0.1 and localhost always refer to the device making the request. A DAV client on another Tailscale or private-network device must use the Bridge host's private IP address, MagicDNS name, or another approved private hostname — not localhost. Do not expose the Bridge listener to the public internet.

When HTTPS is enabled, the exact IP address or hostname used by the DAV client must be present in the certificate's Subject Alternative Names (SANs). Do not bypass certificate verification. The auto-generated localhost certificate from --setup-macos-apple-accounts covers localhost, 127.0.0.1, and ::1 only; an explicit Tailscale IP or MagicDNS name is not in that SAN set and must be added to a custom certificate. Certificate support for explicit Tailscale IPs and MagicDNS names is tracked in #518.

Opening a remote or wildcard listener in a browser can show Radicale works! or a similar generic Radicale status response. That confirms the DAV listener is reachable; it is not the SilentSuite dashboard.

Platform note on the 127/8 loopback range ​

127.0.0.1 is the normal loopback address and is what the Bridge uses by default. The whole 127.0.0.0/8 range is loopback on Linux, but the Bridge treats only numeric loopback literals as dashboard-eligible and the generated localhost certificate covers 127.0.0.1 (not every 127.x.x.x address). Use 127.0.0.1 unless you have a specific reason to use another loopback address, and add that address to your certificate SANs when TLS is on.

Multi-Account Use ​

The bridge can keep multiple accounts active in one local bridge profile. Each account has its own credentials, local cache namespace, sync thread, and DAV path.

bash
silentsuite-bridge --login
silentsuite-bridge --login
silentsuite-bridge --list-accounts

Each account uses a URL containing the account email:

text
http://localhost:37358/work@example.com/
http://localhost:37358/personal@example.com/

Use the matching account email and password in your calendar/contact client. A client authenticated as one account cannot access another account's DAV path.

You can add or re-authenticate accounts from the dashboard with Add / Re-authenticate Account. It shows the dashboard sign-in form and starts syncing the account after login succeeds; you do not need to restart the bridge.

To remove only the local login/session for one account while keeping its local cache for future re-login:

bash
silentsuite-bridge --logout work@example.com

To fully remove one account's local bridge data, including its decrypted local cache:

bash
silentsuite-bridge --remove-account work@example.com

WARNING

The bridge local cache contains decrypted calendar, contact, and task data. Use --remove-account when retiring a shared or untrusted machine.

3. Keep The Bridge Running ​

Leave silentsuite-bridge running. The bridge will:

  • Start the CalDAV/CardDAV server on localhost:37358
  • Show a system tray icon (green = connected, yellow = warning, red = error)
  • Sync automatically in the background

Dashboard ​

The bridge serves a status dashboard at:

http://localhost:37358/

The dashboard shows:

  • Connection status
  • All configured accounts
  • Last sync time
  • Per-account CalDAV/CardDAV URLs with copy buttons
  • Add / Re-authenticate, Log out, and Remove account actions
  • Recent sync log

Use Log out to remove local bridge credentials while keeping that account's local cache for re-login. Use Remove account to delete local bridge credentials and that account's decrypted local bridge cache on this computer. Other configured accounts are not affected.

Auto-Start ​

Install Auto-Start ​

bash
silentsuite-bridge --install-autostart

This configures the bridge to start when you log in:

  • Linux: Creates a systemd user service
  • macOS: Creates a launchd agent
  • Windows: Adds a startup registry entry

Listener settings survive auto-start ​

Auto-start entries run the bridge with a clean environment, so shell exports are not visible to the restarted process. When you run --install-autostart, the bridge first validates the effective configuration and then persists only the variables you explicitly exported among SILENTSUITE_LISTEN_ADDRESS, SILENTSUITE_LISTEN_PORT, SILENTSUITE_SERVER_HOSTS, and SILENTSUITE_ALLOW_REMOTE into the "network" object of settings.json. All three platform entries read that same profile. Environment variables still take precedence over the persisted values whenever they are set.

bash
SILENTSUITE_LISTEN_ADDRESS=::1 SILENTSUITE_LISTEN_PORT=45123 silentsuite-bridge --install-autostart
  • With nothing exported, no "network" object is written and the bridge keeps 127.0.0.1:37358.
  • A non-loopback address without SILENTSUITE_ALLOW_REMOTE=1 is refused before anything is written. The permission is persisted together with the bind. The dashboard is served only on bound loopback listeners; a remote-only profile has no dashboard, while a mixed SILENTSUITE_SERVER_HOSTS profile (loopback + remote) keeps the dashboard on the loopback entry and serves DAV on both.
  • Nothing else from the environment (server URL, data directory, log file, SSL paths, credentials) is ever persisted by this command.
  • Running --install-autostart again merges newly exported variables over the retained profile; values you do not export again are kept.
  • SILENTSUITE_DATA_DIR (and, on Linux, XDG_DATA_HOME) cannot be combined with --install-autostart; the command refuses and changes nothing, because the restarted bridge would read the default data directory.
  • If the service manager does not confirm the start, the command exits non-zero and says so; check systemctl --user status silentsuite-bridge or launchctl list io.silentsuite.bridge.

The persisted profile is validated strictly on every start. If settings.json contains an invalid or unknown "network" entry, or is not valid JSON at all, the bridge stops before binding and names the offending key or file without printing its content; other settings are left untouched, and --remove-autostart still works.

Every change to settings.json (this profile, the dashboard sync interval, SSL settings) is written atomically and one writer at a time: writers hold a lock on settings.json.lock in the data directory, so changing the sync interval in the dashboard while --install-autostart runs can never discard the freshly persisted profile, and two overlapping --install-autostart runs apply one after the other with both of their changes kept. If the dashboard cannot save the interval (write failed, durability not confirmed, another process still writing), it shows Not saved: with the reason and keeps the last acknowledged value instead of reporting Saved; the selector is disabled while a save is in flight.

Remove Auto-Start ​

bash
silentsuite-bridge --remove-autostart

This removes the startup entry but keeps the persisted "network" profile, so a manual silentsuite-bridge run still binds the same way. To reset to the loopback defaults, delete the "network" object from settings.json in the bridge data directory.

  • Removal works even when settings.json holds an invalid "network" object; it starts no listener and writes no settings.
  • Linux/macOS: the bridge is stopped/unloaded first. If systemd or launchd does not confirm that, the command exits non-zero, keeps the entry so you can retry, and never reports the bridge as removed.
  • Windows: only the sign-in Run entry is deleted. A bridge process that is already running keeps running until you stop it (for example with Stop-Process).

Uninstall ​

Windows PowerShell Installer ​

If you installed the Bridge on Windows with the PowerShell installer, Docker is not involved. The installer downloads silentsuite-bridge.exe into your Windows user profile, adds that folder to your user PATH, and creates a per-user startup entry so the Bridge can run after you sign in.

To remove the local Bridge app from Windows 11, open PowerShell as your normal Windows user and run:

powershell
# Stop the Bridge if it is running
Get-Process silentsuite-bridge -ErrorAction SilentlyContinue | Stop-Process -Force

# Remove the startup entry
& "$env:LOCALAPPDATA\SilentSuite\silentsuite-bridge.exe" --remove-autostart 2>$null
Remove-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Run" -Name "SilentSuiteBridge" -ErrorAction SilentlyContinue

# Remove the installed Bridge executable and installer log
Remove-Item -Recurse -Force "$env:LOCALAPPDATA\SilentSuite" -ErrorAction SilentlyContinue

Optional: remove the Bridge install folder from your user PATH:

powershell
$userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
$newPath = ($userPath -split ";" | Where-Object { $_ -and $_ -ne "$env:LOCALAPPDATA\SilentSuite" }) -join ";"
[Environment]::SetEnvironmentVariable("PATH", $newPath, "User")

Then sign out and back in, or restart Windows.

If you want to remove local Bridge account data before deleting the executable, list the configured accounts and remove each one first:

powershell
& "$env:LOCALAPPDATA\SilentSuite\silentsuite-bridge.exe" --list-accounts
& "$env:LOCALAPPDATA\SilentSuite\silentsuite-bridge.exe" --remove-account your@email.com

Uninstalling the local Bridge only removes the desktop sync helper from this computer. It does not cancel a hosted SilentSuite trial or subscription. Cancel the trial from your SilentSuite billing/account page if you do not want it to continue.

Environment Variables ​

VariableDefaultDescription
SILENTSUITE_SERVER_URLhttps://server.silentsuite.ioEtebase server URL
SILENTSUITE_LISTEN_ADDRESS127.0.0.1IP address to listen on (persisted by --install-autostart when exported)
SILENTSUITE_LISTEN_PORT37358Port to listen on (persisted by --install-autostart when exported)
SILENTSUITE_SERVER_HOSTSlisten address and portRadicale host:port list (persisted by --install-autostart when exported)
SILENTSUITE_ALLOW_REMOTEunsetRequired for any non-loopback bind (in SILENTSUITE_LISTEN_ADDRESS or SILENTSUITE_SERVER_HOSTS); the dashboard is served only on bound loopback listeners, so a remote-only profile has no dashboard (persisted by --install-autostart when exported)
SILENTSUITE_DATA_DIRPlatform-specificData storage location (not supported with --install-autostart)
SILENTSUITE_SYNC_INTERVAL900 (15 min)Sync interval in seconds
SILENTSUITE_LOG_LEVELINFOLog level (DEBUG, INFO, WARNING, ERROR)
SILENTSUITE_LISTENER_DETAILunsetPrint requested, bound and failed listener addresses even when stdout is not a terminal. By default those addresses appear only on an interactive terminal; the launchd log file, the systemd journal and redirected output receive bounded lines without addresses

For self-hosted servers:

bash
export SILENTSUITE_SERVER_URL=https://sync.your-domain.com
silentsuite-bridge

CLI Reference ​

bash
silentsuite-bridge                    # Start the bridge
silentsuite-bridge --version          # Show version
silentsuite-bridge --check-update     # Check for a newer release (no mutation)
silentsuite-bridge --self-update      # Download, verify, and install the latest
                                      # release (requires a frozen release binary)
silentsuite-bridge --login            # Add or re-authenticate an account
silentsuite-bridge --list-accounts    # List configured accounts
silentsuite-bridge --logout EMAIL     # Remove local credentials; keep cache
silentsuite-bridge --remove-account EMAIL  # Remove credentials and local cache
silentsuite-bridge --manual-login     # CLI add/re-authenticate (headless/dev)
silentsuite-bridge --install-autostart  # Install auto-start
silentsuite-bridge --remove-autostart   # Remove auto-start
silentsuite-bridge --no-tray          # Start without system tray

Updating the Bridge ​

Check for updates ​

Run --check-update to see whether a newer release is available without downloading or changing anything:

bash
silentsuite-bridge --check-update

This prints the running version, compares it against the latest compatible GitHub release, and reports whether an update, current, or another state (development build, unsupported platform, network error) applies. The check does not touch any configuration, data directory, or server state.

Apply an update (release binary only) ​

bash
silentsuite-bridge --self-update

This downloads the latest compatible release binary and its .sha256 sidecar, verifies the checksum, and safely replaces the running executable. The command requires a frozen release binary (installed via the official installer or a GitHub download) in a writable location. Source and editable installs are refused; update those manually with git or pip. Same-version replacement and downgrades are always refused. After replacement, the updater attempts to restart the bridge through systemd (Linux), launchd (macOS), or prints an exact manual restart command when automatic restart is unavailable.

What happens to the running process during update ​

  • Linux/macOS: The verified candidate is staged on the same filesystem, the live binary is atomically replaced, and the bridge daemon is restarted via systemd or launchd.
  • Windows: The running .exe is never overwritten in-process. A verified candidate is staged and a PowerShell helper script is launched to complete the swap after the old process exits, preserving a backup. If the helper cannot be launched, the updater prints an exact manual recovery instruction.

Autostart continues to reference the same installed executable path; it is not changed to point at temporary staging paths.

Recovery after a failed update ​

A failed download, checksum, or replace leaves the installed executable intact. If the replacement fails mid-swap, the original is preserved or restored from the same-directory backup. In all cases, the autostart entries (systemd/launchd/registry) are not modified, so the bridge can be restarted manually from the same path. A manual reinstall via the installer script or a direct GitHub download is always an available recovery path.

Manual installer update ​

The existing bridge/install.sh and bridge/install.ps1 installers still work for new installations and manual upgrades. Running the installer over an existing installation downloads the latest release and replaces the binary after verifying its checksum. This is the recommended path when automatic self-update is not available (source installs, unsupported platforms, or when you prefer a fresh download).

Troubleshooting ​

Bridge won't start ​

On the default localhost bind, the bridge can start before an account is configured so you can log in through http://localhost:37358/. If you configured a remote-only bind (no loopback entry in SILENTSUITE_SERVER_HOSTS), the dashboard is not served on any listener; add an account first with:

bash
silentsuite-bridge --login

Can't connect from your app ​

  1. On the Bridge host with the default loopback bind, open http://127.0.0.1:37358/ and confirm the dashboard loads. For an intentional remote bind, test the configured scheme and private-network address instead; Radicale works! or a similar generic Radicale status response confirms listener reachability, not dashboard availability.
  2. Check the tray icon color (green = OK, red = error)
  3. Check the dashboard sync log for errors
  4. If you installed on Windows, also check %LOCALAPPDATA%\SilentSuite\install.log and %LOCALAPPDATA%\SilentSuite\bridge.log

SSL: WRONG_VERSION_NUMBER ​

A client connected using HTTP while bridge HTTPS is enabled. Enable SSL in the DAV client and use an https:// URL. TLS fails before the request reaches the Bridge application, so an HTTPS-only listener cannot redirect that plaintext HTTP request.

If HTTPS is not enabled for this bridge profile, use the http:// URL shown by the dashboard instead. All clients using one bridge profile must use the listener's configured scheme.

The sign-in page and dashboard show different ports ​

This is expected during browser sign-in. silentsuite-bridge --login opens a temporary local sign-in page on a random port such as 65486. The actual CalDAV/CardDAV bridge always uses http://127.0.0.1:37358/ unless you changed SILENTSUITE_LISTEN_PORT.

Use the CalDAV/CardDAV URL shown on the success page or dashboard, for example:

text
http://127.0.0.1:37358/your@email.com/

Do not copy the browser address-bar URL from the temporary sign-in page into Thunderbird, Outlook, or another DAV client. After sign-in, the success page waits for the real dashboard and automatically switches the tab to http://127.0.0.1:37358/ once it is reachable.

Thunderbird says no calendars, tasks, or contacts were found ​

  1. Open http://127.0.0.1:37358/ and confirm the dashboard loads. If it does not load, the bridge daemon is not running yet.
  2. Confirm the dashboard shows your configured account and a recent successful sync. If the sync log shows an error, fix that first.
  3. In Thunderbird, use the full account URL from the dashboard: http://127.0.0.1:37358/your@email.com/.
  4. Use your SilentSuite account email as the username and your SilentSuite account password as the password.
  5. If discovery still returns nothing, copy the dashboard sync log plus %LOCALAPPDATA%\SilentSuite\bridge.log into a support report. Do not include passwords or session tokens.

System tray not visible (GNOME) ​

GNOME removed native tray support. Install the AppIndicator extension to restore it. KDE, XFCE, and other desktop environments support the tray natively.

Firewall blocking ​

With the default bind, ensure localhost:37358 is not blocked by your firewall. If you explicitly enabled a remote bind, allow the configured port only on the intended private-network interface and keep it closed to the public internet.

Next Steps ​

Once the bridge is running, set up your apps:

Released under the AGPL-3.0 License.