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

DependencyRequired VersionNotes
Node.js22+Runtime for both Synth server and Envoy
npm10+Ships with Node.js 22
SQLitebundledEmbedded via better-sqlite3; no external install needed
Docker24+ (optional)Only required for Docker-based deployment
Git2.xFor 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

VolumeContainer PathPurpose
synth-data/dataSynth server's SQLite databases (entities + debrief)
envoy-workspace/workspaceEnvoy'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

VariableDefaultDescription
PORT9410HTTP port for the Synth server
HOST0.0.0.0Bind address
NODE_ENVdevelopmentSet to production for deployed environments
SYNTH_DATA_DIRdataDirectory for SQLite databases (synth.db, debrief.db)
SYNTH_API_KEYunsetEnables bearer token authentication on all endpoints except GET /health. When unset, auth is disabled.
SYNTH_CORS_ORIGINunset (reject all)Allowed CORS origin(s). Single URL or comma-separated list. When unset, all cross-origin requests are rejected.
SYNTH_SEED_DEMOtrueSet to false to skip demo data seeding on first run
SYNTH_RATE_LIMIT_MAX100Maximum requests per time window
SYNTH_RATE_LIMIT_WINDOW_MS60000Rate limit window in milliseconds
SYNTH_MCP_SESSION_TTL_MS3600000MCP session time-to-live (1 hour)
SYNTH_MCP_CLEANUP_INTERVAL_MS600000MCP session cleanup interval (10 minutes)
SYNTH_LLM_API_KEYunsetAPI key for LLM-powered features (planning, diagnostics, artifact analysis). Supports Anthropic, OpenAI, and other providers. Agent degrades gracefully without it.
SYNTH_LLM_PROVIDERanthropicLLM provider to use. Options: anthropic, openai, bedrock, vertex, openai-compatible.
SYNTH_LLM_BASE_URLunsetCustom base URL for the LLM API. Required for openai-compatible provider.

Envoy Environment Variables

VariableDefaultDescription
ENVOY_PORT9411HTTP port for the Envoy agent
ENVOY_HOST0.0.0.0Bind address
ENVOY_BASE_DIR.envoy (cwd)Base directory for deployment workspaces and local state
SYNTH_SERVER_URLemptyURL of the Synth server (e.g., http://synth-server:9410). Required for Envoy to report results back.
SYNTH_LLM_API_KEYunsetEnables 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.

SettingDefaultDescription
environmentsEnabledtrueEnable multi-environment support
agent.conflictPolicypermissiveHow to resolve partition/environment variable conflicts (strict or permissive)
agent.defaultHealthCheckRetries1Default health check retry count for new operations
agent.defaultTimeoutMs30000Default step execution timeout
agent.defaultVerificationStrategybasicDefault verification strategy (basic, full, or none)
agent.llmEntityExposurenamesWhat entity data is sent to the LLM (names or none)
envoy.urlhttp://localhost:9411URL of the Envoy agent for Synth to dispatch deployments
envoy.timeoutMs10000Timeout for Synth-to-Envoy HTTP requests
coBrandingunsetOptional 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.