DK Studio/Documentation
ProductChangelog

Self-hosted deployment

DK Studio runs entirely on infrastructure you control: a Node process for the studio, one Node process per bench for the agents, and a database you choose. This page introduces the shape of an installation, the licence it runs under, the database and schema, the start order, and how to upgrade and restore.

This page covers the in-house installation β€” the mode in which the studio, the socket server and the database run on infrastructure you control. DK Studio also runs as a hosted studio, operated by DK Studio, where you install only the agents on your benches. The two modes are compared in Deployment modes.

The shape of a self-hosted install

ApplicationDirectoryPortRuns where
DK Studioapps/studio3000Your server. Serves the UI, the REST API and the Socket.IO endpoint from one process.
DK Studio Agentapps/agent3001Every bench or machine that owns hardware.

The studio never dials an agent. Each agent dials the studio over HTTP and Socket.IO, so a lab only needs outbound access β€” no inbound port, port forward or VPN client on the bench. See Network requirements.

The requirements are Node.js 24 or newer, pnpm 11, and a database. The agent additionally needs bash at /bin/bash for the shell command, and the optional serialport native bindings if the bench drives a serial port.

Put the studio on a trusted network

The studio's REST API answers anything that can reach port 3000. Keep the install on the lab network, or put an authenticating proxy in front of it. See Network requirements.

The studio licence

The studio's licence is a real entitlement, not a label. The file .studio-license.json records edition, licenseKey, issuedAt, expiresAt, maxAgents and features, and the platform enforces it: maxAgents bounds how many agents the install accepts, and features decides which capability modules are available.

A licence key is written as xxxx-xxxx-xxxx-xxxx, and the first block names the edition.

EditionKey prefixmaxAgentsfeatures
StarterSTR03core, agents
ProfessionalPRF010core, agents, analytics, api
ProPR0025core, agents, analytics, api, advanced
EnterpriseENT0999core, agents, analytics, api, advanced, enterprise

The demo key ENT0-DKST-UDIO-2026 is an enterprise licence with maxAgents 999, marked as a demo licence. It passes validation as it stands, which makes it the key to use for a lab install.

The licence file is written at setup

.studio-license.json is created during the setup wizard and is the record of what the install is entitled to run. Keep it with your backup, next to .db-config.json.

Agent licences are separate and narrower: each one is a single seat for one bench. See Agent registration and entitlements.

Database

The studio supports three engines, chosen during the setup wizard: SQLite (better-sqlite3), PostgreSQL (pg) and MySQL (mysql2). The wizard writes the choice to .db-config.json in the studio's working directory β€” {"dbType": "sqlite", "database": "dkstudio", "initializedAt": "…"}, plus host, port, username and password for the server-based engines. With SQLite the database is a file under DATA_DIR, default ./data/dkstudio.db.

The engine is a storage choice only. On all three, the same studio process serves the UI, the REST API and the realtime socket, and the same schema backs them.

Schema

The schema comes from three parallel DDL files β€” apps/studio/lib/db/init.sqlite.sql, init.postgresql.sql and init.mysql.sql β€” each defining 21 tables. They are applied once, by the setup wizard's initialize step (POST /api/system/setup with {"step":"initialize"}). SQLite executes the file as a whole; PostgreSQL and MySQL apply it statement by statement.

The 21 tables cover the platform end to end:

AreaTables
Identity and accessusers, permissions, settings
Inventoryprojects, products, environments, devices, vehicles, oems
Test domaintest_suites, test_cases, test_runs, executions, schedules, artifacts, reports
Agentsagents, agent_licenses, agent_commands, agent_keys, agent_sessions

An upgraded studio does not re-apply the schema. Keep a copy of the DDL you deployed and apply schema changes by hand inside the maintenance window.

Start order

The order matters: the studio must be running before an agent can register.

  1. Start the studio
    pnpm install
    pnpm build
    pnpm --filter @dkstudio/studio start

    For development, pnpm --filter @dkstudio/studio dev runs the same server with hot reload. The studio listens on port 3000 by default and serves the UI, the REST API and the Socket.IO endpoint on that one port.

  2. Complete the setup wizard

    Open http://<studio-host>:3000. The wizard validates the licence, configures the database, applies the 21-table schema and creates the admin account. Until an admin exists the studio keeps redirecting to the wizard.

  3. Start the agents

    On each bench: pnpm install && pnpm --filter @dkstudio/agent build && pnpm --filter @dkstudio/agent start. The agent's own page opens on port 3001 and offers a registration form.

    For development, pnpm --filter @dkstudio/agent dev runs the same page with hot reload.

The install includes dev dependencies

Both start scripts run TypeScript through tsx, which ships as a development dependency. Install the workspace with a plain pnpm install β€” a production-only install leaves the server without the runner it starts with.

Keeping the processes running

The studio is long-lived: it holds the Socket.IO connections and the database pool. The agent is long-lived on every bench. Run both under a supervisor so they come back after a crash or a reboot.

# /etc/systemd/system/dk-studio.service
[Unit]
Description=DK Studio
After=network.target
 
[Service]
Type=simple
User=dkstudio
WorkingDirectory=/opt/dk-studio/apps/studio
Environment=NODE_ENV=production
Environment=PORT=3000
Environment=DATA_DIR=/var/lib/dk-studio
ExecStart=/usr/bin/pnpm --filter @dkstudio/studio start
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

The working directory is where the four studio files live, so it decides where .db-config.json, .studio-license.json and .setup-complete are found. DATA_DIR moves only the SQLite database file; the other three stay in the working directory.

The agent takes the same shape on the bench, with AGENT_HOST left at its default so the bench page stays on the machine:

# /etc/systemd/system/dk-studio-agent.service
[Unit]
Description=DK Studio Agent
After=network.target
 
[Service]
Type=simple
User=dkstudio
WorkingDirectory=/opt/dk-studio/apps/agent
Environment=NODE_ENV=production
ExecStart=/usr/bin/pnpm --filter @dkstudio/agent start
Restart=always
RestartSec=5
 
[Install]
WantedBy=multi-user.target

The agent registers once, through its own page, and then reconnects on its own after a restart β€” data/agent.json holds the credentials it needs.

systemctl enable --now dk-studio
systemctl enable --now dk-studio-agent

The studio keeps four files in its working directory: .db-config.json (driver and connection details), .studio-license.json (edition, maxAgents, features), .setup-progress.json (setup progress, safe to delete once complete) and .setup-complete (the marker that gates the wizard).

Upgrading

git pull
pnpm install
pnpm build

Stop the studio process, take a backup (below), then start it again with pnpm --filter @dkstudio/studio start. The wizard does not reappear: .setup-complete and .db-config.json are still in place.

Upgrade the studio and the agents together

The socket envelope is {v, type, kind, id, timestamp, payload} and the protocol version is negotiated during the handshake. Update the studio and every agent in the same maintenance window so that both ends speak the same version.

Backup and restore

What to back up, for a SQLite deployment (with the studio stopped):

cp data/dkstudio.db /backup/dkstudio-$(date +%F).db
cp .db-config.json .studio-license.json .setup-complete /backup/

For PostgreSQL and MySQL, use the engine's own dump tooling (pg_dump, mysqldump) and back up .db-config.json alongside it. The database is the source of truth; the JSON files only tell the studio how to reach it and what it is entitled to run.

Restore in this order: stop the studio; put the database back; put .db-config.json back in the studio's working directory β€” without it the studio presents the setup wizard again and starts with an empty view of the world; then start the studio and confirm the agent list is populated.

The agent's own state lives on the bench in data/agent.json, in plain text. It is not part of the studio's backup set β€” but the studio's agents table holds the same api_key and agent_secret values, so a database backup carries the same secret material.