Skip to content. | Skip to navigation

Personal tools
Log in
You are here: Home

Latest Plone Posts

Building a Self Hosted CMS Site using Webflow and Plone (Video Series)

By David Bain ( from Planet Plone. Published on Nov 26, 2015.

One of my personal goals is to make it easier for persons to get started with web development technologies. I teach web programming at my local university, I blog about my preferred CMS (Plone). For front-end development I now point designers at Webflow. In line with that I've recently created a video series that shows how to use Plone as your CMS and Webflow for theme development. Last

Python virtualenvs: Inside project or outside?

By Paul Everitt from Planet Plone. Published on Nov 25, 2015.

I’m a dummy. I pulled the old “pretend to ask an honest question but really to confirm your belief” trick and, shockingly-not, got refuted. My small sample seems to like making their Python virtual environments outside of their projects. Background I do a lot of Python explaining (Py-splaining?) and, contrary to the “see how much […]

Security vulnerability pre-announcement: 20151208

From Planet Plone. Published on Nov 24, 2015.

Hotfix to patch various vulnerabilities

My O’Reilly video series on Pyramid is up

By Paul Everitt from Planet Plone. Published on Nov 24, 2015.

Earlier this year, just before PyCon, I talked to O’Reilly about doing a Pyramid video course in their commercial training catalog. It’s now in “early access”, titled “Web Applications with Python and the Pyramid Framework“. What an effort it turned out to be. I’m certainly grateful that it has wrapped up, but I’m also glad […]

Fixing SSL certificate chains

By Reinout van Rees from Planet Plone. Published on Nov 23, 2015.

This blog post applies when the following two cases are true:

  • Your browser does not complain about your https site. Everything seems fine.
  • Some other tool does complain about not finding your certificate or not finding intermediate certificates. What is the problem?

So: your browser doesn't complain. Let's see a screenshot:

Browser address bar with a nice green closed lock, so ssl is fine

Examples of the errors you can see

Some examples of complaining tools. First curl:

$ curl https://api.letsgxxxxxxx
curl: (60) SSL certificate problem: Invalid certificate chain
More details here:

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

curl has the right error message: Invalid certificate chain.

Let us look at wget:

$ wget https://api.letsgxxxxxx
--2015-11-23 10:54:28--  https://api.letsgxxxxx
Resolving api.letsgxxxxxx...
Connecting to api.letsgxxxxxx||:443... connected.
ERROR: cannot verify api.letsgxxxxxx's certificate, issued by 'CN=COMODO RSA
  Domain Validation Secure Server CA,O=COMODO CA Limited,L=Salford,ST=Greater Manchester,C=GB':
  Self-signed certificate encountered.
To connect to api.letsgxxxxxx insecurely, use `--no-check-certificate'.

wget is right that it cannot verify .... certificate. But its conclusion Self-signed certificate encountered is less helpful. The certificate is not self-signed, it is just that wget has to treat it that way because the certificate chain is incorrect.

If you talk to such an https URL with java, you can see an error like this:
PKIX path building failed:
unable to find valid certification path to requested target

This looks quite cryptic, but the cause is the same. SunCertPathBuilderException: CertPath sure sounds like a path to a certificate that it cannot find.

A final example is with the python requests library:

>>> import requests
>>> requests.get('https://api.letsgxxxxxx')
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/requests/", line 69, in get
    return request('get', url, params=params, **kwargs)
  File ".../requests/", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File ".../requests/", line 465, in request
    resp = self.send(prep, **send_kwargs)
  File ".../requests/", line 573, in send
    r = adapter.send(request, **kwargs)
  File ".../requests/", line 431, in send
    raise SSLError(e, request=request)
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)

How to determine what's wrong

So... you yourself discover the problem. Or a customer calls that he's getting an error like this. Even though everything seems right if you test the https site in the browser.

Solution: go to

If that site says everything is completely right, then you're done. If it still complains about something, you've got work to do.

Most of the checkmarks are probably green:

Green checkmarks in front of many common SSL checks

In cases like this, the problem is in the certificate chain at the bottom of the page. Here's an example of one of our own sites from a few months ago:

Broken chain icon indicating the exact problem spot

Note the "broken chain" icon halfway. Just follow the chain from top to bottom. Everything has to be perfect. We start with the * which is issued by GeoTrust SSL CA - G2.

The certificate GeoTrust SSL CA - G2 in turn is issued by GeoTrust Global CA.

The problem: the next certificate in the chain is not about GeoTrust Global CA, but about GeoTrust SSL CA, which is different. Here the chain breaks. It does not matter that the fourth certificate is about the GeoTrust Global CA we were looking for. The chain is broken. The order in which the certificates are placed must be perfect.

After fixing the order of the certificates in our certificate file, the problem was fixed:

Chain icons indicating that the chain is unbroken

Why is a chain needed?

There are lots of certificates in the wild. All the browsers (and java, and your OS and...) often only store a handful (well, 20+) "root certificates". All the other certificates have to trace their origin back to one of those root certificates.

That is where the intermediate certificates come in: they're a cryptographically signed way to trace the validity of your certificate back to one of the known-good root certificates.

How to fix it

  • If you're handling certificates yourself, you ought to know which files to edit. The main problem will be getting the right intermediary certificates from the issuing party. Often you only get "your" certificate, not the intermediary ones. Ask about it or google for it.

  • Often you won't maintain those certificates yourself. So you have to get your hosting service to fix it.

    If you let someone else take care of the certificate, point them at and tell them to make sure that page is completely happy.

    In my experience (=three times in the last two years!) they'll mail back with "everything works now". But it still won't work. Then you'll have to mail them again and tell them to really check and probably provide screenshots.

Good luck!

robot testing error "Non-existing setting"

From Planet Plone. Published on Nov 19, 2015.

"Test case name cannot be empty."

Plone Conference Boston 2016

From Planet Plone. Published on Nov 19, 2015.

Boston, Massachusetts, USA, October 17-23, 2016

2015-2016 Foundation Membership Committee

From Planet Plone. Published on Nov 19, 2015.

welcome new members on the committee reviewing applications for Plone Foundation membership

Nginx proxying to nginx: getting gzip compression to work

By Reinout van Rees from Planet Plone. Published on Nov 19, 2015.

At work we use gunicorn as our wsgi runner. Like many, gunicorn advises you to run the nginx webserver in front of it. So on every server we have one or more websites with gunicorn. And an nginx in front.

Nginx takes care, of course, of serving the static files like css and javascript. Some gzipping of the results is a very, very good idea:

server {
    listen 80;
    gzip on;
    gzip_proxied any;


Two notes:

  • The default is to only gzip html output. We also want javascript and json. So you need to configure gzip_types.

    (I copy-pasted this from one of my config files, apparently I needed three different javascript mimetypes... Perhaps some further research could strip that number down.)

  • gzip_proxied any tells nginx that gzipping is fine even for proxied requests.

Proxied requests? Yes, because we have a lot of servers and all external traffic first hits our main nginx proxy. So: we have one central server with nginx that proxies requests to the actual servers. So: nginx behind nginx:

server {
    listen   443;
    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://some-internal-server-name/;
    ssl on;
    ssl_certificate ...

Pretty standard "I listen on 443/https and proxy it on port 80 to some internal server" setup.

Works like a charm. Only drawback: gzipping does not work.

The reason? nginx defaults, in this case.

  • The gzip module has a gzip_http_version configuration parameter with a default of 1.1.

    Which means that http 1.0 requests are not gzipped, only 1.1.

  • The proxy module has a proxy_http_version configuration parameter with a default of 1.0.

    Which means that proxied requests are send from the main proxy to the actual webserver with http 1.0.

These two don't match. There are two solutions:

  • Set gzip_http_version 1.0 in the nginx configs on your webservers. This switches on gzip for the http 1.0 connections coming from the proxy.
  • Set proxy_http_version 1.1 on the main proxy so that it sends http 1.1 connections to the webservers.

My choice originally was to do the first one. But a bug report came in for another site and now I've switched it on on the main proxy so that all the sites get the benefit.

Note: you might want to make different choices. Perhaps you have a caching proxy halfway? Perhaps you want the main nginx on the proxy to do the gzipping for you? Etcetera. Check whether the above tips apply to your situation :-)

Plone Comes to Beantown

By Sally Kleinfeldt from Planet Plone. Published on Nov 18, 2015.

I’m excited to share the news that the 2016 Plone Conference will be right here in Boston! Save the dates October 17-23 for a solid week of excellent training, informative talks, inspiring keynotes, and productive sprints like we’ve come to expect from a Plone conference – all for one reasonable (not yet finalized) price. The […]

PyRVA meet up and type hinting

By Paul Everitt from Planet Plone. Published on Nov 18, 2015.

Python’s community has long been considered as valuable as the software, and that extends to Python local meetups. They’re fun to attend, but what’s even more fun is watching one during its formation. Last week I attended the second PyRVA meet up in Richmond, VA and talked about Python 3.5 type hinting in PyCharm. The user group is founded […]

Buildout 2.5.0 has much nicer version conflict reporting

By Reinout van Rees from Planet Plone. Published on Nov 16, 2015.

We use buildout for all our django projects. Nothing wrong with pip, but buildout has extension possibilities build-in (for creating directories, installing user crontabs, local development checkouts and many more) that are quite helpful. And it works better when you need to use system packages (gdal, mapnik, etc).

One area where buildout could use some improvement was the version conflict reporting. Let's say you have pinned django to 1.6.6 (old project that I'll upgrade to 1.8 this week) and you add the django debug toolbar. This is the error you get:

The constraint, 1.6.6, is not consistent with the requirement, 'Django>=1.7'.
  Updating django.
Error: Bad constraint 1.6.6 Django>=1.7

First things first. An easy one is to improve the wording of the message:

  Installing django.
Error: The requirement ('Django>=1.7') is not allowed by
your [versions] constraint (1.6.6)

Now... so there is some package that requires at least django 1.7. But which one? Buildout did not tell you. Which would mean you'd have to grep in all your requirements' sub-requirements for which package actually requires the offending "django>=1.7"...

I've now added some internal logging that stores which package required which dependency. After an error occurs, the list is searched for possible matches.

With this change you'll get a much more helpful output right before the error:

Installing django.
version and requirements information containing django:
  [versions] constraint on django: 1.6.6
  Base installation request: 'sso', 'djangorecipe'
  Requirement of djangorecipe==1.10: Django
  Requirement of djangorecipe==1.10: zc.recipe.egg
  Requirement of djangorecipe==1.10: zc.buildout
  Requirement of sso: django-nose
  Requirement of sso: django-mama-cas
  Requirement of sso: django-debug-toolbar
  Requirement of sso: django-auth-ldap
  Requirement of sso: Django<1.7,>=1.4.2
  Requirement of lizard-auth-server: django-nose
  Requirement of lizard-auth-server: django-extensions
  Requirement of lizard-auth-server: Django<1.7,>=1.6
  Requirement of django-nose: Django>=1.2
  Requirement of django-nose: nose>=1.2.1
  Requirement of django-mama-cas: requests==1.1.0
  Requirement of django-debug-toolbar: sqlparse
  Requirement of django-debug-toolbar: Django>=1.7
  Requirement of django-auth-ldap: python-ldap>=2.0
  Requirement of django-auth-ldap: django>=1.1
  Requirement of translations: Django>=1.4
  Requirement of django-extensions: six>=1.2
  Installing django.
Error: The requirement ('Django>=1.7') is not allowed by
your [versions] constraint (1.6.6)

This makes it much easier to spot the cause (in this case django-debug-toolbar).

There are some unrelated packages in here because I'm doing a textual comparison. The advantage is that it is very robust. And extracting the right package name from requirements without messing things up is harder to get right and takes more code.

So... if you use buildout, give version 2.5.0 a try!

New Website, New Plone

By Sally Kleinfeldt from Planet Plone. Published on Nov 13, 2015.

Like the cobbler’s children who have no shoes, Jazkarta’s website was long overdue for some major work. We began working on a redesign last winter – some modest improvements that morphed into more major changes. When we were ready to move into development in the spring, the Plone 5 release was in beta, so we […]

Dutch Plone user day

By Maurits van Rees from Planet Plone. Published on Nov 10, 2015.

This year my employer Zest Software organised the Dutch Plone user day in Rotterdam. Thank you to Jean-Paul and Fred for the organisation. Special thank you to Coen for translating the Plone posters to Dutch.

If you can read Dutch, head over to the Dutch version of this page for Jean-Paul's welcoming remarks and links to Dutch summaries of the talks.