Development Environment
Before you can write a line of Frappe code, you need a running bench. Coming from
Node.js, think of this as the moment you’d npm install and npm run dev — except
Frappe pulls in a database, a cache, a queue, and a realtime server, so the setup
is heavier. This chapter walks through getting a Frappe v16 + ERPNext bench up,
either natively on Ubuntu or inside a Docker DevContainer, plus the editor wiring
and the failures you’ll actually hit.
Prerequisites
Section titled “Prerequisites”Frappe v16 expects a specific set of system dependencies. Get these versions right up front — most setup failures trace back to a stale Python or Node.
| Dependency | Required Version | Why |
|---|---|---|
| Python | 3.14+ | Frappe v16 server-side runtime |
| Node.js | 24 LTS | Asset building (esbuild) + Socket.IO |
| MariaDB | 10.6+ | Primary database (or Postgres 14+) |
| Redis | 8+ | Caching, queues, real-time messaging |
| Git | 2.x | App management, version control |
| pip | Latest | Python package installer |
| wkhtmltopdf | 0.12.6+ | PDF generation (legacy; v16 adds Chrome) |
| Yarn | 1.x | Node.js dependency management |
Choosing an install method
Section titled “Choosing an install method”There are two practical ways to run a dev bench. Native bench installs
everything directly on the host OS — best for production servers and developers who
want full control. Docker uses the official frappe_docker DevContainer and
sidesteps the “works on my machine” problem entirely. Pick one; the tabs below stay
in sync across the page.
The bare-metal approach on Ubuntu 24.04. You install Python, Node, MariaDB, Redis, and bench directly, then initialize a bench and a site.
-
Install system dependencies.
Terminal window sudo apt update && sudo apt upgrade -y# Install core dependenciessudo apt install -y \git \python3-dev \python3-pip \python3-venv \python3-setuptools \build-essential \libffi-dev \libssl-dev \libjpeg-dev \libpng-dev \zlib1g-dev \libmysqlclient-dev \curl \wget \software-properties-common -
Install Python 3.14. Ubuntu 24.04 ships with Python 3.12 — you need 3.14 for Frappe v16.
Terminal window # Add deadsnakes PPA for newer Python versionssudo add-apt-repository ppa:deadsnakes/ppa -ysudo apt update# Install Python 3.14sudo apt install -y python3.14 python3.14-dev python3.14-venv# Verifypython3.14 --version# Expected output: Python 3.14.x -
Install Node.js 24.
Terminal window # Install Node.js 24 via NodeSourcecurl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -sudo apt install -y nodejs# Verifynode --version# Expected output: v24.x.xnpm --version# Expected output: 10.x.x# Install Yarn globallysudo npm install -g yarn -
Install and configure MariaDB. The
utf8mb4character-set config is mandatory.Terminal window sudo apt install -y mariadb-server mariadb-client# Secure the installationsudo mysql_secure_installation# Switch to unix_socket auth? N# Change root password? Y (set a strong password)# Remove anonymous users? Y# Disallow root login remotely? Y# Remove test database? Y# Reload privilege tables? Y/etc/mysql/mariadb.conf.d/99-frappe.cnf [mysqld]character-set-client-handshake = FALSEcharacter-set-server = utf8mb4collation-server = utf8mb4_unicode_ci[mysql]default-character-set = utf8mb4Terminal window sudo systemctl restart mariadb# Verifymariadb --version# Expected output: mariadb Ver 15.x Distrib 10.x.x-MariaDB -
Install Redis.
Terminal window sudo apt install -y redis-server# Verifyredis-server --version# Expected output: Redis server v=8.x.x ...sudo systemctl enable redis-serversudo systemctl start redis-server -
Install wkhtmltopdf.
Terminal window # Download and install the patched Qt versionwget https://github.com/wkhtmltopdf/packaging/releases/download/0.12.6.1-3/wkhtmltox_0.12.6.1-3.jammy_amd64.debsudo dpkg -i wkhtmltox_0.12.6.1-3.jammy_amd64.debsudo apt install -f -y # Fix any dependency issues# Verifywkhtmltopdf --version# Expected output: wkhtmltopdf 0.12.6.1 (with patched qt) -
Install bench.
Terminal window # Install bench CLIpip install frappe-bench# Verifybench --version# Expected output: 5.x.x -
Initialize a new bench with Frappe v16, from your home directory.
Terminal window bench init frappe-bench --frappe-branch version-16 --python python3.14# Getting frappe# shallow clone https://github.com/frappe/frappe.git --branch version-16 --depth 1# Setting Up Environment / Procfile / Redis# SUCCESS: Bench frappe-bench initializedcd frappe-bench -
Create a site.
Terminal window # Replace <your-mariadb-root-password> with the password you set earlierbench new-site icecream.localhost --mariadb-root-password <your-mariadb-root-password># Installing frappe...# Updating DocTypes for frappe: [========================================] 100%# Site icecream.localhost created successfully.# Set it as the default sitebench use icecream.localhost -
Install ERPNext on the site.
Terminal window # Download the ERPNext appbench get-app erpnext --branch version-16# Install ERPNext on your sitebench --site icecream.localhost install-app erpnext# Installing erpnext...# Updating DocTypes for erpnext: [========================================] 100% -
Start the development server.
Terminal window bench start# 14:30:00 web.1 | * Running on http://0.0.0.0:8000# 14:30:00 socketio.1 | listening on port 9000# 14:30:00 watch.1 | watching for file changes...# 14:30:01 worker.1 | Worker rq:worker started# 14:30:01 schedule.1 | Scheduler started
Open your browser to http://icecream.localhost:8000 and log in:
- Username:
Administrator - Password: the password you set during
bench new-site(oradminif you did not specify one)
The official frappe_docker repository provides a complete development environment
with VS Code DevContainers — it provisions MariaDB, Redis, and the bench for you.
-
Install Docker, Docker Compose, and VS Code with the Dev Containers extension (
ms-vscode-remote.remote-containers).Terminal window # Install Docker (if not already installed)curl -fsSL https://get.docker.com | bashsudo usermod -aG docker $USER# Log out and back in for group changes to take effect# Verifydocker --version# Expected output: Docker version 27.x.xdocker compose version# Expected output: Docker Compose version v2.x.x -
Clone and configure the repo.
Terminal window # Clone the official frappe_docker repogit clone https://github.com/frappe/frappe_docker.gitcd frappe_docker# Copy devcontainer configurationcp -R devcontainer-example .devcontainercp -R development/vscode-example development/.vscode -
Open in the DevContainer.
Terminal window code .VS Code detects the
.devcontainerconfiguration and prompts “Reopen in Container” — click it. If you miss the prompt, pressCtrl+Shift+Pand search for “Dev Containers: Reopen in Container”. The first build takes a few minutes; it provisions MariaDB, Redis, and the Frappe bench automatically. -
Initialize bench inside the container. Open a terminal in VS Code (the working directory is
/workspace/development).Terminal window bench init --skip-redis-config-generation frappe-benchcd frappe-bench# Point bench at the Docker service containersbench set-config -g db_host mariadbbench set-config -g redis_cache redis://redis-cache:6379bench set-config -g redis_queue redis://redis-queue:6379bench set-config -g redis_socketio redis://redis-cache:6379# Create a sitebench new-site icecream.localhost --mariadb-root-password 123 --admin-password admin# Get and install ERPNextbench get-app erpnext --branch version-16bench --site icecream.localhost install-app erpnext# Start the development serverbench start
The development Docker Compose file starts these services:
| Service | Port | Purpose |
|---|---|---|
| frappe | 8000 | Bench development server |
| mariadb | 3306 | Database |
| redis-cache | 6379 | Cache and Socket.IO pub/sub |
| redis-queue | 6380 | Background job queues |
Cloud-based environments (Gitpod / Codespaces)
Section titled “Cloud-based environments (Gitpod / Codespaces)”For zero-local-setup development — workshops, demos, quick experiments — use a cloud environment that builds the same DevContainer in the cloud.
Gitpod reads the .gitpod.yml in the repo and provisions a full environment
when you open this URL (swap in your fork if needed):
https://gitpod.io/#https://github.com/frappe/frappe_dockerGitHub Codespaces:
- Fork
frappe/frappe_dockeron GitHub. - Click the green “Code” button, the Codespaces tab, then “Create codespace on main”.
- The devcontainer configuration is picked up automatically.
- Follow the same
bench initsteps as the Docker method above.
VS Code: extensions and debugging
Section titled “VS Code: extensions and debugging”A little editor wiring makes Frappe far more pleasant — Python autocomplete across apps, and step-through debugging of the request cycle. Drop these files into your bench directory.
The recommended extensions cover Python, ESLint/Prettier for client scripts, the DevContainers extension, and Jinja highlighting for print formats:
{ "recommendations": [ "ms-python.python", "ms-python.debugpy", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "ms-vscode-remote.remote-containers", "samuelcolvin.jinjahtml" ]}The debug config launches the Frappe web server (and a worker) under debugpy so
you can set breakpoints and inspect the stack. Note the --noreload flag — the
auto-reloader and the debugger don’t coexist.
{ "version": "0.2.0", "configurations": [ { "name": "Frappe Web", "type": "debugpy", "request": "launch", "program": "${workspaceFolder}/apps/frappe/frappe/utils/bench_helper.py", "args": ["frappe", "serve", "--port", "8000", "--noreload"], "env": { "DEV_SERVER": "1" }, "cwd": "${workspaceFolder}/sites", "python": "${workspaceFolder}/env/bin/python" }, { "name": "Frappe Worker (short)", "type": "debugpy", "request": "launch", "program": "${workspaceFolder}/apps/frappe/frappe/utils/bench_helper.py", "args": ["frappe", "worker", "--queue", "short"], "cwd": "${workspaceFolder}/sites", "python": "${workspaceFolder}/env/bin/python" } ]}To debug:
- Stop
bench startif it’s running (it would hold port 8000). - Set breakpoints in your Python code.
- Press
F5to start the Frappe Web configuration. - Trigger the code path from the browser.
- VS Code hits your breakpoint with full stack inspection.
Finally, point VS Code’s Python tooling at the bench virtualenv and the app source so imports resolve:
{ "python.defaultInterpreterPath": "./env/bin/python", "python.analysis.extraPaths": [ "./apps/frappe", "./apps/erpnext", "./apps/scoopjoy" ], "[python]": { "editor.defaultFormatter": "ms-python.python" }}Common setup issues and fixes
Section titled “Common setup issues and fixes”bench new-site fails with “Access denied for user ‘root’@‘localhost’”
Section titled “bench new-site fails with “Access denied for user ‘root’@‘localhost’””Grant root access via socket auth, then set a password:
sudo mariadb -u rootALTER USER 'root'@'localhost' IDENTIFIED BY 'your_new_password';FLUSH PRIVILEGES;EXIT;Then retry with bench new-site icecream.localhost --mariadb-root-password your_new_password.
”Node.js version not supported” error
Section titled “”Node.js version not supported” error”# Check current Node versionnode --version
# If it's not v24.x, remove the old version and install Node 24sudo apt remove -y nodejscurl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -sudo apt install -y nodejsbench start shows Redis connection errors
Section titled “bench start shows Redis connection errors”# Verify Redis is runningsudo systemctl status redis-server
# If not runningsudo systemctl start redis-serversudo systemctl enable redis-server
# Check Redis is listeningredis-cli ping# Expected output: PONGSite does not load in the browser (DNS resolution)
Section titled “Site does not load in the browser (DNS resolution)”# For *.localhost domains, add to /etc/hostsecho "127.0.0.1 icecream.localhost" | sudo tee -a /etc/hosts
# Or hit 127.0.0.1:8000 directly, after setting the default site:bench use icecream.localhostPython version mismatch during bench init
Section titled “Python version mismatch during bench init”# Explicitly specify the Python executablebench init frappe-bench --frappe-branch version-16 --python python3.14
# If python3.14 is not in PATH, use the full pathbench init frappe-bench --frappe-branch version-16 --python /usr/bin/python3.14pip install frappe-bench permission error
Section titled “pip install frappe-bench permission error”# Use --user flagpip install --user frappe-bench
# Or create a dedicated venvpython3.14 -m venv ~/bench-envsource ~/bench-env/bin/activatepip install frappe-benchWith a bench running, you’re ready to drive it. The next chapter is a tour of the bench CLI — the single command you’ll live inside for the rest of this course.