Apps
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)
$ cipi app create
Non-interactive (flags)
$ cipi app create \
--user=myapp \
--domain=myapp.com \
--repository=git@github.com:you/myapp.git \
--branch=main \
--php=8.5
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:
$ cipi app create --custom --user=mysite --domain=mysite.com \
--repository=git@github.com:you/mysite.git --docroot=dist
SFTP-only — omit --repository and --branch:
$ 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:
$ 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:
$ cipi worker restart myapp
Edit directly via SSH
You can also edit the file directly over SSH as root or as the app user:
# 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) |
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.
# 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/.
$ 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
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.
$ 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:
# 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:
$ 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:
$ cipi app reset-password myapp
The new password is displayed on screen — save it immediately.
Useful commands once logged in as the app user
# 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/
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.