Skip to content

Server

Environment file

eonpath-server reads its configuration from /etc/eonpath/server.env, an environment file loaded by the systemd unit (EnvironmentFile=). This is the configuration surface installed and pre-populated by the eonpath-server .deb package; see Install: Server for the install steps.

# /etc/eonpath/server.env

# SSH listener (post-quantum SSH proxy method)
EONPATH_SSH_ADDR=0.0.0.0:2022

# Local PQKS API endpoint (used to look up client keys when a client connects)
EONPATH_API_ENDPOINT=http://localhost:8080

# HTTP CONNECT proxy address (for the proxy method's tunnels)
EONPATH_PROXY_ADDR=localhost:2290

# SSH host key path (generated by the postinstall script on first install)
EONPATH_HOST_KEY=/var/lib/eonpath/host_key

# Per-user authorized_keys directory
EONPATH_AUTHORIZED_KEYS_DIR=/var/lib/eonpath/authorized_keys

# WireGuard VPN settings (for the routing method)
EONPATH_WG_KEX_ADDR=0.0.0.0:9998
EONPATH_WG_LISTEN_PORT=51820

# Security audit log (empty discards the events)
EONPATH_AUDIT_LOG=/var/lib/eonpath/audit.log

After editing, apply the change with:

sudo systemctl restart eonpath-server
KeyTypeDefaultDescription
EONPATH_SSH_ADDRaddress0.0.0.0:2022Listen address for the post-quantum SSH proxy method.
EONPATH_API_ENDPOINTURLhttp://localhost:8080Address of the eonpath-api server, used to look up a connecting client’s registered public key.
EONPATH_PROXY_ADDRaddresslocalhost:2290Listen address for the HTTP CONNECT proxy that backs the proxy method’s tunnels.
EONPATH_HOST_KEYpath/var/lib/eonpath/host_keyPath to the server’s SSH host key, generated on first install.
EONPATH_AUTHORIZED_KEYS_DIRpath/var/lib/eonpath/authorized_keysDirectory of per-user authorized_keys files consulted by the SSH proxy method.
EONPATH_WG_KEX_ADDRaddress0.0.0.0:9998TCP listen address for the WireGuard routing method’s key-exchange handshake (see API for the protocol).
EONPATH_WG_LISTEN_PORTint51820UDP port for the WireGuard data tunnel.
EONPATH_AUDIT_LOGpath/var/lib/eonpath/audit.logSecurity audit log. It has to stay under a ReadWritePaths directory, since the unit sets ProtectSystem=strict; set it empty to discard the events. Rotated by /etc/logrotate.d/eonpath-server.

The routing method itself (-wg-enabled) is always passed by the packaged systemd unit’s ExecStart line — the shipped .deb runs both the SSH proxy method and the WireGuard routing method from a single eonpath-server process. Disabling the routing method requires editing the systemd unit directly, since it isn’t exposed through the environment file.

server.conf: registration and endpoints

The unit also passes -config /etc/eonpath/server.conf. Flags override the file, and the unit passes a flag for every ssh:, proxy:, api: and wireguard: value — so on a stock .deb install those sections have no effect; change them in server.env instead, or drop the corresponding flag with systemctl edit eonpath-server.

The registration: and endpoints: sections have no flag counterpart. They are why the file exists.

registration:
  enabled: true
  api_url: "https://api.example.com"   # also the signed audience
  license_key_file: /etc/eonpath/license_key
  timeout: 10s
  max_attempts: 8

endpoints:
  - name: example-ams-1
    method: routing              # WireGuard VPN with SIIT/NAT
    mode: standby                # standby | active
    tunnel_ip: 203.0.113.10      # public address clients connect to
    tunnel_port: 51820
    kex_address: 203.0.113.10:9998   # required for method: routing
    companion_hosts:
      - git.example.com

  - name: example-ams-1-proxy
    method: proxy                # HTTP CONNECT proxy + SSH port forwarding
    mode: standby
    tunnel_ip: 203.0.113.10
    port: 2022                   # required for method: proxy
    forward_port: 9999

The server publishes these endpoints to the API, signed with its ML-DSA-87 identity key. The first push also presents the licence key; after that the signature alone authenticates the server, and the key can be removed from the host. Registration failing never stops the server — an invalid endpoint entry is skipped with an error in the journal and everything else keeps serving.

tunnel_ip is mandatory and never auto-detected: behind NAT, detection would register the private address and produce an endpoint no client can reach. Every name has to be covered by the licence and fall inside a name prefix reserved for your organization.

The licence key is read from the first source that has it: -license-key, EONPATH_LICENSE_KEY, license_key in this file, license_key_file. Prefer the file or the environment — the example ships world-readable.

After editing the endpoint list:

sudo systemctl reload eonpath-server   # re-reads server.conf, re-pushes, drops no tunnel

mode: standby and mode: active

ModeWhat the server doesPublished to clients
standbyRegisters itself and nothing else — no WireGuard interface, no kex listener, no proxy listenerNo
activeServes traffic normallyYes

A standby endpoint doesn’t appear in GET /endpoints at all, so no client ever learns it exists. The state is a commercial fact with a technical consequence, so it’s recorded in the API and enforced on the server: every transition is logged with a timestamp, and the first activation starts a per-endpoint free evaluation window (trial_days on the licence, 30 by default) that is granted once and does not restart.

Switching state is an edit here plus systemctl restart eonpath-server — a restart, not a reload. In standby there was nothing serving to interrupt.

Omitting mode means active, so configs written before the option existed keep working. A field that is present but empty, or holds an unknown value, rejects that endpoint with an error in the journal rather than guessing: a guess costs money in one direction or the other. A fresh install ships mode: standby.

WireGuard VPN settings (command-line flags)

A few less common WireGuard routing-method settings are only available as eonpath-server command-line flags — they can be added to the ExecStart= line in /lib/systemd/system/eonpath-server.service (or a systemd drop-in) if you need to change them from their defaults.

KeyTypeDefaultDescription
-wg-interfacestringwg0WireGuard network interface name.
-wg-server-ipstringfd00:4464::a00:1Server’s internal address inside the VPN’s IPv6 lease range.
-wg-subnetstringfd00:4464::a00:0/112IPv6 subnet the server leases client addresses from.
-wg-masqueradebooltrueEnable NAT masquerading so VPN clients can reach the internet through the server.

SSH proxy method and general server flags

KeyTypeDefaultDescription
-configpath/etc/eonpath/server.conf on a packaged installPath to the YAML configuration file described above; command-line flags override values loaded from it.
-license-keystring(none)Licence key for endpoint registration; takes precedence over EONPATH_LICENSE_KEY and both server.conf sources.
-disable-sshboolfalseDisable the SSH proxy method’s listener entirely.
-proxy-validate-destinationsboolfalseEnable SSRF protection: validate HTTP CONNECT destinations against security rules before dialing them.
-key-revocation-intervalduration5mHow often the server polls the API for revoked keys and removes them from authorized_keys. Set to 0 to disable polling.
-drop-privilegesboolfalseDrop root privileges after binding to listen ports.
-run-as-userstring(auto-detected)User to run as after dropping privileges; used with -drop-privileges.

Post-quantum key exchange (SSH proxy method)

The WireGuard routing method’s key exchange (ML-DSA-87 authentication, ML-KEM-1024 encapsulation) is fixed and not configurable — see Post-Quantum Cryptography. The SSH proxy method’s key exchange algorithm selection can be tuned independently, either as command-line flags or the equivalent environment variables:

KeyTypeDefaultDescription
-pqc-mlkem / PQKEX_MLKEMbooltrueEnable ML-KEM-768 hybrid key exchange for the SSH proxy method.
-pqc-frodokem / PQKEX_FRODOKEMboolfalseEnable FrodoKEM-640 hybrid key exchange (experimental).
-pqc-ntruprime / PQKEX_NTRUPRIMEboolfalseEnable sntrup761 hybrid key exchange (experimental).
-pqc-prefer-classical / PQKEX_PREFER_CLASSICALboolfalsePrefer classical (non-PQC) key exchange algorithms when negotiating with a peer.
-pqc-order / PQKEX_ORDERstring(none)Comma-separated algorithm priority order (for example mlkem,frodokem); setting this auto-enables the listed algorithms and overrides the individual flags above.

Command-line flags take precedence over the equivalent environment variable.