Skip to main content

Installation

This guide walks you through setting up a CoderFlow server. Before exposing the server to a network you do not fully trust, review Security & Hardening.

Install with the installer​

The installer sets up CoderFlow Full on your own Linux server. It creates a separate account to install and run the server.

Supported systems are Ubuntu 22.04 or 24.04 LTS and Debian 12 or 13, on x86-64 or arm64, with systemd and cgroup v2. Install Docker Engine first. Use an ordinary account with sudo permission and access to the local Docker socket.

  1. Download the installer as an ordinary Linux user.

    curl --fail --location --proto '=https' --proto-redir '=https' -o install.sh https://coderflow.ai/install.sh
  2. Read the script and check your host. --preflight-only checks prerequisites without changing the host or invoking sudo.

    less install.sh
    bash install.sh --preflight-only
  3. Run the installer. Review the plan and confirm when prompted.

    bash install.sh
  4. The output prints the server address and Machine ID. Decline the offer to create an administrator in the terminal to receive a one-time setup link. Open that link, create the administrator, and install your license on the License page that follows. The link works on an unlicensed server. Once the key is accepted, the page says Restart the server to finish applying the license. Run sudo systemctl restart coderflow.service on the host, refresh the page, then open the dashboard for the Setup guide. The installer's last note names the same command. See Restart after the first license for --no-systemd and other hosts. If you created the administrator in the terminal instead, sign in with that account and follow the same license steps.

Standalone mode needs Python 3, curl and the other distribution tools listed by preflight. It downloads the server archive as your operator account and verifies npm's SHA-512 integrity value. It keeps temporary files private and removes them on exit. The checks may download these temporary files, but install no software.

:::note Package registry The current installer downloads CoderFlow from registry.npmjs.org, which stops at 0.16.0, so --version cannot select a later release. After installing, upgrade once with the steps for installer-based servers. Do not set --registry to npm.profoundlogic.com: it serves only @profoundlogic packages, and --registry applies to every dependency. See Profound Logic package registry. :::

What changes on the host​

  • A dedicated coderflow account with a home and no password, unless a suitable account already exists.
  • Membership of the docker group for that account. This grants host-level access.
  • A coderflow.service unit, enabled for boot and started after setup.
  • Verified installer copies in a root-owned /opt/coderflow-installer-… directory.
  • NVS, Node.js 24, the server package, setup repository and data in the account's home. The installer also adds NODE_ENV=production to its .profile.
  • Permission for the chosen privileged port, only if you request --authbind.

The installer does not install Docker or authbind. It does not accept passwords or license keys as arguments. Root never runs code from the account's home.

To read the root helper before allowing any privileged work, run bash install.sh --print-root-helper. Use bash install.sh --dry-run to see the commands. After confirmation, the installer stages the files itself and prints both their SHA-256 hashes and their root-owned directory.

Options​

OptionPurpose
--user NAMEDedicated account; default coderflow
--port NUMBERListen port; default 3000
--authbindAllow a port below 512; ports 512–1023 are refused; install authbind first
--version X.Y.ZChoose a published version, including a prerelease
--package /absolute/server.tgzUse a local server archive
--registry HTTPS_URLUse an npm mirror; credentials in the URL are refused
--setup-path /absolute/repositoryReuse an existing setup repository without modifying it
--setup-remote=hosted|noneRemote for a new setup repository; the installer defaults to hosted
--check-host HOSTAdd an outbound HTTPS warning check; repeatable
--helpPrint help offline, without downloads or host checks
--preflight-onlyCheck prerequisites only
--print-root-helperPrint the privileged helper for review
--dry-runCheck prerequisites and print the conditional command plan
--yesSkip questions; never create an admin interactively
--forceBack up and replace a different unit or authbind permission
--no-systemdUse daemon startup on a supported systemd host
--skip-base-imageSkip the installer's explicit base-image build; the server's automatic build is controlled separately below

Paths must be absolute and contain no spaces, shell characters or .. components. --yes uses noninteractive sudo. Authorize sudo beforehand if your policy requires it.

Install a specific version or local package​

For a published version, replace X.Y.Z with its version number:

bash install.sh --version X.Y.Z

For a release candidate, copy install.sh and the server archive onto the host:

bash install.sh --package /absolute/server.tgz

There is no unpacking or manual staging step. The installer takes its helpers and the server from the same archive. A registry download is verified against its published integrity value. A local archive is checked for server-package contents and its SHA-256 is printed; verify that digest with the archive's supplier.

The archive is streamed to private staging owned by the dedicated account. It is not downloaded again. Dependencies may still need npm. NVS and Node need GitHub and nodejs.org, and images need Docker Hub. This is not an offline installation.

Run again or resume​

Rerun the same command after fixing a reported failure. Completed steps remain in place. The installer preserves an existing account's identity and setup repository. Identical staged files and an identical service unit are reused. A different service unit needs --force and receives a backup.

Partial setup or NVS directories are left for inspection. Base-image failure warns without undoing installation. To upgrade, select a new version or archive and restart the service in a maintenance window. Standalone mode resolves latest on each run; pin a version or keep your archive for an identical rerun.

Interactive installation offers coder-server create-user --admin. That command prompts for the password itself. Verify the account as described in the manual admin instructions below when creating it while the server is running.

If you decline, or use --yes, the installer sends a one-time link directly to your terminal. It lasts 60 minutes by default. Creating another link cancels the previous one. An existing user prevents a new first-admin link. See First sign-in for the browser steps.

Without a controlling terminal, the installer creates no link. Sign in as the dedicated account and run coder-server setup-link in a terminal later. During installation, the CLI’s localhost fallback, license and failure notes also go directly to your terminal. They are not copied into installer logs or redirected output. Do not record the terminal while a real link is displayed.

Logs​

Private installer logs are ~/.coderflow-install.*.log in the dedicated account's home. Their mode is 0600. They contain fixed progress messages and never the setup link. Command results are shown on screen.

To inspect service diagnostics:

sudo journalctl -u coderflow.service --since today

Noninteractive startup writes a fixed NO SERVER ADMIN reminder, never a setup link. Preflight reports an inspection it cannot perform as CAN'T TELL. Required failures and unknowns stop installation. AI-provider connectivity and rotational storage produce warnings.

Remove the installation​

There is no automatic uninstall. Back up the data you need and inspect the unit before removing it:

sudo systemctl disable --now coderflow.service
sudo unlink /etc/systemd/system/coderflow.service
sudo systemctl daemon-reload

Restore a reviewed unit backup if needed. Remove only the authbind permission for the chosen port. Uninstall the npm package as the dedicated account.

If the installer created the account, stop its processes and run sudo userdel coderflow without -r. This leaves its home for deliberate archival or removal. Do not delete an account that was reused. Docker, images and server data need separate retention decisions. Reviewed staging directories under /opt can be removed after checking their contents and that they are not links.

For manual staging, detailed checks, older-package compatibility and VM acceptance, read the shipped dist/deploy/install/README.md. Existing installations with direct TLS or a custom server data directory should use the manual path below.

Prerequisites​

The rest of this page is the manual installation path. Run it as the dedicated server account except where a command explicitly needs root.

After preparing the host, install the server and create a setup repository. Then choose either order:

  1. In the terminal before the first start: install the license with coder-server license set, create the administrator with coder-server create-user --admin, then start the server.
  2. In the browser after the first start: start the server, create the administrator with the one-time link, then install the license on the License page that follows.

A Linux server with the following installed:

Optionally, if you'd like the server to listen on a port below 1024 (such as 443 or 80):

  • On Ubuntu and Debian-based distros - Install authbind via APT package manager.
  • Other distros - See your distro's documentation for enabling non-root users to bind network services to privileged ports

Root Permissions​

info

Only a few parts of the installation process require root permissions.
Do not use root permissions (i.e. sudo or su) except where specifically instructed.
The server installs and runs as a non-root user.

Create a Dedicated Linux User For Each Installation​

Each installation of CoderFlow server should run under a unique and dedicated user account, rather than your personal account or root. This provides better security isolation and makes it easier to manage the service.

Create a dedicated user (we suggest coder, but any name works):

# Create the user with a home directory
sudo useradd -m -s /bin/bash coder

# Set a password (optional, if you need interactive login)
sudo passwd coder

# Add the user to the docker group so it can manage containers
sudo usermod -aG docker coder

If coder conflicts with an existing user on your system, choose a different name — the server works the same regardless of the username.

Optional: If Using Server Listen Port Below 1024​

If you'd like to use a server listen port below 1024 (e.g. 443), configure authbind to allow the dedicated CoderFlow user to use the port:

For example, for port 443:

sudo touch /etc/authbind/byport/443
sudo chown coder /etc/authbind/byport/443
sudo chmod 500 /etc/authbind/byport/443

Switch to Dedicated CoderFlow User​

Switch to the dedicated user before proceeding with installation:

sudo su - coder

Install Node.js via NVS​

Use the installation guide to install Node Version Switcher (NVS) in the dedicated user's home directory. This allows each CoderFlow installation/user to use a separate version of Node.js. If you prefer, you can use nvm instead, but NVS will be used in this documentation.

After installing NVS, exit and restart your shell and then install Node 24:

nvs add node/24
nvs use node/24
nvs link node/24

Keep Node.js and task images patched​

Use the latest Node 24.x patch (at least 24.22.1). Patched Node 26.x (at least 26.12.1) is also supported. Node 22 and older, Node 23, and Node 25 are not supported by CoderFlow. Newer majors beyond the known security floors are allowed; keep those lines patched too. These minimums include the October 21, 2026 Node.js security fixes. Continue applying later security updates; these minimums are not a permanent guarantee.

Updating CoderFlow from Admin or npm does not update Node.js. As the dedicated server user, repeat the following when a Node 24 patch is released:

nvs add node/24
nvs use node/24
nvs link node/24
node --version

With nvm instead:

nvm install 24
nvm use 24
nvm alias default 24
node --version

Version managers can keep global npm packages in separate version directories. If needed, reinstall your approved CoderFlow server version under the new Node installation. Update any service ExecStart or PATH that points at the old Node directory, reload the service configuration, and restart CoderFlow using your existing service manager. Check the running Node version in Server Administration → Health (open the CPU Usage card for system details) after restart; the shell version alone does not prove the server was updated. Older or unsupported runtimes produce a startup warning and a visible notice above the Server Version card on Health, as well as in system details, but do not prevent the server from starting.

Then rebuild the CoderFlow base image first, followed by environment images, and recreate task containers from those images. Rebuilding images does not replace existing containers. Base builds explicitly pull the upstream Node 24 image; if the registry is unreachable, they warn and use a locally cached image when available. This fallback does not guarantee patched Node. For air-gapped installs, import an approved patched upstream image before rebuilding and verify node --version inside newly created task containers. Custom Dockerfile stages or independently managed images require their own upstream refresh and runtime verification. --no-cache alone does not pull newer base images.

Setup​

Install the Server​

CoderFlow packages come from Profound Logic's package registry, https://npm.profoundlogic.com/. Point the account's npm at it for the @profoundlogic scope, then look up the current release:

npm config set @profoundlogic:registry https://npm.profoundlogic.com/
npm view @profoundlogic/coderflow-server dist-tags

Install that version, replacing <version> with the latest value printed above:

npm install -g @profoundlogic/coderflow-server@<version>

Always name the version. Without the scope line, an unpinned install silently gets 0.16.0, the last version on registry.npmjs.org; see Pin the version.

npm 11 may print install scripts not yet covered by allowScripts for bcrypt, ssh2, bufferutil and protobufjs, then skip their install scripts. This warning is expected; prebuilt binaries or JavaScript fallbacks can still work. Confirm these modules load with coder-server doctor on releases that include it. On an older package, run this as the dedicated account after installation:

node - "$(npm root -g)/@profoundlogic/coderflow-server/package.json" <<'JS'
const requireServer = require('node:module').createRequire(process.argv[2]);
for (const name of ['bcrypt', 'ssh2', 'bufferutil', 'protobufjs']) requireServer(name);
console.log('Native module entry points load');
JS

Loading does not verify native acceleration. Fix failed dependencies before starting; do not blanket-enable scripts to hide the warning.

Create a Setup Repository​

The setup repository contains your environments, task templates, and configuration.

If your organization already has a setup repository, clone it:

git clone https://github.com/your-org/mycompany-coder-setup.git

Otherwise, create a new one:

coder-server init mycompany-coder-setup --setup-remote=hosted

This creates a Git setup repository with an empty environments/ directory. It creates no environment and sets no default environment. You create the first one in the setup guide after signing in.

--setup-remote=hosted also creates and links a remote kept in this server's hosted setup storage. Use --setup-remote=none for a local repository without a remote; none is the CLI default when the option is omitted. The installer defaults to hosted. Run hosted initialization before starting the server, as the same dedicated account and with the same server data directory the service will use.

Then configure the server to locate the setup directory using a command like this, specifying the path to the setup directory:

coder-server config set coder_setup_path mycompany-coder-setup

Install License​

On a fresh server, create the administrator first, then install the license or trial key on the License page after sign-in. You can start the server without a license to do this. Administrators can later install or replace a license in Server Administration → License. See License administration for status checks, the Ask navigation handoff and limited-mode recovery. Enter credentials in the panel, never in Ask.

For command-line installation instead:

coder-server license set <your-license-key>

Attaching Data to a Seat​

Each running CoderFlow server uses one seat of your floating license while it is active. By default, CoderFlow records its own version against the seat, so support can see which version a server is running. This value appears in the User Data column of the Seat Usage view.

You can attach your own label to a seat — for example, to identify which server or environment it belongs to. Set the CODERFLOW_FLOATING_USER_DATA environment variable before starting the server:

CODERFLOW_FLOATING_USER_DATA="Frankfurt production" coder-server start

Your label is placed first and the CoderFlow version is appended after it. The combined value is limited to 50 characters, so a long label may push the version off the end. The label is purely informational — it has no effect on licensing — and is shown in the Seat Usage view and in the output of coder-server license seats.

info

Set this variable the same way you set other server environment variables (for example, in a systemd unit, a PM2 ecosystem file, or the CoderFlow user's login profile) so that it is present every time the server starts.

Seat Retention on Shutdown​

By default, CoderFlow keeps its seat when the server stops. A persistent server starts and stops routinely, and keeping the seat means it can always start back up — including when the licensing server is temporarily unreachable, because the server also keeps its last signed license locally and starts from that within the grace period. A server that is stopped for good has its seat reclaimed automatically once its license pulse expires, so seats are not held forever.

This differs from products designed to run in short-lived containers, which release their seat on every shutdown. If you run multiple CoderFlow servers from one floating license and want a stopped server to release its seat immediately instead of waiting for the pulse to expire, set CODERFLOW_FREE_SEAT_OSD:

CODERFLOW_FREE_SEAT_OSD=true coder-server start

With this set, a clean shutdown releases the seat right away. Leave it unset (the default) for the persistent-server behavior. The trade-off: retaining seats favors always being able to restart, at the cost of a stopped server continuing to hold its seat until its pulse expires.

Licensing-Server Outages​

CoderFlow is built to keep running — and to start — even when it can't reach the licensing server. Each running server holds a short-lived, cryptographically signed "pulse" that it refreshes on a heartbeat; if the licensing server is unreachable, returns an error, or can't confirm the seat, the server keeps running on its last valid pulse until that grace window expires. It does not stop or fail to start just because a heartbeat didn't get a clean answer.

The only thing that stops a licensed server within its grace window is an explicit, signed revocation from the licensing server (for example, a license cancelled for non-payment) — or the license's own term expiring. A misconfigured, incomplete, or impostor licensing server cannot take your servers down: without a valid signed revocation, an error or "not found" response is always treated as a temporary outage, not a revocation.

Create Admin User​

For a fresh server with no users, use the one-time browser link. Start the server, then run this in another terminal as the dedicated server account, using its configured data directory:

coder-server setup-link

Open the new link and follow First sign-in. An interactive coder-server start also prints a link when no users exist. The setup link works without enabling ordinary one-time login links.

To create the administrator directly in the terminal instead, use:

coder-server create-user --username=admin --email=[email protected] --name="Admin User" --admin

You'll be prompted to set a password.

On a brand-new install, the first created account is automatically granted Server Admin even without --admin (this policy is enforced in the shared user service, so it applies across CLI/API/OIDC auto-provisioning paths).

The commands that change access (create-user, grant-admin and cleanup-users --apply) write the access files directly and do not coordinate with a running server. If the server changes access at the same moment (an administrator editing users, teams, roles or access in the Web UI, or an SSO login that provisions a user), one change can overwrite the other. Run these commands with the server stopped, or, if it is running, check the result afterwards in Administration → People & Access.

Optional: Configure Server Listen Port, TLS, and HTTP/2​

By default the server listens on port 3000. To configure an alternate port (e.g. 443):

coder-server config set server_port 443

To configure a certificate for TLS:

info

Certificate and key files must be in PEM format.
The certificate file must contain the server certificate followed by any intermediate certificates, in that order. Including the root certificate is optional. With Let's Encrypt and most public CAs, use fullchain.pem.
File paths can be given as absolute or relative.
Files must be readable by the dedicated CoderFlow user.

coder-server config set ssl_cert_path mycert.pem
coder-server config set ssl_key_path mykey.pem

A CA certificate bundle (PEM format) can also be configured if your setup requires one:

coder-server config set ssl_ca_path myca.pem

Run coder-server config show to see all configuration keys and their current values.

HTTP Protocol Selection​

CoderFlow's default http_protocol setting is auto:

  • With both ssl_cert_path and ssl_key_path configured, CoderFlow automatically serves normal browser traffic over HTTP/2. Clients that do not support HTTP/2 fall back to HTTPS/1.1 on the same port, and terminal, code-server, and task-application WebSockets continue to use the HTTP/1.1 Upgrade mechanism on that port.
  • Without TLS, CoderFlow keeps its existing cleartext HTTP/1.1 listener. This is also the normal private-backend configuration when a reverse proxy owns the public certificate.
  • If only the certificate or only the key is configured, startup fails with an actionable error instead of silently choosing another protocol.

No Nginx, load balancer, or other customer-managed process is required for the built-in HTTP/2 path. You can persist a mode explicitly when you need to control a rollout:

# Default: HTTP/2 when TLS is complete; HTTP/1.1 otherwise
coder-server config set http_protocol auto

# Force HTTP/1.1, including on a direct-TLS installation
coder-server config set http_protocol http1

# Require HTTP/2 mode; startup fails unless TLS is configured
coder-server config set http_protocol http2

Restart CoderFlow after changing the protocol setting. Removing the setting restores auto:

coder-server config remove http_protocol
coder-server restart
warning

An existing direct-HTTPS installation with no http_protocol override begins offering HTTP/2 after upgrading to a version with built-in HTTP/2 support. To stage that transport change separately, set http_protocol to http1 before restarting the upgraded server, then return it to auto when ready.

When a reverse proxy terminates TLS, do not also configure CoderFlow's certificate and key on the private backend. Leave the backend on auto (which resolves to HTTP/1.1 without TLS) or explicitly set http_protocol to http1. Continue to configure trusted proxy headers as described below.

Verify the Active Protocol​

A successful built-in HTTP/2 startup reports the resolved mode, its ALPN protocols, and the WebSocket fallback in the server log:

httpProtocol="HTTP/2 with HTTP/1.1 fallback"
alpn=["h2","http/1.1"]
webSockets="HTTP/1.1 Upgrade on the same TLS port"

coder-server status also reports HTTP/2 + HTTP/1.1 fallback. From another machine, use a curl build with HTTP/2 support to verify what the public endpoint negotiates:

curl --http2 --silent --show-error --output /dev/null \
--write-out 'HTTP %{http_version}, status %{http_code}\n' \
https://coderflow.example.com/health

The expected result is HTTP 2, status 200. You can also open the browser developer tools Network panel and add the Protocol column; the main document and ordinary page resources should report h2. WebSocket requests reporting HTTP/1.1 are expected.

If a TLS endpoint unexpectedly reports HTTP/1.1, check coder-server config show, confirm that both TLS paths are configured and readable, and inspect the startup diagnostics. When a reverse proxy is in front, verify HTTP/2 at the public proxy endpoint; the private CoderFlow hop should remain HTTP/1.1.

Set the Public URL​

When TLS is enabled, also set the server's public base URL. Include the port unless the server listens on the default HTTPS port (443) — for example, with the default listen port of 3000:

coder-server config set site_url https://coderflow.example.com:3000

Task containers call back into the server — to fetch Git credentials for cloning and to use the API — using a URL the server hands them at launch. Tasks started from the web UI use the URL from your browser's address bar, but background tasks (schedules, webhooks, chat triggers) use site_url or, when it is unset, a callback URL the server recorded from the first admin request it saw — a value that is written once and never updated automatically. On an installation that previously ran without TLS, that recorded URL is a plain http:// address, which stops working the moment the server switches to HTTPS — background tasks then fail to clone repositories or reach the API, with no obvious error. Setting site_url avoids this.

Note that the callback URL is injected into each task container when it is created. Task containers that already existed before a protocol or hostname change keep their old URL, so those tasks must be relaunched after the change.

site_url is also used to generate password-setup and login links, so it is worth setting on any installation reached via a hostname rather than an IP address.

If task containers need to reach the server at a different URL than the public one (for example an internal address), set the CODERFLOW_INTERNAL_URL environment variable for the server process — it takes precedence over site_url.

The server logs a warning at startup if TLS is enabled but background task containers would be handed a plain-HTTP callback URL.

One-time login links are disabled by default. To allow administrators to generate them (for example with the create-login-link command):

coder-server config set login_links_enabled true

The generated links use site_url as their base, so set it first.

Certificate Renewal​

Certificate files are read once, at startup. The server does not watch them for changes, so after a certificate is renewed the server must be restarted to load the new files. Plan for this with any ACME automation — for example, a certbot deploy hook:

#!/bin/sh
# /etc/letsencrypt/renewal-hooks/deploy/coderflow.sh
# Copy the renewed files somewhere the dedicated user (here: coder) can read
# them (Let's Encrypt keeps its live directory root-only), then restart.
install -d -o coder -g coder -m 750 /home/coder/certs
install -o coder -g coder -m 640 \
/etc/letsencrypt/live/coderflow.example.com/fullchain.pem \
/etc/letsencrypt/live/coderflow.example.com/privkey.pem \
/home/coder/certs/
su - coder -c "coder-server restart"

Adjust the paths and user name to your installation, and point ssl_cert_path and ssl_key_path at the copied files. su - coder starts a login shell, so settings persisted in the dedicated user's profile — such as NODE_ENV=production and the NVS/nvm Node.js setup — are applied to the restarted server. If you manage the process with PM2, replace the restart line with su - coder -c "pm2 restart coderflow --update-env".

Optional: Configure Trusted Proxy Headers​

If CoderFlow runs behind nginx, Apache, Cloudflare, or another reverse proxy, enable trusted proxy handling before configuring HTTPS-only integrations such as OAuth providers:

coder-server config set trust_proxy true

The same setting is available as an environment variable, which takes precedence over the configuration key when both are set:

TRUST_PROXY=true coder-server start

You can also enable Trust Proxy later from Server Settings -> General Settings and restart the server. This lets CoderFlow read forwarded protocol, host, and client IP headers correctly. See Server Operations & Monitoring for operational notes.

Your proxy must send the standard X-Forwarded-Proto, X-Forwarded-Host, and X-Forwarded-For headers. If X-Forwarded-Proto is missing, CoderFlow sees plain-HTTP requests and will generate http:// URLs — including the callback URLs handed to task containers — even though users reach the proxy over HTTPS.

Optional: Allow Personal AI Endpoints on Private Networks​

By default, server-side tests of personal AI-provider accounts and Gemini task preflight only accept public destination addresses. If users connect to an internal enterprise AI gateway, an administrator can enable private destinations in the server process environment:

CODERFLOW_AI_ALLOW_PERSONAL_PRIVATE_ENDPOINTS=true coder-server start

Persist this variable in the server's launch configuration (for example, the dedicated user's profile or your process manager's environment) and restart the server with the updated environment. Use the exact value true; unset or other values leave private destinations disabled. This is a server environment variable, not a coder-server config set key or a task-container environment setting.

The opt-in applies to all personal accounts on the server and allows RFC1918 IPv4 ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) and IPv6 unique-local addresses (fc00::/7). It also covers DNS names resolving to those ranges. Enable it only when personal accounts should be able to contact private services reachable from this server.

Loopback, link-local/metadata, and other special ranges remain blocked for personal endpoints, including IPv4-mapped IPv6 forms. For a loopback AI gateway, configure a server account under Server Settings → AI Providers instead. Server-managed accounts retain their existing local/private reach without this variable.

For both account scopes, provider connection tests, Gemini preflight, and Claude model-context lookups refuse redirects and compressed responses. Use the final API URL and have gateways honor Accept-Encoding: identity. Requests also have response-size and completion-time limits. These rules cover these server-side checks; they do not grant or restrict task-container network access. See private and local custom endpoints.

Optional: Configure Server Log Retention​

CoderFlow keeps recent server output in an in-memory buffer and also writes it to daily files under server-logs/ in the server data directory. The persisted history is what lets the Logs tab in Server Administration query further back than the buffer holds, and it survives a server restart.

History is kept for 14 days by default. Set SERVER_LOG_RETENTION_DAYS before starting the server to change the window, or set it to 0 to disable persistence entirely and keep logs in memory only:

SERVER_LOG_RETENTION_DAYS=30 coder-server start

Files older than the retention window are deleted when the server starts and when logging rolls over to a new day. Set this variable the same way you set other server environment variables, so it is present every time the server starts.

See Server Operations & Monitoring for how the Logs tab queries this history.

Optional: Keep Feedback Reports on This Server​

Send Feedback offers Send to Profound Logic, which sends a report its author has reviewed to coderflow.ai. On a server that must not connect to the internet, set CODERFLOW_FEEDBACK_URL=off in the server process environment and restart. The dialog then offers only Download report, for the person to email the report themselves:

CODERFLOW_FEEDBACK_URL=off coder-server start

Ask CoderFlow usage telemetry is off unless an administrator turns it on, and can be sent to your own processing server instead (see Usage telemetry).

Start the Server​

For production installations, set NODE_ENV=production. Persist it in the dedicated user's shell profile so that every way the server gets started — daemon mode, coder-server restart, PM2, and deploy hooks — inherits it:

echo 'export NODE_ENV=production' >> ~/.profile
source ~/.profile

Then start the server:

coder-server start

NODE_ENV=production is reflected in the environment field of the startup log line (which otherwise reports development) and enables production safeguards — for example, the server refuses to start if authentication has been disabled via DISABLE_AUTH.

If using a listen port below 1024 (e.g. 443, 80) and using authbind to allow that, the server must be started like this instead:

authbind --deep coder-server start

Once running, open the first-admin link or sign in with the admin user you created (default port 3000). Follow First sign-in.

First sign-in​

The first-admin link works while the server has no users, including before a license is installed. It is single use and expires after 60 minutes by default. coder-server setup-link --ttl=120 gives it a different lifetime in minutes; the accepted range is 5–1440. Issuing another link cancels the previous one. Use the link straight away, on a machine you trust, because a browser keeps an opened address in its history; the link stops working once it is used, replaced or expired.

  1. Open the link printed in your terminal. If it uses localhost, open it on the server or replace that host and port with the server's reachable address. Set the public URL for future links.
  2. Enter Username, Full Name, Email, Password and Confirm Password, then choose Create Administrator. The password needs at least eight characters. A field-validation error lets you correct the field and submit again.
  3. You are signed in automatically unless the server requires MFA or cannot establish the session. In that case, sign in with the account just created and complete the normal MFA enrollment or challenge.
  4. On an unlicensed server, the License page follows sign-in. Install your license or trial key there, using the Machine ID printed by the installer or shown on that page if needed to obtain a trial. Once the key is accepted, the page says Restart the server to finish applying the license and how: on a server installed with the installer, run sudo systemctl restart coderflow.service on the host, then refresh the page. See Restart after the first license.
  5. Open the dashboard. The setup guide opens for Server Admins on a server not yet in use.

This link is no longer valid can mean the link is wrong, expired, used or replaced, or that the server already has a user. Sign in if you already created the account. Otherwise, run coder-server setup-link again while no users exist. The page removes the token from its address; if you reload before submitting, open the original link again. If account creation fails after consuming the link, the page says so; issue a new link from the terminal.

Links are printed only to an interactive terminal. They are never printed to a pipe, redirected output, systemd journal or server log. --print-url-only removes the surrounding link description but still requires a terminal. Do not record a terminal session displaying a real link.

Under systemd, open a terminal as the service account and run coder-server setup-link with the same configuration and server data directory as the service. For the installer's default account, use sudo -iu coderflow first. In a containerized server installation, open an interactive terminal inside the server container as its server account, with its existing data volume and environment. A task container cannot issue this link. Noninteractive startup prints only a reminder to create an administrator.

The setup-link command exits with 0 when it prints a link, 1 on failure, 2 when users already exist, or 3 when standard output is not a terminal.

Check an installation​

Run doctor as the non-root account that runs CoderFlow, with the same setup and server data paths. It works before or after the server starts:

coder-server doctor
coder-server doctor --json

Doctor reads host prerequisites and the same checks as the Setup page. It changes no configuration, installs nothing, builds nothing and acquires no license seat. It checks such things as the runtime, Docker access, storage, the listen port, outbound HTTPS and native dependency loading. --json prints a structured report with host.checks and setup.rows for automation.

Exit codeMeaning
0The report contains no required Action needed item. Warnings and unknown checks can still remain.
1At least one required item needs action.
2Doctor could not run, for example because of the wrong account, unreadable configuration, invalid arguments or a whole-run timeout.

Can't tell means an inspection could not determine the answer. It does not mean a prerequisite is absent or healthy. Read the explanation and suggested next step even when the exit code is 0. Doctor cannot certify a real task's build, tests or application from configuration alone.

Set Up Git Providers​

Connect code in the setup guide, or follow Git Providers.

Configure Your Environment​

A new setup repository has no environment. Use the setup guide to create the first one, or open Environments → Actions → New Environment. Generate from repository proposes a Draft from your code. Review its configuration and Finish setup items, build its image, and set Status to Active when it is ready.

The base image builds automatically​

After the first licensed start, CoderFlow starts a background base-image build when it can confirm that the image is missing and no base build is running. An unlicensed start does not use this attempt. An existing image, a build already running, or an unavailable Docker check starts no new build.

The automatic attempt is recorded in the server data directory before it starts. A failed attempt is not retried on every restart. Review the Base image row on Setup and the build output in Build History, then retry manually as shown below. Existing images are not automatically refreshed by this feature.

To disable this first-start build, set the JSON boolean auto_build_base_image to false in the setup repository's setup.json before starting the server. Omitting it leaves the feature enabled. The installer's --skip-base-image option skips its own explicit build command; use the setting to disable the server's automatic attempt too.

Build Docker Images​

Docker images must be built before you can run tasks. There are two ways to build images: through the Web UI or using the CLI.

Build Base Image​

If the automatic build has not succeeded, or you need to rebuild later, build the shared base image that environments inherit from.

Web UI:

  1. Open Environments → Actions → Build Images....
  2. Select Rebuild base image.
  3. Review the build options, then choose Build and wait for its result.

CLI:

coder-server build base
Run this as the dedicated CoderFlow user

The base image bakes in the numeric UID/GID of the dedicated user you created above, so coder-server build base builds the image directly only when it runs as that user — which is the case if you followed Switch to Dedicated CoderFlow User.

Run as any other account (including root), the command instead asks the running server to build, which requires an authenticated session (coder login, or CODER_API_KEY). If you need to trigger a build from a root shell or a provisioning script, switch to the dedicated user with its own environment first:

sudo -iu coder coder-server build base
# or
runuser -l coder -c 'coder-server build base'

Use a login shell (-i / -l) so HOME belongs to the dedicated user; otherwise the command cannot tell which account the server runs as and will fall back to asking the server. The same applies before the server's first start, since the account is identified from the server's data directory — start the server first, as this guide does above.

Build Environment Image​

Build your environment's Docker image.

Web UI:

  1. Navigate to Settings → Environments
  2. Select your environment, if it's not already selected
  3. Go to the Build tab
  4. Click Build Now

CLI:

coder-server build <environment-name>

Replace <environment-name> with the environment you created. Rebuild after changing build settings or scripts.

Set Up LLM Access​

Use AI provider in the setup guide, or Server Settings → AI Providers. Choose Add Account, connect a subscription or API key, and select it under Tasks use. See AI Provider Authentication. A server Claude API key separately enables Ask CoderFlow and helper features.

Verify Installation​

First, open Administration → Server Administration → Health to check that host metrics load. See Server Operations & Monitoring for details.

Health dashboard with CPU, memory, I/O, disk, container and uptime metrics for a demonstration server

Then follow First task to run Get to know this repository, review its build, tests, running app and screenshot, and record a passing named test on the finished task. Check First verified task on Setup for Ready.

Server Management​

Running as a Daemon​

Use the --daemon flag to run the server in the background:

coder-server start --daemon

Manage the daemon with:

# View logs
coder-server logs

# Stop server
coder-server stop

# Restart
coder-server restart

# Check health
curl http://your-server:3000/health

Using PM2​

As an alternative to the built-in daemon mode, you can use PM2 for process management.

PM2 provides additional features like automatic restarts on crash and system boot persistence.

Install PM2 Globally​

npm install -g pm2

Start CoderFlow with PM2​

If using a listen port below 1024 (e.g. 443, 80) and using authbind to allow that, the server must be started like this:

pm2 start --name coderflow authbind -- --deep coder-server start

Otherwise start like this:

pm2 start --name coderflow coder-server -- start

View Logs​

pm2 logs coderflow

Stop/Restart​

pm2 stop coderflow
pm2 start coderflow
pm2 restart coderflow

Auto-start On System Boot​

Save the PM2 process list to disk:

pm2 save

Generate a PM2 startup script:

pm2 startup

pm2 startup outputs a commmand string to your terminal, which must be run as root, to configure the system's service manager to start up PM2 at system boot.

Rolling Back to an Earlier Version​

Ask CoderFlow keeps a record of the changes it proposed and you confirmed, in the assistant-actions directory of the server data directory. What a rollback needs depends on the version you go back to. This applies however you install the earlier version, including from Server Administration (see Server Updates).

Going back to a version released before this one. An earlier version can read this record only while everything in it is something that version knows. Once this version has run, the record can hold things earlier versions do not know: a saved objective that Ask deleted and, for older versions, also a saved objective that Ask launched or an Ask change from before the upgrade that this version marks as no longer made in Ask. The earlier version then cannot read the record at all. A version that already shows Ask change from another CoderFlow version cards keeps reading it, and shows an Ask change this version no longer makes as an earlier Ask change that cannot be confirmed, in that version's own wording. If this version has ever shown an Ask change from another CoderFlow version card, an earlier version also cannot track the progress of the tasks and deployments Ask started until the directory is moved aside. If you go back without the steps below, Ask still answers questions and looks things up there, but its changes are refused. To roll back safely:

  1. Stop the server.

  2. In the server data directory (SERVER_DATA_PATH, by default ~/.coder/data), rename the assistant-actions directory out of the way. Do not delete it, and do not edit the files in it:

    mv ~/.coder/data/assistant-actions ~/.coder/data/assistant-actions.before-rollback
  3. Start the earlier version. It starts an empty record: earlier Ask cards and Recent actions entries are not shown, and nothing in them is run again.

Going back from a later version to this one, or to any version after it. Keep the assistant-actions directory as it is. This version reads it, and shows each change the later version made in a way it does not know as a read-only Ask change from another CoderFlow version card to the person who made it: it cannot be confirmed or cancelled, and nothing in it runs. This version keeps those records unchanged, so they show normally again after you upgrade. If the later version changed the record's format in a way this version cannot read, Ask's changes are refused as above: follow the same steps to move the directory aside.

In every case:

  • Do not restore a copy of assistant-actions taken before the upgrade: changes confirmed since then would show as waiting again and could be confirmed a second time.
  • Do not edit state.json or the other files in it.
  • If you moved the directory aside, keep the assistant-actions directory that is current when you upgrade again: the newer version reads the one the earlier version created. Putting the renamed directory back instead also works, but the Ask cards made on the earlier version in between are then lost.