Cipi Agent
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 |
$ 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):
$ php artisan vendor:publish --tag=cipi-config $ php artisan cipi:status # verify config and DB connectivity
/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.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:
$ 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:
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.
$ curl -H "Authorization: Bearer YOUR_CIPI_HEALTH_TOKEN" \
https://yourdomain.com/cipi/health
{
"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:
/home/{app_user}/.cipi/deploy.json(Cipi deploy metadata)/home/{app_user}/.cipi/last_commit/home/{app_user}/logs/deploy.log.git/HEADorgit 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:
$ 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 |
debug … emergency |
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:
$ 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):
{
"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):
{
"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:
{
"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:
$ 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:
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 |
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.
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:anonymizeon the server or triggerPOST /cipi/dbfrom 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 |
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
- An authenticated
POST /cipi/dbrequest (with a recipientemail) queuesAnonymizeDatabaseJob - The job runs
php artisan cipi:anonymize, which:- dumps the database with
mysqldumporpg_dump - streams through
INSERTstatements and rewrites only the columns listed inanonymization.json - writes the result to
storage/cipi/anonymized_{jobId}.sql
- dumps the database with
- On success, Laravel sends an email with a time-limited download URL (15 minutes)
GET /cipi/db/{token}serves the file — no Bearer token; the URL itself is the credential- 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:
{ "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_TOKENchooses 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:
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}"
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):
$ 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):
$ composer require cipi/agent # commit, push, deploy — or run on the current release
2. Enable the service and create a token:
$ php artisan cipi:service anonymize --enable $ php artisan cipi:generate-token anonymize
3. Scaffold the configuration file:
$ 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).
$ 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).
{
"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
|
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):
export APP_URL="https://myapp.example.com" export CIPI_ANONYMIZER_TOKEN="your-token-from-env"
1. Queue an anonymization job
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):
{
"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:
https://myapp.example.com/cipi/db/AbCdEf...?expires=1710000000&signature=...
Save it with curl (paste the full URL from the email — no Bearer header):
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:
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"}'
{
"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:
$ 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):
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_TOKENin 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
fakeEmailwas set on that column
/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
- GitHub —
X-Hub-Signature-256HMAC-SHA256 - GitLab —
X-Gitlab-Tokenheader 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 |
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.