Working with Cookieplone what's the right way to support www and the naked domain?
This is a continuation from this conversation:
Working with Cookieplone what's the right way to support www and the naked domain in the Traefik setup with varnish?
I had the issue with my recent setup from 2025 and newer Cookieplone devops templates.
Prerequisites
A DNS Setup pointing at the IP of the server both from naked domain example.com and subdomain www.example.com
A Cookieplone devops setup using Cookieplone (1.0.0) and cookieplone-templates (1ee1cfe) or later using the devops option with Traefik with the following default setup in devops/stacks/project-title.example.com.yml Only traefik part, rest omitted.
It worked for me with a project setup created by Cookieplone 0.9.7 and cookieplone-templates (83b50c6).
---
version: '3.8'
services:
traefik:
image: traefik:v2.11
ports:
- 80:80
- 443:443
deploy:
replicas: 1
update_config:
parallelism: 1
delay: 5s
order: start-first
labels:
- traefik.enable=true
- traefik.constraint-label=public
- traefik.http.services.traefik-public.loadbalancer.server.port=8000
## Basic Authentication
### Note: all dollar signs in the hash need to be doubled for escaping.
### To create user:password pair, it's possible to use this command:
### echo $(htpasswd -nb user password) | sed -e s/\\$/\\$\\$/g
### Defaults to admin:admin
#- traefik.http.middlewares.admin-auth.basicauth.users=admin:$$apr1$$uZPT5Fgu$$AmlIdamxT5ipBvPlsdfD70
#- traefik.http.routers.traefik-public-https.rule=Host(`traefik-project-dummy.example.com`)
#- traefik.http.routers.traefik-public-https.entrypoints=https
#- traefik.http.routers.traefik-public-https.tls=true
#- traefik.http.routers.traefik-public-https.service=api@internal
#- traefik.http.routers.traefik-public-https.middlewares=admin-auth
# GENERIC MIDDLEWARES
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
- traefik.http.middlewares.https-redirect.redirectscheme.permanent=true
- traefik.http.middlewares.gzip.compress=true
- traefik.http.middlewares.gzip.compress.excludedcontenttypes=image/png, image/jpeg, font/woff2
# GENERIC ROUTERS
- traefik.http.routers.generic-https-redirect.entrypoints=http
- traefik.http.routers.generic-https-redirect.rule=HostRegexp(`{host:.*}`)
- traefik.http.routers.generic-https-redirect.priority=1
- traefik.http.routers.generic-https-redirect.middlewares=https-redirect
# acsr note: additions goes here below
volumes:
# unchanged below
...
I ran into issues when using approaches published elsewhere here (mentioned above) when the letsencrypt certificates were not in effect, when the www prefix was hit on http and a certificate warning blocked the further redirection process.
Solution is resort the stuff and use a different order.
additions to the stacks/*.yml going into the labels just below the existing stuff (as marked above in the example)![]()
# GENERIC MIDDLEWARES ✅ keep as-is
...
# GENERIC ROUTERS ✅ keep as-is
...
# Explicit www router → forces cert provisioning at startup
- traefik.http.routers.wwwsecure-explicit.rule=Host(`www.example.com`)
- traefik.http.routers.wwwsecure-explicit.entrypoints=https
- traefik.http.routers.wwwsecure-explicit.tls=true
- traefik.http.routers.wwwsecure-explicit.tls.certresolver=le
- traefik.http.routers.wwwsecure-explicit.middlewares=wwwtohttps
- traefik.http.routers.wwwsecure-explicit.service=svc-varnish
- traefik.http.routers.wwwsecure-explicit.priority=10
# HostRegexp catchall as fallback
- traefik.http.routers.wwwsecure-catchall.rule=HostRegexp(`{host:(www\.).+}`)
- traefik.http.routers.wwwsecure-catchall.entrypoints=https
- traefik.http.routers.wwwsecure-catchall.tls=true
- traefik.http.routers.wwwsecure-catchall.tls.certresolver=le
- traefik.http.routers.wwwsecure-catchall.middlewares=wwwtohttps
- traefik.http.routers.wwwsecure-catchall.service=svc-varnish
- traefik.http.routers.wwwsecure-catchall.priority=5
# Strip www and redirect to naked domain
- traefik.http.middlewares.wwwtohttps.redirectregex.regex=^https?://(?:www\.)?(.+)
- traefik.http.middlewares.wwwtohttps.redirectregex.replacement=https://$${1}
- traefik.http.middlewares.wwwtohttps.redirectregex.permanent=true
# Or if you prefer www as the canonical (naked → www), flip the regex:
# - traefik.http.middlewares.trim_www.redirectregex.regex=^https://(?!www\.)(.+)
# - traefik.http.middlewares.trim_www.redirectregex.replacement=https://www.$${1}
# - traefik.http.middlewares.trim_www.redirectregex.permanent=true
IMPORTANT: Make sure the DNS A-Record (or CNAME) for the secondary domain
www.example.comis in place during deployment, or the fetching of the letsencrypt cert will fail!
Note: The commented out section for the other order is a suggestion and was not tested in production
When confirmed by a second party, this should go into the cookieplone templates as options or at least into the docs. It worked for me.
Warning: NOT tested for possible inefficiencies in the routing and redirection. I needed just something that worked NOW.
Notes on where to put this kind of experience, forum, chats, tickets or a discussion area on github, where the template code lives.
The Traefik config tweak was done by me in the already generated stack config for testing.
Actually you may need to integrate that into newly generated stacks (e.g. for staging) manually until this is supported by the cookieplone template itself.
Having those options managed by the template is convenient but adds complexity to the general setup that has to be maintained.
So having it here, possibly as a hint in the docs with an example in the Readme would be enough for now.
@ericof what do you think?
Suggestion: Use Discussions on Github to share experience with cookieplone.
Having this challenge to share experience with templates is quite common, and it is hard to fix again and again on your own when the forum is too unspecific.
I learned that opening a discussion area on github with userland examples (provided not as tickets) can lower the noise and leaves the responsibility to the contributors, that even need no Contributor Agreement signed.
A drawback ist that experience is bloated elsewhere like with stackoverflow.
But too user specific examples are not well enough matured to live in the docs.
An example is the Zotero Actions & Tags plugin, that uses userscripts (like greasemonkey) to add functionalities. The author leaves the creativity to the users and they use the discussion area on github for that.
In the description of the discussion area an Announcement link goes to adocument that showcases the process:
You can handle the www alias outside the Plone installation. It is another site, another config, it just redirect to the non www. site, acquiring a certificate by its own. See it as another docker container that have a traefik config read by Docker.
@yurj Good point, this is why I discuss it here before suggesting it as a general solution. But it is worth a discussion where it should live in the setup. You need another certificate in both cases.
When comparing the approaches, load / resources on the host for having another container and time to restart etc. are worth to consider. Especially when dealing with subdomains for PloneAppMultiligual per language etc.
No idea what are the other requirements in the field for these setups.
But it would be worth sharing those examples without bloating the basic setup template.
@jensens was talking about a more dense setup he uses with one Traefik managing a lot of VHosts on a cluster of different Plone Sites during the last Alpine Sprint. His is not Cookieplone based.