Build
Deploy and run the agent
The agent is a single binary you run on your own infrastructure. It serves the Excel add-in, executes your functions against your data sources, and reports back to ConnXL over outbound connections only. This page is the operator's reference — install it as a service, upgrade it, monitor it, and retire it.
12 min read
The agent is one self-contained executable. It has no installer, no runtime dependency, no database of its own, and it reads its entire configuration from environment variables plus the config snapshot it pulls from ConnXL. Everything below assumes you already created an add-in and an environment in the dashboard — the Agent page's Deploy tab is where you download a binary that is already stamped with its identity.
One agent per environment
Each environment runs its own agent, and the certificate the agent enrolls for is what binds it to that environment. You can run many replicas of the same environment's agent behind a load balancer — they all share one enrollment token and each gets its own certificate.
Download and verify the binary
Deploy → Download configured agent gives you a binary with its backend URL, add-in ID, environment ID and a fresh enrollment token already embedded, so it runs with zero environment variables. Platforms: Windows x64, Linux x64, Linux arm64.
Each download is published alongside a SHA256SUMS file. Verify before you run it:
# Linux / macOS
sha256sum -c SHA256SUMS --ignore-missing
# Windows PowerShell
(Get-FileHash .\connxl-agent.exe -Algorithm SHA256).Hash -eq (Get-Content .\SHA256SUMS | Select-String 'connxl-agent.exe').ToString().Split()[0]Confirm what you have at any time:
connxl-agent --version # prints the build version
connxl-agent --licenses # prints third-party noticesA stamped binary carries a credential
The embedded enrollment token is a real credential for that one environment. Treat a configured download like a secret: don't commit it to a repo or share it between environments. If one leaks, Regenerate on the Deploy tab revokes every token issued for that environment at once.
Run it as a service
The agent runs in the foreground and logs to stdout, so any service manager works. Give it a dedicated user and a stable working directory — it writes its enrolled identity there.
Linux (systemd)
[Unit]
Description=ConnXL Agent
After=network-online.target
Wants=network-online.target
[Service]
Type=simple
User=connxl
WorkingDirectory=/opt/connxl
ExecStart=/opt/connxl/connxl-agent
Restart=always
RestartSec=5
Environment=CONNXL_DATA_DIR=/var/lib/connxl
# TimeoutStopSec must exceed the agent's 10s in-flight request drain.
TimeoutStopSec=30
[Install]
WantedBy=multi-user.targetsudo systemctl daemon-reload
sudo systemctl enable --now connxl-agent
sudo systemctl status connxl-agentWindows (service)
The binary is a plain console application, so register it with sc.exe or a service wrapper such as NSSM:
# Using NSSM (handles stdout redirection and restarts)
nssm install ConnXLAgent "C:\Program Files\ConnXL\connxl-agent.exe"
nssm set ConnXLAgent AppDirectory "C:\Program Files\ConnXL"
nssm set ConnXLAgent AppEnvironmentExtra "CONNXL_DATA_DIR=C:\ProgramData\ConnXL"
nssm set ConnXLAgent AppStdout "C:\ProgramData\ConnXL\logs\stdout.log"
nssm start ConnXLAgentRun it in a container
There is no published image — build a minimal one around the Linux binary. The agent needs CA certificates for outbound TLS and a persistent volume for its identity, or it re-enrolls on every restart.
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*
COPY connxl-agent /usr/local/bin/connxl-agent
ENV CONNXL_DATA_DIR=/var/lib/connxl
VOLUME /var/lib/connxl
EXPOSE 3000
ENTRYPOINT ["/usr/local/bin/connxl-agent"]Kubernetes. Run it as a Deployment behind a Service, with the enrollment token from a Secret. Use a liveness probe only — see the health-endpoint warning in section 6.
spec:
containers:
- name: connxl-agent
image: your-registry/connxl-agent:0.1.0
ports:
- containerPort: 3000
env:
- name: CONNXL_BACKEND_URL
value: https://api.connxl.com
- name: CONNXL_ADDIN_ID
value: "<add-in id>"
- name: CONNXL_ENV_ID
value: "<environment id>"
- name: CONNXL_ENROLL_TOKEN
valueFrom:
secretKeyRef: { name: connxl-agent, key: enrollToken }
livenessProbe:
httpGet: { path: /healthz, port: 3000 }
initialDelaySeconds: 10
periodSeconds: 30
terminationGracePeriodSeconds: 30The enrollment token is reusable
Every replica can use the same token — each exchange yields its own certificate. That is what makes a scaled Deployment work from a single Secret.
Environment variables
A stamped binary needs none of these; every variable still overrides its stamped value. Only the identity group is required on an unstamped binary.
Identity and backend
| Variable | What it does | Default |
|---|---|---|
CONNXL_BACKEND_URL | ConnXL API base URL. Required (or stamped) — the agent refuses to boot without it | — |
CONNXL_ENROLL_TOKEN | One-time-per-agent enrollment credential; reusable across replicas | — |
CONNXL_ENROLL_ATTESTATION | aws | gcp | azure — enroll with the host's cloud identity instead of a token | — |
CONNXL_ADDIN_ID | Add-in this agent serves | stamped value |
CONNXL_ENV_ID | Environment this agent serves | stamped value |
CONNXL_BOOTSTRAP_URL | Separate URL for cert-less enrollment | CONNXL_BACKEND_URL |
CONNXL_REPLICA_ID | Label distinguishing replicas in the dashboard | hostname |
CONNXL_ZONE, CONNXL_REGION | Placement labels reported with health | empty |
CONNXL_HEARTBEAT_SECONDS | Heartbeat interval, capped at 60 | 30 |
Listener and TLS
| Variable | What it does | Default |
|---|---|---|
CONNXL_LISTEN_ADDR | Bind address for the add-in surface | :3000 |
CONNXL_TLS_TERMINATION | edge (plain HTTP behind a TLS-terminating load balancer) or agent (agent serves HTTPS from cert.pem/key.pem beside the binary) | edge |
CONNXL_TRUSTED_PROXY | Trust forwarded headers (X-Forwarded-For/-Proto/-Host) from the fronting proxy: needed for network access rules AND to build the OAuth sign-in callback as https:// when TLS terminates on a load balancer — without it user sign-in fails with a redirect-URI mismatch. Set only behind a proxy you control | off |
Storage and identity files
| Variable | What it does | Default |
|---|---|---|
CONNXL_DATA_DIR | Base directory for identity/ and logs/ | connxl-agent/ beside the binary |
CONNXL_MTLS_CERT | Where the enrolled client certificate is stored | <data dir>/identity/cert.pem |
CONNXL_MTLS_KEY | Where the enrolled private key is stored | <data dir>/identity/key.pem |
CONNXL_STATE_DIR | Entitlement-lease cache | the identity directory |
Logging
| Variable | What it does | Default |
|---|---|---|
CONNXL_LOG_LEVEL | debug | info | warn | error. error also hides retryable failures (a failed heartbeat, a failed re-enrolment) — prefer warn to cut noise | info |
CONNXL_LOG_FORMAT | json for one JSON object per line | text |
CONNXL_LOG_MAX_MB | Size at which the log file rotates | 100 |
CONNXL_LOG_MAX_FILES | Rotated files retained; the on-disk footprint is roughly MAX_MB × MAX_FILES | 5 |
Secrets
| Variable | What it does | Default |
|---|---|---|
CONNXL_SECRETS_KEY | Passphrase for the encrypted-file secret store | — |
CONNXL_SECRETS_TTL_SECONDS | Cache TTL for resolved secret:// references; 0 disables | 300 |
CONNXL_SECRETS_AWS_REGION | Region for AWS Secrets Manager references | — |
CONNXL_SECRETS_AWS_ENDPOINT | Custom Secrets Manager / Parameter Store endpoint — a VPC endpoint, a FIPS endpoint, or an emulator | — |
CONNXL_SECRETS_GCP_ENDPOINT | Custom GCP Secret Manager endpoint. When set, Application Default Credentials are skipped | — |
CONNXL_SECRETS_AZURE_ENDPOINT | Custom Azure Key Vault endpoint. When set, DefaultAzureCredential is skipped | — |
Endpoint overrides must be https
The three _ENDPOINT variables are ignored unless the URL is https or points at a loopback address, and the agent logs a warning when it rejects one. Setting an override also skips that cloud's credential chain, so a plaintext endpoint would send secret names and receive secret values in the clear, unauthenticated, with no auth error to signal the mistake.
Database pool tuning
Each SQL connector reads its own pool knobs, prefixed by engine — POSTGRES_MAX_OPEN_CONNS, MYSQL_MAX_IDLE_CONNS, SQLSERVER_CONN_MAX_LIFETIME, and so on (MAX_OPEN_CONNS defaults to 20, MAX_IDLE_CONNS to 5). Leave them alone unless you are hitting a server-side connection limit.
Network requirements
Every connection to ConnXL is initiated by the agent outbound. Nothing needs to reach the agent from the internet, and no inbound firewall rule is required for ConnXL itself.
Outbound — allow to your ConnXL API host on TCP 443:
| Path | Protocol | When |
|---|---|---|
POST /v1/agent/enroll | HTTPS | first boot only |
GET /v1/agent/certificates/trust-bundle | HTTPS | first boot only |
POST /v1/agent/certificates/renew | HTTPS | automatic renewal |
GET /v1/agent/config/snapshot | HTTPS | on boot and after every change |
POST /v1/agent/heartbeat | HTTPS | every 30s |
GET /v1/agent/config/stream | HTTPS/SSE | persistent |
GET /v1/agent/control | WSS | persistent |
POST /v1/agent/telemetry/ingest | HTTPS | periodic |
Two of these — the SSE config stream and the WebSocket control channel — are long-lived connections. Middleboxes that kill idle connections will cause repeated reconnects; the agent recovers, but the dashboard will flap.
Inbound: your Excel users (and your load balancer) must reach the agent on CONNXL_LISTEN_ADDR, default port 3000.
Also allow: your own data sources, and — only if you use cloud-identity enrollment — the instance metadata endpoint (169.254.169.254).
Behind an HTTP proxy
HTTPS_PROXY, HTTP_PROXY and NO_PROXY are honored on every connection the agent makes to ConnXL, including the long-lived SSE and WebSocket channels — so a host with no direct egress works. Client-certificate authentication is unaffected: the proxy opens a CONNECT tunnel and the TLS handshake stays end-to-end.
If your proxy inspects TLS rather than tunnelling it, its root CA must be trusted by the operating system the agent runs on — the agent uses the system trust store. Outbound calls to your own REST data sources follow the same variables, unless that connection uses a custom CA or client certificate.
Health checks and monitoring
The agent serves GET /healthz on its listen address. It returns 200 ok whenever the process is running.
/healthz is a liveness check, not a readiness check
It checks nothing — not backend connectivity, not enrollment, not whether a config snapshot ever arrived. An agent that has lost its connection to ConnXL and is serving a stale function set still answers 200. Use it to detect a dead process or an unreachable host; do not use it as a Kubernetes readiness probe or treat it as proof the agent is working.
For real health, use the dashboard: the environment's Agent page shows each replica's CPU, memory and disk with a 24-hour timeline, the last heartbeat, and the config version actually applied. The backend flags an agent offline after roughly 90 seconds without a heartbeat, and alerts can notify you — see Alerts.
Upgrade to a new version
The agent never updates itself. When a replica reports a version older than the latest release, the dashboard flags it and can raise an Update available notification, but nothing is downloaded or replaced without you. An upgrade is: put the new binary in place and restart.
Because there is no deregistration handshake with your load balancer, take the instance out of rotation yourself first — /healthz will keep returning 200 right through a shutdown, so it cannot signal the drain for you.
- Remove the replica from the load balancer.
- Send
drainfrom the Agent page. This tears down streaming subscribers so they reconnect elsewhere; it does not stop the listener or exit. - Stop the service (
SIGTERM, orsystemctl stop). In-flight requests get up to 10 seconds to finish, so allow at least 30 seconds of stop timeout. - Replace the binary and start the service again.
- Confirm the new version on the Agent page, then return the replica to rotation.
With more than one replica, do this one at a time and the environment stays up throughout.
Rolling back
Rollback is the same procedure with the older binary — the agent keeps no version-specific state on disk, and its enrolled certificate stays valid. Keep the previous binary until you have confirmed the new one is serving.
What the agent stores on disk
| Location | Contents |
|---|---|
<data dir>/identity/ | The enrolled mTLS certificate and private key (directory mode 0700) |
<data dir>/logs/ | One dated log file per day, pruned after 7 days |
<state dir>/lease.json | Cached entitlement lease |
~/.connxl/ | The OS-keyring index and the encrypted-file secret store, if used |
Cached function results are held in memory, or in Valkey/Redis when the environment configures an external cache — never on disk.
You do not need to back any of this up. If the data directory is lost, the agent re-enrolls automatically on the next boot and carries on, as long as its enrollment token (or cloud attestation, or stamped identity) is still in its environment. The only cost is a new certificate and a fresh log history. You need a new token only if an admin has since clicked Regenerate.
Do protect the private key
Nothing needs backing up, but the identity directory holds a live credential. Keep it on local disk with its restrictive permissions intact rather than on a shared volume, and never bake it into a machine image that gets cloned.
Sizing and scaling
The agent is a lightweight proxy: it holds no dataset, and its work is dominated by waiting on your data sources. A small instance — 1 vCPU and 512 MB of memory — comfortably runs a typical environment, and disk use is limited to a week of logs.
Scale out, not up. Add replicas behind a load balancer when you need throughput or redundancy:
- All replicas of an environment share one enrollment token and appear individually on the Agent page.
- No session affinity is required — the agent keeps no per-user state between requests.
- Size for concurrency at your data sources first; the SQL pool defaults (20 open connections per engine, per replica) multiply by replica count.
Retire an agent
To decommission a host cleanly:
- Take it out of rotation and confirm traffic has moved to another replica.
- Stop the service and disable it from starting at boot.
- Evict the replica from the environment's Agent page. This block-lists it so it cannot reconnect even if the process comes back — the reliable way to cut off a host you no longer control.
- Delete the data directory to destroy the private key on disk.
- If you are retiring every agent for that environment, click Regenerate on the Deploy tab so the old enrollment tokens stop working.
Stopping the process is not revocation
A stopped agent still holds a valid certificate. Until you evict it, restarting the binary rejoins the environment. Evict first, then delete.
Glossary
Every ConnXL term in one place, with the one distinction people get wrong most often: an add-in is what you create, an agent is what runs it.
Install the add-in
Installing ConnXL means two things: running the agent on a host your Excel users can reach, and getting the generated manifest into Excel. The agent serves the add-in; the manifest just tells Excel where the agent lives.