Skip to main content

Professional CLI for Frappe deployment and management.

Project description

frappe-cli

PyPI version Python License: MIT Tests

A production-ready CLI that installs and operates Frappe / ERPNext on Ubuntu — from a bare VPS to a working HTTPS site in one command.

Built with Python + Click + Rich. Every step is independently runnable, self-healing, and idempotent — safe to re-run on partially-installed servers.


Highlights

  • One-command bootstrap: frappe install wizard provisions a fresh Ubuntu VPS end-to-end (MariaDB → Redis → Node → bench → site → ERPNext → nginx → supervisor → SSL).
  • 17 individually runnable steps: frappe step <name> lets you re-run, debug, or compose any wizard step on its own (same code path as the wizard).
  • Multi-bench friendly: works on fresh and non-fresh VPS — auto-detects existing bench installs and existing bench directories.
  • Self-healing: automatically repairs the supervisor symlink that vanilla bench setup production sometimes misses on multi-bench hosts.
  • Hard verification: polls supervisorctl status for RUNNING and pings bench Redis for PONG before declaring success.
  • Resumable: the wizard saves progress; if a step fails you can fix and frappe install wizard --resume.
  • Operator-friendly utilities: frappe ssl list/setup, frappe service status, frappe backup setup, frappe firewall setup, and more.

Installation

frappe-cli is published on PyPI: https://pypi.org/project/frappe-cli/.

With uv (recommended)

uv installs CLIs in isolated environments, similar to pipx, and is extremely fast.

# Install uv (if you don't have it yet)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install frappe-cli globally
uv tool install frappe-cli

# Verify
frappe --version
frappe --help

To upgrade later:

uv tool upgrade frappe-cli

With pip

# User install (no sudo required)
pip install --user frappe-cli
export PATH="$HOME/.local/bin:$PATH"

# Or system-wide
sudo pip install frappe-cli

frappe --help

With pipx

pipx install frappe-cli
frappe --help

Requirements

Requirement Version
Python ≥ 3.10
OS Ubuntu 22.04 or 24.04 (other Debian variants work, others untested)
User A non-root user with sudo access

Note: frappe-cli will install Node.js, MariaDB, Redis, nginx, supervisor, wkhtmltopdf, certbot, and uv for you. You do not need to pre-install them.


Quick start: bootstrap a fresh VPS

The fastest path from a clean Ubuntu server to a working HTTPS Frappe site:

sudo apt update && sudo apt install -y python3-pip curl

# 1. Install frappe-cli
curl -LsSf https://astral.sh/uv/install.sh | sh
uv tool install frappe-cli

# 2. Run the interactive wizard (≈30–60 min depending on the host)
frappe install wizard

You'll be prompted for:

Prompt Example
Bench directory my-bench
Site (FQDN, must resolve to this host) erp.example.com
Frappe branch version-15
App to install erpnext
App branch version-15
MariaDB root password (new password)
Site Administrator password (new password)
Let's Encrypt email you@example.com
Sudo password (your user password)

If a step fails, fix the issue and resume from where it stopped:

frappe install wizard --resume

When it's done:

curl -I https://erp.example.com   # HTTP/2 200, served by nginx, valid Let's Encrypt cert

Command structure

frappe <group> <command> [options]
Group What it does
install wizard End-to-end automated installer with state + resume
step Run any individual wizard step on its own (recommended for debugging / partial setups)
ssl Issue / list Let's Encrypt certificates for existing sites
site Create, list, backup, restore sites
app Get / install / update / remove Frappe apps
service Restart, status, logs for bench + system services
backup Manual + scheduled backups (optionally to an external HD)
firewall UFW configuration with secure defaults
maintenance Log rotation, etc.
monitor Live logs and system health (stubs / growing)
optimize Performance tuning (stubs / growing)
rollback Restore from backup, uninstall site, etc.
config YAML config get/set/validate

Every command supports --help and many support --dry-run and --debug.


Everyday recipes

Add SSL to an existing site

# See all sites and which are still on HTTP
frappe ssl list

# Issue an HTTPS cert for one site (auto-detects the owning bench)
frappe ssl setup --site-name erp.example.com

# First time ever using Let's Encrypt on this host? Provide an email
frappe ssl setup --site-name new.example.com --email you@example.com

Re-run a single wizard step

Every step the wizard runs is also exposed as a standalone command. Same code, same self-healing, same verification.

# Show all steps in execution order
frappe step list

# Run just SSL for one site
frappe step ssl --bench-name my-bench --site-name erp.example.com

# Re-do the production setup (nginx + supervisor) for a bench
frappe step production --bench-name my-bench

# Try a step without executing anything
frappe step production --bench-name my-bench --dry-run

# Force a step even when check() says "already done"
frappe step ssl --bench-name my-bench --site-name erp.example.com --force

The full step catalogue:

# Command Purpose
1 frappe step system-update apt-get update && upgrade
2 frappe step system-deps Frappe's required apt packages
3 frappe step uv-check Ensure uv is installed
4 frappe step nodejs Install Node.js + Yarn
5 frappe step mariadb-install Install MariaDB + utf8mb4 config
6 frappe step mariadb-secure Secure MariaDB root user
7 frappe step redis Install Redis server
8 frappe step wkhtmltopdf Install wkhtmltopdf + X11 fonts
9 frappe step bench-install uv tool install frappe-bench
10 frappe step bench-init bench init <name> --frappe-branch ...
11 frappe step site-create bench new-site <site>
12 frappe step app-get bench get-app <url>
13 frappe step dns-multitenant bench config dns_multitenant on
14 frappe step production bench setup production + supervisor self-heal + verify
15 frappe step app-install bench --site <s> install-app <app>
16 frappe step bench-restart supervisorctl reread/update + nginx reload
17 frappe step ssl bench setup lets-encrypt <site>

Add another site to an existing bench

frappe step site-create     --bench-name my-bench --site-name shop.example.com
frappe step dns-multitenant --bench-name my-bench
frappe step app-install     --bench-name my-bench --site-name shop.example.com --app-url erpnext
frappe step bench-restart   --bench-name my-bench
frappe step ssl             --bench-name my-bench --site-name shop.example.com

Set up an automated backup

frappe backup setup \
  --bench-name my-bench \
  --site-name erp.example.com \
  --admin-email you@example.com

Service health check

frappe service status --bench-name my-bench --site-name erp.example.com
frappe service restart

Firewall (UFW)

frappe firewall setup        # opens 22, 80, 443 by default

Tips for non-fresh VPS

frappe-cli is designed to work on hosts that already have bench installed or already have other Frappe benches:

  • frappe step bench-install — checks if bench is on PATH (any of ~/.local/bin, /usr/local/bin, /usr/bin) and skips if found.
  • frappe step bench-init — skips if the target bench directory already has apps/frappe/.
  • frappe step production — explicitly creates the missing supervisor.conf symlink that vanilla bench setup production sometimes forgets on multi-bench hosts.
  • frappe step ssl — uses sudo test -f so it can correctly detect existing certs in the root-owned /etc/letsencrypt/live/ directory.

Why frappe-cli over raw bench?

Pain point bench alone frappe-cli
Fresh VPS bootstrap 8+ manual steps, lots of doc-hopping One command
Multi-bench supervisor symlink Sometimes silently missing → "Redis connection refused" on install-app Auto-created and verified
Redis health check before install-app None TCP PING/PONG on queue/cache/socketio ports
bench setup lets-encrypt prompts Two interactive [y/N] prompts Automated
State across reboots / partial failures Manual --resume from saved state
Re-running a single step Find the command, get the args right frappe step <name>
Listing sites without SSL grep + sudo find frappe ssl list

Configuration file (optional)

For reproducible installs, pass a YAML config with --config:

# production.yaml
system:
  timezone: "Africa/Nairobi"
  locale: "en_US.UTF-8"
  user: "frappe"
frappe:
  branch: "version-15"
  bench_name: "my-bench"
  site_name: "erp.example.com"
  admin_password: "changeme"
  mariadb_root_password: "changeme"
services:
  enable_ssl: true
  enable_ufw: true
backup:
  admin_email: "you@example.com"
  retention_days: 7

See src/frappe_cli/data/example_config.yaml.


Logs and troubleshooting

  • All commands log to /var/log/frappe-installer.log (with local fallback if not writable).
  • Use --debug on any command for verbose subprocess output.
  • Use --dry-run on step / install commands to preview what would run.
  • For a known-working manual flow you can compare against, see docs/superpowers/test3-bench-setup.md — a step-by-step runbook used to verify every wizard step.

Development

git clone https://github.com/okama12/frappe-cli.git
cd frappe-cli

# Install dependencies
poetry install

# Run all tests (133 passing)
PYTHONPATH=src poetry run pytest tests/

# Lint (ruff + black --check + isort --check + mypy)
poetry run bash scripts/lint.sh

# Try a local build
pip install --editable .
frappe --help

Project layout

src/frappe_cli/
├── cli.py                  # root Click group
├── install/
│   ├── wizard.py           # `frappe install wizard`
│   ├── context.py          # InstallContext dataclass
│   ├── state.py            # ~/.frappe-cli-state.json (resume support)
│   └── steps/              # one InstallStep class per wizard step
├── step/                   # `frappe step <name>` — thin wrappers around steps/
├── ssl/                    # `frappe ssl setup`, `frappe ssl list`
├── site/, app/, service/, backup/, firewall/, ...
└── utils/                  # shell, errors, logging, validators

Tests live under tests/ (one file per command group, plus test_install_steps.py for the wizard's step classes).


Contributing

  1. Fork → feature branch.
  2. Add or improve a command group / step.
  3. Add tests in tests/ (use click.testing.CliRunner).
  4. Run poetry run bash scripts/lint.sh and PYTHONPATH=src poetry run pytest.
  5. Open a PR with a clear description.

About

Built by Rashidi Okama in Tanzania to make day-to-day Frappe work easier.

Run frappe about for the in-CLI credits panel. If this project saves you time, please star the repo — it really helps.


License

MIT © Rashidi Okama

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

frappe_cli-0.1.31.tar.gz (67.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

frappe_cli-0.1.31-py3-none-any.whl (96.4 kB view details)

Uploaded Python 3

File details

Details for the file frappe_cli-0.1.31.tar.gz.

File metadata

  • Download URL: frappe_cli-0.1.31.tar.gz
  • Upload date:
  • Size: 67.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for frappe_cli-0.1.31.tar.gz
Algorithm Hash digest
SHA256 49884392e4c384f7ec0ce5180cdacfcd38153bfa2b8d284412df2206407ac299
MD5 25cc061917368e73a31ee39db612994b
BLAKE2b-256 54d4f9768c072ccccfb28291483ddc44709ad27f89713e7b2ecb235c77686d3d

See more details on using hashes here.

File details

Details for the file frappe_cli-0.1.31-py3-none-any.whl.

File metadata

  • Download URL: frappe_cli-0.1.31-py3-none-any.whl
  • Upload date:
  • Size: 96.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for frappe_cli-0.1.31-py3-none-any.whl
Algorithm Hash digest
SHA256 1cb0f06591bca82a484e3693f51fc206cb899b1acd062c86b05503e14ce77343
MD5 a46f19fdac0087da2b8cf78b9a63ee48
BLAKE2b-256 73a7f1909761cb16210ceb3bca2ba91e3075aa48ae36c9a0886b9eded353bf4e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page