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.28.tar.gz (64.9 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.28-py3-none-any.whl (93.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: frappe_cli-0.1.28.tar.gz
  • Upload date:
  • Size: 64.9 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.28.tar.gz
Algorithm Hash digest
SHA256 a1b919afee0a70652ff419e9d72cc98078d7d2c429af934385c97c9a465dda20
MD5 1720eeaeb0dcf5485f6dfcb2833a4af2
BLAKE2b-256 085cc61d2121e7085ef546bd627d9dff8dabdce22e6abb6dbf2a96cc5593e085

See more details on using hashes here.

File details

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

File metadata

  • Download URL: frappe_cli-0.1.28-py3-none-any.whl
  • Upload date:
  • Size: 93.7 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.28-py3-none-any.whl
Algorithm Hash digest
SHA256 047c551dfe9107ded7b8463d29edd06d0ca399ee7d835673939296f52504dcf5
MD5 2e985614930f2349a5e57c23f2589a2f
BLAKE2b-256 83b8d16d3fb2f8125533c545745a055dfac6c1085204e8782efbbad90d9445c6

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