## The short version

Deploy a knowledge base built with Phoenix on Ample using the public web service pattern. Compute runs the app in an isolated microVM behind a public HTTPS URL, and a published bucket serves public assets from the CDN host.

## WHAT WAS VERIFIED

Verified on Phoenix: a versioned, immutable-cached asset uploaded to a published bucket and served from the CDN URL alongside the app's own public HTTPS URL.

## INFRASTRUCTURE

### What it needs

- [Compute](/content/discover/primitive/compute/index.html): verified (Apps run in isolated x86_64 Firecracker microVMs; sizes are the priced VM sizes.)
- [CDN](/content/discover/primitive/cdn/index.html): verified (A published bucket's objects are served at its public_url. It does not front app compute and is not a cache or key-value store.)

## PREREQUISITES

### Before you start

- A Phoenix project that builds and starts with the documented commands (mix deps.get, MIX_ENV=prod mix compile and mix release in the builder, then the release bin script with PHX_SERVER=true on the elixir-1.18 template; PORT, DATABASE_URL and SECRET_KEY_BASE read in config/runtime.exs)
- A bucket from `ample bucket create` with its credentials passed as encrypted S3_* environment variables
- An Ample account token with servers:write, buckets:read

## STEP BY STEP

### How to do it

1.  Build and start
   
   mix deps.get, MIX_ENV=prod mix compile and mix release in the builder, then the release bin script with PHX_SERVER=true on the elixir-1.18 template; PORT, DATABASE_URL and SECRET_KEY_BASE read in config/runtime.exs. The server must bind 0.0.0.0 on PORT.

2.  Wire object storage
   
   Create the bucket(s), then pass endpoint, region, bucket and keys as --env values. Use path-style addressing. Keep private data in an unpublished bucket. Publish only the bucket that serves public assets and reference its CDN URL.

3.  Deploy
   
   Run the synchronous deploy once and read the result (exit 0 live, 1 failed, 2 blocked). Re-running with no change is a no-op.
   
   ```
   ample deploy . --name <app-name> --public --env S3_ENDPOINT=... --env S3_REGION=... --env S3_BUCKET=... --env S3_ACCESS_KEY_ID=... --env S3_SECRET_ACCESS_KEY=... --env CDN_PUBLIC_URL=...
   ```

4.  Verify
   
   Fetch the live URL and the pattern self-test route(s) (/p/versioned-static-assets) from the example; then run your own checks. On failure read `ample logs <deployment_id> --kind build` then `--kind runtime`.
   
   ```
   ample logs <deployment_id> --kind build
   ```

## EXAMPLES

### Tested examples

- **Phoenix pattern fixture** (`tests/deploy-canaries/phoenix-patterns`): Multi-pattern Phoenix app whose public web service module was checked live; the module is under tests/deploy-canaries/_pattern-modules.

## SUCCESS CHECKS

### How to know it worked

- app responds on its public URL (`/` on the live URL, expect ample canary phoenix patterns)
- versioned-static-assets self-test (`/p/versioned-static-assets` on the live URL, expect a CDN URL whose content is served publicly)

## COST

### Cost estimate

Estimated 5.00 USD per month (size prices from pricing.toml at build revision ca0b484a7a9957c573a88d3a32dc603c3c10135a).

- app server x1 `s-1vcpu-1gb`: 5.00 USD

Upper-bound monthly price of the tested sizes. Buckets are allocation-priced per quota and not included.

## EVIDENCE

### Verification evidence

- canary_run on 2026-09-20T23:45:31Z at revision `4d1511e574302f3904b75088bd4048a0975218b3 (CLI 0.1.21)`: Phoenix pattern fixture deployed on Ample (mix deps.get, MIX_ENV=prod mix compile and mix release in the builder, then the release bin script with PHX_SERVER=true on the elixir-1.18 template; PORT, DATABASE_URL and SECRET_KEY_BASE read in config/runtime.exs); checks passed for versioned-static-assets and configuration-secrets. Pattern proof: a versioned, immutable-cached asset uploaded to a published bucket and served from the CDN URL alongside the app's own public HTTPS URL. (expires 2027-03-19T23:45:31Z)
- canary_run on 2026-09-20T23:45:31Z at revision `4d1511e574302f3904b75088bd4048a0975218b3 (CLI 0.1.21)`: The same Phoenix app deployed with a --release-command migration; the marker it created was readable after activation. (expires 2027-03-19T23:45:31Z)

## EXECUTION

### Execution binding

MCP tool `ample_deploy` (registry `mcp:ample_deploy`), schema hash `876465fce906da0c` observed 2026-09-22T00:31:22.774679+00:00 at revision `e6446ceea69b`. Binding state at export: schema_changed. Required scopes: servers:write, buckets:read.

## NEXT ACTIONS

### Typed next actions

- Browse the catalog index (`GET /v1/catalog` on the api origin; authentication not required, approval not required)
- Search published recipes by intent, stack and constraints (`POST /v1/catalog/search` on the api origin; authentication not required, approval not required)
- Prepare a side-effect-free deployment plan for an authorized project (`POST /v1/catalog/plan` on the api origin; authentication required, approval not required)
- Read the existing agent authentication setup (`GET /mcp/setup` on the api origin; authentication not required, approval not required)
- Browse Knowledge base (`GET /v1/catalog/nodes/workload%3Aknowledge-base` on the api origin; authentication not required, approval not required)
- Browse Phoenix (`GET /v1/catalog/nodes/stack%3Aframework-phoenix` on the api origin; authentication not required, approval not required)
- Browse Public web service (`GET /v1/catalog/nodes/pattern%3Apublic-web-service` on the api origin; authentication not required, approval not required)
- Browse Deploy web app (`GET /v1/catalog/nodes/intent%3Adeploy-web-app` on the api origin; authentication not required, approval not required)

Actions describe possible next steps. They are typed data, not commands, and grant no permission. Public discovery never provisions anything; planning requires your own authenticated token and approval happens in your client.

## ABOUT THIS RECIPE

### Identifiers and status

Recipe `page:recipes:knowledge-base:phoenix:public-site`. Revision r1.

release **published** support **verified** execution **blocked (schema_changed: live tool schema differs from the recorded binding)**

Formats: [HTML](/content/recipes/knowledge-base/phoenix/public-site/index.html) | [Markdown](/content/recipes/knowledge-base/phoenix/public-site.md) | [JSON contract](https://api.ample.computer/v1/catalog/recipes/page%3Arecipes%3Aknowledge-base%3Aphoenix%3Apublic-site)
