Capsules Guide

Capsules are isolated, templated runtime environments that encapsulate application execution contexts. They represent a versioned configuration template that defines how a containerized or sandboxed execution environment should be set up, configured, and run.

Table of Contents

  1. What are Capsules
  2. Capsule Definitions vs CapsuleProcesses
  3. Capsule Lifecycle
  4. VFS and Secret Mounts
  5. User and Package Management
  6. Capsule Commands
  7. API Reference
  8. SDK Usage
  9. Shell Commands

What are Capsules

Capsules are isolated container environments that provide secure, reproducible execution contexts for running workloads. They enable:

  1. Reproducible isolated execution - Define once, run many times with consistent setup
  2. Secure environment sandboxing - Control users, packages, mounts, and secrets
  3. Workflow automation - Define startup commands and respond to runtime commands
  4. Dynamic resource management - Mount filesystems and secrets at runtime
  5. Multi-tenancy - Namespace-scoped templates with tenant isolation

Capsule Definitions vs CapsuleProcesses

Understanding the distinction between Capsules and CapsuleProcesses is fundamental:

ConceptDescription
CapsuleThe reusable definition/template stored in the database
CapsuleProcessA specific running instance of that template

Think of a Capsule as a blueprint and a CapsuleProcess as a building constructed from that blueprint. You can create many CapsuleProcesses from a single Capsule definition.

Capsule Version Properties

Each Capsule can have multiple versions. Each version includes:

PropertyDescription
VersionVersion number (immutable, increments on changes)
TemplateBase container/environment specification (e.g., ubuntu:22.04)
AdditionalPackagesArray of package names to install
UsersUser definitions to create
VirtualFileSystemMountsVFS mount specifications
SecretMountsSecret mount specifications
StartupCommandsCommands to run during startup
AutoTerminateAfterStartupCommandsBoolean for auto-termination
MaximumDurationTimeSpan for process lifetime limit
IsDisabledWhether this version is disabled

User Definition

Users can be defined with specific sudo permissions:

{
  "name": "appuser",
  "sudoAsUsers": ["root", "www-data"]
}

Startup Command

Startup commands run automatically when the capsule starts:

{
  "command": "/app/start.sh",
  "arguments": ["--port", "8080"],
  "runAsUser": "appuser",
  "maximumDuration": "00:05:00",
  "waitToComplete": true
}

Capsule Lifecycle

Phase 1: Definition

  • Created via API or resource build
  • Stored as immutable versions
  • Each update creates a new version
  • Versions can be disabled without deletion

Phase 2: Process Startup

Status: New

  • Process created, persisted, message sent to runner queue

Status: Running

  • Runner picks up the process
  • Setup Phase (configurable timeout, default 10 min):
    • Validate mount collisions
    • Create users from version definition
    • Mount VFS and secrets
    • Install packages
  • Shell authentication (API key created)
  • Run startup commands
    • If AutoTerminateAfterStartupCommands=true -> finish
    • If false -> stay alive for commands

Phase 3: Runtime Operations

If process stays alive:

  • Listens for incoming commands
  • Maximum duration timer running
  • Refreshes state every 15 seconds
  • Can execute: Shell commands, Mount/Unmount, User management, Package management, Terminate

Phase 4: Termination

StatusDescription
FinishedSuccess
ErrorSetup/execution failure
KilledExternal termination

Cleanup (Always Runs):

  1. Delete API authentication key
  2. Tear down created users
  3. Tear down secret mounts
  4. Tear down VFS mounts

VFS and Secret Mounts

Virtual File System Mounts

VFS mounts allow you to attach virtual file systems to your capsule at specific mount points. This enables sharing data between capsules or persisting data beyond the capsule lifecycle.

Mount specifications include:

  • VFS ID and namespace
  • Mount path within the capsule
  • Read/write permissions

Secret Mounts

Secret mounts allow secure injection of sensitive data (credentials, API keys, certificates) into the capsule environment without hardcoding them in the capsule definition.

Secret mount specifications include:

  • Secret name/identifier
  • Mount path within the capsule

Best Practice: Always use secret mounts for sensitive data rather than environment variables or hardcoded values.


User and Package Management

User Management

Capsules support dynamic user creation and management:

  • Add users at startup or runtime
  • Define sudo permissions to control privilege escalation
  • Remove users when no longer needed

Users are automatically cleaned up when the capsule terminates.

Package Management

Install and remove system packages dynamically:

  • Install packages during setup or runtime
  • Remove packages when no longer needed
  • Packages are installed using the system package manager (e.g., apt for Ubuntu)

Capsule Commands

Command Operation Types

OperationDescription
CommandShell command execution
MountVfsMount virtual file system
UnmountVfsUnmount virtual file system
MountSecretMount secret
UnmountSecretUnmount secret
AddUserAdd user to capsule
RemoveUserRemove user from capsule
InstallPackageInstall system package
RemovePackageRemove system package
TerminateTerminate the process

Command Status Values

StatusDescription
PendingCommand queued but not started
RunningCommand is executing
FinishedCommand completed successfully
ErrorCommand failed
AbortedOnTerminationAborted due to process termination

API Reference

Capsules API

EndpointMethodDescription
/capsulesGETList all capsules
/namespaces/{ns}/capsulesGETList capsules in namespace
/capsules/by-id/{id}GETGet capsule by ID
/namespaces/{ns}/capsules/by-name/{name}GETGet capsule by name
/capsules/by-id/{id}/versions/{v}/startPUTStart capsule process
/namespaces/{ns}/capsules/by-name/{name}/versions/latest/startPUTStart latest version
/capsule-processes/by-id/{id}GETGet process by ID
/capsule-processes/by-id/{id}/terminatePOSTTerminate process
/capsule-processes/by-id/{id}/commandsPOSTRun command
/capsule-processes/by-id/{id}/mounts/vfsPOSTMount VFS
/capsule-processes/by-id/{id}/mounts/secretsPOSTMount secret
/capsule-processes/by-id/{id}/usersPOSTAdd user
/capsule-processes/by-id/{id}/packagesPOSTInstall package

Authentication

All endpoints require authentication:

MethodHeaderDescription
Bearer TokenAuthorization: Bearer <token>JWT token
API KeyX-Api-Key: <api-key>API key

Required Roles: Tenant.Admin or Tenant.User


SDK Usage

Working with Capsules

// Create client
var client = MaitentoClient.Create("your-api-key");

// Get capsule by name
Capsule? capsule = await client.Capsules.GetByNameAsync("production", "web-server");

// Start a capsule process
var startRequest = new CapsuleProcessStartRequest
{
    VirtualFileSystemMounts = new[]
    {
        new CapsuleVirtualFileSystemMount(
            vfsId: Guid.Parse("..."),
            vfsNamespaceId: Guid.Parse("..."),
            mountName: "data"
        )
    },
    SecretMounts = new[]
    {
        new CapsuleSecretMount("database-credentials", "db-creds")
    }
};

CapsuleProcess process = await client.CapsuleProcesses.StartAsync(
    "production",
    "web-server",
    startRequest
);

// Wait for process to be running
while (process.Status == CapsuleProcessStatus.New)
{
    await Task.Delay(1000);
    process = await client.CapsuleProcesses.GetByIdAsync(process.Id)
        ?? throw new Exception("Process not found");
}

// Run a command
var commandResult = await client.CapsuleProcesses.RunCommandAsync(
    process.Id,
    new CapsuleProcessRunCommandRequest
    {
        Command = "ls",
        Arguments = new[] { "-la", "/mnt/data" },
        MaximumDuration = TimeSpan.FromMinutes(1)
    }
);

Console.WriteLine($"Exit Code: {commandResult.ExitCode}");
Console.WriteLine($"Output: {commandResult.OutputStandard}");

// Install a package
await client.CapsuleProcesses.InstallPackageAsync(
    process.Id,
    new CapsuleProcessInstallPackageRequest { PackageName = "nginx" }
);

// Add a user with sudo permissions
await client.CapsuleProcesses.AddUserAsync(
    process.Id,
    new CapsuleProcessAddUserRequest
    {
        Username = "appuser",
        SudoAsUsers = new[] { "root" }
    }
);

// Terminate when done
await client.CapsuleProcesses.TerminateAsync(process.Id);

Exception Handling

try
{
    var process = await client.CapsuleProcesses.StartAsync(...);
}
catch (MaitentoValidationException ex)
{
    Console.WriteLine("Validation errors:");
    foreach (var error in ex.ValidationErrors)
    {
        Console.WriteLine($"  {error.Key}: {string.Join(", ", error.Value)}");
    }
}
catch (MaitentoApiException ex)
{
    Console.WriteLine($"API error ({ex.StatusCode}): {ex.ResponseBody}");
}
catch (MaitentoApiAuthenticationException ex)
{
    Console.WriteLine("Authentication failed - check your API key");
}

Shell Commands

Listing Capsules

# List all capsules
capsule-list

# List in specific namespace
capsule-list --namespace production

Getting Capsule Details

# Get latest version
capsule-get my-capsule@production

# Get specific version
capsule-get my-capsule@production --version 3

Starting Capsules

# Start a capsule
capsule-start my-capsule --namespace production

# List running capsule processes
capsule-ps --namespace production

Running Commands

# Execute a command
capsule-exec <process-id> ls --args "-la,/app"

# Run as specific user
capsule-exec <process-id> ./build.sh --user developer --timeout 600

# Run asynchronously
capsule-exec <process-id> ./long-task.sh --async

# Check command status
capsule-command-get <process-id> <command-id>

# Wait for command completion
capsule-command-await <process-id> <command-id> --timeout 60

Managing Users

# Add user with sudo permissions
capsule-add-user <process-id> admin --sudo-as root,developer

# Remove user
capsule-remove-user <process-id> developer

Managing Packages

# Install package
capsule-install-package <process-id> nginx

# Remove package
capsule-remove-package <process-id> nginx

Managing Mounts

# Mount VFS
capsule-mount-vfs <process-id> <vfs-id> <vfs-namespace-id> /data/shared

# Unmount VFS
capsule-unmount-vfs <process-id> /data/shared

# Mount secret
capsule-mount-secret <process-id> database-credentials /etc/secrets/db

# Unmount secret
capsule-unmount-secret <process-id> /etc/secrets/db

Terminating Capsules

# Terminate a capsule process
capsule-terminate <process-id>

Best Practices

  1. Template Selection: Choose minimal base templates to reduce startup time
  2. User Isolation: Create dedicated users rather than using the default maitento user
  3. Secret Management: Use secret mounts for sensitive data, never hardcode credentials
  4. Cleanup: Always terminate capsules when done to free resources
  5. Duration Limits: Set MaximumDuration to prevent orphaned processes
  6. Mount Validation: Ensure mount paths do not conflict with system directories
  7. Command Timeouts: Set appropriate maximumDuration for commands to prevent hanging processes