Skip to main content

Deploy with Docker

Goal: run a Hub, the admin console and PostgreSQL 16 on one server with a single command.

Before you start:

  • Windows, macOS: Docker Desktop in Linux container mode.
  • Linux: Docker Engine with Compose v2.
  • Python 3.12 or later on the host. You don't need Node.js or a database on the host.
  • A network connection for the first build, and 20 GB of free disk space.

Images are built from the source on your machine, using Docker Hub, npm, PyPI and the official PostgreSQL image.

1. Start​

In the source folder, run:

python ops/self-host/deploy.py up

On macOS and Linux you can use python3 ops/self-host/deploy.py up. You can also run ops/self-host/deploy.cmd up or sh ops/self-host/deploy.sh up.

The first run:

  1. creates a private configuration with its own database password, initial administrator password, signing key and connector encryption key;
  2. builds the admin console and the Hub image;
  3. migrates the new database;
  4. runs a health check.

When the health check passes, it shows the address: http://127.0.0.1:18989. Build time depends on your network and mirrors.

2. Get the administrator password​

python ops/self-host/deploy.py credentials

The account is admin. After you sign in, change the password in User management. credentials always shows the first-boot password; it does not reset a password you have changed. Normal startup and build logs don't print passwords.

3. Connect clients​

Follow Connect the desktop client and use this Hub's address.

Manage the instance​

CommandWhat it does
python ops/self-host/deploy.py statusShow container status
python ops/self-host/deploy.py logsShow logs
python ops/self-host/deploy.py stopStop this instance. The database, files and keys are kept
python ops/self-host/deploy.py up --no-buildRestart the image you already built
python ops/self-host/deploy.py upRebuild after updating the source, then start

stop never removes volumes or other Docker resources. If a build or health check fails, the command reports the failure instead of starting a partial service. You can run it again.

Use another port or directory​

python ops/self-host/deploy.py up --port 18990 --data-dir "/srv/soduwork-team"

The directory must be outside the source folder and empty. Each directory has its own Compose project and data volumes. Use the same --data-dir for every later command. --port applies only to the first start.

Give your team access​

The Hub is mapped only to 127.0.0.1, and PostgreSQL is not mapped to the host. For team access:

  1. Set up an HTTPS reverse proxy on this server that forwards to 127.0.0.1:18989. It must support WebSocket and long streaming responses.

  2. Set the public address on the first start:

    python ops/self-host/deploy.py up --public-url https://work.example.com

    Replace work.example.com with your domain. Use an HTTPS origin only, without /api, account names or query strings.

To change the address of an existing instance, stop it, edit publicUrl in its deployment.json, then run python ops/self-host/deploy.py up --no-build.

The launcher does not request certificates, change DNS or change the firewall. After the proxy is live, check sign-in, file upload, WebSocket and a streaming chat through it.

Where the data is​

SystemPrivate configuration directory
Windows%LOCALAPPDATA%\SoduWork\self-host
macOS~/Library/Application Support/SoduWork/self-host
Linux$XDG_DATA_HOME/soduwork/self-host, or ~/.local/share/soduwork/self-host
  • deployment.json holds this instance's passwords and keys. Keep it private and do not commit it.
  • The database and business files live in Docker named volumes. Their names start with the project value in deployment.json.
  • The configuration directory is not a backup of your data. Resetting or uninstalling Docker Desktop, or deleting volumes, deletes the data.

Where work runs​

The Hub container does not run agents. Local work runs in each user's client. For cloud work, register a separate runner in the admin console (Runners and cloud environments). The container runs as a regular user and does not mount the Docker socket.

Next​

Edit this page