Sharing teammates with your team
A team server lets other people on your team use agents that run on a computer you control. Each person signs in with their own account and uses only the agents they can access.
1. Sign in
Sign in with your email address. You receive a short code, and Artzi stores your session on this computer.
2. Publish this computer as a server
Open the server menu and choose to publish. The server stays online while this computer is on and Artzi is running.
3. Invite a teammate
Create an invitation and send the link. The person opens it, signs in and joins the server.
4. Choose who can use each agent
Set an access role for each agent. A teammate can only see and chat with the agents their role allows.
If you stop Artzi or turn the computer off, the server goes offline until you start it again.
Linux server
Download the Linux deb and its SHA256SUMS file into the same folder. Verify the package before installing:
sha256sum -c --ignore-missing SHA256SUMS && sudo apt install ./Artzi-<v>-amd64.deb
Then enable the user service:
loginctl enable-linger
systemctl --user enable --now artzi-server
artzi-server login you@example.com
Enter the sign-in code at the prompt. Check the server with artzi-server status, set its name with
artzi-server name "Workstation", and sign out with artzi-server logout.
To install a later release, download its deb and checksum manifest into one folder, then run:
artzi-server upgrade ./Artzi-<v>-amd64.deb
The command verifies the published SHA-256 checksum, package name, architecture and version before installing. It reinstalls the same version or upgrades to a newer one; downgrades are refused because older versions may not be able to open newer data. The build signature is not checked yet.
An operator can also approve a release for staged updates through the existing client controls or CLI:
sudo /usr/sbin/artzi-server-update configure --user SERVICE_USER
systemctl --user daemon-reload
systemctl --user restart artzi-server
sudo /usr/sbin/artzi-server-update offer /private/releases/Artzi-<v>-amd64.deb --checksums /private/releases/SHA256SUMS
artzi-server update check --json
artzi-server update stage --json
artzi-server update status --json
artzi-server update apply --json
Poll until the stage is ready before applying. Apply waits for idle work; artzi-server update cancel
cancels the wait. The separate coordinator verifies the stored package and preserves an interruption
checkpoint outside the app installation. It resumes the same verified release after an interrupted
install. Publisher signatures remain unchecked for unsigned builds. Enrollment covers the existing
user unit and its private profile; close other desktop or unmanaged server processes before applying.
For a custom profile, give its canonical path to configure --profile PATH and keep the unit aligned.
Use /usr/sbin/artzi-server-update status and sudo /usr/sbin/artzi-server-update recover --retry
for operator recovery when a partial install cannot run the app CLI.
To use your own account service, configure the user unit:
systemctl --user edit artzi-server
Add:
[Service]
Environment=ARTZI_ACCOUNT_API_URL=https://account.example.com
Then run systemctl --user daemon-reload and systemctl --user restart artzi-server. Sign out with
artzi-server logout before switching between the default and a self-hosted account service. A signed-in
server refuses to send its session to a different origin.
Agent display
Computer Use runs on a separate virtual display so screenshots and input do not reach the server's
administration desktop. The deb recommends Xvfb, xauth, xdotool, x11-utils and ImageMagick. Check
artzi-server status for the display number, dimensions and recovery guidance if its tools are missing.
Workspace-only agents on Linux require bubblewrap and user namespaces. If the sandbox check fails,
Workspace-only refuses to start; artzi-server status shows the reason.
Uninstalling
Both sudo apt remove artzi and sudo apt purge artzi keep your user data:
~/.config/Artzistores sign-in, server identity and name, settings and chats.~/Artzistores the workspace, unlessARTZI_HOMEpoints elsewhere.- Your OS keyring keeps Artzi's storage key, which the saved sign-in needs.
- Systemd user overrides and the enable link are retained.
Remove takes away the artzi command, the artzi-server wrapper and the system-wide unit. Purge also
removes the AppArmor profile if one was installed. Neither deletes data under your home directory. To delete user data, first
stop and disable the service, then remove ~/.config/Artzi, the workspace path (~/Artzi or ARTZI_HOME),
any ~/.config/systemd/user/artzi-server.service.d override and
~/.config/systemd/user/default.target.wants/artzi-server.service; remove the Artzi account entry from your
OS keyring separately.
Linux container
Build the Linux release and its local container image from a checkout:
bun install
bun run dist:linux
bun run container:build
container:build verifies the deb against dist/SHA256SUMS, checks its package name and architecture,
and builds artzi-server:local. An explicit deb path can be passed after the command. The image build
checks the checksum again before unpacking. Nothing is uploaded. Checksums establish that the image
contains the selected artifact; signatures and registry provenance are not checked yet.
Create the keyring secret once, then start and claim the server:
(umask 077; test ! -e docker/keyring-password && openssl rand -hex 32 | tr -d '\n' > docker/keyring-password)
docker compose -f docker/compose.yaml up -d
docker compose -f docker/compose.yaml exec server artzi-server login you@example.com
docker compose -f docker/compose.yaml exec server artzi-server status --json
docker compose -f docker/compose.yaml exec server artzi-server name "Team server"
The code is entered at the prompt. A fresh headless server publishes automatically after sign-in.
It connects out through the account service and relay, so the Compose file publishes no ports.
To use your own infrastructure, add ARTZI_ACCOUNT_API_URL=https://account.example.com and
ARTZI_SIGNAL_URL=wss://relay.example.com to the service's environment. Sign out before changing account services.
The named /data volume keeps settings, identity, encrypted credentials, keyring, provider homes and
the workspace when a container is replaced. The image runs as user 1000:1000; a bind-mounted data
directory must belong to that user. The keyring secret stays in a separate read-only mount. Keep a
secure copy of both the data and the original secret: a different secret cannot unlock the saved
keyring, and the server refuses to start with it. Anyone able to read both can unlock the credentials.
Keep the secret out of repositories and backups that contain the data.
The runtime has a read-only root filesystem, no effective capabilities, no-new-privileges, a
512-process limit, 1 GiB shared memory and private temporary directories. Only SYS_CHROOT remains
in the bounding set for Chromium's sandbox. The bundled seccomp policy allows user namespaces while
retaining Docker's other syscall restrictions. The host must permit unprivileged user namespaces;
startup refuses when they are blocked. Do not disable the Electron sandbox or the container's security policy.
Docker's default AppArmor policy prevents bubblewrap's nested mounts. Under that policy,
status reports Workspace-only unavailable, and Workspace-only commands refuse to run. Full access
commands run within the container. Computer Use has its own authenticated virtual display. Do not
mount the Docker socket, a personal home directory or other host data into the server.
To replace the image, build the newer verified release, then run docker compose -f docker/compose.yaml up -d --force-recreate.
Do not replace it with an older version: newer data may not open in older builds. Container updates
replace the image; artzi-server upgrade is for systemd installations. docker compose down retains
the data volume; down --volumes deletes it. The 60-second stop period lets Artzi stop agents and close
its database, after which the runtime ends remaining processes.
Run bun run container:verify to check the image with disposable data, a local account service and
relay, and a headless Chrome client. It checks unsafe startup refusal, claim, remote workspace access,
recreation, crash recovery, secret retention and shutdown. The verified container target is Linux x64
with an Ubuntu 22.04 userspace and Docker. Other architectures, Podman, Kubernetes and rootless Docker
are not checked yet.
Multiple Linux instances
The instance operator manages rootful Docker on the Ubuntu 22.04 x64 test target, using Docker's iptables firewall backend. Install Bun, Docker, systemd, iptables, util-linux and e2fsprogs, and build the local image above. From that checkout, install the operator and create an instance:
sudo "$(command -v bun)" scripts/linux-instances.ts setup
sudo artzi-instance create design --cpus 1 --memory 2g --disk 20g
sudo artzi-instance run design login you@example.com
sudo artzi-instance run design name "Design server"
sudo artzi-instance run design status --json
sudo artzi-instance list
Sign-in reads the code from stdin or a prompt that hides input. Each command requires the instance
ID explicitly. IDs contain 1–24 lowercase letters, digits or hyphens and start with a letter or digit.
CPU, memory and persistent disk quotas are mandatory; sizes use m, g or t (binary units).
The image must already exist locally: create --image <tag-or-digest> pins its immutable image ID.
Images are never pulled or published by the operator. The image label is checked; image signatures
are not checked yet. Keep the pinned image available for recovery.
The default root is /srv/artzi, accessible only to root. Setup copies Bun, the operator, backup
worker and container seccomp policy there, so boot and subsequent commands do not depend on the
checkout. A custom installation uses a canonical absolute path with safe root-owned ancestors:
sudo "$(command -v bun)" scripts/linux-instances.ts --root /srv/artzi-other setup --subnet 172.31.0.0/16.
Use that installed root's .tools/bun .tools/operator.js --root /srv/artzi-other for later commands.
The artzi-instance shortcut belongs to the default root.
Each instance has its own preallocated ext4 disk, data directory, keyring secret and container. Only its own data and read-only secret are mounted. The disk quota bounds persistent data; RAM also accounts for shared memory and temporary files. Docker logs rotate at 10 MiB with three files. The operator leaves at least 1 GiB free before reserving a disk. Backups, verification and retained recovery disks need additional host space. The same sandbox and Workspace-only limitation described above applies to every instance.
The default network is 172.30.0.0/16; setup rejects overlap with existing Docker networks. A different
private /16–/28 subnet can be supplied with --subnet. Instances have no published ports, cannot
connect to one another or host services, and cannot reach private, loopback, link-local, metadata,
benchmark or multicast destinations. IPv6 is disabled and blocked at the bridge. Public egress and
Docker DNS remain available. Repeat --deny <IPv4-CIDR> at setup to block additional destinations.
Private account/relay services are therefore outside this deployment profile; use public HTTPS/WSS
endpoints, with both --account-url and --relay-url on create, when using your own services.
Setup installs a scoped firewall unit before Docker and persistent loop mounts before container
startup. If isolation rules are absent, up refuses. A missing data mount remains owned by root and
unwritable, so the server refuses to create an empty replacement profile. Rootless Docker, user
namespace remapping, other firewall backends and other container engines are not checked yet.
The host and its root/Docker administrators remain trusted.
Instance backups and recovery
Create a backup and use the exact backup ID printed by that command:
sudo artzi-instance backup design
sudo artzi-instance verify design 20261028T120000Z-aabbccdd
sudo artzi-instance restore design 20261028T120000Z-aabbccdd --confirm design
sudo artzi-instance status design
Backup briefly stops the target container and all its processes, copies its complete data (including
SQLite WAL files), then restarts it if it was running. The bundle contains manifest.json,
data.tar.gz and SHA256SUMS. Before publishing it under /srv/artzi/backups/<instance>/<backup-id>,
the operator extracts it onto a separate quota-bounded disk, checks every path, type, mode and file
checksum, and runs SQLite quick_check. Archive and database processing run as an unprivileged
user in a constrained container with no network. No tenant archive is extracted by root.
Restore repeats those checks while the current instance remains available. It requires the same instance ID, original keyring secret, pinned image and application version, and a disk at least as large as the backup's quota. A failed verification leaves the current disk selected and running. After verification, restore stops the target, switches its disk pointer atomically and starts it again if it was running. Startup failure selects the previous disk again. A crash during the switch leaves a pointer to either the previous disk or the fully verified recovery disk. Other instances are not stopped or changed. Only one operator mutation runs at a time per root; overlapping commands fail instead of queuing a destructive action.
Backups contain private workspace and account data. They are checksummed, not signed or encrypted;
store exported copies in protected storage. Keep a separate secure copy of each instance's original
/srv/artzi/instances/<instance>/keyring-password. Its fingerprint is in the manifest; the secret
itself is never included. Losing it prevents credential recovery. For recovery on a new host, load
the exact pinned image, set up the operator, create the same ID and quotas with
--secret-file /root/original-keyring-password (a private root-owned file), copy the root-owned backup
bundle into the same backups/<instance>/<backup-id> layout, and run verify followed by restore.
Changing the instance ID or using a different build is deliberately rejected.
Successful restores retain the previous disk. After checking recovery, explicitly reclaim old disks
and incomplete backups with sudo artzi-instance prune design --confirm design. status lists backup
IDs, old disks and incomplete backups, and reports a missing or changed secret. Completed backups are never pruned automatically.
stop design and up design control the runtime. To delete an instance, use
sudo artzi-instance remove design --confirm design; this deletes its disks and secret, retaining
its backup bundles. Save the original secret separately first. teardown --confirm /srv/artzi
removes the scoped network and boot configuration only after all instances have been removed.
Run sudo "$(command -v bun)" scripts/smoke-linux-instances.ts in a disposable Ubuntu VM to exercise
two tenants, real resource limits and disk exhaustion, denied network access, SQLite WAL recovery,
corrupt backup refusal, explicit confirmation, restore, pruning and removal. The smoke creates and
removes its own data root, containers, network and firewall rules.
Own account, relay and TURN services
Use bun run services prepare for the account/site services and bun run stack prepare for
Signal and TURN. The tools validate private credentials, certificates, routing and matching keys.
The service operations runbook
covers preparation, the disposable rehearsal, rotation and the integrations that need separate
operator registrations. Real domains, certificates, Cloudflare resources and SMTP credentials are
operator inputs. Sign out before changing services, then configure both ARTZI_ACCOUNT_API_URL
and ARTZI_SIGNAL_URL for the installed client or server.
Hosted servers
Desktop Settings → General and web Settings list the hosted servers your account owns. Inspect shows the desired state and last account observation. Wake and Retry work while a server is offline. Provider delays show the next attempt; exhausted failures can be retried on the same server.
Delete server requires typing the exact server name. Access ends immediately, while Deleting remains visible until cleanup finishes. If a request fails, refresh the list before trying again. Creation is available only when the service operator has configured hosting; the default service has no provider.