# Security

> How workloads are isolated from each other and from the platform — VMs, networks, TLS, secrets, access

URL: https://pier.run/docs/security

Pier runs every app target in its own virtual machine, on a network that denies by
default, behind an edge that terminates TLS for every hostname. This page states what is
in place today; it is not a compliance report.

## Isolation

* **Each app instance is a microVM** (Kata Containers on Cloud Hypervisor): its own kernel,
  its own memory. A container escape ends inside a VM with nothing else in it.
* **Postgres instances** run in their own pods with their own storage; buckets are
  per-project namespaces in object storage with per-project credentials.
* **Network policy is default-deny.** Nothing reaches an app except the edge; an app
  reaches its environment's Postgres and buckets through the links it declares. Node-to-node
  traffic is encrypted with WireGuard. App containers see no other tenant's addresses.

## Edge and TLS

* Every hostname, generated (`<id>.app.pier.run`, `<id>.pg.pier.run`, …) and custom, is
  served over TLS; port 80 redirects. Certificates for custom domains are issued after DNS
  verification and renewed automatically.
* Postgres is reachable only over TLS (`sslmode=require`), with a per-session credential
  from `pier psql` / `pier pg credentials` (one hour) or the instance's own credentials.
* `pier ssh` uses 15-minute certificates and re-checks your membership on every connection
  ([SSH](/docs/ssh)).

## Secrets

* A `secret: true` variable's value is stored in the platform's vault and delivered to the
  container at start; it never appears in `pier.yaml`, in deploy plans, or in logs. `pier
  vars reveal` shows it to a member with the role to read it.
* Sessions are opaque tokens, stored hashed, 30-day expiry; `pier logout` revokes.
  Two-factor authentication (TOTP) is available for every account.

## Access and audit

* Workspace roles gate every action ([roles](/docs/workspaces-and-billing#roles)); the
  platform's own operators have a separate, audited role.
* Every change is an event with an actor (`pier events --all-projects`): who deployed,
  paused, changed a variable or opened a shell, and when.

## Your responsibilities

* Commit `pier.yaml`; never commit `.pier/dev.env` (it is gitignored by `pier config init`).
* Give CI its own member with the `developer` role and its own session.
* Prefer links (`from:`) to pasted connection strings; a credential rotation then requires
  no configuration change.

## See also

[SSH](/docs/ssh) · [Environment variables](/docs/vars) · [Domains](/docs/resources/domains)
