Skip to main content
Archil’s persistent sandboxes make it simple to create long-running machines that simplify access to your Archil disk. They are ideal for starting network services (such as web hosting, git hosting, or databases), interactive development environments, or running untrusted AI-generated code for longer than an individual bash tool. Persistent sandboxes can keep running by resetting their timeout, and can be forked so you can run multiple copies of the same sandbox in parallel. Persistent sandboxes are built on full-featured Linux microVMs that are colocated with your Archil disk data for maximum security and performance. If you instead need the ability to run one-off bash, Python, or Node code against your Archil disk, consider using serverless execution instead.
Persistent sandboxes are available in preview in Archil’s AWS regions. During the preview period, sandboxes may be pre-empted. Planned maintenance pauses them so they can be resumed. If a host fails unexpectedly, its sandboxes are marked failed and lose in-memory state; start them again to boot from disk.
You can easily create a persistent sandbox using the TypeScript SDK (or the Python SDK):
Archil sandboxes run on x86-64 (amd64) and support between 1 and 32 vCPU cores and between 0.25 and 64 GiB of memory. Sandboxes run as the root Linux user (uid: 0, gid: 0).

Network egress

To prevent platform abuse, network egress is limited to the Team plan and above. On the Developer plan, all network egress is denied. Once upgraded, network egress can also be configured for the sandbox firewall. Sandboxes created on the Developer plan keep denying egress after an upgrade until you replace their network policy.

Attaching an Archil disk

Pass mounts when creating a sandbox to give it access to files on an existing Archil disk. The disk must belong to your account and be in the same region as the sandbox:
Archil handles mount authentication automatically. Deleting a sandbox removes its root filesystem. Mounted disks and their data are preserved. With a single mount, path is optional and defaults to /mnt/archil. To mount more disks, add an entry for each one with a separate path, such as /mnt/data and /mnt/models. Use subdirectory to expose only part of a disk. See Create Sandbox for the full mount options and path restrictions. By default, a mount takes exclusive access to the disk. To share it across sandboxes, use readOnly (read_only in Python and REST) for readers or conditional for writers. Coordinate concurrent writes in your application to avoid overwriting each other’s changes. See Sharing Disks for how these modes work. Sandboxes keep their mounts across stop/start and pause/resume. To change them, stop the sandbox and pass a new mounts list to Start Sandbox. Omit mounts to keep the saved list, or pass [] to remove all mounts without deleting their disks. For a paused sandbox, resume() keeps its mounts; use start() to change them, which boots from disk and discards the paused memory state.

Passing environment variables

Environment variables can be set for the whole sandbox, for a single command, or both. Variables passed when the sandbox is created apply to every command that runs inside it:
Individual processes can add or override their own variables by passing env to run:

Starting and stopping sandboxes

A sandbox runs until you shut it down or its TTL expires. There are two ways to suspend one, and they differ in how much state they keep. Stopping a sandbox sends SIGTERM to every running process and shuts down the VM, leaving the disk intact:
Starting it again boots a fresh VM from that same disk:
Everything written to disk survives, but memory does not, so your application handles shutdown and startup the same way it would on any machine. You can instead pause a VM to snapshot memory alongside the disk, so a resumed sandbox picks up exactly where it left off, with running processes intact:
Deleting a sandbox releases all of its resources and cannot be undone. A sandbox has to be stopped before it can be deleted, unless it has already exited or failed:

Forking a sandbox

In some situations, you may want to fork a sandbox into multiple branches from a single point in time. This makes it simple to, for example, start sandboxes from a template without needing to incur startup latency for a slow-running program or run parallel experiments on sandbox state from some point in the past. A sandbox without additional disk mounts can be forked while running, paused, or stopped:
After forking, newSandbox will be able to run commands independently of the original sandbox, starting from the exact state of the original sandbox. Forking a running sandbox pauses it while the snapshot is taken and resumes it once the fork is accepted, so attached process connections close; reconnect with attach. A paused or stopped sandbox is left as it is, and a fork of a stopped sandbox boots from its disk. A sandbox with mounted disks must be stopped before forking. The fork gets its own root filesystem but mounts the same additional disks as its parent, so changes to those disks are shared. To run both sandboxes at once, use a shared mount mode or give each sandbox separate disks. Separate disks also keep their data isolated. During the preview period, all child sandboxes forked from a parent must be deleted before the parent sandbox is deleted.

Hosting network services

Archil sandboxes support the ability to host network services, including creating per-sandbox preview URLs for CI-like workflows. There are two ways to expose a port for a network service, depending on whether you are inside or outside the sandbox. Outside the sandbox, you can specify a list of ports to expose when creating the sandbox or dynamically expose a port later.
Exposed ports are public: they accept any TCP protocol over TLS with SNI, without authentication. For private access, leave the port unexposed and create a port token. Send the token in the X-Archil-Token header; requests without a valid token get 401. Tokens are checked when a connection opens, so revoking or expiring a token blocks new connections while open ones stay open. Token access supports HTTP/1.1 over HTTPS only, and publicly exposed ports ignore tokens.
Inside the sandbox, archil services create runs a command as a supervised service: it starts immediately and restarts if it exits. Service ports are private by default, so reach them by exposing the port or with a port token. To let services publish their own hostnames, create the sandbox with enable_service_ingress: true through the Create Sandbox API.
For example, in a sandbox with service ingress enabled, the following runs python3 -m http.server 8080 and returns a stable HTTPS URL that proxies traffic to local port 8080. Without service ingress, the service still runs, but its hostname is not routed until you expose the port.
Traffic to an exposed port or service hostname, or a request with a valid port token, automatically starts a stopped sandbox or resumes a paused one, including one paused by its TTL. All sandbox ports are served over TLS.
Exposed ports and service hostnames are publicly accessible. Use port tokens, or include authentication/authorization in your service, if you want to expose a private service.

Choosing a base image

Use baseImage to start from a public Linux OCI image, such as python:3.13. The default is ubuntu:26.04. For private images, build with your registry credentials first, then pass the returned imageId when creating the sandbox. See Sandbox images for examples and how to reuse builds.

Setting a time to live

A sandbox has a hard timeout and an optional idle timeout. Both pause the sandbox, preserving its disk, memory, and processes for resume(). Attached process connections close when it pauses; reconnect after resuming. If the pause snapshot fails, the sandbox is marked failed. Stop a paused sandbox before deleting it.
Updating the hard timeout resets its deadline from now, capped at 24 hours after the current session started. An idle-only update leaves that deadline unchanged and resets the idle countdown if no process connection is open. Omitted settings stay unchanged. Updates to a paused or stopped sandbox apply to its next powered-on session. Starting or resuming begins a new session with a fresh timeout. Open direct process connections prevent idle expiry. Detached processes and service-port traffic do not keep the idle timer alive. Leave idle timeout disabled for unattended jobs or services that must stay running between connections. Activity does not extend the hard timeout. setTimeout() can extend it only within the session’s 24-hour limit. For REST, use Set sandbox timeouts.

Opening interactive shells

By default, processes run without allocating a pseudo-terminal (pty). This is usually desirable, since it signals to the process that it is not in an interactive terminal. However, some commands, such as those that emit color, full-screen tools like vim and top, or tools that need interactive input should instead be launched in a pseudo-terminal. Provide terminal dimensions to launch a process in a pseudo-terminal. The process can then interactively receive input and stream output to the caller:

Next steps