Syncle

Installation

Syncle installs with one command on any machine that has Docker. The installer needs Docker with Compose v2 and curl, and nothing else — Node, Postgres and Redis run in containers, and the app image is pulled prebuilt from GHCR, so nothing is compiled and the repository is never cloned.

The one-command install

curl -fsSL https://syncle.dev/install | sh -s -- up

syncle.dev/install redirects to install.sh at the head of the repository, so this is the same script you can read on GitHub before running it. The trailing -s -- up hands the script an up argument so it starts Syncle immediately after installing; drop it to install without starting. The script checks its prerequisites up front and stops with a plain error if curl or Docker is missing, or if docker compose version fails.

What it actually does, in order:

  1. Resolves the version to install — the newest published release, falling back to main if the GitHub API is unreachable.
  2. Downloads exactly two files into ~/.syncle: docker-compose.app.yml and the syncle launcher.
  3. Generates SYNCLE_MASTER_KEY — the key that encrypts saved database credentials — into ~/.syncle/.env, created with mode 600. An existing key is kept on a re-run.
  4. Pins SYNCLE_IMAGE in the same file, so syncle up keeps running the installed version until syncle update moves the pin.
  5. Installs the launcher to /usr/local/bin (retrying with sudo), or to ~/.local/bin if it cannot — printing the export PATH="$HOME/.local/bin:$PATH" line to add if that directory is not already on your PATH.

Four environment variables steer the installer and the launcher; the defaults are right for almost everyone:

VariableDefaultPurpose
SYNCLE_HOME~/.syncleWhere the compose file, .env and version marker live. Read by both the installer and the launcher.
SYNCLE_PORT3002Host port for the web GUI. Read by the launcher.
SYNCLE_REFnewest releaseGit ref the installer fetches its two files from.
SYNCLE_IMAGEthe tag matching the releaseApp image to run instead of the default GHCR one.

The syncle launcher

After install, the syncle command manages the stack from any directory. Running it with no arguments means syncle up.

CommandWhat it does
syncle upPull newer images, start everything, wait for the web GUI, open it in the browser.
syncle downStop and remove the containers. Data is kept.
syncle restartRestart the running containers.
syncle statusShow container status. Alias: syncle ps.
syncle logs [svc]Follow logs, optionally for one of api, web, postgres, redis. syncle logs api shows the first-run setup token.
syncle openOpen the web GUI in the browser.
syncle updateFetch the newest release and restart.
syncle uninstallStop everything and delete all data. Asks first.
syncle versionPrint the installed Syncle version.

syncle up pulls images best-effort — offline, it falls back to what is already downloaded — then starts the containers and polls the web GUI until it answers. The browser opens via open on macOS or xdg-open on Linux; anywhere else the URL is printed instead. On a first run it also reads the one-time setup token from the api container and opens the GUI with the setup form prefilled — the quickstart walks through what happens from there.

Ports

The web GUI is the only published port — http://localhost:3002 by default. To run it somewhere else, set the port at launch:

SYNCLE_PORT=8080 syncle up

The API listens on 4002 inside the compose network but is deliberately not published: the browser reaches it through the web app's /api proxy, so only one port has to be open. The compose file carries a commented ports mapping on the api service for calling the HTTP API directly from outside the stack. Syncle's own Postgres and Redis publish no host ports at all.

The manual Docker Compose route

If you would rather not pipe curl into sh, the same stack runs from the compose file alone. Set an explicit master key first — generated once, then kept forever:

curl -fsSLO https://raw.githubusercontent.com/osmanahmadxai/SYNCLE/main/docker-compose.app.yml
export SYNCLE_MASTER_KEY="$(openssl rand -base64 32)"
docker compose -f docker-compose.app.yml up -d

With SYNCLE_MASTER_KEY left empty, the API generates a key of its own inside the syncle-api-data volume — stored next to the data it protects, and lost with it if the volume is removed — which is why setting one explicitly is worth the extra line. Compose reads the variable on every up, so keep it somewhere it will be set again; an .env file next to the compose file works, which is exactly what the installer sets up in ~/.syncle.

On this route there is no launcher to fetch the first-run setup token for you. It is printed to the api container's console — read it with docker compose -f docker-compose.app.yml logs api.

Image tags

One app image runs both the api and web containers: ${SYNCLE_IMAGE:-ghcr.io/osmanahmadxai/syncle:latest}. Image tags on GHCR drop the release tag's v prefix: the git tag v1.1.0 publishes image 1.1.0, and asking for ghcr.io/osmanahmadxai/syncle:v1.1.0 gets not found. The installer maps this for you (and installs from main as latest); when pinning by hand with SYNCLE_IMAGE, use the numeric tag.

Building the image yourself

The compose file has an opt-in build profile that builds the image from a checkout of the repository instead of pulling it:

docker compose -f docker-compose.app.yml --profile build build
SYNCLE_IMAGE=syncle-app:local docker compose -f docker-compose.app.yml up -d

The first command produces syncle-app:local from the repository's Dockerfile; the second runs the stack from it. The builder service itself never starts and is never pulled.

Updating and uninstalling

syncle update re-runs the installer, which refreshes the compose file and the launcher and re-pins the image to the newest release — the encryption key in ~/.syncle/.env is preserved — then pulls the images and restarts the containers.

syncle down stops the containers and keeps all data; the next syncle up carries on where you left off. syncle uninstall is the destructive one: after a y/N confirmation it removes the containers, images and every data volume, deletes ~/.syncle, and removes the launcher from the PATH. Syncle's metadata — saved connections, bridges, job history — lives in those volumes and goes with them, so read the self-hosting page on what to back up first.