---
title: "Quickstart: Run Caracal Locally"
description: Bring up the complete Caracal authority plane with one local command.
pageType: workflow
---

This quickstart brings up the full Caracal OSS stack, verifies service health, and prepares the default Gateway-first flow: a zone, an agent app, a tool/provider resource, and a policy template. You operate it as one local stack even though the internals are split into separate trust-boundary services.

:::note[Contributors]
This page covers the **installed binary** workflow. If you are building Caracal from source, follow [Local Setup](../contributing/setup/) instead.
:::

## What you will operate

For local adoption, Caracal has one operator surface:

```sh
caracal up
caracal status
caracal down
```

Those commands manage the containers, secrets, health checks, and startup order. You do not need to start services manually for the default local path.

## What runs inside the stack

The stack consists of five Caracal services plus Postgres and Redis:

| Service | Port | Purpose |
| ------- | ---- | ------- |
| PostgreSQL | 5432 | Persistent state (zones, policies, sessions, audit events) |
| Redis | 6379 | Event streams, revocation signals, JTI replay tracking |
| STS | 8080 | Public token exchange with OPA policy evaluation |
| API | 3000 | Control-plane REST — zones, policies, resources, grants |
| Gateway | 8081 | Default tool/provider execution plane |
| Audit | 9090 | Audit event consumer and ledger writer |
| Coordinator | 4000 | Agent session lifecycle and delegation graph |

All ports are bound to `127.0.0.1` only. They are not exposed on external interfaces. The service split exists to preserve security boundaries; the local operating model is still one stack.

## Step 1: Install the CLI

Install `caracal` and `caracal-tui` via the [Installation](./installation/) page, then verify:

```sh
caracal --version
```

## Step 2: Start the stack

```sh
caracal up
```

On first run, `caracal up` automatically:

1. Creates a runtime home directory for Caracal:
   - **Linux/WSL**: `~/.local/share/caracal/` (or `$XDG_DATA_HOME/caracal/`)
   - **macOS**: `~/Library/Application Support/caracal/`
2. Generates secret files under `$CARACAL_HOME/secrets/` (database passwords, admin token, encryption keys). Services consume them via the `*_FILE` convention; no secret strings are written to any `.env` file.
3. Writes `$CARACAL_HOME/caracal.env`, an operator override template with every tunable entry commented out. Uncomment a line to override the built-in default (issuer URL, S3 export, resource limits, etc.). Mode/version/registry are pinned and rejected if set.
4. Pulls versioned container images and starts the five Caracal services plus Postgres and Redis.

The startup sequence is:

1. PostgreSQL and Redis start and pass health checks.
2. Database migrations run once and complete.
3. STS, API, Gateway, Coordinator, and Audit start in dependency order.

First startup takes 30–60 seconds while Docker pulls images and PostgreSQL initializes.

:::caution
Do not edit files under `$CARACAL_HOME/secrets/` unless you are rotating secrets — they back the running stack. Operator overrides go in `$CARACAL_HOME/caracal.env`, which is safe to edit.
:::

## Step 3: Check service health

```sh
caracal status
```

You should see all five application services reporting healthy:

```
api            3000  ✓ ok      200
sts            8080  ✓ ok      200
gateway        8081  ✓ ok      200
audit          9090  ✓ ok      200
coordinator    4000  ✓ ok      200
```

If a service is not healthy within two minutes, check its logs:

```sh
docker logs caracal-sts-1 --tail 50
```

## Step 4: Provision the golden path

The stack starts with an empty database. Create the product objects needed for a Gateway-mediated agent call. The admin token is read from `$CARACAL_HOME/secrets/caracalAdminToken` automatically — no manual export is needed.

```sh
caracal zone create --name local
# → captures the new zone id, e.g. zone_abc123

LOCAL_AGENT_SECRET="$(openssl rand -hex 32)"
caracal app create \
  --zone zone_abc123 \
  --name local-agent \
  --credential-type password \
  --client-secret "$LOCAL_AGENT_SECRET"
# → captures the agent application id, e.g. app_def456

caracal resource create \
  --zone zone_abc123 \
  --identifier "resource://local-tool" \
  --scopes "tool:read,tool:write" \
  --name "Local Tool" \
  --upstream-url "http://host.docker.internal:8090" \
  --gateway-application-id app_def456
# → creates the tool/provider resource and its Gateway provider route

caracal policy template list
caracal policy template use baseline-scopes --zone zone_abc123 --name "Local Gateway Policy"
# → creates a policy from the baseline scopes template
```

Create a policy set, add the created policy version, activate it, then grant the agent app the resource scopes:

```sh
caracal policy-set create --zone zone_abc123 --name "Local Policies"
caracal policy-set version pset_abc123 --zone zone_abc123 --policy-versions pver_abc123
caracal policy-set activate pset_abc123 --zone zone_abc123 --version psetver_abc123

caracal grant create \
  --zone zone_abc123 \
  --app app_def456 \
  --user local-user \
  --resource res_abc123 \
  --scopes tool:read,tool:write
```

The `--gateway-application-id` value is the same-zone service identity Gateway uses for the internal STS exchange. In production, use a dedicated Gateway application identity; for local smoke tests, reusing the local agent app is acceptable.

Author `caracal.toml` in your project directory with the values from the previous step:

```toml
zone_url = "http://localhost:8080"
zone_id  = "zone_abc123"

application_id     = "app_def456"
app_client_secret  = "<value of LOCAL_AGENT_SECRET>"

[[credentials]]
env      = "RESOURCE_TOKEN"
resource = "resource://local-tool"

[mcp_governance]
mode = "block"
```

Set the file mode to `0600` — it contains your application's client secret.

```sh
chmod 600 caracal.toml
```

## Step 5: Verify scoped access

With the stack and `caracal.toml` in place, request a short-lived access token for the registered resource:

```sh
caracal credential read resource://my-api
```

If successful, a signed Caracal access token is printed to stdout. This proves the public STS allowed the agent app to access the resource; provider-native credentials are not returned to the CLI.

Decode it to inspect the claims:

```sh
caracal credential read resource://my-api | cut -d. -f2 | base64 -d | jq .
```

You should see claims including `zone_id`, `scope`, `target`, and an expiry (`exp`) 15 minutes from now.

To test the full product path, run a local HTTP service on port `8090`, then call it through the Gateway from an SDK integration or a process launched by `caracal run`. The Gateway verifies the Caracal token, resolves the provider route, forwards the upstream call, and records action-result audit.

## Stopping the stack

```sh
caracal down
```

This stops and removes containers but preserves the named volumes (`postgresData`, `redisData`). State persists across restarts.

## What is running

At this point you have:

- A fully operational local Caracal authority plane
- A zone with an agent app, tool/provider resource, active policy template, grant, and Gateway provider route
- A `caracal.toml` that the CLI and SDKs can read for configuration

Continue to [First Integration](./first-integration/) to wire an application to Caracal using the SDK.
