# Hosting

Deploy apps and static sites with Composal hosting. Configure services, custom domains, CDN delivery, and managed resources from your workspace.

## Hosting model

Composal hosting manages your organization's apps, environments, services, and deployments. It supports public services, static sites, custom domains, CDN delivery, and runtime controls.

Managed public services receive an HTTPS hostname derived from the app, environment, service, and datacenter. You do not need to supply a `--deployed-url` for a service Composal manages.


## Deployment regions

Use `aws-us-west-2` for Oregon or `aws-us-east-1` for Northern Virginia. The
hosting locations API (`GET /api/v1/hosting/locations`) returns the current
selectable regions. Enable a location for your app before adding a placement
there.

London `lon1` and legacy Oregon `or1` are retired and cannot be selected for new
placements or volumes. Existing deployment history retains its original region.
Persistent block volumes are available in both AWS regions; choose the same
region for the volume and its service. A volume can attach to one service
instance at a time and requires the stable deployment channel.

## Deploy a service

Use the CLI to create a deployment and follow it while it runs.

```sh
com deploy create --app <app> --service web --env production --watch
com deploy dashboard --app <app>
```

Deploy a tagged or digest-pinned public Docker image without a build:

```sh
com deploy image --app grafana --service grafana --env production-west --region aws-us-west-2 --image grafana/grafana:13.2.2 --wait
```

Hosted source builds publish to the v2 Composal registry and deploy an immutable, verified image digest. Build runners receive credentials scoped to their isolated build repository; completing or revoking the runner lease invalidates those credentials. Existing releases keep their recorded image references for rollback.

Use the v2 Composal registry for your own images:

```sh
com deploy image --app grafana --service grafana --env production-west --image registry.composal.ai/vex/grafana:13.2.2 --wait
```

V2 images must belong to the app's organization and an unbound or matching app
repository. Composal stores immutable repository IDs and verifies the v2 image
in each deployment region; repository renames do not change a release's image.
Hosting credentials grant pull access only.

Docker Hub shorthand follows Docker's normal rules: `redis:7` resolves to
`docker.io/library/redis:7`, and `grafana/grafana:13.2.2` resolves to
`docker.io/grafana/grafana:13.2.2`. Other public registries use a full reference,
such as `ghcr.io/owner/image:tag`. Private external registry credentials are not
currently supported. Composal verifies the image in the deployment region and
pins its digest before replacing instances. Composal registry images retain
organization and app ownership checks.

Compatible deployments can share a build or reuse a retained image. Composal
checks the exact source revision, build settings, builder runtime and delivered
build-secret versions, then verifies the retained image by its immutable digest.
Rotating or editing a build secret requires a new build; unavailable credentials
block deployment.

Each deployment still creates its own release with its selected environment's
runtime settings. The deployment page links to the producer and its build logs.
A reused image shows a skipped build, while rollout progress belongs to the new
deployment. If a shared producer fails or is canceled, waiting deployments
return to normal build orchestration.

In the web app, you can inspect your organization's applications, environments, services, deployment history, and runtime controls.

## Preview environments

A preview is a short-lived copy of an app built from one source revision. A
preview profile holds its defaults: the source environment to copy, variables,
build inputs, credentials and expiry. Each preview records its source revision
and configuration snapshot and has its own deployment and runtime. Organization
members can inspect previews; administrators manage their configuration and
lifecycle. Preview URLs require organization membership unless an administrator
explicitly makes the preview public.

### Set up PR previews for Verify

With a preview profile, [Composal Verify](/docs/verify/pr-testing/composal-preview)
creates, builds and deploys a preview of each pull request's commit itself, then
runs your Scenarios against it. You do not need a separate Verify environment
pointing at a preview URL. You need an organization administrator and a Verify
project with its GitHub repository added under **PR Testing → Add repositories**.

1. Create an app linked to the project's repository, and a service for each
   process. Verify opens one public service; workers stay internal.

   ```sh
   com app create --project <project> --body-json '{"slug":"shop","name":"Shop","root_path":"."}'
   com service create --app shop --slug web --public --internal-port 3000 --healthcheck-path /health --source-path .
   com service create --app shop --slug worker --source-path .
   ```

   A root path of `.` overlaps every other app on the repository. Use a
   subdirectory root when one repository needs several apps.
2. Commit a `Dockerfile` in each service's source path. Previews always build
   from source, using the source path as the build context.
3. Create a source environment and deploy every service to it once. A preview
   copies only the services placed in its source environment.

   ```sh
   com hosting location locations --json
   com env create --app shop --body-json '{"slug":"staging","name":"Staging","kind":"staging","status":"active","location_id":"<location-id>","auto_deploy":false}'
   com deploy create --app shop --service web --env staging --watch
   com deploy create --app shop --service worker --env staging --watch
   ```
4. Create the preview profile. Verify-created previews deploy without anyone
   approving shared configuration, so give the profile a value for every key
   the app reads, and every build argument:

   ```sh
   com preview-profile create --app shop --body-json '{"name":"PR previews","slug":"pr","source_environment_id":"staging","ttl_days":3,"configuration":{"variables":{"NODE_ENV":"production"},"build_variables":{"VITE_API_BASE":"/api"},"required_keys":["DATABASE_URL"]}}'
   ```

   A source-environment or app-wide variable that the profile does not cover
   blocks deployment with `Preview needs sharing approval for configuration`.
5. Bind credentials to the profile instead of putting them in variables. An
   app-wide secret that is not bound or masked blocks deployment.

   ```sh
   com hosting preview-profile-secret-binding create --app shop --path preview_profile_id=pr --body-json '{"env_key":"DATABASE_URL","secret_id":"<secret-id>"}'
   com hosting preview-profile-secret-binding create --app shop --path preview_profile_id=pr --body-json '{"env_key":"STRIPE_SECRET_KEY","mode":"masked"}'
   ```
6. Try the profile with a manual preview, then delete it:

   ```sh
   com preview create --app shop --body-json '{"name":"Profile check","slug":"profile-check","app_preview_profile_id":"pr","source_ref":"<branch>"}'
   com preview deploy --app shop --id profile-check
   com preview operations --app shop --id profile-check
   com preview delete --app shop --id profile-check
   ```
7. Save PR testing with the profile and the public service, then follow
   [Composal Preview](/docs/verify/pr-testing/composal-preview):

   ```sh
   com verify pr-testing setup --project <project> --previews composal --preview-profile pr --service web --accounts <environment> --pr-check --on
   ```

### Manage previews

Open an app's previews to create a preview from a source environment or a Change.
Preview defaults control automatic Change provisioning.

Pause a preview and wait for cleanup before changing its secrets, backing connections,
placement or resource limits. Compare its configuration with production, review any
source drift and approve the selected sharing before deployment. Shared secret references
follow the selected version policy; copying a secret creates a separately managed preview
secret. Rotating a build secret requires a fresh build. Redeploy the selected preview to
deliver new secret versions to its runtime.

Explicitly shared managed data connections use their authorized managed secret
version for both public and provider-private URLs. An attached VPC takes precedence
for the private URL. Changing private endpoint availability requires reviewing the
source again; an unavailable or malformed selected endpoint blocks deployment.

Explicitly selected bucket connections share the bucket's managed access-key JSON
under the same environment key as the source. The payload includes the access key,
secret key, endpoint, bucket and region. Local overrides and masks retain precedence;
sharing runtime bucket credentials does not expose them to builds. Rotating an access
key requires redeploying the selected preview. New or rotated environment bucket credentials stay
scoped to that environment.

Preview storage mounts require explicit selection. You can share a captured ephemeral
source cache, or provision a compatible volume in the preview environment and select it
for the captured mount. Production data volumes cannot be shared with a preview writer.
The mount keeps the source path and read-only setting. A single-writer volume requires
one service, one instance and compatible placement and rollout settings. Source refresh
clears storage selections so you can review them again.

Pausing preserves preview-owned volumes. Deletion, expiry and Change closure stop
workloads before destroying preview-owned volumes and their data. Referenced shared
resources remain available; cleanup refuses to destroy a volume referenced by another
consumer. Retain a preview before Change closure or expiry to keep it available, and
inspect lifecycle history for cleanup progress and retryable failures.

For GitHub PR testing, choose an existing profile in **Verify → Integrations → GitHub → Composal Preview**. Verify provisions and deploys the PR head, then waits for healthy rollouts and its HTTPS URL. See [Source Control](/docs/verify/source-control/github#preview-source) for configuration and release availability.

## Preview networking, URLs and volumes

What a preview contains:

- Each service runs one instance in one region.
- Release and prestart commands do not run. Run any database migrations when
  the process starts.
- Volumes and data-resource connections are not attached unless an
  administrator selects them for that preview. Previews that Verify creates have
  none, so a service starts without its volume.
- Service bindings are not carried into the preview, so their URL variables are
  absent.

Each public service in a preview gets its own hostname,
`pv-<token>-<service>-<app>-<org>.app.vex.so`, shortened when long. The token is
assigned when the preview is created. `com preview show` lists the preview's URLs
once its rollout finishes.

No environment variable gives a service its own preview URL or the address of
another service in the same preview. Private service names are
`<service>.<app>.internal` on port 8444, and a preview copy is
`<service>.<app>-<token>.internal`, so a profile cannot hold them. Serve the
browser app and its API from one public service, call the API with relative
paths, and build emailed links from the incoming request's origin.

A service with a persistent volume needs the `stable` deployment channel and a
single instance. The default channel is `blue_green`.

For email sign-in tests, the app must send real mail. Verify follows a sign-in
link only when its origin is the preview's URL, the test account's login URL, or
an origin listed in the account's [`email_link_auth_origins`](/docs/verify/credentials/managed#email-link).

## Domains and delivery

Composal can attach custom domains, validate ownership, and expose CDN delivery state. Static-site deployments have their own upload and finalization path, while managed services use the platform’s public TLS routing after the API verifies that a domain belongs to the selected app service.

## Inspect runtime state

Use deployment logs and the dashboard for the current allocation and service state.

```sh
com deploy logs --app <app> <allocation-id> --task web
com deploy dashboard --app <app>
```

For container-image workflows, use [Composal registry](/docs/registry). For the server contract, consult the [OpenAPI reference](/docs/api).

See the [Remote builders guide](/docs/remote-builders) for upcoming organization-managed builders with persistent layer caches, native Docker connections, and direct pushes to `registry.composal.ai`. The implementation is in review, the Unix supervisor is implemented, and production gateway deployment is unfinished.
