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
- What are Capsules
- Capsule Definitions vs CapsuleProcesses
- Capsule Lifecycle
- VFS and Secret Mounts
- User and Package Management
- Capsule Commands
- API Reference
- SDK Usage
- Shell Commands
What are Capsules
Capsules are isolated container environments that provide secure, reproducible execution contexts for running workloads. They enable:
- Reproducible isolated execution - Define once, run many times with consistent setup
- Secure environment sandboxing - Control users, packages, mounts, and secrets
- Workflow automation - Define startup commands and respond to runtime commands
- Dynamic resource management - Mount filesystems and secrets at runtime
- Multi-tenancy - Namespace-scoped templates with tenant isolation
Capsule Definitions vs CapsuleProcesses
Understanding the distinction between Capsules and CapsuleProcesses is fundamental:
| Concept | Description |
|---|---|
| Capsule | The reusable definition/template stored in the database |
| CapsuleProcess | A 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:
| Property | Description |
|---|---|
Version | Version number (immutable, increments on changes) |
Template | Base container/environment specification (e.g., ubuntu:22.04) |
AdditionalPackages | Array of package names to install |
Users | User definitions to create |
VirtualFileSystemMounts | VFS mount specifications |
SecretMounts | Secret mount specifications |
StartupCommands | Commands to run during startup |
AutoTerminateAfterStartupCommands | Boolean for auto-termination |
MaximumDuration | TimeSpan for process lifetime limit |
IsDisabled | Whether 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
- If
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
| Status | Description |
|---|---|
Finished | Success |
Error | Setup/execution failure |
Killed | External termination |
Cleanup (Always Runs):
- Delete API authentication key
- Tear down created users
- Tear down secret mounts
- 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
| Operation | Description |
|---|---|
Command | Shell command execution |
MountVfs | Mount virtual file system |
UnmountVfs | Unmount virtual file system |
MountSecret | Mount secret |
UnmountSecret | Unmount secret |
AddUser | Add user to capsule |
RemoveUser | Remove user from capsule |
InstallPackage | Install system package |
RemovePackage | Remove system package |
Terminate | Terminate the process |
Command Status Values
| Status | Description |
|---|---|
Pending | Command queued but not started |
Running | Command is executing |
Finished | Command completed successfully |
Error | Command failed |
AbortedOnTermination | Aborted due to process termination |
API Reference
Capsules API
| Endpoint | Method | Description |
|---|---|---|
/capsules | GET | List all capsules |
/namespaces/{ns}/capsules | GET | List capsules in namespace |
/capsules/by-id/{id} | GET | Get capsule by ID |
/namespaces/{ns}/capsules/by-name/{name} | GET | Get capsule by name |
/capsules/by-id/{id}/versions/{v}/start | PUT | Start capsule process |
/namespaces/{ns}/capsules/by-name/{name}/versions/latest/start | PUT | Start latest version |
/capsule-processes/by-id/{id} | GET | Get process by ID |
/capsule-processes/by-id/{id}/terminate | POST | Terminate process |
/capsule-processes/by-id/{id}/commands | POST | Run command |
/capsule-processes/by-id/{id}/mounts/vfs | POST | Mount VFS |
/capsule-processes/by-id/{id}/mounts/secrets | POST | Mount secret |
/capsule-processes/by-id/{id}/users | POST | Add user |
/capsule-processes/by-id/{id}/packages | POST | Install package |
Authentication
All endpoints require authentication:
| Method | Header | Description |
|---|---|---|
| Bearer Token | Authorization: Bearer <token> | JWT token |
| API Key | X-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
- Template Selection: Choose minimal base templates to reduce startup time
- User Isolation: Create dedicated users rather than using the default
maitentouser - Secret Management: Use secret mounts for sensitive data, never hardcode credentials
- Cleanup: Always terminate capsules when done to free resources
- Duration Limits: Set
MaximumDurationto prevent orphaned processes - Mount Validation: Ensure mount paths do not conflict with system directories
- Command Timeouts: Set appropriate
maximumDurationfor commands to prevent hanging processes