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 -- upsyncle.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:
- Resolves the version to install — the newest published release, falling back to
mainif the GitHub API is unreachable. - Downloads exactly two files into
~/.syncle:docker-compose.app.ymland thesynclelauncher. - 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. - Pins
SYNCLE_IMAGEin the same file, sosyncle upkeeps running the installed version untilsyncle updatemoves the pin. - Installs the launcher to
/usr/local/bin(retrying with sudo), or to~/.local/binif it cannot — printing theexport 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:
| Variable | Default | Purpose |
|---|---|---|
SYNCLE_HOME | ~/.syncle | Where the compose file, .env and version marker live. Read by both the installer and the launcher. |
SYNCLE_PORT | 3002 | Host port for the web GUI. Read by the launcher. |
SYNCLE_REF | newest release | Git ref the installer fetches its two files from. |
SYNCLE_IMAGE | the tag matching the release | App 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.
| Command | What it does |
|---|---|
syncle up | Pull newer images, start everything, wait for the web GUI, open it in the browser. |
syncle down | Stop and remove the containers. Data is kept. |
syncle restart | Restart the running containers. |
syncle status | Show 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 open | Open the web GUI in the browser. |
syncle update | Fetch the newest release and restart. |
syncle uninstall | Stop everything and delete all data. Asks first. |
syncle version | Print 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 upThe 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 -dWith 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 -dThe 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.
