Getting Started
Installation
Cipi installs a complete Laravel-ready production stack on any Ubuntu 24.04+ VPS with a single
command. The installer takes roughly 10 minutes and sets up Nginx, MariaDB, PHP, Redis, Supervisor,
Fail2ban, UFW, Certbot, Deployer, and the cipi CLI itself.
During installation, the wizard asks for your SSH public key (accepted formats:
ssh-rsa, ssh-ed25519, ecdsa) before any package is
installed. Cipi creates a dedicated cipi Linux user for admin SSH
access
and applies SSH hardening: root login is disabled, cipi uses public-key only (group
cipi-ssh), app users (group cipi-apps) can connect with password. Login
attempts are limited to 3 with a 20-second grace period, and X11 forwarding is disabled.
The installer also generates a random 40-character root password, stores it in
/etc/cipi/server.json, and displays it in the installation summary. Pasted SSH keys are
automatically sanitized — comments, carriage returns, and excess whitespace are stripped before
validation.
Standard installation
$ wget -O - https://cipi.sh/setup.sh | bash
Non-interactive installation
For automated setups, pass your SSH public key via the SSH_PUBKEY environment variable
to skip the interactive prompt:
$ SSH_PUBKEY="ssh-ed25519 AAAA..." wget -O - https://cipi.sh/setup.sh | bash
ssh-keygen -t rsa -b 4096
AWS (root login disabled by default)
$ ssh ubuntu@your-server-ip $ sudo -s $ wget -O - https://cipi.sh/setup.sh | bash
At the end of the installation you will see a summary screen with the SSH access details, the
auto-generated root password, and the MariaDB root password.
Save them immediately — they are shown only once. Credentials are stored in
/etc/cipi/server.json, which — like all Cipi configuration files — is
encrypted at rest using AES-256-CBC via the built-in Vault
system. Credentials, SSH keys, .env files, and database dumps are protected both on
disk
and during transfer (via Sync encrypted archives). Cipi also enforces
GDPR-compliant log retention with automatic rotation policies for application,
security, and HTTP logs — see Log retention for details.
/etc/cipi/server.json.Post-installation access
After installation, admin access uses public-key authentication as the
cipi user (root login is disabled). App users can SSH directly with
ssh myapp@server-ip and the password generated at app creation. To run
cipi commands or perform any administrative task, connect as cipi and
then escalate:
# 1. connect to the server (key-based auth only) $ ssh cipi@your-server-ip # 2. escalate to root to run cipi commands cipi@server:~$ sudo -s # 3. now you can use all cipi commands root@server:~# cipi status root@server:~# cipi app list # 4. to work as an app user, switch with su root@server:~# su - myapp
Requirements
- Ubuntu 24.04 LTS or higher
- Root access (or
sudo -son AWS) - Ports 22, 80, and 443 open
- A clean server — do not install Cipi on a server with an existing web stack
Cipi is tested and works on: DigitalOcean, AWS EC2, Vultr, Linode / Akamai, Hetzner, Google Cloud, OVH, Scaleway, and any KVM or bare-metal host running Ubuntu.
Quick Start
1. Create your first app
The interactive wizard asks for a username, primary domain, Git repository URL (SSH format) and branch when applicable, and PHP version. Laravel apps always require a repository; for custom apps you can leave the repository empty to host the site via SFTP only — see custom apps.
$ cipi app create
Or pass all flags directly to skip interactive mode:
$ cipi app create \
--user=myapp \
--domain=myapp.com \
--repository=git@github.com:you/myapp.git \
--branch=main \
--php=8.5
At the end, Cipi prints a credentials summary — save it, shown only once — including
the server's public IP address (for DNS configuration), the SSH deploy key, database credentials,
a ready-to-use mariadb+ssh:// connection URL for GUI clients (TablePlus, DBeaver,
Sequel Pro), webhook URL, and webhook token.
2. Add the deploy key to your Git provider
If you have configured a GitHub or GitLab token via cipi git, this step is
automatic — Cipi adds the deploy key and creates the webhook for you. See
Git auto-setup for details.
Otherwise, copy the ssh-ed25519 ... key shown after app creation and add it as a
Deploy Key in your repository:
- GitHub: Repository → Settings → Deploy keys → Add deploy key
- GitLab: Repository → Settings → Repository → Deploy keys
3. Prepare your Laravel project
Cipi uses the database driver for cache, sessions, and queues. Run these once inside your Laravel project, commit, and push the generated migrations:
$ php artisan cache:table $ php artisan session:table $ php artisan queue:table $ php artisan migrate
artisan migrate --force on every deploy. The cache,
session, and queue tables will be created on first deploy if you commit the migrations.4. Deploy
$ cipi deploy myapp
Deployer clones your repo into a new releases/N/ directory, runs
composer install --no-dev, links .env and storage/, runs
migrations, runs artisan optimize, creates storage:link, swaps the
current symlink atomically, and restarts queue workers. Zero downtime.
5. Install SSL
$ cipi ssl install myapp
Certbot provisions a Let's Encrypt certificate, configures Nginx for HTTPS, and updates
APP_URL in .env. Your Laravel app is now live on
https://myapp.com.
Tech Stack
Cipi brings a complete, production-ready stack to your Ubuntu server. Here is everything that gets installed and configured:
| Component | Role |
|---|---|
| Ubuntu | Base OS (24.04 LTS or higher) |
| Nginx | Web server, reverse proxy, SSL termination |
| PHP-FPM | PHP runtime (multiple versions via ondrej/php PPA) |
| MariaDB | Relational database (drop-in MySQL replacement) |
| Redis | In-memory store for cache, sessions, queues, broadcast |
| Supervisor | Process manager for Laravel queue workers |
| Deployer | Zero-downtime deployment tool |
| Certbot | Let's Encrypt SSL certificates |
| UFW | Firewall (ports 22, 80, 443) |
| Fail2ban | Progressive brute-force protection with recidive jail |
| unattended-upgrades | Automatic security patches |
| Composer | PHP dependency manager |
| cipi CLI | Server management and orchestration |
App Structure
When you run cipi app create, Cipi creates a fully isolated environment for the app.
Here is everything that gets set up:
/home/myapp/ ← isolated Linux user (chmod 750) ├── .ssh/ │ ├── id_ed25519 ← deploy key (private) │ └── id_ed25519.pub ← deploy key (public — add to Git) ├── .deployer/ │ └── deploy.php ← Deployer config (auto-generated) ├── current -> releases/3/ ← symlink to active release ├── releases/ │ ├── 1/ │ ├── 2/ │ └── 3/ ← latest release (last 5 kept) ├── shared/ │ ├── .env ← auto-compiled by Cipi │ └── storage/ ← persistent storage └── logs/ ├── nginx-access.log ├── nginx-error.log ├── php-fpm-error.log ├── worker-default.log └── deploy.log
In addition to the home directory, Cipi creates these system files:
PHP-FPM pool: /etc/php/8.5/fpm/pool.d/myapp.conf (user=myapp) Nginx vhost: /etc/nginx/sites-available/myapp Supervisor: /etc/supervisor/conf.d/myapp.conf Crontab: * * * * * php artisan schedule:run MariaDB: database 'myapp', user 'myapp'@'localhost'
The .env is auto-compiled with all credentials — database name, password, webhook token,
and APP_KEY. You never have to touch it manually, but you can always edit it with
cipi app env myapp.