Install Plone backend from its Packages – Step by Step#


For system requirements and pre-requisites for the installation see System requirements.

We install the Plone backend with pip, cookiecutter-zope-instance, mxdev and other fancy helpers.


There will be one single cookiecutter template to install both backend and frontend from its packages. You will find the instructions on Installation – jump in and enfold the beauty. That chapter is for you if you want to develop and want to jump in with all steps prepared by an overall cookiecutter. The subsequent sections explain the installation of the backend step by step. You will learn the details of the installation included in the future overall cookiecutter.

Installation steps#

Create a new directory to hold your project, make it your current directory, then issue the following commands in a shell session.

Create a Python virtual environment in the current directory.

python3.9 -m venv venv
source venv/bin/activate

Update Python package management tools.

pip install -U pip wheel

packages tree

The Plone packages and dependencies are installed in trees.

┌── plone/
│   ├── …
│   ├── app/
│       ├── caching/
│       ├── content/
│       └── …
├── zope/
│   ├── …

Install Plone 6 with constrained requirements using pip.

pip install Plone -c

mkwsgiinstance's minimal Zope configuration

mkwsgiinstance creates a home with a minimal configuration for a Zope instance.

┌── etc/
│   ├── site.zcml
│   ├── zope.conf
│   └── zope.ini
├── inituser
└── var/
    ├── cache/
    ├── log/
    └── REAMDME.txt/

Create a Zope instance with the given username and password in the current directory.

mkwsgiinstance -u admin:admin -d .

All commands so far

python3.9 -m venv venv
source venv/bin/activate
pip install -U pip wheel
pip install Plone -c
mkwsgiinstance -u admin:admin -d .

Start the Zope instance.

runwsgi ./etc/zope.ini

You can stop the instance later with ctrl-esc.

If you now open the browser with http://localhost:8080/, you see that you already can create a Plone instance. Before doing this, we configure our Zope instance for blobs, configure add-ons, etc..

For the configuration, you have two options:

  1. manual configuration by editing site.zcml and zope.conf (^Configuring and Running Zope)

  2. generate configuration by applying cookiecutter-zope-instance

Generate Plone / Zope configuration with cookiecutter#

Cookiecutter creates projects from project templates. cookiecutter-zope-instance is such a template that allows to create a complete Zope configuration. Zope configuration means:

  • type of storage: direct filestorage/blobs, relational database, ZEO, you name it

  • ports

  • threads/caches

  • debugging/profiling options

Install cookiecutter:

pip install cookiecutter

You could now run cookiecutter to create a Zope instance sceleton including configuration with the following command. It prompts you for parameter values.


Instead we prepare a configuration file instance.yaml with the parameters we want to set. In this section we will learn how to configure our Zope / Plone installation via instance.yaml. A minimal example with one add-on configured:


Reference of configuration options of cookiecutter-zope-instance.

    initial_user_name: 'admin'
    initial_user_password: 'admin'

        package_includes: ['collective.easyform']

    db_storage: direct

Add-ons are listed here to be loaded by Zope app. As python packages they also need to be installed with pip. The documented installation of add-ons with pip is achieved via a requirements.txt file. We list an add-on like for example collective.easyform in


Install your requirements:

pip install -r requirements.txt

You have done two things so far: You installed your add-on packages and you have prepared an initializing file to roll out a Zope / Plone project, configured to load your installed add-on packages.

You are now ready to apply cookiecutter to generate the Zope configuration:

cookiecutter -f --no-input --config-file instance.yaml
Cookiecutter options used here#



-f, --overwrite-if-exists

Overwrite the contents of the output directory if it already exists. Data in var stays untouched.


Do not prompt for parameters and only use cookiecutter.json file content

--config-file instance.yaml

User configuration file

Summed up tasks and commands

Summed up tasks and commands after creating a Zope instance with mkwsgiinstance:

  • Create an instance.yaml for presets.

  • Create a requirements.txt for the installation of python packages.

  • Install add-ons and generate Zope skeleton with configuration (apply cookiecutter)

    pip install -r requirements.txt
    cookiecutter -f --no-input --config-file instance.yaml

cookiecutter creates a new directory instance with your Zope and Plone configuration. This directory will also comprise file storage, blob storage, etc..

It's time to start the new Zope instance.

runwsgi -v instance/etc/zope.ini

Head over to http://localhost:8080/ and see that Plone is running. You could now create a Plone instance Create a Plone instance and enable the add-on collective.easyform in Site Setup http://localhost:8080/Plone/prefs_install_products_form.

If you want to run Plone with some add-ons, you are ready with the installation of the backend.
If you decided to go with the Plone Classic UI this is also your frontend.
If you decided to go with the Plone Volto frontend, then section Volto frontend explains your next steps.

If you want to develop a Plone package, then the subsequent section is for you.

Checkout or version pinning of a Plone package#

If you want to checkout a Plone Core package for development or just want to override the constraints of Plone, then a first attempt would be to define constraints with a constraints.txt to tell pip to install a different version of a Plone package.

# constraints.txt with unresolvable version conflict

Unfortunatly pip does not allow this way of overwriting constraints.

mxdev is made for assembling Plone constraints with your needs of version pinning or source checkouts.
It reads your requirements.txt and so your constraints.txt, fetches the requirements/constraints of Plone and writes the files requirements-mxdev.txt and constraints-mxdev.txt. Both are containing the combined requirements and constraints, but modified according to the configuration in mx.ini. The generated files are transparent about where constraints were fetched from and comments are added when a modification was necessary.

In summary, mxdev operates on three files to tell pip which packages to install with which version. A minimal example set of files would look like the following.


-c constraints.txt


# List of add-ons that are needed.



# constraints of add-ons


# constraints of Plone packages
version-overrides =

url =
branch = master
extras = test

A run of mxdev reads requirements.txt, constraints.txt and mx.ini, and writes new combined requirements in requirements-mxdev.txt and writes new constraints in constraints-mxdev.txt according to mx.ini:

  • 'version-overrides' in section [settings]

  • checkout settings in [packagename] sections

checkout packages or define constraints

Summed up tasks and commands to checkout packages or define constraints:


  • requirements.txt

  • constraints.txt

  • mx.ini

pip install mxdev
mxdev -c mx.ini
pip install -r requirements-mxdev.txt
runwsgi instance/etc/zope.ini

So with the three files above, install and run mxdev with:

pip install mxdev
mxdev -c mx.ini

You are now ready to install your packages with pip and the new requirements file:

pip install -r requirements-mxdev.txt

Et voilà. Zope can be restarted:

runwsgi instance/etc/zope.ini


You have seen how mxdev helps with versions and checkouts. It can do a lot more for you. See mxdev for more information.

You can now continue with chapter Create a Plone instance.