The following is a very opinionated way to install Plone 6 Classic
and addons.
It avoids very usefull tools like plonecli
and mxdev
. For real use I encourage to use these tools!
The purpose of this gist is to help to understand some basics.
It has been tested in a plain vanilla debian11
(Bullseye
) installation.
It also assumes a user and group map:map
. Replace both to your actual user and group.
apt
or pip
packages are installed just before they are needed/used.
sudo apt-get update
sudo apt-get install -y python3-distutils python3-dev python3-venv python3-pip
PLONE_VERSION=6.0.0b3
PLONE_HOME=/home/Plone-${PLONE_VERSION}
cd ~
sudo rm -rf ${PLONE_HOME}
sudo mkdir -p ${PLONE_HOME}
cd ${PLONE_HOME}
sudo chown map:map ${PLONE_HOME}
cd ${PLONE_HOME}
python3 -m venv ${PLONE_HOME}
${PLONE_HOME}/bin/python --version && ${PLONE_HOME}/bin/pip --version
Python 3.9.2
pip 22.3 from /home/Plone-6.0.0b3/lib/python3.9/site-packages/pip (python 3.9)
${PLONE_HOME}/bin/pip install -U pip "setuptools==65.5.0" "wheel==0.37.1"
${PLONE_HOME}/bin/pip install Plone \
-c https://dist.plone.org/release/${PLONE_VERSION}/constraints.txt
${PLONE_HOME}/bin/pip install "zope.mkzeoinstance==4.1"
cd ${PLONE_HOME}
${PLONE_HOME}/bin/mkzeoinstance ${PLONE_HOME}/parts/zeoserver localhost:8100
${PLONE_HOME}/bin/pip install "cookiecutter==2.1.1"
sudo apt-get install -y git
git config --global user.email "mail@domain.com"
git config --global user.name "map"
cd ${PLONE_HOME}/parts
cat <<'EOF' | sudo tee ${PLONE_HOME}/parts/client1.yaml
default_context:
target: 'client1'
wsgi_listen: '*:8080'
initial_user_name: 'admin'
initial_user_password: 'admin'
db_storage: 'zeo'
db_zeo_server: 'localhost:8100'
#db_filestorage_location: "filestorage/Data.fs"
db_blobs_location: "blobstorage"
EOF
${PLONE_HOME}/bin/cookiecutter -f --no-input \
--config-file ${PLONE_HOME}/parts/client1.yaml \
--checkout 1.0.0b1 \
https://github.com/plone/cookiecutter-zope-instance
sed -i \
's|CHAMELEON_CACHE client1/var/cache|CHAMELEON_CACHE '${PLONE_HOME}'/parts/client1/var/cache|' \
${PLONE_HOME}/parts/client1/etc/zope.conf
grep --color "CHAMELEON_CACHE.*client1" \
${PLONE_HOME}/parts/client1/etc/zope.conf
sed -i \
"s|r'client1|r'"${PLONE_HOME}"/parts/client1|" \
${PLONE_HOME}/parts/client1/etc/zope.ini
grep --color "/home.*client1" ${PLONE_HOME}/parts/client1/etc/zope.ini
rm -f ${PLONE_HOME}/parts/client1.yaml
cat <<'EOF' | sudo tee ${PLONE_HOME}/parts/client2.yaml
default_context:
target: 'client2'
wsgi_listen: '*:8081'
initial_user_name: 'admin'
initial_user_password: 'admin'
db_storage: 'zeo'
db_zeo_server: 'localhost:8100'
#db_filestorage_location: "filestorage/Data.fs"
db_blobs_location: "blobstorage"
EOF
${PLONE_HOME}/bin/cookiecutter -f --no-input \
--config-file ${PLONE_HOME}/parts/client2.yaml \
--checkout 1.0.0b1 \
https://github.com/plone/cookiecutter-zope-instance
sed -i \
's|CHAMELEON_CACHE client2/var/cache|CHAMELEON_CACHE '${PLONE_HOME}'/parts/client2/var/cache|' \
${PLONE_HOME}/parts/client2/etc/zope.conf
grep --color "CHAMELEON_CACHE.*client2" \
${PLONE_HOME}/parts/client2/etc/zope.conf
sed -i \
"s|r'client2|r'"${PLONE_HOME}"/parts/client2|" \
${PLONE_HOME}/parts/client2/etc/zope.ini
grep --color "/home.*client2" ${PLONE_HOME}/parts/client2/etc/zope.ini
rm -f ${PLONE_HOME}/parts/client2.yaml
${PLONE_HOME}/bin/pip install "mr.bob==1.0.0"
${PLONE_HOME}/bin/pip install "bobtemplates.plone==6.1"
sudo apt-get install -y tox isort
mkdir -p ${PLONE_HOME}/src
rm -rf ${PLONE_HOME}/src/myaddon.name
cd ${PLONE_HOME}/src
cat <<EOF > ${PLONE_HOME}/src/myvariables.ini
[variables]
author.name = theAuthor
author.email = mail@domain.com
author.github.user = GitHubUsername
package.description = An add-on for Plone
package.git.init = True
package.git.autocommit: True
plone.version = 6
python.version = python3.9
vscode_support = False
EOF
${PLONE_HOME}/bin/mrbob \
--config ${PLONE_HOME}/src/myvariables.ini \
-O ${PLONE_HOME}/src/myaddon.name \
bobtemplates.plone:addon
${PLONE_HOME}/bin/pip install -e ${PLONE_HOME}/src/myaddon.name
cd ${PLONE_HOME}
${PLONE_HOME}/parts/zeoserver/bin/zeoctl start
Be careful! This deletes an existing 'Plone' Site!
cat <<'EOF' | tee create_plone_site.py
from Zope2.Startup.run import make_wsgi_app
global_config = { 'debug_mode': 'true', 'debug_exceptions': 'false' }
zope_conf = "parts/client2/etc/zope.conf"
print("make_wsgi_app(%s, %s)" % (global_config, zope_conf))
_ = make_wsgi_app(global_config, zope_conf)
import Zope2
app = Zope2.app()
app._p_jar.sync()
from Testing.makerequest import makerequest
app = makerequest(app)
from AccessControl.SecurityManagement import newSecurityManager, noSecurityManager
admin_username='admin'
acl_users = app.acl_users
user = acl_users.getUser(admin_username)
user = user.__of__(acl_users)
newSecurityManager(None,user)
from Products.CMFPlone.factory import addPloneSite
plone_site_name = 'Plone'
if app.hasObject(plone_site_name):
app.manage_delObjects(plone_site_name)
print("Deleted existing '%s'" % plone_site_name)
plone_site = addPloneSite(
app, plone_site_name,
title='MyPloneSite',
description='',
extension_ids=('plonetheme.barceloneta:default', 'plone.app.caching:default'),
setup_content=True,
default_language='de',
portal_timezone='Europe/Berlin')
import transaction
transaction.commit()
print("Created '%s'" % plone_site)
EOF
${PLONE_HOME}/bin/python3 create_plone_site.py
cat <<EOF | sudo tee ${PLONE_HOME}/client1.service
[Unit]
Description=Zope client client1
After=network.target
[Service]
User=map
WorkingDirectory=${PLONE_HOME}
ExecStart=${PLONE_HOME}/bin/runwsgi -v ${PLONE_HOME}/parts/client1/etc/zope.ini
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo rm -f /etc/systemd/system/client1.service
sudo ln -s ${PLONE_HOME}/client1.service /etc/systemd/system/client1.service
cat <<EOF | sudo tee ${PLONE_HOME}/client2.service
[Unit]
Description=Zope client client2
After=network.target
[Service]
User=map
WorkingDirectory=${PLONE_HOME}
ExecStart=${PLONE_HOME}/bin/runwsgi -v ${PLONE_HOME}/parts/client2/etc/zope.ini
Restart=always
[Install]
WantedBy=multi-user.target
EOF
sudo rm -f /etc/systemd/system/client2.service
sudo ln -s ${PLONE_HOME}/client2.service /etc/systemd/system/client2.service
sudo systemctl daemon-reload
#${PLONE_HOME}/parts/zeoserver/bin/zeoctl start
sudo systemctl start client1
sudo apt-get install -y curl
curl -s -i \
-X GET http://localhost:8080/Plone/@addons/myaddon.name \
-H "Accept: application/json" \
--user admin:admin \
| grep -C 10 --color "\"is_installed.*"
curl -s -i \
-X POST http://localhost:8080/Plone/@addons/myaddon.name/install \
-H "Accept: application/json" \
--user admin:admin
curl -s -i \
-X GET http://localhost:8080/Plone/@addons/myaddon.name \
-H "Accept: application/json" \
--user admin:admin \
| grep -C 10 --color "\"is_installed.*"
sudo systemctl stop client1
${PLONE_HOME}/parts/zeoserver/bin/zeoctl stop