---
title: Tenancy
description: NOITE_TENANCY decides whether other people may push code — multi runs tenant code sandboxed, single is just you.
---

`NOITE_TENANCY` decides whether other people may push code to the install. Unset, it is `multi` off `localhost` and `single` on `localhost`.

- **`multi`**: tenant builds and release commands run as the unprivileged `build` user with a cleared environment (no platform secret reaches them), tenant fleets as the `fleet` user, and an nftables policy on those users closes new connections to loopback, private ranges and cloud metadata. The one private address allowed is the object store the fleet's own celld needs; Worker code can reach it but holds no keys. `/data` is private to the runner. Release commands are skipped until scoped per-app bucket keys exist. All of this needs `NET_ADMIN`, `SETUID`, `SETGID` and `CHOWN`, which `docker/compose.yaml` grants; without them the runner keeps `/ready` at 503 with the reason and refuses builds.
- **`single`**: only you push code. No egress policy, and release commands run with the root bucket keys.

The repository's isolation lane (`make e2e-isolation`, also runnable from the CI workflow) proves the `multi` claims: a hostile tenant app tries to read platform secrets and files and to reach every internal API from its build, its release command and its Worker, and the lane asserts every attempt fails while internet egress still works.

`NOITE_TENANCY` and related knobs are documented in [Environment variables](/reference/environment-variables).
