# Zero-Knowledge Workflows

**Page:** guides/zero-knowledge

[Download Raw Markdown](./guides/zero-knowledge.md)

---

# Zero-Knowledge Workflows

**Every cloud provider makes the same promise: "Your data is secure." Then they read your data to train AI models, hand it to governments without telling you, or suffer breaches that expose millions of records.** The promise is structurally impossible to keep because their architecture requires them to have access to your data in order to serve it.

Hoody's architecture is different. Not because we are more trustworthy -- because the system does not require trust.

You rent bare metal servers. Physical machines. Not virtual instances on shared hardware. Not containers on someone else's hypervisor. Actual hardware where you control the disk, the memory, the network, and the encryption keys. Your containers run on hardware you control. We cannot read your data because we do not have access to the hardware it lives on.

This is not a privacy feature. It is the architecture.

---

## What Zero-Knowledge Means in Hoody

Zero-knowledge means the platform operator (Hoody) cannot access your data even if compelled to do so. Here is how:

| Layer | Traditional Cloud | Hoody |
|-------|------------------|-------|
| Hardware | Shared with other tenants | Dedicated bare metal you control |
| Hypervisor | Provider-controlled | None -- containers run on your hardware |
| Disk encryption | Provider holds the keys | You hold the keys |
| Network | Provider can inspect traffic | Encrypted within your server |
| Backups | Provider can read snapshots | Snapshots live on your disk |
| AI training | Your data may be used | Your data never leaves your hardware |

The fundamental difference: in traditional cloud, the provider is in the trust chain. In Hoody, the provider is not. Your server is a physical machine. Your containers are processes on that machine. Your data is bytes on that disk. Hoody manages the orchestration layer -- container creation, proxy routing, service coordination -- but your actual data stays on hardware you control.


This is not marketing language. This is an architectural fact. Hoody's API manages container lifecycle and proxy routing. The container data -- files, databases, processes, memory -- exists on your bare metal server. Hoody's infrastructure does not have filesystem access to your containers.


---

## Encrypted Filesystems

hoody-files supports encrypted storage through the crypt backend. Files are encrypted before they hit the disk and decrypted on read. The encryption key never leaves your container.


  
    ```bash
    # Configure encrypted storage backend
    hoody files backends connect crypt \
      --remote "/secure-data" \
      --password "$ENCRYPTION_KEY"

    # Write a file to encrypted storage
    hoody files put secrets/api-keys.json \
      --backend "encrypted-vault"

    # Read it back -- transparently decrypted
    hoody files get secrets/api-keys.json \
      --backend "encrypted-vault"
    ```
  
  
    ```typescript
    import { HoodyClient } from '@hoody-ai/hoody-sdk';

    const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });

    const containerClient = await client.withContainer({
      id: CONTAINER_ID,
      project_id: PROJECT_ID,
      server: SERVER,
    });

    // Configure encrypted backend
    const vault = await containerClient.files.backends.connectCrypt({
      remote: '/secure-data',
      password: process.env.ENCRYPTION_KEY,
    });

    // Write encrypted file -- reference the backend by its returned id
    const payload = JSON.stringify({ stripe: 'sk_live_...', github: 'ghp_...' });
    await containerClient.files.put('secrets/api-keys.json', new Blob([payload]), {
      backend: vault.data.id,
    });

    // Read transparently decrypted
    const secrets = await containerClient.files.get('secrets/api-keys.json', {
      backend: vault.data.id,
    });
    ```
  
  
    ```bash
    # Configure encrypted backend -- returns { data: { id, ... } }; use data.id for subsequent calls
    curl -X POST "https://$PROJECT_ID-$CONTAINER_ID-files-1.$SERVER.containers.hoody.icu/api/v1/backends/crypt" \
      -H "Content-Type: application/json" \
      -d '{
        "remote": "/secure-data",
        "password": "'$ENCRYPTION_KEY'"
      }'

    # Write to encrypted storage. The request body IS the file content; the
    # backend is selected via the ?backend= query parameter (replace $BACKEND_ID
    # with the id returned above).
    curl -X PUT "https://$PROJECT_ID-$CONTAINER_ID-files-1.$SERVER.containers.hoody.icu/api/v1/files/secrets/api-keys.json?backend=$BACKEND_ID" \
      -H "Content-Type: application/json" \
      -d '{"stripe": "sk_live_...", "github": "ghp_..."}'

    # Read from encrypted storage (transparently decrypted)
    curl "https://$PROJECT_ID-$CONTAINER_ID-files-1.$SERVER.containers.hoody.icu/api/v1/files/secrets/api-keys.json?backend=$BACKEND_ID"
    ```
  


**What happens on disk:** The file `secrets/api-keys.json` is stored as encrypted bytes. If someone physically extracts the disk, they get ciphertext. If someone gains shell access without the encryption key, they get ciphertext. The file is only readable through the hoody-files service with the correct key.

---

## Vault Secrets Management

For secrets that need to be available to applications without storing them in plaintext files, use hoody-sqlite's KV store as a secrets vault:


  
    ```bash
    # Store secrets in the KV store (--db is required; --create-db-if-missing on first use)
    hoody kv set "vault:stripe_key" --db /hoody/databases/app.db --create-db-if-missing \
      --body '"sk_live_abc123..."'

    hoody kv set "vault:database_url" --db /hoody/databases/app.db \
      --body '"postgres://user:pass@host:5432/db"'

    hoody kv set "vault:jwt_secret" --db /hoody/databases/app.db \
      --body '"your-256-bit-secret"'

    # Retrieve secrets programmatically
    hoody kv get "vault:stripe_key" --db /hoody/databases/app.db
    ```
  
  
    ```typescript
    import { HoodyClient } from '@hoody-ai/hoody-sdk';

    const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });

    const containerClient = await client.withContainer({
      id: CONTAINER_ID,
      project_id: PROJECT_ID,
      server: SERVER,
    });

    // Store secrets. The value is the raw string; `db` is required.
    const kvOpts = { db: '/hoody/databases/app.db', create_db_if_missing: true };
    await containerClient.sqlite.kvStore.set('vault:stripe_key', 'sk_live_abc123...', kvOpts);

    await containerClient.sqlite.kvStore.set('vault:jwt_secret', 'your-256-bit-secret', kvOpts);

    // Retrieve in your application
    const stripeKey = await containerClient.sqlite.kvStore.get('vault:stripe_key', { db: '/hoody/databases/app.db' });
    ```
  
  
    ```bash
    # Store a secret. The body IS the value (raw string), and `db` is required.
    curl -X PUT "https://$PROJECT_ID-$CONTAINER_ID-sqlite-1.$SERVER.containers.hoody.icu/api/v1/sqlite/kv/vault:stripe_key?db=/hoody/databases/app.db&create_db_if_missing=true" \
      -H "Content-Type: text/plain" \
      -d 'sk_live_abc123...'

    # Retrieve a secret (the response body is the raw stored value)
    curl "https://$PROJECT_ID-$CONTAINER_ID-sqlite-1.$SERVER.containers.hoody.icu/api/v1/sqlite/kv/vault:stripe_key?db=/hoody/databases/app.db"
    ```
  


The KV store lives in SQLite, which lives on your bare metal disk. Secrets never traverse infrastructure you do not control. Combine with the crypt backend for defense in depth -- encrypted filesystem holding an encrypted database holding your secrets.

---

## Container Isolation as the Security Boundary

Each container is a complete, isolated Linux environment. The isolation is not just logical -- it is enforced at the operating system level:

```
┌──────────────────────────────────────────────────┐
│                 YOUR BARE METAL SERVER            │
│                                                  │
│  ┌─────────────┐  ┌─────────────┐  ┌──────────┐ │
│  │ Container A  │  │ Container B  │  │ Cont. C  │ │
│  │             │  │             │  │          │ │
│  │ Own files   │  │ Own files   │  │ Own files│ │
│  │ Own network │  │ Own network │  │ Own net  │ │
│  │ Own procs   │  │ Own procs   │  │ Own procs│ │
│  │ Own users   │  │ Own users   │  │ Own users│ │
│  │             │  │             │  │          │ │
│  │ CANNOT SEE  │  │ CANNOT SEE  │  │ CANNOT   │ │
│  │ B or C      │  │ A or C      │  │ SEE A, B │ │
│  └─────────────┘  └─────────────┘  └──────────┘ │
│                                                  │
│  Shared: CPU, RAM, Disk (but isolated views)     │
└──────────────────────────────────────────────────┘
```

**What container isolation means in practice:**

- Container A cannot read Container B's files, even though they share the same physical disk
- A process in Container A cannot see or kill processes in Container B
- Network traffic is isolated -- containers cannot sniff each other's traffic
- A compromised container cannot escape to the host or other containers
- An AI agent running in Container A has full root access inside A and zero access outside A

This is why container isolation is the correct security primitive for the AI era. When you give an AI agent root access to a container, the blast radius is exactly one container. Not your server. Not your other projects. Not your data.

---

## Privacy Patterns

### Pattern 1: Realm-Restricted Tokens for Tenant Isolation

When building multi-tenant applications, use realms to create isolated API scopes:


  
    ```bash
    # NOTE: There is no hoody realms create CLI command.
    # Realms are configured through the Hoody dashboard.
    # List existing realms:
    hoody realms list

    # Create containers within each realm
    hoody containers create --project $PROJECT_ID \
      --server-id $SERVER_ID \
      --name "acme-app" \
      --hoody-kit

    hoody containers create --project $PROJECT_ID \
      --server-id $SERVER_ID \
      --name "globex-app" \
      --hoody-kit
    ```
  
  
    ```typescript
    import { HoodyClient } from '@hoody-ai/hoody-sdk';

    const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });

    // NOTE: There is no createRealm method in the SDK.
    // Realms are configured through the Hoody dashboard.
    // Realms are returned as an opaque array of 24-hex IDs -- any human
    // naming convention is external/out-of-band (e.g. tracked in your own notes).
    const realms = await client.api.realms.list();
    const realmIds = realms.data.realm_ids; // string[] of 24-hex realm IDs
    if (realmIds.length < 2) {
      throw new Error(`Need at least two realms to isolate customers; got ${realmIds.length}. Create them via the Hoody dashboard first.`);
    }
    const [acmeRealmId, globexRealmId] = realmIds;

    // Containers in different realms are completely isolated
    const acmeApp = await client.api.containers.create(PROJECT_ID, {
      name: 'acme-app',
      server_id: SERVER_ID,
      realm_ids: [acmeRealmId],
      hoody_kit: true,
    });

    const globexApp = await client.api.containers.create(PROJECT_ID, {
      name: 'globex-app',
      server_id: SERVER_ID,
      realm_ids: [globexRealmId],
      hoody_kit: true,
    });
    ```
  
  
    ```bash
    # NOTE: There is no POST /api/v1/realms endpoint.
    # Realms are configured through the Hoody dashboard.
    # List available realms:
    curl "https://api.hoody.icu/api/v1/realms" \
      -H "Authorization: Bearer $HOODY_TOKEN"

    # Create container in realm
    curl -X POST "https://api.hoody.icu/api/v1/projects/$PROJECT_ID/containers" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "acme-app",
        "server_id": "'$SERVER_ID'",
        "realm_ids": ["'$ACME_REALM_ID'"],
        "hoody_kit": true
      }'
    ```
  


Realm-scoped API tokens can only access containers within their realm. A token for `tenant-acme-corp` cannot see, list, or access any container in `tenant-globex-inc`. The isolation is enforced at the API level.

### Pattern 2: Encrypt Data at Rest

Layer encryption for sensitive data:

```typescript
// Layer 1: hoody-files crypt backend encrypts the filesystem
// Layer 2: Application-level encryption for specific fields

// @mode serverless
const SQLITE = "https://PROJECT-CONTAINER-sqlite-1.SERVER.containers.hoody.icu";

// Store with application-level encryption
const crypto = require('crypto');
const key = Buffer.from(process.env.ENCRYPTION_KEY, 'hex');
const iv = crypto.randomBytes(16);
const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);

const sensitiveData = JSON.stringify({ ssn: '123-45-6789', salary: 150000 });
let encrypted = cipher.update(sensitiveData, 'utf8', 'hex');
encrypted += cipher.final('hex');

await fetch(SQLITE + "/api/v1/sqlite/db?db=/hoody/databases/app.db", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    transaction: [{ query: "INSERT INTO employee_records (name, encrypted_data, iv) VALUES (?, ?, ?)", values: ["Alice Chen", encrypted, iv.toString('hex')] }]
  })
});
```

Two layers: the filesystem is encrypted by the crypt backend, and sensitive fields are encrypted again at the application level. Even if someone bypasses the filesystem encryption, the data inside is still ciphertext.

### Pattern 3: Control Network Egress with Firewall

Prevent containers from sending data to unauthorized destinations:


  
    ```bash
    # Lock down outbound traffic
    hoody firewall reset -c $CONTAINER_ID

    # Resolve the hostnames you want to allow to IPv4/CIDR first — the firewall
    # API only accepts numeric destinations (host `dig +short api.stripe.com`).
    STRIPE_CIDR=$(dig +short api.stripe.com | awk '{print $1"/32"; exit}')
    GITHUB_CIDR=$(dig +short api.github.com  | awk '{print $1"/32"; exit}')

    hoody firewall egress create -c $CONTAINER_ID \
      --action allow --protocol tcp --destination-port 443 \
      --destination "$STRIPE_CIDR" --description "Allow Stripe API"

    hoody firewall egress create -c $CONTAINER_ID \
      --action allow --protocol tcp --destination-port 443 \
      --destination "$GITHUB_CIDR" --description "Allow GitHub API"
    ```
  
  
    ```typescript
    import { HoodyClient } from '@hoody-ai/hoody-sdk';

    const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });

    // Reset firewall to deny-all default
    await client.api.firewall.reset(CONTAINER_ID);

    // Whitelist specific destinations. The egress `destination` must be an
    // IPv4 address or CIDR range — resolve the hostname to an IP first.
    await client.api.firewall.addEgressRule(CONTAINER_ID, {
      destination: '203.0.113.10/32', // resolved IP for api.stripe.com
      destination_port: '443',
      action: 'allow',
      protocol: 'tcp',
      description: 'Allow Stripe API',
    });
    ```
  
  
    ```bash
    # Reset firewall (deny-all default)
    curl -X POST "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID/firewall/reset" \
      -H "Authorization: Bearer $HOODY_TOKEN"

    # Whitelist specific destination. `destination` must be an IPv4 address or
    # CIDR range — resolve the hostname to an IP first (e.g. dig +short api.stripe.com).
    curl -X POST "https://api.hoody.icu/api/v1/containers/$CONTAINER_ID/firewall/egress" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
        "destination": "203.0.113.10/32",
        "destination_port": "443",
        "action": "allow",
        "protocol": "tcp",
        "description": "Allow Stripe API"
      }'
    ```
  


With egress deny-all, the container cannot phone home, cannot exfiltrate data, cannot communicate with any server you have not explicitly approved. This is essential when running untrusted code or AI agents that might attempt to send data externally.

---

## Compliance and Data Sovereignty

Physical servers mean physical locations. This is the simplest compliance argument there is:

**Data residency:** Your server is in Frankfurt. Your data is in Frankfurt. Not "primarily" in Frankfurt. Not "replicated from" Frankfurt. Physically, magnetically, on a disk in Frankfurt.

**GDPR:** European personal data lives on European hardware. Period. No transatlantic transfer to worry about, no data processing agreements with cloud sub-processors, no "our servers might be anywhere" hedging.

**HIPAA:** Protected health information on dedicated hardware with encrypted filesystems, firewall-controlled network access, and container isolation between patient datasets.

**SOC 2:** Audit trail through HTTP request logs. Access control through proxy permissions. Encryption through crypt backend. Isolation through containers. Every compliance requirement maps to an HTTP-observable, configurable control.

```
┌────────────────────────────────────────────────┐
│  YOUR SERVER: Frankfurt, Germany               │
│  Physical address: DataCenter GmbH, Room 4B    │
│                                                │
│  Container: patient-records                    │
│  ├── Encrypted filesystem (crypt backend)      │
│  ├── Firewall: egress deny-all                 │
│  ├── Proxy: IP whitelist (clinic IPs only)     │
│  ├── Realm: healthcare-prod                    │
│  └── Snapshots: daily, 90-day retention        │
│                                                │
│  Data location: This building. This rack.      │
│  Data access: Clinic IPs only.                 │
│  Data encryption: AES-256, keys on-server.     │
│  Data retention: 90-day snapshot history.       │
│  Audit trail: Every HTTP request logged.        │
└────────────────────────────────────────────────┘
```

Try expressing that compliance posture with a shared cloud VM. You cannot. The architecture prevents it.

---

## The AI Safety Angle

Here is the argument that makes zero-knowledge workflows urgent rather than merely prudent:

**AI agents running in your infrastructure can see everything.** When you give an AI agent access to a container -- terminal, files, database, browser -- it has the same access as a developer. It can read credentials, query databases, browse the filesystem.

On shared infrastructure, a compromised or misbehaving AI agent could:

- Exfiltrate data through network requests
- Access other tenants' resources through hypervisor vulnerabilities
- Persist malicious code that survives container restarts
- Send your data to the AI provider's training pipeline

On Hoody's bare metal + container architecture:

- **Container isolation** prevents the agent from escaping its sandbox
- **Firewall rules** prevent unauthorized network communication
- **Snapshots** let you roll back any changes the agent made
- **Bare metal** means no hypervisor attack surface
- **Encrypted filesystems** mean even disk-level access yields ciphertext


  
    ```bash
    # The AI safety workflow:

    # 1. Create an isolated container for the experiment and capture its ID
    EXPERIMENT_ID=$(hoody containers create --project $PROJECT_ID \
      --server-id $SERVER_ID \
      --name "ai-experiment" \
      --hoody-kit | jq -r '.data.id')

    # 2. Lock down network
    hoody firewall reset -c $EXPERIMENT_ID

    # 3. Snapshot clean state
    hoody snapshots create --container $EXPERIMENT_ID \
      --alias "clean-slate"

    # 4. Let the AI agent run via the prompt endpoint
    curl -X POST "https://$PROJECT_ID-$EXPERIMENT_ID-workspaces-1.$SERVER.containers.hoody.icu/api/v1/agent/prompt/sync" \
      -H "Content-Type: application/json" \
      -d '{"parts": [{"type": "text", "text": "Analyze this dataset and build a classification model"}], "autoApprove": true}'

    # 5. Inspect results
    # 6. Restore clean state if needed
    hoody snapshots restore -c $EXPERIMENT_ID --name "clean-slate"
    ```
  
  
    ```typescript
    import { HoodyClient } from '@hoody-ai/hoody-sdk';

    const client = new HoodyClient({ baseURL: 'https://api.hoody.icu', token: process.env.HOODY_TOKEN });

    // 1. Isolated container
    const experiment = await client.api.containers.create(PROJECT_ID, {
      name: 'ai-experiment',
      server_id: SERVER_ID,
      hoody_kit: true,
    });

    // 2. Lock down network
    await client.api.firewall.reset(experiment.data.id);

    // 3. Snapshot clean state
    await client.api.containers.createSnapshot(experiment.data.id, {
      alias: 'clean-slate',
    });

    // 4. Let the AI work in isolation
    // Using raw fetch to show the HTTP surface directly.
    const agentBase = `https://${PROJECT_ID}-${experiment.data.id}-workspaces-1.${SERVER}.containers.hoody.icu`;
    await fetch(`${agentBase}/api/v1/agent/prompt/sync`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        parts: [{ type: 'text', text: 'Analyze this dataset and build a classification model' }],
        autoApprove: true,
      }),
    });

    // 5. Inspect results via files, terminal, sqlite
    // 6. Restore if needed
    await client.api.containers.restoreSnapshot(experiment.data.id, 'clean-slate');
    ```
  
  
    ```bash
    # 1. Create isolated container
    curl -X POST "https://api.hoody.icu/api/v1/projects/$PROJECT_ID/containers" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"name": "ai-experiment", "server_id": "'$SERVER_ID'", "hoody_kit": true}'

    # 2. Lock down network
    curl -X POST "https://api.hoody.icu/api/v1/containers/$EXPERIMENT_ID/firewall/reset" \
      -H "Authorization: Bearer $HOODY_TOKEN"

    # 3. Snapshot clean state
    curl -X POST "https://api.hoody.icu/api/v1/containers/$EXPERIMENT_ID/snapshots" \
      -H "Authorization: Bearer $HOODY_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{"alias": "clean-slate"}'

    # 4. Let AI work
    curl -X POST "https://$PROJECT_ID-$EXPERIMENT_ID-workspaces-1.$SERVER.containers.hoody.icu/api/v1/agent/prompt/sync" \
      -H "Content-Type: application/json" \
      -d '{"parts": [{"type": "text", "text": "Analyze this dataset and build a classification model"}], "autoApprove": true}'

    # 5-6. Inspect and restore if needed (restore = PATCH the snapshot by name)
    curl -X PATCH "https://api.hoody.icu/api/v1/containers/$EXPERIMENT_ID/snapshots/clean-slate" \
      -H "Authorization: Bearer $HOODY_TOKEN"
    ```
  


The AI agent has full autonomy inside an air-gapped container. It can read data, write code, run experiments -- but it cannot exfiltrate anything because the firewall blocks all outbound traffic. When the experiment is done, inspect the results. If anything looks wrong, restore the clean snapshot. The data never left your hardware.


Zero-knowledge is not about preventing AI from being useful. It is about letting AI be maximally useful -- full root access, full filesystem access, full database access -- while ensuring the blast radius of any mistake or misbehavior is exactly one container on hardware you control.


---

## Defense in Depth

The strongest security posture layers multiple controls:

```
Layer 1: Bare Metal        → No shared hardware, no hypervisor attack surface
Layer 2: Container          → Process isolation, filesystem isolation
Layer 3: Firewall           → Network egress control, deny-all default
Layer 4: Proxy Permissions  → Authentication before HTTP reaches the container
Layer 5: Encrypted FS       → Data encrypted at rest (crypt backend)
Layer 6: Application        → Field-level encryption, input validation
Layer 7: Snapshots          → Rollback capability, audit via diff
Layer 8: Realms             → API-level tenant isolation
```

Each layer is independently configurable through HTTP. Each layer can be audited through HTTP. Each layer is a security boundary that an attacker must breach independently. Compromise one layer and the others still hold.

This is not defense in depth as a marketing term. It is eight distinct, HTTP-configurable security boundaries between an attacker and your data.

---

## What's Next

- **[Building a Full-Stack Application](/guides/full-stack-app/)** -- Build with security from the start
- **[Deploying Autonomous AI Agents](/guides/ai-agents/)** -- AI agents in isolated containers
- **[Proxy Permissions](/foundation/proxy/permissions/)** -- Fine-grained access control
- **[Firewall Configuration](/foundation/networking/firewall/)** -- Network-level security
- **[Encrypted Cloud Storage](/foundation/storage/cloud/)** -- Multi-backend encrypted storage