Plone deployment CLI.
plonex is a helper tool designed to simplify everyday project operations with Plone.
Note
plonex At the moment plonex is in early development and may have breaking changes. Use with caution and report issues.
If you just want to test plonex, you can initialize a new project and run the ZEO server and client with these commands:
plonex init myproject
cd myproject
plonex supervisor startThis is enough to get a ZEO server running in the background and a ZEO client in the foreground, with all configuration generated for you.
Your site will be available at http://localhost:8080.
When you run a command, plonex does more than simply spawn a process:
- it finds the correct project root (a parent folder containing a file named
etc/plonex.yml) - it loads and merges configuration from all supported files
- it prepares temporary/generated config files when needed
- it exports environment variables defined in configuration
- it runs the appropriate executable from your virtualenv
This means commands are reproducible and configuration-driven.
You change behavior in YAML files (or CLI flags), and plonex applies that
consistently across services.
Add this to your shell startup file:
eval "$(register-python-argcomplete plonex)"All commands accept these options:
plonex [--target PATH] [--verbose] [--quiet] [--version] <command> ...
-t, --target: target project folder (defaults to current directory).-v, --verbose: set log level toDEBUG.-q, --quiet: reduce log output (WARNINGand above).-V, --version: print installed plonex version.
For all commands except init, plonex resolves the target by walking upward until it finds etc/plonex.yml.
If you run plonex without a command, it displays the help message unless a
default action is configured in etc/plonex.yml.
plonex separates intent from implementation.
You declare intent with simple commands such as plonex zeoclient fg or
plonex db pack, and plonex translates that into the correct low-level command,
with the correct paths, environment variables, and generated configuration files.
This approach has a few practical benefits:
- You do not need to remember long binary paths or many flags.
- Team members can share the same commands while keeping local overrides in YAML.
- Automation in CI can reuse exactly the same command set used locally.
In other words, plonex behaves like an orchestration layer over project runtime
tools, while still letting you control details through configuration.
You can configure what happens when you run plonex with no explicit command.
By default, plonex shows the command help.
If you want a different behavior, set either default_action or
default_actions in etc/plonex.yml.
You can extend a project from one or more profiles declared in etc/plonex.yml.
Example:
profiles:
- /path/to/plonex-profile
- https://github.com/example/plonex-profile.git
http_port: 8081Profile configuration is loaded before the local project configuration, so the
local etc/plonex.yml remains the highest-precedence place for site-specific
overrides such as ports, hostnames, and service settings.
Profiles can themselves declare profiles, which allows a profile to extend
another profile before the local project overrides both.
Relative profile paths in the project etc/plonex.yml are resolved from the
project root. Relative profile paths declared inside a profile are resolved from
that profile root.
One practical way to organize profiles inside a repository is:
myproject/
├── etc/
│ └── plonex.yml
└── profiles/
├── default/
│ └── etc/
│ └── plonex.yml
├── production/
│ └── etc/
│ └── plonex.yml
└── development/
└── etc/
└── plonex.yml
For example, profiles/default/etc/plonex.yml can hold shared defaults used by
every environment:
plone_version: 6.1.4
http_address: 0.0.0.0
zeo_address: var/zeo.sock
environment_vars:
TZ: Europe/RomeThen profiles/production/etc/plonex.yml can extend default and add
production-specific values:
profiles:
- ../default
http_port: 8080
debug_mode: falseAnd profiles/development/etc/plonex.yml can also extend default but keep
more developer-friendly settings:
profiles:
- ../default
http_port: 8081
debug_mode: true
log_level: debugFinally, the project etc/plonex.yml chooses which profile to inherit from and
keeps the final local overrides:
profiles:
- profiles/development
http_port: 8082In this example the resulting http_port is 8082, because the local
etc/plonex.yml overrides profiles/development, which overrides
profiles/default.
plonex generates a merged var/constraints.txt for installation.
By default it starts from the Plone release constraints selected by
plone_version. The generated etc/plonex.yml does not include a
plonex_base_constraint entry unless you decide to add one.
Default behavior:
plone_version: 6.1.4This means the base constraint is effectively:
https://dist.plone.org/release/{{ plone_version }}/constraints.txtIf you want to override that base, add
plonex_base_constraint.
Supported values are:
- remote URLs
- local files relative to the project root
resource://package:pathreferences
Examples:
plonex_base_constraint: https://example.org/constraints/base.txtplonex_base_constraint: etc/constraints/base.txtplonex_base_constraint: resource://my.package:constraints/base.txtIf an old etc/constraints.d/000-plonex.txt file still exists, plonex warns
that it is ignored and suggests removing it. For compatibility, if neither
plone_version nor plonex_base_constraint is configured, plonex still tries
to infer plone_version from that legacy file.
Single action examples:
default_action: describedefault_action: zeoclient fgEquivalent list form:
default_action:
- zeoclient
- fgIf you want to run multiple commands in sequence, use default_actions:
default_actions:
- supervisor start
- zeoclient fgThis is useful when you want plain plonex to bootstrap a common local
workflow, for example starting Supervisor first and then bringing up the client.
Notes:
default_actionsruns in order.- each action can be written as a shell-like string or a list of tokens.
- command-line global options such as
-vand-qstill apply.
plonex init .
plonex dependencies
plonex zeoserver
plonex zeoclient fgWhat happens:
initcreates project skeleton and base config.dependenciesensures.venvexists and installs pinned dependencies.zeoserverstarts ZEO using generated config intmp/zeoserver.zeoclient fgrenders instance config intmp/zeoclientand starts in foreground.
plonex db pack --days N
plonex db backupWhat happens:
db packreadszeo_addressfrom merged options and callszeopack.db backuprunsrepozoagainst the project Data.fs location.
plonex supervisor start
plonex supervisor status
plonex supervisor restart
plonex supervisor graceful --interval 2.0What happens:
plonexgeneratesetc/supervisord.confand service templates if needed.- it runs
supervisordandsupervisorctlfrom your project virtualenv. - status/restart actions use the same generated config file, so behavior is consistent.
plonex supervisor gracefulrestarts each configured service one by one in the order reported bysupervisorctl status.--intervalcontrols the pause between service restarts.
You can also set the default interval in YAML:
supervisor_graceful_interval: 2.0Put that in etc/plonex.yml or another merged plonex config file. The CLI flag
still wins over YAML when both are provided.
init [target]
- Initialize project folders and base config.
- If
targetis omitted,plonexprompts for a folder and suggests the current directory as the default.
compile
- Compile merged configuration into
var/plonex.yml. - If
sourcesis configured, compile also generatesvar/gitman.yml. - The default checkout location is
srcwhensources_locationis omitted.
Example:
sources:
my.package:
repo: https://github.com/example/my.package.git
rev: maindescribe
- Render a project description from current configuration.
--html: also export the description tovar/plonex_description/index.html.--browse: open the generated HTML report in your default browser (implies HTML generation).
dependencies [--persist|--persist-local|--persist-profile]
- Install from merged requirements/constraints.
-p, --persist: save auto-detected missing constraints into the project'setc/constraints.d/.--persist-local: save auto-detected missing constraints into a local (git-ignored)etc/constraints.d/999-autoinstalled.local.txt.--persist-profile: save auto-detected missing constraints into the first configured profile'setc/constraints.d/.--update-sources: update sources before installing dependencies (uses Gitman under the hood).
To enable source updates by default in project configuration:
sources_update_before_dependencies: true
sources:
my.package:
repo: https://github.com/example/my.package.git
rev: maininstall <package> [<package> ...]
- Add one or more packages and run dependency installation.
sources [update|force-update|tainted|list|missing|clone-missing|suggest-existing]
- Manage configured source checkouts (uses Gitman under the hood).
update: run a regular sources update (executed by Gitman).force-update: run a forced update (--force), asking for confirmation by default.force-update --yes: skip confirmation.tainted: list checkouts with local changes.list: show configured checkouts and whether each is clean, tainted, or missing.missing: show configured checkouts that are not present on disk.clone-missing: clone missing configured checkouts (usingrepoand optionalrev).clone-missing --yes: skip confirmation prompt before cloning.suggest-existing: inspect existing unmanaged checkouts and print a ready-to-paste YAML snippet foretc/plonex.ymlwith inferredrepoandrev.suggest-existing --apply: write inferred entries intoetc/plonex.yml.suggest-existing --apply-local: write inferred entries intoetc/plonex-sources.local.yml.suggest-existing --apply-profile: write inferred entries into theetc/plonex.ymlof the first configured profile.
When unmanaged existing checkouts are detected, sources list and sources tainted
also print a suggested sources section to add into etc/plonex.yml.
upgrade
- Run Plone upgrade steps.
zeoserver
- Start ZEO server.
zeoclient [options] [action]
- Options:
-n, --name: client name (default:zeoclient)-c, --config: extra config file (repeatable)-p, --port: HTTP port--host: HTTP host
- Actions:
console(default)fgstartstopstatusdebug
run [args ...]
- Run an instance script through the ZEO client wrapper.
adduser [-c FILE] <username> [password]
- Create a Zope user (password can be omitted to auto-generate one).
supervisor [status|start|stop|restart|graceful]
- Manage supervisord for project services.
gracefulaccepts--interval SECONDSand falls back tosupervisor_graceful_intervalfrom YAML, defaulting to1.0.
db backup
- Run Data.fs backup.
db pack [--days DAYS]
- Pack ZODB revisions older than
DAYS(default:7). - Uses merged
zeo_addressfrom your config files.
db restore
- Placeholder (not implemented yet).
zopetest <package> [-t TEST]
- Run
zope-testrunnerfor a package.
robotserver [--layer LAYER]
- Start robot test server.
robottest <paths...> [--browser BROWSER] [-t TEST]
- Run Robot Framework tests.
test
- Placeholder command.
Options are merged in this order (higher wins):
- CLI options
- Files passed with
-c/--config etc/plonex-<service>.*.ymletc/plonex-<service>.ymletc/plonex.*.yml(alphabetical precedence)etc/plonex.yml- Profiles declared by
etc/plonex.ymland nested profileplonex.ymlfiles - Service defaults
Why this matters:
- you can keep sane defaults in
etc/plonex.yml, - inherit shared defaults from one or more profiles,
- add machine- or developer-specific overrides in
etc/plonex.local.yml, - and still force one-off values from the command line when needed.
This is especially useful for paths like zeo_address, ports, or feature flags
that can vary by environment.
Useful settings include:
log_level:DEBUG,INFO,WARNING,ERROR,CRITICALenvironment_vars: environment variables exported before service executionzeo_address: socket/host used by ZEO client anddb packblobstorage: blob storage pathhttp_port,http_address
Example:
zeo_address: /srv/components/zeo/var/zeo.socket
blobstorage: /srv/components/zeo/var/blobstorage
environment_vars:
TZ: Europe/RomeService-specific overrides are useful when one command needs different settings. For example:
etc/plonex.yml: shared defaults.etc/plonex.local.yml: local machine overrides (socket paths, local ports).etc/plonex-zeoclient.yml: zeoclient-only adjustments.
Because these files are merged with precedence, you can keep common settings in one place and make only small targeted overrides where needed.
plonex supports declarative helper services in etc/plonex.yml.
These services are not intended to be run directly as a top-level command.
Instead, they run automatically as dependencies of runtime commands.
This is useful when a command needs generated files before execution, for example Supervisor program snippets or other rendered templates.
Example:
services:
- template:
run_for: supervisor
source_path: resource://plonex.supervisor.templates:program.conf.j2
target_path: tmp/supervisor/etc/supervisor/zeoclient.conf
options:
name: zeoclient
command: tmp/zeoclient/bin/instance fg
autostart: falseIn this example:
- the template is rendered only when running a command mapped to
supervisor, - the rendered file is prepared before
supervisord/supervisorctlis called, - and the dependency is fully controlled from YAML.
run_for accepts either a string or a list of command names:
services:
- template:
run_for: [supervisor, zeoclient]
source: etc/templates/runtime.conf.j2
target: tmp/runtime.confNotes:
- service entries must be a list of single-key mappings,
- unknown service names raise a configuration error,
- relative
source/targetpaths are resolved from the project target folder, resource://...template sources are supported.
Recommended pattern:
- keep long-lived defaults in
etc/plonex.yml, - keep machine-specific path overrides in
etc/plonex.local.yml, - add
run_foronly where generation must be scoped to specific commands.
More examples:
- Add extra ZCML includes for the ZEO client:
zcml_additional:
- etc/zcml/010-my-package-meta.zcml
- etc/zcml/020-my-package-configure.zcml
- etc/zcml/030-my-package-overrides.zcmlThese files are rendered or copied into tmp/zeoclient/etc/package-includes/
before plonex zeoclient ... runs. File names matter: plonex expects the
usual -meta.zcml, -configure.zcml, or -overrides.zcml suffixes.
- Add extra
zope.confsnippets for the ZEO client:
zope_conf_additional:
- etc/zopeconf/cache.j2
- etc/zopeconf/instancesettings.confFor example, etc/zopeconf/cache.j2 could contain:
<product-config my.package>
some-setting value
</product-config>
Each listed file is appended to the generated tmp/zeoclient/etc/zope.conf.
Jinja templates can use the current service context.
- Generate a Supervisor program for an auxiliary service such as a websocket worker, Celery worker, or custom script:
services:
- template:
run_for: supervisor
source_path: resource://plonex.supervisor.templates:program.conf.j2
target_path: tmp/supervisor/etc/supervisor/worker.conf
options:
program: worker
command: .venv/bin/python -m mypackage.worker
process_name: worker
directory: "{{ target }}"
priority: 20That way plonex supervisor start manages not only zeoserver and
zeoclient, but also your additional long-running process.
- Combine service dependencies and zeoclient extras in the same project:
zcml_additional:
- etc/zcml/020-my-package-configure.zcml
zope_conf_additional:
- etc/zopeconf/cache.j2
services:
- template:
run_for: supervisor
source: etc/templates/worker.conf.j2
target: tmp/supervisor/etc/supervisor/worker.confThis keeps all project-specific runtime wiring in etc/plonex.yml while still
letting the generated files live under tmp/.
plonex is a wrapper around executables inside your virtualenv. Paths are resolved from the project target (typically .venv/bin/...).
Most commands follow the same lifecycle:
- Resolve target folder.
- Merge options from config files and CLI.
- Generate required runtime files under
tmp/and/oretc/. - Execute the real binary from
.venv/bin/....
So when you type a short command like plonex db pack, plonex still applies your
configuration first (for example zeo_address) and only then calls zeopack.
That is why changing config files can change command behavior without changing
the command itself.
Common command mappings:
plonex zeoserver
.venv/bin/runzeo -C tmp/zeoserver/etc/zeo.confplonex zeoclient fg(and other zeoclient actions)
tmp/zeoclient/bin/instance fgplonex run path/to/script.py
tmp/zeoclient/bin/instance run path/to/script.pyplonex adduser admin secret
.venv/bin/addzopeuser -c tmp/zeoclient/etc/zope.conf admin secretplonex db pack --days 7
.venv/bin/zeopack -u <zeo_address> -d 7<zeo_address> is read from merged plonex configuration, not hardcoded.
plonex db backup
.venv/bin/repozo -Bv -r var/backup -f var/filestorage/Data.fsplonex supervisor start
.venv/bin/supervisord -c etc/supervisord.confplonex supervisor status
.venv/bin/supervisorctl -c etc/supervisord.conf statusplonex supervisor graceful --interval 2
.venv/bin/supervisorctl -c etc/supervisord.conf status
.venv/bin/supervisorctl -c etc/supervisord.conf restart <service1>
sleep 2
.venv/bin/supervisorctl -c etc/supervisord.conf restart <service2>
...plonex dependencies
.venv/bin/uv pip install -r var/requirements.txt -c var/constraints.txtplonex robottest tests/acceptance/*.robot
.venv/bin/robot --variable BROWSER:firefox tests/acceptance/*.robotplonex robotserver
.venv/bin/robot-server --debug-mode --verbose Products.CMFPlone.testing.PRODUCTS_CMFPLONE_ROBOT_TESTINGplonex zopetest plone.api -t test_get
.venv/bin/zope-testrunner --all --quiet -pvc --path <package_path> -t test_getNote: plonex also renders temporary config files under tmp/ before running several services (for example tmp/zeoclient/etc/zope.conf).
plonex looks for etc/plonex.yml by walking up from the target directory.
Use one of these approaches:
- run commands from inside your project tree,
- pass
--target /path/to/project, - or initialize a project first with
plonex init.
Run plonex compile and inspect var/plonex.yml.
That file shows the final merged options and helps verify which file/flag won.
Typical causes:
- a higher-priority config file overrides your value,
- a command-line option is overriding YAML,
- or a service-specific file exists and takes precedence for that service.
Check zeo_address in your merged config and ensure the socket/host exists.
If needed, set it in etc/plonex.local.yml for machine-specific environments.
If commands fail because binaries are missing, run:
plonex dependenciesThis recreates or updates environment-installed tooling used by runtime commands.
db restoreis not implemented yet.testis currently a placeholder command.
These commands are listed for interface completeness but do not provide full behavior yet.