---
title: "Security model: what stays in your cloud"
description: "What runs in Stagely and what stays in your cloud account, what Stagely sees, how each connection is authenticated, and how access ends."
url: https://stagely.dev/docs/security
---

Stagely has two sides: a side that Stagely runs and a side that you run. Stagely plans deploys and decides who can open a stagelet. Your cloud account builds and runs everything, and keeps every cloud credential and secret value. Stagely holds the GitHub App credentials, and gives the customer agent (`stagely-agent`) a short-lived source token for each deploy.

## What lives where

| Data                       | Where it lives                                                                                                                                                                                                       | Does Stagely see it?                                                                                                                      |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| Cloud provider credentials | The agent host, and your computer while setup runs                                                                                                                                                                   | No                                                                                                                                        |
| Application secret values  | The agent's encrypted store, or a file that your pipeline supplies. During a deploy, the agent also writes them to a root-only file on the stagelet's machine, and the containers get them as environment variables. | No. Stagely keeps only their names.                                                                                                       |
| Plain config values        | Stagely's config snapshots and compiled deploy bundles                                                                                                                                                               | Yes                                                                                                                                       |
| Source code                | Build workers in your cloud get the full source. Stagely reads `.stagely.yml` and the Compose files in memory while it plans a deploy.                                                                               | Briefly, the plan inputs. The bundle that Stagely keeps for resets holds the resolved Compose model and the contents of `env_file` files. |
| Built images               | Your registry                                                                                                                                                                                                        | No                                                                                                                                        |
| Stagelet traffic           | From the gateway to the stagelet's machine                                                                                                                                                                           | No                                                                                                                                        |

## Network

- The agent and the gateway each open one WebSocket connection to Stagely. Your cloud account needs no inbound port from Stagely.
- The agent host accepts only SSH, and only from the address ranges that you gave setup. It accepts no other inbound traffic.
- The gateway host is the only part that is open to the whole internet, on ports 80 and 443. It also accepts SSH from the address ranges that you gave setup. It holds no cloud credentials and no secret values.
- Stagelet machines and build workers accept traffic only from the agent and the gateway. The cloud's firewall enforces this. The firewalls of Hetzner Cloud and Vultr do not filter private networks, so on these clouds each machine also adds host firewall rules at every boot.
- Registry credentials differ by cloud. On DigitalOcean, AWS, Google Cloud, Azure and Vultr, each job gets short-lived registry credentials. On Hetzner Cloud, every machine, stagelet machines included, signs in with the registry user and password that you gave setup, and that password can push. Machines never get cloud API credentials.

## Credentials at each boundary

| Boundary                     | Credential                                                                                                                                               |
| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Person to account            | A GitHub sign-in, then a browser session, checked against current membership and role on every request                                                   |
| Account to repository        | A GitHub App installation that a member linked to the account. Stagely asks GitHub for short-lived tokens, each narrowed to one repository and one use.  |
| Stagely to agent and gateway | A one-time enrollment token, then the agent's or the gateway's own key pair, which signs its connection. Each job the agent takes carries a lease token. |
| Visitor to stagelet          | A pass that works once, for 30 seconds. The gateway trades it for a session on that stagelet only.                                                       |
| Coding agent to account      | OAuth with PKCE, through a consent page. Access tokens last 15 minutes. Stagely checks each one against a live grant.                                    |
| CLI to account               | The same OAuth server, through a loopback redirect. The token works only at the API, in the account chosen on the consent page.                          |

A coding agent's token works only at the MCP endpoint, and the CLI's token works only at the API. Neither works at the other's endpoint.

## Sessions and how access ends

- A stagelet session belongs to the member who opened the stagelet. When a coding agent or the CLI opened the stagelet, the session also belongs to that grant. A session lasts at most one hour and never outlives its grant.
- When you remove a member, revoke a grant or delete the stagelet, the access ends within about 50 seconds.
- The gateway confirms its sessions with Stagely every 20 seconds. When the gateway loses its connection to Stagely, it refuses every session that it could not confirm in the last 50 seconds. It also closes open connections, such as WebSockets, within about a minute. So the gateway fails closed.
- Stagely removes access first when it deletes a stagelet. It withdraws the route, ends the sessions and waits for the gateway to confirm. Only then does the agent delete the machine.

## Pull requests from forks

A pull request from a fork can hold code from anyone who can fork your repository. Its stagelet gets the project's config and secrets. So a pull request from a fork deploys only when someone with write access asks: with the deploy label, the comment command, the console or MCP. New commits on the fork never deploy it on their own.

## The Compose rules

Stagely refuses Compose settings that give a container access to its machine or weaken its isolation, such as privileged mode, host namespaces, devices, bind mounts and the Docker socket. Stagely also refuses build options that reach the shared build worker. Stagely checks your Compose files when it plans a deploy. The agent checks the resolved project again before it builds. See [Compose rules](https://stagely.dev/docs/app/compose.md).

## Public host names

The gateway gets a certificate for each stagelet host name. Every certificate goes into public Certificate Transparency logs, so stagelet host names become public. To open a stagelet, a visitor still needs a pass from Stagely.
