Installation & Configuration
This guide covers installing and configuring Synth for production use. Synth runs as two components: the Synth server (the orchestration server) and Envoy (lightweight deployment agents on target machines).
Prerequisites
| Dependency | Required Version | Notes |
|---|---|---|
| Node.js | 22+ | Runtime for both Synth server and Envoy |
| npm | 10+ | Ships with Node.js 22 |
| SQLite | bundled | Embedded via better-sqlite3; no external install needed |
| Docker | 24+ (optional) | Only required for Docker-based deployment |
| Git | 2.x | For cloning the repository (unless using Docker images) |
Quick Start with install.sh
The installer script sets up the Synth server and/or Envoy as system services on Linux (systemd) or macOS (launchd). It clones the repository, builds all packages, copies artifacts to the install directory, and creates service definitions.
# Install both the Synth server and Envoy
curl -fsSL https://raw.githubusercontent.com/synth-deploy/synth/main/install.sh | bash
# Or clone and run locally
git clone https://github.com/synth-deploy/synth.git
cd synth-deploy
./install.sh --local Installer Options
./install.sh [OPTIONS]
Options:
--component <name> server, envoy, or all (default: all)
--install-dir <path> Installation directory (default: /opt/synth)
--data-dir <path> Data/SQLite directory (default: /var/lib/synth)
--local Use current directory as source instead of cloning
--server-url <url> Synth server URL for Envoy (default: http://localhost:9410) After installation, the script prints service management commands specific to your OS. Default paths:
- Install directory:
/opt/synth - Data directory:
/var/lib/synth(SQLite databases, logs, Envoy workspaces)
Linux (systemd)
# Synth server
sudo systemctl start synth-server
sudo systemctl status synth-server
journalctl -u synth-server -f
# Envoy service
sudo systemctl start synth-envoy
sudo systemctl status synth-envoy
journalctl -u synth-envoy -f macOS (launchd)
# Synth server
launchctl load ~/Library/LaunchAgents/com.synthdeploy.server.plist
launchctl unload ~/Library/LaunchAgents/com.synthdeploy.server.plist
tail -f /var/lib/synth/server.log
# Envoy service
launchctl load ~/Library/LaunchAgents/com.synthdeploy.envoy.plist
launchctl unload ~/Library/LaunchAgents/com.synthdeploy.envoy.plist
tail -f /var/lib/synth/envoy.log Docker Deployment
The included docker-compose.yml runs both the Synth server and Envoy with
health checks, volume persistence, and resource limits.
# Clone the repository
git clone https://github.com/synth-deploy/synth.git
cd synth-deploy
# Start both services
docker compose up -d
# Verify
curl http://localhost:9410/health
curl http://localhost:9411/health The Synth server listens on port 9410 and Envoy on port 9411. The Envoy container waits for the Synth server's health check to pass before starting.
Production docker-compose.yml
Customize the compose file for production by setting environment variables, disabling demo seed data, and enabling authentication:
services:
synth-server:
build:
context: .
dockerfile: Dockerfile.server
ports:
- "9410:9410"
volumes:
- synth-data:/data
environment:
- NODE_ENV=production
- SYNTH_DATA_DIR=/data
- SYNTH_API_KEY=your-secret-key
- SYNTH_CORS_ORIGIN=https://deploy.example.com
- SYNTH_SEED_DEMO=false
- SYNTH_LLM_API_KEY=sk-ant-...
mem_limit: 512m
cpus: 1.0
envoy:
build:
context: .
dockerfile: Dockerfile.envoy
ports:
- "9411:9411"
volumes:
- envoy-workspace:/workspace
environment:
- NODE_ENV=production
- SYNTH_SERVER_URL=http://synth-server:9410
depends_on:
synth-server:
condition: service_healthy
mem_limit: 512m
cpus: 1.0
volumes:
synth-data:
envoy-workspace: Docker Volumes
| Volume | Container Path | Purpose |
|---|---|---|
synth-data | /data | Synth server's SQLite databases (entities + debrief) |
envoy-workspace | /workspace | Envoy's deployment workspaces and artifacts |
Both containers run as a non-root synth user (UID/GID 1000)
with memory limited to 512 MB and 1 CPU core by default.
Configuration Reference
Synth Server Environment Variables
| Variable | Default | Description |
|---|---|---|
PORT | 9410 | HTTP port for the Synth server |
HOST | 0.0.0.0 | Bind address |
NODE_ENV | development | Set to production for deployed environments |
SYNTH_DATA_DIR | data | Directory for SQLite databases (synth.db, debrief.db) |
SYNTH_API_KEY | unset | Enables bearer token authentication on all endpoints except GET /health. When unset, auth is disabled. |
SYNTH_CORS_ORIGIN | unset (reject all) | Allowed CORS origin(s). Single URL or comma-separated list. When unset, all cross-origin requests are rejected. |
SYNTH_SEED_DEMO | true | Set to false to skip demo data seeding on first run |
SYNTH_RATE_LIMIT_MAX | 100 | Maximum requests per time window |
SYNTH_RATE_LIMIT_WINDOW_MS | 60000 | Rate limit window in milliseconds |
SYNTH_MCP_SESSION_TTL_MS | 3600000 | MCP session time-to-live (1 hour) |
SYNTH_MCP_CLEANUP_INTERVAL_MS | 600000 | MCP session cleanup interval (10 minutes) |
SYNTH_LLM_API_KEY | unset | API key for LLM-powered features (planning, diagnostics, artifact analysis). Supports Anthropic, OpenAI, and other providers. Agent degrades gracefully without it. |
SYNTH_LLM_PROVIDER | anthropic | LLM provider to use. Options: anthropic, openai, bedrock, vertex, openai-compatible. |
SYNTH_LLM_BASE_URL | unset | Custom base URL for the LLM API. Required for openai-compatible provider. |
Envoy Environment Variables
| Variable | Default | Description |
|---|---|---|
ENVOY_PORT | 9411 | HTTP port for the Envoy agent |
ENVOY_HOST | 0.0.0.0 | Bind address |
ENVOY_BASE_DIR | .envoy (cwd) | Base directory for deployment workspaces and local state |
SYNTH_SERVER_URL | empty | URL of the Synth server (e.g., http://synth-server:9410). Required for Envoy to report results back. |
SYNTH_LLM_API_KEY | unset | Enables LLM-powered diagnostic investigation on the Envoy. Supports same providers as the server. |
Application Settings (API-managed)
These settings are managed through the PUT /api/settings endpoint
and stored in SQLite. They control runtime behavior independent of environment
variables.
| Setting | Default | Description |
|---|---|---|
environmentsEnabled | true | Enable multi-environment support |
agent.conflictPolicy | permissive | How to resolve partition/environment variable conflicts (strict or permissive) |
agent.defaultHealthCheckRetries | 1 | Default health check retry count for new operations |
agent.defaultTimeoutMs | 30000 | Default step execution timeout |
agent.defaultVerificationStrategy | basic | Default verification strategy (basic, full, or none) |
agent.llmEntityExposure | names | What entity data is sent to the LLM (names or none) |
envoy.url | http://localhost:9411 | URL of the Envoy agent for Synth to dispatch deployments |
envoy.timeoutMs | 10000 | Timeout for Synth-to-Envoy HTTP requests |
coBranding | unset | Optional operator branding: operatorName, logoUrl, accentColor |
mcpServers | [] | External MCP servers for data enrichment (array of {name, url, description?}) |
Architecture Overview
┌─────────────┐ ┌─────────────┐
│ Synth │◄────────►│ Envoy │
│ (port 9410)│ │ (port 9411)│
├─────────────┤ ├─────────────┤
│ REST API │ dispatch │ Executor │
│ MCP Server │─────────►│ Health │
│ Agent │ │ Scanner │
│ Debrief │◄─────────│ Reporter │
│ Entity DB │ report │ Query │
└──────┬──────┘ └──────┬──────┘
│ │
SQLite DBs Workspace Dir
(synth.db, (deployment
debrief.db) artifacts)
Synth is the orchestration server. It stores all entities
(partitions, artifacts, environments, deployments) in SQLite, runs the
intelligent agent, and exposes both a REST API and an MCP server. The UI is
served as static files from the Synth server.
Envoy is a lightweight agent deployed on target machines. It
receives deployment instructions from Synth, executes shell commands in
isolated workspaces, runs health checks and verification, and reports results
back. Envoy maintains its own local state and can run LLM-powered diagnostics
when deployments fail.
Communication flows one direction at dispatch time (Synth sends instructions
to Envoy) and one direction at report time (Envoy posts results back to
Synth). There is no persistent connection between them.
Multi-Envoy Setup
For deploying across multiple machines, install Envoy on each target and point
them at your Synth server.
With Docker
# On target machine: run Envoy pointed at your Synth server
docker run -d \
--name synth-envoy \
-p 9411:9411 \
-v envoy-workspace:/workspace \
-e SYNTH_SERVER_URL=http://server-host:9410 \
-e ENVOY_PORT=9411 \
synth-deploy/envoy
With install.sh
# On target machine: install Envoy only
./install.sh --component envoy --server-url http://server-host:9410
Registering Envoys with Synth
After starting an Envoy, configure Synth to dispatch to it by updating the
Envoy endpoint in settings:
curl -X PUT http://localhost:9410/api/settings \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your-api-key" \
-d '{"envoy": {"url": "http://envoy-host:9411", "timeoutMs": 10000}}'
Each Envoy identifies itself to Synth using a generated ID based on its
host and port (e.g., envoy-0.0.0.0:9411). Envoys report
deployment results and debrief entries back to Synth automatically when
SYNTH_SERVER_URL is set.
Troubleshooting
Synth server fails to start: "EACCES: permission denied"
The data directory is not writable. Ensure the SYNTH_DATA_DIR
path exists and is owned by the user running the Synth server. In Docker, the
synth user (UID 1000) must own the mounted volume.
Envoy cannot reach Synth
Verify SYNTH_SERVER_URL is set and reachable from the Envoy
host. In Docker Compose, use the service name (http://synth-server:9410).
For remote setups, ensure firewalls allow traffic on port 9410.
# From the Envoy host
curl -f http://server-host:9410/health
CORS errors in the browser
Set SYNTH_CORS_ORIGIN to your UI's origin. For development:
SYNTH_CORS_ORIGIN=http://localhost:5173
For production with multiple origins:
SYNTH_CORS_ORIGIN=https://deploy.example.com,https://admin.example.com
Authentication: "401 Unauthorized"
When SYNTH_API_KEY is set, all requests except
GET /health require an Authorization: Bearer <key>
header. Verify the key matches exactly.
Demo data keeps appearing
The Synth server seeds demo data on first startup if the database is empty. To disable:
SYNTH_SEED_DEMO=false
Agent features not working (intent resolution, diagnostics)
LLM-powered features require SYNTH_LLM_API_KEY to be set. Without
it, the agent degrades gracefully: deployments still work, but natural-language
intent resolution and diagnostic investigation are disabled. Check the health
endpoint for LLM connectivity status:
curl http://localhost:9410/health | jq .checks.llm
High memory usage
Both containers default to 512 MB memory limits. If deployments involve large
artifacts or many concurrent operations, increase mem_limit in the
compose file. For bare-metal installs, monitor with:
# systemd
systemctl status synth-server
journalctl -u synth-server --since "1 hour ago" | grep -i memory
Envoy workspace filling up disk
Envoy automatically cleans up old deployment workspaces every 10 minutes,
keeping the most recent 50 workspaces or those less than 30 days old. If disk
usage is still a concern, reduce the workspace retention or mount a larger
volume.