Installation

Cipi Agent (cipi/agent on Packagist) is the official Laravel companion for Cipi. It bridges your application and the server control panel with:

  • Webhook-triggered deploys from GitHub and GitLab
  • Health monitoring (app, database, cache, queue, deploy commit)
  • An in-app MCP server for AI assistants (Cursor, VS Code, Claude Desktop)
  • A GDPR-oriented database anonymizer

On a Cipi-managed server, cipi app create injects the required .env variables automatically. Health check and MCP can work on any Laravel host; full deploy and log access expect a Cipi-managed environment.

Requirements

Requirement Version
PHP 8.3+
Laravel 12+ or 13+ (package 1.5.2+)
Database (anonymizer) MySQL or PostgreSQL
CLI tools (anonymizer) mysqldump or pg_dump on the server
bash
$ composer require cipi/agent

The service provider auto-discovers — no config/app.php change is needed. After install, commit and push; Cipi deploys the update on the next release.

Optional — publish the config file (non-Cipi or custom defaults):

bash
$ php artisan vendor:publish --tag=cipi-config
$ php artisan cipi:status   # verify config and DB connectivity
Agent vs panel API: this package runs inside each Laravel app (/cipi/* on the app domain). The server-level cipi/api package runs on a separate API vhost and manages the whole server — see Agent vs Cipi API.
After installing the package, commit and push. Cipi will pick it up on the next deploy automatically.

Artisan commands

Command Description
php artisan cipi:status Show Cipi config values and connectivity status
php artisan cipi:deploy-key Print the SSH deploy key for this app
php artisan cipi:mcp Show the MCP endpoint URL and setup snippets for Cursor, VS Code, and Claude Desktop
php artisan cipi:generate-token {type} Generate a secure token. Type can be mcp, health, or anonymize
php artisan cipi:service {type} --enable|--disable Toggle a service on or off. Updates .env in place. Type: mcp, health, or anonymize
php artisan cipi:init-anonymize Scaffold the anonymization config at /home/{app_user}/.db/anonymization.json
php artisan cipi:anonymize {config} {output} Run an anonymized database dump directly from the CLI (no HTTP)

Webhook — Automatic Deploys

The agent exposes a POST endpoint at /cipi/webhook. When your Git provider sends a push event, the agent verifies the signature and writes a .deploy-trigger flag file. A cron job running every minute as the app user detects this file, removes it, and runs Deployer in the background.

This design means the webhook response is instant (no HTTP timeout waiting for deployment to complete) and Deployer runs with the correct user permissions — no sudo required.

Configure your Git provider

Provider Webhook URL Authentication
GitHub https://yourdomain.com/cipi/webhook X-Hub-Signature-256 HMAC — use CIPI_WEBHOOK_TOKEN as Secret
GitLab https://yourdomain.com/cipi/webhook X-Gitlab-Token header — same token value

The token to use is stored in .env as CIPI_WEBHOOK_TOKEN. You can also retrieve it any time with:

bash
$ cipi deploy myapp --webhook

Branch filtering

By default every push triggers a deploy. To restrict deploys to a specific branch, add this to your .env:

env
CIPI_DEPLOY_BRANCH=main

Pushes to any other branch will receive a skipped response and no deploy will be triggered.

Health Check

The agent also exposes a GET endpoint at /cipi/health that returns a JSON payload with the status of the app, database, cache, queue, and the currently deployed Git commit hash. Useful for external monitoring services such as UptimeRobot. Protected by the CIPI_HEALTH_TOKEN Bearer token — generate one with php artisan cipi:generate-token health.

bash
$ curl -H "Authorization: Bearer YOUR_CIPI_HEALTH_TOKEN" \
    https://yourdomain.com/cipi/health
json
{
  "status": "healthy",
  "app_user": "myapp",
  "php": "8.5",
  "laravel": "12.0.0",
  "environment": "production",
  "checks": {
    "app":      { "ok": true, "version": "2.1.0", "debug": false },
    "database": { "ok": true, "database": "myapp_prod" },
    "cache":    { "ok": true },
    "queue":    { "ok": true, "pending_jobs": 0 },
    "deploy":   { "ok": true, "commit": "a1b2c3d4…", "short_commit": "a1b2c3d" }
  },
  "timestamp": "2026-06-10T14:22:01.000000Z"
}

The deploy commit is resolved from the first available source:

  1. /home/{app_user}/.cipi/deploy.json (Cipi deploy metadata)
  2. /home/{app_user}/.cipi/last_commit
  3. /home/{app_user}/logs/deploy.log
  4. .git/HEAD or git rev-parse HEAD

Authentication

The Bearer token is resolved in order: CIPI_HEALTH_TOKEN (dedicated), then CIPI_WEBHOOK_TOKEN (fallback). Disable the endpoint entirely with php artisan cipi:service health --disable or CIPI_HEALTH_CHECK=false.

Monitoring integrations

The health endpoint works with any HTTP checker that supports Bearer tokens — e.g. UptimeRobot, Better Stack, Grafana, or custom cron + curl. Poll checks.queue.pending_jobs for queue backlog alerts.

MCP Server

cipi-agent includes a built-in MCP server (Model Context Protocol) that exposes your application to AI assistants such as Cursor, VS Code (with GitHub Copilot), and Claude Desktop. The endpoint implements MCP 2024-11-05 over HTTP using JSON-RPC 2.0 and is protected by the CIPI_MCP_TOKEN Bearer token.

The MCP endpoint is available at POST /cipi/mcp and is disabled by default. To enable it:

bash
$ php artisan cipi:service mcp --enable
$ php artisan cipi:generate-token mcp

Available tools

The MCP server exposes six tools that an AI assistant can invoke by name:

Tool Description
health App, database, cache, and queue status — same data as the /cipi/health endpoint
app_info Full application configuration: app user, PHP version, Laravel version, environment, queue/cache/session drivers, deploy branch, and all Cipi URLs
deploy Trigger a new zero-downtime deployment — writes the .deploy-trigger file; Deployer picks it up within 1 minute
logs Read the last N lines (default 50, max 500) from application logs. Supports type (laravel, nginx, php, worker, deploy), level for Laravel severity filtering (e.g. error), and search for keyword filtering. Laravel daily rotation (laravel-YYYY-MM-DD.log) is auto-detected.
db_query Execute SQL queries against the application database — equivalent to cipi app tinker. Supports SELECT, SHOW, DESCRIBE, EXPLAIN (read) and INSERT, UPDATE, DELETE (write). Results formatted as ASCII table, capped at 100 rows. Destructive DDL (DROP TABLE/DATABASE, TRUNCATE, GRANT/REVOKE, file I/O) is blocked.
artisan Run any Artisan command (e.g. migrate:status, queue:size, cache:clear). Long-running and interactive commands like serve, queue:work, and tinker are blocked

logs tool parameters

Parameter Values Description
type laravel, nginx, php, worker, deploy Log file to read (Laravel daily rotation auto-detected)
level debugemergency Minimum severity — Laravel logs only
search any string Case-insensitive keyword filter; stack traces stay intact
lines 1–500 (default 50) Number of lines to return

Blocked operations (MCP safety)

  • Artisan: serve, tinker, queue:work, queue:listen, schedule:work, horizon, octane:start, reverb:start
  • SQL: DROP, TRUNCATE, GRANT, REVOKE, file I/O — read/write capped at 100 rows

Setup instructions

Run the cipi:mcp Artisan command to get the endpoint URL and ready-to-paste configuration snippets for your AI client:

bash
$ php artisan cipi:mcp

The command prints the available tools and the JSON configuration for Cursor, VS Code, and Claude Desktop.

Cursor

Add the following to ~/.cursor/mcp.json (or go to Cursor → Settings → MCP):

json
{
  "mcpServers": {
    "cipi-myapp": {
      "type": "http",
      "url": "https://yourdomain.com/cipi/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_CIPI_MCP_TOKEN"
      }
    }
  }
}

Replace cipi-myapp with your app user name, yourdomain.com with your actual domain, and YOUR_CIPI_MCP_TOKEN with the token from your .env. Cursor connects natively over HTTP — no bridge needed.

VS Code

VS Code (with GitHub Copilot) supports MCP natively since version 1.102. Add the following to .vscode/mcp.json in your project (or run MCP: Open User Configuration for a global setup):

json
{
  "servers": {
    "cipi-myapp": {
      "type": "http",
      "url": "https://yourdomain.com/cipi/mcp",
      "headers": {
        "Authorization": "Bearer YOUR_CIPI_MCP_TOKEN"
      }
    }
  }
}

Replace cipi-myapp, yourdomain.com, and YOUR_CIPI_MCP_TOKEN as above. Use MCP: Add Server from the Command Palette for a guided setup. VS Code connects over HTTP — no bridge needed.

Claude Desktop

Claude Desktop requires the mcp-remote bridge to convert stdio to HTTP. Add the following to ~/Library/Application Support/Claude/claude_desktop_config.json:

json
{
  "mcpServers": {
    "cipi-myapp": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://yourdomain.com/cipi/mcp",
        "--header",
        "Authorization: Bearer YOUR_CIPI_MCP_TOKEN"
      ]
    }
  }
}

Install mcp-remote globally once with:

bash
$ npm install -g mcp-remote

What you can do with it

Once connected, your AI assistant can interact with the Cipi-managed application in natural language. For example:

conversation
User:  Is the app healthy? Any pending jobs in the queue?

Claude: Calling health tool...
         Status: healthy — database, cache, and queue all OK.
         Queue: 0 pending jobs.

User:  Show me the last errors from the log.

Claude: Calling logs tool (lines: 100)...
         Found 2 errors in the last 100 lines:
         [2026-03-04 14:22:01] production.ERROR: Connection refused [...]
         [2026-03-04 14:23:15] production.ERROR: Redis timeout [...]

User:  Clear the cache and deploy the latest version.

Claude: Calling artisan tool (cache:clear)...
         Cache cleared successfully.
         Calling deploy tool...
         Deploy queued — Deployer will run within 1 minute.

User:  What's the current migration status?

Claude: Calling artisan tool (migrate:status)...
         All 47 migrations have been run.

User:  How many users signed up in the last 7 days?

Claude: Calling db_query tool (SELECT COUNT(*) FROM users WHERE created_at >= ...)...
         | count |
         |-------|
         | 23    |
The MCP server does not require SSH access to the VPS. It works entirely over HTTPS using the same Bearer token used by the webhook and health check endpoints. This makes it ideal for teams where developers should be able to monitor and deploy without root access.
Keep your CIPI_MCP_TOKEN secret. Anyone with the token can trigger deploys, read logs, run database queries, and run Artisan commands through the MCP endpoint. If you suspect a leak, regenerate the token with php artisan cipi:generate-token mcp and restart the application.
Two MCP servers in Cipi: Agent MCP (POST /cipi/mcp on the app domain, 6 tools, one app's DB/logs) vs panel API MCP (POST /mcp on the API domain, 29 tools, whole server). Use Agent MCP for app-specific debugging; use panel API MCP to create apps, manage SSL, or list all databases.

Database Anonymizer

cipi-agent includes a built-in database anonymizer that creates sanitized copies of your production database — ideal for sharing with developers, QA teams, or staging environments without exposing real user data. It supports both MySQL and PostgreSQL, uses Faker-based transformations configured via a JSON file, and runs as a background job so large databases do not block HTTP requests.

This feature lives inside your Laravel application (the cipi/agent package). It is separate from the server-level database backup API exposed by cipi api — see Agent vs Cipi API below.

Use cases

  • Local development — give every developer a realistic dataset without copying production emails, addresses, or payment notes
  • Staging / preview environments — refresh a non-production database from production structure and volume, with PII replaced
  • QA and demos — reproduce bugs that depend on relational data without GDPR risk
  • Vendor or contractor access — share a SQL dump when a full VPN + production access is not acceptable
  • CI pipelines — run cipi:anonymize on the server or trigger POST /cipi/db from a secure automation step

Prerequisites

Requirement Why
composer require cipi/agent The anonymizer is part of the agent package, not the Cipi server CLI
Queue worker running POST /cipi/db dispatches AnonymizeDatabaseJob — without a worker the job never runs. As root: cipi worker list myapp; as the app user: sudo cipi-worker status myapp
mysqldump or pg_dump The command shells out to the native dump tool for your DB driver
Laravel mail (MAIL_* in app .env) Success and failure notifications are sent via Laravel's mailer — if SMTP is missing or misconfigured, the anonymization job can still finish but no email is delivered and the download link is only in that message
anonymization.json on the server Must exist at /home/{app_user}/.db/ or /home/{app_user}/.cipi/ before triggering a job

Agent vs Cipi API

Both Cipi components touch databases, but they solve different problems:

Agent anonymizer (cipi/agent) Cipi API backups (cipi/api)
Scope One Laravel app's database (from the app's .env) Any database on the Cipi server (MariaDB vault)
Runs on Inside the app (PHP + queue worker) On the Cipi host via sudo cipi db … jobs
Output SQL dump with Faker-transformed sensitive columns Full compressed backup — real data, unchanged
Auth CIPI_ANONYMIZER_TOKEN (per app) Sanctum token with dbs-manage (per server)
Typical endpoint POST https://myapp.com/cipi/db POST https://api.example.com/api/dbs/{name}/backup
GDPR / PII Designed for safe sharing — only configured columns are transformed Disaster recovery and cloning — treat backups as production-secret
Use Cipi API DbBackup when you need a faithful snapshot for restore. Use the agent anonymizer when people need data that looks real but must not contain real identities. You can use both on the same project: backup for ops, anonymize for humans.

How it works

  1. An authenticated POST /cipi/db request (with a recipient email) queues AnonymizeDatabaseJob
  2. The job runs php artisan cipi:anonymize, which:
    • dumps the database with mysqldump or pg_dump
    • streams through INSERT statements and rewrites only the columns listed in anonymization.json
    • writes the result to storage/cipi/anonymized_{jobId}.sql
  3. On success, Laravel sends an email with a time-limited download URL (15 minutes)
  4. GET /cipi/db/{token} serves the file — no Bearer token; the URL itself is the credential
  5. On failure, a plain-text error email is sent to the same address

Email notifications

The HTTP API does not return the download URL in the JSON response — email is the only delivery channel for POST /cipi/db. Understanding who receives it and what must be configured avoids silent failures.

Who receives the email?

Exactly the address you pass in the JSON body — nothing else:

json
{ "email": "developer@example.com" }
  • Success → HTML email with the signed download link (15 minutes)
  • Failure → plain-text email with the error and job ID
  • No CC, BCC, or fallback to the Cipi admin, CIPI_APP_USER, or a fixed address in .env
  • Whoever holds CIPI_ANONYMIZER_TOKEN chooses the recipient on each request

Laravel mail must work

Notifications use Laravel's Mail facade and your application's MAIL_* settings — the same config as password resets or contact forms. This is independent of Cipi server SMTP (cipi smtp configure for backup/deploy alerts on the host).

Typical production .env entries:

env
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_USERNAME=...
MAIL_PASSWORD=...
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=noreply@myapp.example.com
MAIL_FROM_NAME="${APP_NAME}"
Job succeeded, inbox empty? The dump may already exist under storage/cipi/anonymized_{jobId}.sql on the server even when mail failed. The API still returned {"status":"queued"} immediately — that only means the job was queued, not that email delivery succeeded. Check storage/logs/laravel.log for mail errors, verify MAIL_*, and send a test message before relying on POST /cipi/db in production.

Quick mail test (as the app user, before your first export):

bash
$ php artisan tinker --execute="Mail::raw('Cipi anonymizer mail test', fn (\$m) => \$m->to('you@example.com')->subject('Mail test'));"

If that message does not arrive, fix Laravel mail first — or use the CLI path (php artisan cipi:anonymize) which writes the file directly and skips email.

Setup — step by step

Run these commands on the server as the app user (SSH: ssh myapp@your-server or sudo su - myapp as root — see SSH as the app user):

1. Install the agent (if not already in composer.json):

bash
$ composer require cipi/agent
# commit, push, deploy — or run on the current release

2. Enable the service and create a token:

bash
$ php artisan cipi:service anonymize --enable
$ php artisan cipi:generate-token anonymize

3. Scaffold the configuration file:

bash
$ php artisan cipi:init-anonymize

This creates /home/{app_user}/.db/anonymization.json (permissions 0640) from the built-in template. The file lives outside the Git repository — it is never deployed with your code. Use --force to overwrite an existing file.

4. Edit the config to match your real tables and sensitive columns (see Configuration).

5. Verify queue and mail: confirm the worker runs jobs and Laravel can send to the address you will pass in POST /cipi/db (see Email notifications).

bash
$ php artisan cipi:status          # DB connectivity
$ php artisan queue:work --once   # optional: confirm worker can run jobs
# send a test email — must arrive before using POST /cipi/db
$ php artisan tinker --execute="Mail::raw('Mail test', fn (\$m) => \$m->to('you@example.com')->subject('Mail test'));"

6. Trigger your first anonymized export via HTTP or CLI (see examples below).

Configuration

Valid paths (first match wins):

  • /home/{app_user}/.db/anonymization.json — recommended
  • /home/{app_user}/.cipi/anonymization.json — alternative

The JSON file has two top-level keys: transformations (required) and options (optional).

json
{
  "transformations": {
    "users": {
      "name": "fakeName",
      "email": "fakeEmail",
      "password": "password",
      "phone": "fakePhoneNumber",
      "address": "fakeAddress"
    },
    "orders": {
      "customer_notes": "fakeParagraph",
      "shipping_address": "fakeAddress"
    },
    "support_tickets": {
      "user_message": "fakeParagraph",
      "agent_response": "fakeParagraph"
    }
  },
  "options": {
    "hash_algorithm": "auto",
    "preserve_ids": true,
    "faker_locale": "en_US"
  }
}

Under transformations, each key is a table name. Nested keys are column names; values are transformation types (not raw Faker method names — see table below). Columns not listed keep their original values, so you can anonymize PII while preserving foreign keys, enums, and business logic fields.

Supported transformations

Transformation Example output
fakeName Full name (e.g. "Jane Cooper")
fakeFirstName / fakeLastName First or last name only
fakeEmail Random email address
fakeCompany Company name
fakeAddress / fakeCity / fakePostcode Street address, city, postal code
fakePhoneNumber Phone number
fakeDate Random date string
fakeUrl URL
fakeParagraph Lorem-style paragraph (notes, bios, ticket bodies)
password Re-hashes the value using hash_algorithm (bcrypt, argon, or Laravel auto) — use on users.password so login still works with a known test password if you set one before dump, or accept random hashes

Options

Option Default Description
hash_algorithm auto auto (Laravel default), bcrypt, argon, argon2i, argon2d
faker_locale en_US Faker locale for names, addresses, etc. (e.g. it_IT, de_DE)
preserve_ids true Reserved for future use — IDs are kept unless you add an id column under transformations
Anonymization is opt-in per column. If a table holds PII in a JSON column, blob, or column you forgot to list, that data is copied verbatim. Review schema regularly — especially metadata, settings, and audit tables.

HTTP API — endpoints

Method Endpoint Auth Description
POST /cipi/db Bearer CIPI_ANONYMIZER_TOKEN Queue anonymization job; email sent when complete
POST /cipi/db/user Bearer CIPI_ANONYMIZER_TOKEN Resolve users.id from email (debug helper)
GET /cipi/db/{token} Signed URL (from email) Download the .sql dump; expires in 15 minutes

When the anonymizer is disabled (CIPI_ANONYMIZER=false), routes return 404 — the endpoints are hidden entirely.

Practical examples (curl)

Set variables once (replace with your app domain and token from .env):

bash
export APP_URL="https://myapp.example.com"
export CIPI_ANONYMIZER_TOKEN="your-token-from-env"

1. Queue an anonymization job

bash
curl -sS -X POST "${APP_URL}/cipi/db" \
  -H "Authorization: Bearer ${CIPI_ANONYMIZER_TOKEN}" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{"email": "developer@example.com"}'

Successful response (200):

json
{
  "status": "queued",
  "message": "Database anonymization job has been queued. You will receive an email with download instructions when complete.",
  "email": "developer@example.com"
}

The HTTP call returns immediately with status: queued — that does not guarantee the notification email was sent. Processing can take minutes on large databases (job timeout: 1 hour). The completion message goes only to the email in your JSON body; if nothing arrives, check storage/logs/laravel.log for mail transport errors, php artisan queue:failed for a failed job, and that MAIL_* is configured (see Email notifications).

2. Download the dump (from email link)

The completion email contains a URL like:

text
https://myapp.example.com/cipi/db/AbCdEf...?expires=1710000000&signature=...

Save it with curl (paste the full URL from the email — no Bearer header):

bash
curl -sS -L -o anonymized.sql "PASTE_FULL_SIGNED_URL_FROM_EMAIL"

# Import locally (MySQL example)
mysql -u root -p myapp_local < anonymized.sql

Expired or invalid links return 410 Gone or 404. Request a new export with POST /cipi/db if the 15-minute window passed.

3. Look up a user ID by email

After anonymization, emails are fake — but user IDs stay the same. Use this before anonymizing to map a known production email to an ID you can find later in the dump:

bash
curl -sS -X POST "${APP_URL}/cipi/db/user" \
  -H "Authorization: Bearer ${CIPI_ANONYMIZER_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{"email": "customer@production.com"}'
json
{
  "user_id": 42,
  "email": "customer@production.com",
  "found_at": "2026-06-10T14:22:01+00:00"
}

This queries the live users table — run only when you are allowed to touch production data. It does not modify anything.

4. Error responses (troubleshooting)

HTTP Meaning Fix
403 Invalid or missing Bearer token Regenerate with php artisan cipi:generate-token anonymize
404 Service disabled or config file missing cipi:service anonymize --enable and cipi:init-anonymize
422 Missing or invalid email in JSON body Send {"email":"you@example.com"}
400 Invalid JSON or empty transformations Validate anonymization.json syntax and content
500 Token not configured, DB error, or dump tool missing Check .env, mysqldump/pg_dump, Laravel logs
API returned queued but no email (job may have succeeded) Verify MAIL_* and send a test with php artisan tinker; read storage/logs/laravel.log for SMTP errors — or use cipi:anonymize on the server to get the file without mail

CLI — run without HTTP

For scripts, cron, or one-off exports on the server:

bash
$ php artisan cipi:anonymize \
    /home/myapp/.db/anonymization.json \
    /home/myapp/anonymized_export.sql

The command prints three steps (dump → transform → save) and exits non-zero on failure. It does not send email — copy the file via SCP or your own secure channel.

Comparison curl: Cipi API raw backup

For reference, a non-anonymized server backup via Cipi API looks like this (different host, token, and semantics):

bash
export CIPI_API_URL="https://api.myserver.com"
export CIPI_API_TOKEN="sanctum-token-with-dbs-manage"

curl -sS -X POST "${CIPI_API_URL}/api/dbs/myapp_db/backup" \
  -H "Authorization: Bearer ${CIPI_API_TOKEN}" \
  -H "Accept: application/json"

That returns 202 with a job_id — poll GET /api/jobs/{id} for the backup path on the server. The archive contains real production data; restrict access accordingly.

Security and GDPR tips

  • Store CIPI_ANONYMIZER_TOKEN in secrets management — anyone with it can queue dumps and query /cipi/db/user
  • Rotate the token after team changes: php artisan cipi:generate-token anonymize
  • Disable when not needed: php artisan cipi:service anonymize --disable (endpoints return 404)
  • Download links expire in 15 minutes — forward emails carefully
  • Document which columns are transformed for your DPA / privacy policy
  • Test the dump: grep for a known production email — it should not appear if fakeEmail was set on that column
The anonymization config maps your database schema. Keep it outside your repository (default path /home/{app_user}/.db/ is already excluded from deploys). Never commit anonymization.json to version control.

Security

Cipi Agent uses defense in depth: each feature has its own Bearer token and can be toggled off independently. When disabled, routes return 404 (hidden, not 403).

Token isolation

Feature Token variable Endpoint
Webhook deploy CIPI_WEBHOOK_TOKEN POST /cipi/webhook
Health check CIPI_HEALTH_TOKEN (fallback: webhook token) GET /cipi/health
MCP server CIPI_MCP_TOKEN POST /cipi/mcp
DB anonymizer CIPI_ANONYMIZER_TOKEN POST /cipi/db, POST /cipi/db/user

Webhook verification

  • GitHubX-Hub-Signature-256 HMAC-SHA256
  • GitLabX-Gitlab-Token header comparison

Source code and releases: github.com/cipi-sh/agent (MIT).

ENV Variables

These variables are automatically injected by Cipi into the app's .env during cipi app create. Toggle optional features with php artisan cipi:service {type} --enable|--disable or set them manually.

Variable Description Default
CIPI_WEBHOOK_TOKEN Secret for webhook authentication (GitHub HMAC / GitLab token) auto-generated
CIPI_APP_USER Linux username for this app (paths, deploy script) auto-set
CIPI_PHP_VERSION PHP version reported in health check system PHP
CIPI_DEPLOY_SCRIPT Path to Deployer config ~/.deployer/deploy.php
CIPI_DEPLOY_BRANCH Branch that triggers a deploy (empty = any branch) empty
CIPI_ROUTE_PREFIX URL prefix for all agent routes cipi
CIPI_LOG_CHANNEL Laravel log channel for deploy events null
CIPI_HEALTH_CHECK Enable /cipi/health true
CIPI_HEALTH_TOKEN Bearer token for health (falls back to webhook token) none
CIPI_MCP Enable /cipi/mcp false
CIPI_MCP_TOKEN Bearer token for MCP none
CIPI_ANONYMIZER Enable anonymizer at /cipi/db false
CIPI_ANONYMIZER_TOKEN Bearer token for anonymizer none
Use php artisan cipi:generate-token {type} to generate tokens for mcp, health, or anonymize. Use php artisan cipi:service {type} --enable|--disable to toggle services — the command updates your .env in place.