A command-line tool for setting up and managing Frappe environments. Configuration lives in a single bench.yml file. No Docker.
Ubuntu 22.04 LTS (other Debian-based distros are best-effort)
- Python 3.10+
sudoaccess (needed duringbench initto install system packages via apt)
macOS (development only)
- Python 3.10+
- Homebrew (
brewin$PATH)
pip install frappe-clibench init will install MariaDB, Redis, Node.js, and any other system dependencies itself.
1. Create a directory for your bench and scaffold a config:
mkdir my-bench && cd my-bench
bench newThis writes a starter bench.yml. Open it and fill in your apps, sites, and database credentials.
2. Run the setup:
bench initThis will:
- Install MariaDB, Redis, Node.js via
apt(orbrewon macOS) - Create a Python virtualenv at
env/usinguv - Clone your apps into
apps/and install each one withuv pip install -e - Create your sites (database credentials are generated and managed by frappe)
- Build JavaScript and CSS assets
- Generate a
Procfilefor running all processes
3. Start everything:
bench startAll processes (web, workers, Redis) start in the foreground. Press Ctrl-C to stop.
4. Stop from another terminal:
bench stop5. Open the app:
Visit http://site1.localhost:8000 (or whatever site/port you configured).
A minimal config for a single Frappe site:
bench:
name: my-bench
python: "3.14"
process_manager: honcho
http_port: 8000
socketio_port: 9000
apps:
- name: frappe
repo: https://github.com/frappe/frappe
branch: version-16
sites:
- name: site1.localhost
admin_password: "admin"
apps:
- frappe
mariadb:
host: localhost
port: 3306
root_password: "your_root_password"
admin_user: root
version: "10.6" # optional — omit to use the package manager default
redis:
cache_port: 13000
queue_port: 11000
socketio_port: 12000
version: "7" # optional — macOS only; see docs/config.md for Linux notes
workers:
default: 2
short: 1
long: 1Note: Database name and credentials are generated automatically by frappe's
new-site. You don't configure them — they're written intosites/<sitename>/site_config.jsonafterbench init.
| Command | What it does |
|---|---|
bench new |
Scaffold a starter bench.yml in the current directory |
bench init |
Install system packages, clone apps, create sites, build assets, generate process config |
bench start |
Start all processes (web, workers, Redis) in the foreground |
bench stop |
Stop a running bench (works across terminal sessions via PID file) |
bench build |
Rebuild JavaScript and CSS assets |
bench update |
Pull latest app commits, reinstall packages, migrate all sites |
bench start-admin |
Start the admin UI as a background daemon (default: http://localhost:8002) |
bench stop-admin |
Stop the background admin UI |
bench admin |
Start the admin UI in the foreground (dev use) |
bench setup nginx |
Generate and install nginx config |
bench setup letsencrypt |
Obtain SSL certificates |
bench setup production |
Full production setup (nginx + supervisor + SSL) |
All commands read bench.yml from the current directory or the nearest parent directory that contains one.
Update bench.yml to enable nginx, SSL, and supervisor:
bench:
name: prod-bench
python: "3.14"
process_manager: supervisor
apps:
- name: frappe
repo: https://github.com/frappe/frappe
branch: version-16
sites:
- name: mysite.example.com
admin_password: "changeme"
apps: [frappe]
ssl: true
mariadb:
root_password: "root_secret"
redis:
cache_port: 13000
queue_port: 11000
socketio_port: 12000
nginx:
enabled: true
letsencrypt:
email: ops@example.comThen run bench init followed by:
bench setup productionThis installs nginx, obtains a Let's Encrypt certificate, and starts all processes under supervisor.
bench start-admin # start on default port 8002 (background daemon)
bench stop-admin # stop the daemon
bench start-admin --port 9000 # custom portThe admin starts as a background daemon and auto-stops after 15 minutes of inactivity — so you don't accidentally leave it running. Use bench stop-admin to stop it immediately.
For interactive/foreground use during development:
bench admin # foreground, Ctrl-C to stopThe admin interface provides:
- App git status and installed versions
- Site configuration and installed apps
- Process status (running / stopped)
- Live log tailing
- MariaDB binary log viewer
- Run common commands (migrate, clear-cache, build) with streamed output
The admin reads all state directly from the filesystem on each request — it keeps no state of its own.
After bench init, your bench directory looks like this:
my-bench/
├── bench.yml # your config
├── apps/ # cloned app source code
│ └── frappe/
├── sites/ # site data
│ ├── assets/ # built JS/CSS (symlinked from apps)
│ ├── apps.txt # installed app list read by frappe
│ ├── common_site_config.json # redis URLs, ports
│ └── site1.localhost/
│ └── site_config.json # db credentials (set by frappe)
├── env/ # shared Python virtualenv
├── logs/ # per-process log files
├── pids/ # bench.pid, admin.pid, admin.port
└── config/ # Procfile, Redis configs, Nginx configs
- docs/config.md — complete
bench.ymlfield reference - docs/commands.md — what each command does, step by step
- docs/production.md — nginx, Let's Encrypt, and DNS multitenancy
- docs/admin.md — admin interface design
- docs/architecture.md — Python package layout and class design