Aakvatech Limited - Frappe Pilot Admin, Bench URLs & Switch Bench

Frappe Pilot introduces an administration layer above individual Frappe sites. Understanding the difference between Pilot Admin, benches, sites, and sibling-bench management makes multi-bench servers

 · 9 min read

Understanding Frappe Pilot Admin, Bench URLs, and Switch Bench

When running multiple Frappe benches using Frappe Pilot, one of the first potentially confusing commands is:

pilot ls

For example:

NAME       MODE        MANAGER  SITES  ADDRESS
dev-bench  production  systemd  0      https://dev.example.com
v15        production  systemd  1      https://v15.example.com

At first glance, the ADDRESS column can look like the address of a Frappe or ERPNext site.

It is not.

It is the URL for the Pilot Admin interface associated with that bench.

Understanding this distinction is especially important when running multiple benches on the same server.

The three administrative layers

A useful way to think about Pilot is that there are three different administrative scopes.

Linux Server
│
├── Pilot / Host
│   └── pilot ls
│
├── Bench: dev-bench
│   ├── Pilot Admin
│   │   └── https://dev.example.com
│   │
│   └── Frappe Sites
│
└── Bench: v15
    ├── Pilot Admin
    │   └── https://v15.example.com
    │
    └── Frappe Sites
        └── erp.example.com

These layers should not be confused with one another.

1. Pilot CLI / server level

Commands such as:

pilot ls

operate at the Pilot installation level and can discover the benches managed on the server.

For example:

NAME       MODE        MANAGER  SITES  ADDRESS
dev-bench  production  systemd  0      https://dev.example.com
v15        production  systemd  1      https://v15.example.com

This tells us that Pilot currently knows about two benches.

2. Pilot Admin / Bench Admin

Each bench has its own Pilot Admin interface.

The Pilot Admin can manage operational aspects of the bench, including areas such as:

  • Sites
  • Applications
  • Processes
  • Tasks
  • Logs
  • Updates
  • Domains
  • Databases
  • Resource limits
  • Backups
  • Storage
  • Bench configuration

The ADDRESS shown by pilot ls is derived from that bench's Admin configuration.

Conceptually:

[admin]
domain = "v15.example.com"
tls = true

results in:

https://v15.example.com

being displayed by pilot ls.

3. Frappe / ERPNext Administrator

A Frappe site inside the bench has its own completely separate Administrator account.

For example:

https://erp.example.com

might use:

Username: Administrator
Password: <site administrator password>

That credential does not authenticate against the Pilot Admin interface.

Therefore:

Pilot Admin password
        ≠
Frappe Administrator password

They secure different layers of the system.

What exactly does pilot ls ADDRESS mean?

Looking at Pilot's ListCommand, the address is generated from the bench's Admin configuration.

If the Admin has a configured domain, Pilot uses that hostname.

Conceptually:

admin = bench.config.admin

if admin.domain:
    return admin.domain

Pilot then determines whether the URL should be HTTP or HTTPS based on the TLS configuration and availability of the Admin certificate.

This explains output such as:

dev-bench  production  systemd  0  http://admin.example.com
v15        production  systemd  1  https://v15.example.com

The two addresses are not two ERPNext sites.

They are two Pilot Admin endpoints, one for each bench.

Changing the Pilot Admin hostname

Pilot provides a dedicated command:

pilot set-admin-domain

Its syntax is:

usage: pilot set-admin-domain [-h] [--tls] domain

For example, if the Admin URL is currently:

http://admin.example.com

and we want:

https://dev.example.com

enter the relevant bench directory:

cd ~/pilot/benches/dev-bench

and run:

pilot set-admin-domain dev.example.com --tls

The DNS record for:

dev.example.com

should point to the Pilot server before certificate issuance is attempted.

Pilot handles the Admin-domain change through its Admin-domain management functionality, including updating configuration and republishing the appropriate nginx routing.

Afterwards:

cd ~/pilot
pilot ls

should show the new address.

For example:

dev-bench  production  systemd  0  https://dev.example.com

Importantly, changing the Admin domain does not rename the bench.

The bench remains:

dev-bench

Only its Pilot Admin hostname changes.

Setting or resetting the Pilot Admin password

Pilot has a separate command for its Admin password:

pilot set-admin-password

The current implementation describes this command as:

Set the admin panel password

If the password argument is omitted, Pilot prompts for it securely.

Therefore, the preferred approach is:

cd ~/pilot/benches/v15
pilot set-admin-password

rather than placing the password directly on the command line.

Although Pilot supports supplying a password as an argument, interactive entry is generally preferable because command-line arguments can be exposed through shell history or process inspection.

Password storage

Modern Pilot does not need to retain the clear-text Admin password.

The current implementation stores a password verifier/hash using PBKDF2-HMAC-SHA256.

This is another reason not to try to manually edit:

password = "..."

inside bench.toml.

Use:

pilot set-admin-password

instead.

Is there a separate "main Pilot Admin"?

This requires an important distinction.

There is not necessarily a completely separate global URL such as:

https://pilot.example.com

sitting above all bench Admin interfaces.

Instead, Pilot supports sibling-bench management from an existing Pilot Admin interface.

This is where the Switch Bench functionality comes in.

A server may therefore look like:

Pilot Server
│
├── dev-bench
│   └── Pilot Admin
│       └── dev.example.com
│
└── v15
    └── Pilot Admin
        └── v15.example.com

When sibling-bench management is enabled, an Admin interface can expose functionality such as:

Switch Bench
New Bench

allowing the administrator to navigate or manage benches on the same Pilot host.

So instead of thinking of Pilot as:

Global Pilot Admin
    ↓
Bench Admin
        ↓
Sites

a better model is:

Pilot Host
    ↓
Bench Admin
    ├── This bench
    └── Sibling benches, when permitted

Why "Switch Bench" may be missing

The presence of Switch Bench has nothing to do with whether the bench contains a Frappe site.

A bench with:

SITES = 0

can still show Switch Bench.

The feature is controlled by:

[admin]
allow_bench_management = true

The Pilot frontend checks the value returned by the backend and only adds Switch Bench when this capability is enabled.

Conceptually, the UI does:

if allowBenchManagement:
    show "Switch Bench"

The same capability also controls the UI components used for:

Switch Bench
New Bench

This is an important security boundary because an administrator who can manage sibling benches has considerably more authority than an administrator restricted to only the current bench.

Development checkout versus release installation

One particularly useful discovery in Pilot's source is the default behavior for:

allow_bench_management

Pilot explicitly describes sibling-bench management as primarily a development convenience.

The relevant logic effectively behaves as:

def default_allow_bench_management():
    return is_dev_build

This means a development checkout can default to:

allow_bench_management = true

while a release/production installation keeps it disabled until an operator explicitly enables it.

This explains a common situation:

pilot ls

shows several benches, but the Pilot Admin UI does not show:

Switch Bench

The benches exist.

The UI simply does not have permission to manage sibling benches.

Enabling Switch Bench

Inspect the bench configuration:

cd ~/pilot/benches/dev-bench

Then:

grep -A10 '^\[admin\]' bench.toml

You may find:

[admin]
domain = "dev.example.com"
tls = true
allow_bench_management = false

To allow sibling-bench management, the relevant configuration is:

[admin]
allow_bench_management = true

Before enabling this on a production host, understand the scope carefully.

This setting does more than display another navigation item.

It enables functionality intended to manage other benches on the same Pilot server.

Therefore:

allow_bench_management = false

means approximately:

This Admin interface manages its own bench.

while:

allow_bench_management = true

means approximately:

This Admin interface may perform host-level operations involving sibling benches.

That distinction should be considered part of the server's security model.

What settings exist under [admin]?

At the time of writing, Pilot's AdminConfig defines the following Admin configuration fields:

port
timeout
enabled
password
jwt_secret
jwks_url
jwks_audience
domain
tls
allow_bench_management
recovery_codes

A simplified configuration might look like:

[admin]
port = 7000
timeout = 180
enabled = true
domain = "v15.example.com"
tls = true
allow_bench_management = true

Several fields should generally be managed through Pilot itself rather than edited manually.

In particular:

password
jwt_secret
recovery_codes

are security-sensitive configuration.

port

Controls the Admin service port.

Pilot currently defaults this to:

7000

with its internal Gunicorn process using the adjacent internal port.

timeout

Controls the Admin timeout value.

The current default is:

180 seconds

enabled

Controls whether the Pilot Admin functionality is enabled.

password

Contains the Pilot Admin password verifier.

It should normally be changed using:

pilot set-admin-password

jwt_secret

Used for local JWT/session-related functionality.

jwks_url

Allows the Admin backend to trust tokens from an external JWKS issuer.

This becomes relevant in centrally managed or federated authentication deployments.

jwks_audience

Restricts externally issued tokens to the expected audience.

domain

Defines the Pilot Admin hostname.

Example:

domain = "v15.example.com"

tls

Controls whether the Admin hostname is served using HTTPS.

tls = true

allow_bench_management

Controls whether this Admin interface can manage sibling benches.

This is the setting behind functionality such as:

Switch Bench
New Bench

recovery_codes

Pilot also supports break-glass recovery codes for authentication recovery.

Because these are security-sensitive credentials, they should not be exposed unnecessarily.

A practical multi-bench Pilot architecture

For a server hosting different Frappe versions, a sensible structure might be:

Ubuntu Server
│
└── Pilot
    │
    ├── Bench: v15
    │   ├── Admin:
    │   │   https://v15.example.com
    │   │
    │   ├── ERPNext Site A
    │   └── ERPNext Site B
    │
    ├── Bench: v16
    │   ├── Admin:
    │   │   https://v16.example.com
    │   │
    │   └── ERPNext Site C
    │
    └── Bench: development
        ├── Admin:
        │   https://dev.example.com
        │
        └── Development Sites

An operator could then choose whether one or more of these Admin interfaces should have:

allow_bench_management = true

depending on the required security model.

Useful commands to remember

List all Pilot benches:

pilot ls

Enter a particular bench:

cd ~/pilot/benches/v15

Set its Pilot Admin password:

pilot set-admin-password

Change its Admin hostname:

pilot set-admin-domain v15.example.com --tls

Inspect its Admin configuration:

grep -A15 '^\[admin\]' bench.toml

Check all benches again:

cd ~/pilot
pilot ls

Key lessons

The main operational lessons are:

  1. The ADDRESS shown by pilot ls is the Pilot Admin URL for a bench, not the Frappe site's URL.

  2. Every bench can have its own Pilot Admin hostname.

  3. The Pilot Admin password is independent from the Frappe Administrator password.

  4. Use:

    pilot set-admin-password
    

    to manage the Pilot Admin credential.

  5. Use:

    pilot set-admin-domain <hostname> --tls
    

    to change the Pilot Admin hostname.

  6. A bench does not need any Frappe sites before its Pilot Admin interface can be used.

  7. The Switch Bench menu is not controlled by site count.

  8. Switch Bench is controlled by:

    [admin]
    allow_bench_management = true
    
  9. Release/production-style Pilot installations can deliberately leave sibling-bench management disabled.

  10. Enabling allow_bench_management should be treated as an administrative privilege because it expands the Admin interface's scope beyond the current bench.

Final recommendation

When operating Pilot in production, give every bench an explicit Admin hostname:

v15.example.com
v16.example.com
dev.example.com

Use HTTPS for each Admin endpoint and maintain separate Pilot Admin credentials from your Frappe site Administrator credentials.

For normal production benches, consider leaving:

allow_bench_management = false

unless cross-bench administration is genuinely required.

If one trusted Admin interface is intended to act as the operational entry point for the whole Pilot server, enabling:

allow_bench_management = true

there can provide the Switch Bench experience without requiring a separate global Pilot dashboard.

This produces a much clearer operational model:

Pilot Host
   ↓
Trusted Bench Admin
   ↓
Switch Bench
   ↓
Individual Bench
   ↓
Frappe Sites

and keeps the distinction between server administration, bench administration, and ERPNext/Frappe site administration explicit.

Reference articles and discussions

  • Frappe Pilot GitHub repository: https://github.com/frappe/pilot/
  • Pilot bench listing implementation (pilot/commands/bench/list.py): https://github.com/frappe/pilot/blob/develop/pilot/commands/bench/list.py
  • Pilot Admin configuration (pilot/config/admin.py): https://github.com/frappe/pilot/blob/develop/pilot/config/admin.py
  • Pilot configuration documentation: https://github.com/frappe/pilot/blob/develop/docs/configuration.md
  • Pilot Admin API documentation: https://github.com/frappe/pilot/blob/develop/docs/admin-api.md
  • Pilot Admin frontend bench-navigation logic (useAppMenu.ts): https://github.com/frappe/pilot/blob/develop/admin/frontend/dashboard/src/components/navigation/useAppMenu.ts
  • Pilot Admin session/bootstrap handling (useSession.ts): https://github.com/frappe/pilot/blob/develop/admin/frontend/dashboard/src/composables/auth/useSession.ts
  • Pilot Admin layout and Bench Switcher (MainLayout.vue): https://github.com/frappe/pilot/blob/develop/admin/frontend/dashboard/src/layouts/MainLayout.vue
  • Pilot Admin password command (pilot/commands/sites/set_admin_password.py): https://github.com/frappe/pilot/blob/develop/pilot/commands/sites/setadminpassword.py
  • Technical exploration and operational testing performed during an Aakvatech Pilot multi-bench deployment.
  • OpenAI ChatGPT was used to assist repository analysis, technical interpretation, and article drafting.

Aakvatech Limited is a Frappe Gold Partner and ERPNext implementation company headquartered in Dar es Salaam, Tanzania, operating across East Africa and the UAE.

This article was co-created using AI to accelerate drafting, with final insights curated and validated by the author. Any customer, personal, or sensitive data referenced during drafting has been anonymized or masked where applicable. All contributors, reference URLs, tools, and materials used to assist this content curation are credited in the Reference section.


No comments yet.

Add a comment
Ctrl+Enter to add comment