Skip to main content

Running the proxy

Applies to SynapseOS builds from 2026-10-09 (20261009-141152 and later). See What changed.

The proxy is already on the unit. Give it its own configuration before you start it.

What ships​

Synapse is one binary with two modes. The agent (synapse-agent.service) runs on every appliance; the proxy (synapse-proxy.service) is installed beside it and left disabled. Nothing needs installing.

Do not start the shipped unit as it is

As shipped, synapse-proxy.service reads the same /etc/synapse/config.yaml as the agent. One file holds one mode, one firewall block and one capture block, so a proxy started that way re-attaches the kernel packet filter on the external interface and takes enforcement away from the agent. Both services keep reporting healthy while that happens. The steps below give the proxy a configuration of its own first.

Derive a configuration for the proxy​

Start from the agent's file and flip only what has to differ. The agent keeps packet capture, detection and kernel enforcement; the proxy keeps everything else, so a later Synapse release that adds settings reaches both files.

python3 - <<'EOF'
import os, yaml
c = yaml.safe_load(open("/etc/synapse/config.yaml"))
def section(name):
if not isinstance(c.get(name), dict): # absent, or present but empty
c[name] = {}
return c[name]
c["mode"] = "proxy"
section("capture")["enabled"] = False # the agent owns packet capture
section("ids")["enabled"] = False # the agent owns detection
section("firewall")["mode"] = "none" # the agent owns the kernel filter
# Created with its final mode: the file carries platform.api_key.
fd = os.open("/etc/synapse/config-proxy.yaml", os.O_WRONLY | os.O_CREAT | os.O_TRUNC, 0o640)
with os.fdopen(fd, "w") as f:
yaml.safe_dump(c, f, default_flow_style=False, sort_keys=False)
EOF

Rerun this after changing the agent's file, so the two do not drift apart.

Point the service at it​

/etc/systemd/system/synapse-proxy.service.d/10-separate-config.conf
[Service]
ExecStart=
ExecStart=/usr/bin/synapse --daemon --daemon-pid-file /run/synapse-proxy.pid --config /etc/synapse/config-proxy.yaml

The empty ExecStart= line clears the shipped command before the new one is set; systemd appends otherwise.

Say where traffic goes​

The proxy routes by hostname, from /etc/synapse/upstreams.yaml. A minimal file with one host, TLS terminated on the appliance:

/etc/synapse/upstreams.yaml
version: 2
hosts:
"app.example.com":
tls:
terminate:
cert: "/etc/synapse/certs/default.crt"
key: "/etc/synapse/certs/default.key"
upstream: "10.0.0.5:443"

Every terminating host needs the tls.terminate block, even one only ever served over plain HTTP. A file that does not parse leaves the proxy with no routes at all, so every host answers 404, not only the broken one. Passthrough hosts, weighted backends, health checks and the rest of the format are on the Configuration page.

Provide a certificate​

If /etc/synapse/certs/ holds your certificate already, skip this. Otherwise a self-signed placeholder lets the TLS listener start; clients will not trust it, so replace it with a real one.

mkdir -p /etc/synapse/certs
openssl req -x509 -newkey rsa:2048 -nodes -days 3650 \
-keyout /etc/synapse/certs/default.key -out /etc/synapse/certs/default.crt \
-subj "/CN=default.$(hostname)"
chmod 0640 /etc/synapse/certs/default.key

Open the ports​

The proxy listens on ports 80 and 443 by default (proxy.address_http and proxy.address_tls), and the base firewall drops inbound traffic to both until told otherwise. Add them to the services chain and reload it; see The base firewall.

tcp dport { 80, 443 } accept comment "synapse proxy"

Start it​

systemctl daemon-reload
systemctl enable --now synapse-proxy
systemctl status synapse-proxy synapse-agent

Both services should be active. The agent still owns the packet filter; the proxy serves the hosts in upstreams.yaml, and reloads that file whenever it changes.

Written out from the installer

These are the steps Gen0Sec's own configuration tooling performs, written out for a unit you manage by hand. The upstreams format shown is the one Synapse 0.8.5 and later read.