cipi app create

cipi app create supports two app types: Laravel (default) and Custom (--custom). Laravel apps get a fully isolated environment: Linux user, PHP-FPM pool, Nginx vhost, MariaDB database, Supervisor worker, crontab entry, Deployer zero-downtime releases, SSH deploy key, and auto-compiled .env. Custom apps are simpler — see custom apps for details.

Laravel app (default)

bash
$ cipi app create

Non-interactive (flags)

bash
$ cipi app create \
    --user=myapp \
    --domain=myapp.com \
    --repository=git@github.com:you/myapp.git \
    --branch=main \
    --php=8.5
--userLinux username for the app. Must be unique, lowercase, alphanumeric.
--domainPrimary domain (e.g. myapp.com). Used for Nginx vhost and APP_URL.
--repositorySSH Git URL (e.g. git@github.com:you/repo.git). Must be SSH, not HTTPS.
--branchBranch to deploy. Defaults to main.
--phpPHP version for this app (e.g. 8.5). Defaults to PHP 8.5. Must be an installed version.
If a GitHub or GitLab token is configured, Cipi automatically adds the SSH deploy key and creates the webhook on the repository — no manual steps needed. See Git auto-setup for setup instructions and fallback options when auto-configuration is not available.

cipi app create --custom

Creates a custom app with classic deploy (no zero-downtime): code is deployed into htdocs — no current/shared symlinks. Ideal for static sites, SPAs (Vue, React, Svelte), WordPress, other CMS, or any non-Laravel PHP project or framework.

During creation you only choose the document root (default /, or e.g. www, dist, public). Nginx is pre-configured with index index.html index.php, try_files $uri $uri/ /index.php?$args, and error_page 404 /404.html — no prompts for try_files or entry point.

Git optional (SFTP-only)

The Git repository is optional for custom apps. Laravel apps still require a repository. If you skip the repository for a custom app, Cipi creates /home/<app>/htdocs with a placeholder index.html and does not configure a deploy key or webhook — you upload files with SFTP (or SCP/rsync) to ~/htdocs as the app user. The onboarding output explains this “no repo — SFTP only” workflow. If you do provide a repository, behavior is unchanged: use cipi deploy <app> to pull code into htdocs.

What’s included and what you add

Custom apps have no database, no .env, no cron, and no queue workers. When a repository is configured, a deploy key and (with Git auto-setup) webhook are shown; for SFTP-only apps, those are omitted. The post-creation summary lists SSH access and next steps accordingly.

If your custom app needs a database (e.g. WordPress, Drupal), create one with cipi db create --name=<app> after deployment. See cipi db for backup, restore, and password management.

With Git — non-interactive example:

bash
$ cipi app create --custom --user=mysite --domain=mysite.com \
    --repository=git@github.com:you/mysite.git --docroot=dist

SFTP-only — omit --repository and --branch:

bash
$ cipi app create --custom --user=mysite --domain=mysite.com --docroot=dist

With a repository, use cipi deploy <app> to deploy; code is cloned into /home/<app>/htdocs.

app list / app show / app edit / app delete

Command Description
cipi app list List all apps with domain, PHP version, and status
cipi app show <app> Full details: domain, PHP, deploy key, workers, webhook. For custom apps: type "Custom", docroot; webhook (and deploy key) omitted when SFTP-only without a repository.
cipi app edit <app> --php=8.5 Hot-swap PHP version. Updates FPM pool, Nginx socket, Supervisor, crontab, Deployer config, and .env — zero downtime
cipi app edit <app> --branch=develop Change the deploy branch
cipi app env <app> Open the app's .env file in nano as the app user. Exits with error for custom apps (no .env).
cipi app reset-password <app> Regenerate the app's Linux user SSH password. The new password is displayed on screen — save it immediately
cipi app reset-db-password <app> Regenerate the app's MariaDB password and automatically update the DB_PASSWORD value in the app's .env file. Exits with error for custom apps (no database).
cipi app delete <app> Permanently remove the app, user, database (if Laravel), Nginx vhost, FPM pool, and Supervisor workers. For custom apps, skips database drop (none was created). Asks for confirmation.

Managing ENV variables

Every Laravel app has a single .env file living at /home/<app>/shared/.env. Custom apps have no .env. It is created and pre-populated by Cipi during app create with the database credentials, APP_KEY, APP_URL, cache/session/queue settings, and the webhook token. The shared/ directory is symlinked into every release, so the same .env is always active regardless of which release is current.

Edit interactively via CLI

The safest way to change ENV values is through Cipi itself — it opens the file in nano as the app user, with the correct permissions:

bash
$ cipi app env myapp

Save with Ctrl+O then exit with Ctrl+X. Changes take effect immediately for new requests — no restart needed for most values. If you change queue connection or cache driver, restart the workers:

bash
$ cipi worker restart myapp

Edit directly via SSH

You can also edit the file directly over SSH as root or as the app user:

bash
# as root
$ nano /home/myapp/shared/.env

# or switch to the app user first
$ su - myapp
$ nano ~/shared/.env

Key ENV variables set by Cipi

Variable Description Set by
APP_KEY Laravel encryption key — generated once at app creation Cipi
APP_URL Updated automatically by cipi ssl install Cipi
DB_CONNECTION Always mysql (MariaDB is drop-in compatible) Cipi
DB_DATABASE / DB_USERNAME / DB_PASSWORD Auto-generated credentials for the app's isolated database Cipi
CACHE_STORE database — uses the app's MariaDB Cipi
SESSION_DRIVER database Cipi
QUEUE_CONNECTION database Cipi
CIPI_WEBHOOK_TOKEN HMAC secret for cipi-agent webhook validation Cipi
CIPI_APP_USER Linux username owning this app Cipi
CIPI_MCP Enable or disable the built-in MCP server at /cipi/mcp User (true by default)
Do not change DB credentials manually. If you need to regenerate the database password use cipi db password myapp — it updates both MariaDB and the .env atomically. Editing them by hand risks leaving the two out of sync.

Adding your own variables

Add any custom variable at the bottom of the file as you normally would in a Laravel project. They are preserved across deploys because the .env lives in shared/ and is never overwritten by Deployer.

env
# your custom variables
STRIPE_KEY=sk_live_...
STRIPE_SECRET=sk_live_...
MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org

cipi app logs

Tail application logs in real-time. Logs are rotated daily and kept for 14 days. By default, all logs are shown including Laravel daily logs (laravel-YYYY-MM-DD.log) from shared/storage/logs/.

bash
$ cipi app logs myapp                  # all logs (incl. Laravel daily logs)
$ cipi app logs myapp --type=nginx     # Nginx access + error
$ cipi app logs myapp --type=php       # PHP-FPM errors
$ cipi app logs myapp --type=worker    # queue worker output
$ cipi app logs myapp --type=deploy    # deploy history
$ cipi app logs myapp --type=laravel   # Laravel application logs
--type=nginxNginx access and error logs
--type=phpPHP-FPM error log
--type=workerSupervisor / queue worker output
--type=deployDeployer output — full deploy history with timestamps
--type=laravelLaravel application logs from shared/storage/logs/ (daily rotating laravel-YYYY-MM-DD.log)

app artisan & app tinker

Run Artisan commands and Tinker as the app user with the correct PHP version and open_basedir context — exactly as they would run during a deploy.

bash
$ cipi app artisan myapp migrate:status
$ cipi app artisan myapp queue:retry all
$ cipi app artisan myapp db:seed --class=ProductionSeeder
$ cipi app artisan myapp cache:clear
$ cipi app tinker myapp

SSH as the app user

Each app runs under its own isolated Linux user. Sometimes you need to work directly inside that user's environment — inspect files, run one-off scripts, or debug something that only reproduces as the correct user.

Direct SSH as app user (recommended)

App users can SSH directly to the server with the password generated at app creation:

bash
# connect as the app user (password auth)
$ ssh myapp@your-server-ip

# you are directly inside the app user's shell
myapp@server:~$ pwd
/home/myapp

myapp@server:~$ cd ~/current
myapp@server:~$ ls

The password is shown when the app is created (or use cipi app reset-password myapp to regenerate it). This works for SFTP clients, IDE remote sessions, and terminal access.

Via cipi (admin path)

If you are already connected as cipi, you can switch directly to any app user:

bash
$ ssh cipi@your-server-ip
cipi@server:~$ sudo su - myapp

myapp@server:~$ pwd
/home/myapp

Reset the app user password

If you need to regenerate an app user's password (e.g. for direct SSH or SFTP), use:

bash
$ cipi app reset-password myapp

The new password is displayed on screen — save it immediately.

Useful commands once logged in as the app user

bash
# navigate to the active release
myapp@server:~$ cd ~/current

# run artisan directly with the correct PHP version
myapp@server:~$ /usr/bin/php8.5 ~/current/artisan tinker

# inspect the shared .env
myapp@server:~$ cat ~/shared/.env

# tail all logs
myapp@server:~$ tail -f ~/logs/*.log

# check active releases
myapp@server:~$ ls -lt ~/releases/
The app user's open_basedir restriction limits PHP to /home/myapp. This is enforced at the PHP-FPM level, not at the shell level — you can access any file your shell user can read when working in the terminal.