---
title: "oz0-node sandbox setup"
description: "Prepare this machine for sandbox tier 1."
canonical_url: "https://docs.oz0.ai/reference/cli/oz0-node/sandbox/setup"
---
# oz0-node sandbox setup

> Prepare this machine for sandbox tier 1.

For: Operators and developers looking up a command.

Prepare this machine for sandbox tier 1. As root, setup installs bubblewrap with the distribution's package manager (apt-get, dnf, apk or zypper) when bwrap is missing.

Where the kernel lets only AppArmor-profiled programs create user namespaces (kernel.apparmor_restrict_unprivileged_userns=1, Ubuntu 24.04 and later), it makes sure Ubuntu's own bwrap-userns-restrict profile is loaded: Ubuntu 25.04 and later ship it enabled, and then setup does nothing more; on 24.04 it downloads the apparmor-profiles package with apt-get (checked against the archive's signed indexes) without installing it, unpacks it in a temporary directory, copies only extra-profiles/bwrap-userns-restrict into /etc/apparmor.d and loads it with apparmor_parser.

Installing the package would also enforce its other profiles (dnsmasq, smbd, php-fpm and more). That profile lets /usr/bin/bwrap create the sandbox's namespaces and denies every capability to what runs inside.

setup never writes a profile of its own: an unconfined profile for bwrap that allows userns would let any local user hold every capability in a user namespace. It warns about such profiles, and leaves them, and kernel settings, to you. It ends by running `sandbox check` as the node's account (oz0-node, else nobody) and prints how to undo what it did; --undo removes the profile it copied (it records the copy in /var/lib/orchestrator-zero-node-sandbox), and no other.

It waits up to five minutes for apt's locks, which unattended-upgrades holds on a fresh cloud machine. install.sh runs it unless given --no-sandbox-setup. Restart a running node afterwards: it finds its tier when it starts.

## Usage

```bash
oz0-node sandbox setup [flags]
```

## Flags

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --account
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        oz0-node when it exists, else nobody
      </code>
    </td>
    
    <td>
      check the tier as this user afterwards
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --dry-run
      </code>
    </td>
    
    <td>
      bool
    </td>
    
    <td>
      
    </td>
    
    <td>
      say what setup would do, and change nothing (needs no root)
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --undo
      </code>
    </td>
    
    <td>
      bool
    </td>
    
    <td>
      
    </td>
    
    <td>
      unload and remove the profile setup copied into /etc/apparmor.d (not one a package installed)
    </td>
  </tr>
</tbody>
</table>

## Inherited flags

<table>
<thead>
  <tr>
    <th>
      Flag
    </th>
    
    <th>
      Type
    </th>
    
    <th>
      Default
    </th>
    
    <th>
      Description
    </th>
  </tr>
</thead>

<tbody>
  <tr>
    <td>
      <code>
        --data-dir
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        ~/.local/share/orchestrator-zero-node
      </code>
    </td>
    
    <td>
      where the node keeps its identity, uv, Python, runtimes and state
    </td>
  </tr>
  
  <tr>
    <td>
      <code>
        --log-level
      </code>
    </td>
    
    <td>
      string
    </td>
    
    <td>
      <code>
        info
      </code>
    </td>
    
    <td>
      log level: debug, info, warn or error
    </td>
  </tr>
</tbody>
</table>

See [all `oz0-node` commands](https://docs.oz0.ai/reference/cli/oz0-node) and the [global flags](https://docs.oz0.ai/reference/cli/oz0-node#global-flags).


## Sitemap

See the full [sitemap](https://docs.oz0.ai/sitemap.md) for all pages.
