Deploy Graft with Docker
Run your own Sync server for Eidos Lite. Start the container, generate its private
initialization link on the server, then open that complete link to choose storage.
Graft creates the access key for you. The root address and /setup alone are not
authorized setup entry points.
Use local disk for the simplest setup, or configure S3-compatible storage in the browser. Both options need persistent disk space on your server.
Before you start
Section titled “Before you start”- A Linux AMD64 or ARM64 server with Docker Engine and Compose v2 and curl.
- An HTTPS address supplied by your existing proxy or hosting platform. If you need a proxy, use the optional Caddy configuration below.
- Eidos Lite with Spark active on each computer that will use this server. An official Sync subscription is not required.
Caddy is optional. Replace sync.example.com below with your actual hostname.
Run the commands on your server.
1. Download and configure
Section titled “1. Download and configure”For a new installation, create a private directory and download the deployment file:
mkdir -m 700 ~/graft-synccd ~/graft-synccurl -fL --retry 3 -o compose.yaml \ https://github.com/eidos-space/graft/releases/download/graft-docker-v0.2.1/compose.yamlcat > .env <<'EOF_ENV'GRAFT_PUBLIC_ORIGIN=https://sync.example.comEOF_ENVThe file uses the public Graft Docker 0.2.1 release and pins the image by digest. No GitHub login, source checkout or local build is needed. Use an HTTPS address without a path. Run later Compose commands from this directory.
2. Connect HTTPS
Section titled “2. Connect HTTPS”With your existing proxy or platform
Section titled “With your existing proxy or platform”Forward your HTTPS address to http://127.0.0.1:8787 on the server. A proxy in
another container needs the same Docker network and upstream http://graft:8787.
Keep port 8787 private. Allow request bodies of at least 64 MiB and transfers of
at least 120 seconds. Forward paths and authorization headers unchanged and
disable API caching. Continue to step 3.
Optional: add Caddy
Section titled “Optional: add Caddy”Use this option only if you need a proxy. Point your domain’s DNS to the server, make ports 80 and 443 reachable, and ensure no other service occupies them.
curl -fL --retry 3 -o compose.caddy.yaml \ https://github.com/eidos-space/graft/releases/download/graft-docker-v0.2.1/compose.caddy.yamlcurl -fL --retry 3 -o Caddyfile \ https://github.com/eidos-space/graft/releases/download/graft-docker-v0.2.1/Caddyfilecat >> .env <<'EOF_ENV'GRAFT_DOMAIN=sync.example.comCOMPOSE_FILE=compose.yaml:compose.caddy.yamlEOF_ENVUse the same hostname in GRAFT_DOMAIN and GRAFT_PUBLIC_ORIGIN. Caddy starts
alongside Graft and manages certificates. No host installation or system-file editing is needed.
3. Start and open setup
Section titled “3. Start and open setup”Run both commands on your server, from the directory containing compose.yaml.
Get the initialization link before opening the browser; do not open the root
address or type /setup manually to configure storage.
docker compose up -d --waitdocker compose exec graft node services/graft-remote-docker/manage.mjs setup-linkOpen the complete URL printed by setup-link, including #token=…, in your
browser. It points to /setup at your public address and proves access to the
server terminal. Keep the whole link private. Filling in storage details does not
provide this authorization. If HTTPS is not ready, check DNS and proxy logs, then retry.
The link survives restarts until setup completes. If you close the page early,
run the same command to obtain it again. Opening /setup without that link does
not grant permission to configure the server.
4. Complete setup in the browser
Section titled “4. Complete setup in the browser”Choose Local disk to continue without extra fields. To use S3-compatible storage, enter the details of an existing private bucket:
| Field | Value |
|---|---|
| S3 endpoint | Your provider’s HTTPS S3 API endpoint |
| Region | The region specified by your provider |
| Bucket name | An existing dedicated bucket, or one with a prefix reserved for this installation |
| Access Key ID / Secret Access Key | Bucket-scoped S3 credentials |
Advanced settings contain the object prefix (default graft/), path-style
addressing and an optional session token. Use a dedicated prefix ending in /
and the addressing style your provider supports.
For S3, choose Test connection. Graft writes, reads and deletes a temporary object. Correct errors before continuing. Credentials also need multipart-upload permissions, including aborting incomplete uploads; versioned buckets need permission to delete object versions. This connection test does not verify large multipart uploads. Avoid retention, Object Lock or expiration rules that interfere with the installation’s objects.
Click Complete setup. Save the displayed server address and access key in your password manager. The key grants access to every Space on this server. The page displays it only once; see recovery below if you lose it.
Graft generates the key and saves configuration automatically. No terminal password generation, secret-file creation or permission commands are needed. Restarting or upgrading does not reopen setup.
5. Connect Lite
Section titled “5. Connect Lite”In Lite, open Sync → Add server, enter a name, paste the server address and access key, then choose Test and save. Select the server for your Space and follow the prompts. See Connect a self-hosted server.
The server address must not include /setup or the initialization credential.
Your Space sync password is separate: it encrypts and unlocks your Space.
Save both. For an already connected Space, use Switch server instead of
replacing its address.
Add a record and a small attachment, then download the Space on another computer. Open both, edit a record there and confirm the first computer receives the change. This checks synchronization beyond a server health check.
Maintain the installation
Section titled “Maintain the installation”Retrieve the access key
Section titled “Retrieve the access key”If you did not save the key, run this on the server:
docker compose exec graft node services/graft-remote-docker/manage.mjs access-keyThis retrieves the existing key without changing it or reopening setup. Do not include keys or initialization links in screenshots or support messages.
Stop, restart and back up
Section titled “Stop, restart and back up”Use docker compose stop and docker compose start from the deployment directory.
Keep its files and data volumes. Do not use docker compose down -v unless you
intend to delete the installation’s local data. Run one Graft instance per data volume.
Pause synchronization and stop Graft before backing up:
- Local storage: back up the complete
/datavolume, including its private configuration. - S3 storage: back up
/dataand matching bucket objects while stopped. Neither copy alone is sufficient. S3 mode still uses server disk for metadata, upload parts and assembled uploads. - Back up Compose files,
.env, externally managed secrets and, if used, Caddy’s certificate data. Keep Space sync passwords separately.
Protect backups: web configuration contains the server key and any S3 credentials. Test restoration into a separate empty volume and verify a client download. Object storage alone is not a backup; synchronization can delete objects.
Upgrade an existing installation
Section titled “Upgrade an existing installation”Back up first. Download the new release’s files into a separate directory and
compare them with your installation. Update the image reference and necessary
settings, preserving data volumes, .env and credentials. Then run:
docker compose pulldocker compose up -d --waitUpgrading from 0.1.1: keep your existing Compose file and mounted access-key
file. Update its image reference to the new release’s digest. Existing key-file
deployments remain supported and skip web setup. Replacing their Compose file
with the new default would omit the key mount. The compose.secrets.yaml release
asset supports externally managed keys with the new template.
Changing storage mode, endpoint, bucket or prefix does not migrate data. Deploy a separate server with fresh storage, then use Lite’s Switch server flow.
S3 provider examples
Section titled “S3 provider examples”For Cloudflare R2, use the bucket’s S3 endpoint and
region auto.
Create S3 credentials with
bucket-scoped Object Read & Write permission, rather than a general API token.
For Backblaze B2, use the bucket’s endpoint and region and a bucket-restricted
application key:
keyID is the Access Key ID and applicationKey is the Secret Access Key.
Web setup was tested with local disk and MinIO S3. R2 storage was also tested in the previous server release; B2 is a configuration example, not a claim of live B2 acceptance. Provider storage, request and transfer charges apply.
Troubleshooting
Section titled “Troubleshooting”| Problem | Next step |
|---|---|
| Container fails to start | Run docker compose logs --tail=100 graft; check volume permissions and free disk space. |
| Setup link does not open | Check the public address, DNS and HTTPS proxy. With optional Caddy, inspect docker compose logs --tail=100 caddy. |
| Test connection / Complete setup stays disabled | Run docker compose exec graft node services/graft-remote-docker/manage.mjs setup-link on the server from the Compose directory; open its complete output, including #token=…. Storage fields cannot authorize setup. |
| Initialization link is invalid or incomplete | Retrieve it again from the same installation. Links do not expire with time; they become invalid when setup completes. If already complete, use the access-key command above instead. |
| Setup rejects a submission | Open the link directly at the HTTPS address matching GRAFT_PUBLIC_ORIGIN, without a redirect to another origin. |
| Setup says it is complete | Use your saved key or the access-key recovery command. |
| S3 test fails | Check endpoint, region, bucket, addressing style and permissions. If deletion was denied, clean up any leftover test object before retrying. |
/healthz returns 503 before setup |
Expected: finish setup first. Container liveness uses /livez; it does not prove synchronization works. |
| Lite reports an authorization error | Use the server key, not the setup credential, S3 credentials or Space sync password. |