Our multi-network multisite WordPress installation at WSU has 1022 sites spread across 342 unique domain names. We have 481 SSL certificates on the server to help secure the traffic to and from these domains. And we have 1039 unique server blocks in our nginx configuration to help route that traffic.
Configuring a site for HTTPS is often portrayed as a difficult process. This is mostly true depending on your general familiarity with server configuration and encryption.
The good thing about process is only having to figure it out a few times before you can automate it or define it in a way that makes things less difficult.
Pieces used during SSL certification
A key—get it—to understanding and defining the process of HTTPS configuration is to first understand the pieces you’re working with.
- Private Key: This should be secret and unique. It is used by the server to sign encrypted traffic that it sends.
- Public Key: This key can be distributed anywhere. It is used by clients to verify that encrypted traffic was signed by your private key.
- CSR: A Certificate Signing Request. This contains your public key and other information about you and your server. Used to request digital certification from a certificate authority.
- Certificate Authority: The issuer of SSL certificates. This authority is trusted by the server and clients to verify and sign public keys. Ideally, a certificate authority is trusted by the maximum number of clients. (i.e. all browsers)
- SSL Certificate: Also known as a digital certificate or public key certificate. This contains your public key and is signed by a certificate authority. This signature applies a level of trust to your public key to help clients when deciding its validity.
Of the files and keys generated, the most important for the final configuration are the private key and the SSL certificate. The public key can be generated at any time from the private key and the CSR is only a vessel to send that public key to a certificate signing authority.
Losing or deleting the SSL certificate means downloading the SSL certificate again. Losing or deleting the private key means restarting the process entirely.
Obtaining an SSL certificate
The first step in the process is to generate the private key for a domain and a CSR containing the corresponding public key.
openssl req -new -newkey rsa:2048 -nodes -sha256 -keyout jeremyfelt.com.key -out jeremyfelt.com.csr
This command will generate a 2048 bit RSA private key and a CSR signed with the SHA-256 hash algorithm. No public key file is generated as it is inserted directly into the CSR file.
Next, submit the CSR to a certificate signing authority. The certificate signing authority will sign the public key and return a digital certificate including the signature, your public key, and other information.
The certificate signing authority is often the part of the process that is annoying and difficult to automate.
If you’re purchasing the signature of a certificate through a certificate authority or reseller such as GoDaddy or Namecheap, the steps to purchase the initial request, submit the CSR, and download the correct certificate file can often be confusing and very time consuming.
Luckily, in WSU’s case, we have a university subscription to InCommon, a reseller of Comodo certificates. This allows us to request as many certificates as we need for one flat annual fee. It also provides a relatively straight forward web interface for requesting certificates. Similar to other resellers, we still need to wait as the request is approved by central IT and then generated by Comodo via InCommon.
Even better is the new certificate authority, Let’s Encrypt, which provides an API and a command line tool for submitting and finishing a certificate signing request immediately and for free.
Configuring the SSL certificate
This is where the process starts becoming more straight forward again. And where I’ll only focus on nginx as my familiarity with Apache disappeared years ago.
A cool thing about nginx when you’re serving HTTP requests is the flexibility of server names. It can use one server
block in the configuration to serve thousands of sites.
server { listen 80; server_name *.wsu.edu wsu.io jeremyfelt.com foo.bar; root /var/www/wordpress; }
However, when you serve HTTPS requests, you must specify which files to use for the private key and SSL certificate:
server {
listen 443 ssl http2;
server_name jeremyfelt.com;
root /var/www/wordpress;
ssl on;
ssl_certificate /etc/nginx/ssl/jeremyfelt.com.cer;
ssl_certificate_key /etc/nginx/ssl/jeremyfelt.com/key;
}
If you are creating private keys and requesting SSL certificates for individual sites as you configure them, this means having a server block for each server name.
There are three possibilities here:
- Use a wildcard certificate. This would allow for one server block for each set of subdomains. Anything at *.wsu.edu would be covered.
- Use a multi-domain certificate. This uses the SubjectAltName portion of a certificate to list multiple domains in a single certificate.
- Generate individual server blocks for each server name.
A wildcard certificate would be great if you control the domain and its subdomains. Unfortunately, at WSU, subdomains point to services all over the state. If everybody managing multiple subdomains also had a wildcard certificate to make it easier to manage HTTPS, the likelihood of that private key and certificate leaking out and becoming untrustworthy would increase.
Multi-domain certificates can be useful when you have some simple combinations like www.site.foo.bar and site.foo.bar. To redirect an HTTPS request from www to non-www, you need HTTPS configured for both. A minor issue is the size of the certificate. Every domain added to a SubjectAltName field increases the size of the certificate by the size of that domain text.
Not a big deal with a few small domains. A bigger deal with 100 large domains.
The convenience of multi-domain certificates also depends on how frequently domains are added. Any time a domain is added to a multi-domain certificate, it would need to be re-signed. If you know of several in advance, it may make sense.
If you hadn’t guessed yet, we use option 3 at WSU. Hence the 1039 unique server blocks! 🙂
From time to time we’ll request a small multi-domain certificate to handle the www to non-www redirects. But that too fits right into our process of putting the private key and certificate files in the proper place and generating a corresponding server block.
Using many server blocks in nginx for HTTPS
Private keys are generated, CSRs are submitted, SSL certificates are generated and downloaded.
Here’s what a generated server block at WSU looks like:
# BEGIN generated server block for fancy.wsu.edu # # Generated 2016-01-16 14:11:15 by jeremy.felt server { listen 80; server_name fancy.wsu.edu; return 301 https://fancy.wsu.edu$request_uri; } server { server_name fancy.wsu.edu; include /etc/nginx/wsuwp-common-header.conf; ssl_certificate /etc/nginx/ssl/fancy.wsu.edu.cer; ssl_certificate_key /etc/nginx/ssl/fancy.wsu.edu.key; include /etc/nginx/wsuwp-ssl-common.conf; include /etc/nginx/wsuwp-common.conf; } # END generated server block for fancy.wsu.edu
We listen to requests on port 80 for fancy.wsu.edu
and redirect those to HTTPS.
We listen to requests on port 443 for fancy.wsu.edu
using a common header, provide directives for the SSL certificate and private key, and include the SSL configuration common to all server blocks.
wsuwp-common-header.conf
This is the smallest configuration file, so I’ll just include it here.
listen 443 ssl http2;
root /var/www/wordpress;
Listen on 443 for SSL and HTTP2 requests and use the directory where WordPress is installed as the web root.
These directives used to be part of the generated server blocks until nginx added support for HTTP2 and immediately deprecated support for SPDY. I had to replace spdy
with http2
in all of our server blocks so instead decided to create a common config and include it.
WSU’s wsuwp-common-header.conf is open source if you’d like to use it.
wsuwp-ssl-common.conf
This is my favorite configuration file and one I often revisit. It contains all of the HTTPS specific nginx configuration.
# Enable HTTPS.
ssl on;
# Pick the allowed protocols
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# And much, much more...
This is a case where so much of the hard stuff is figured out for you. I regularly visit things like Mozilla’s intermediate set of ciphers and this boilerplate nginx configuration and then make adjustments as they make sense.
WSU’s wsuwp-ssl-common.conf is open source if you’d like to use it.
wsuwp-common.conf
And the configuration file for WordPress and other things. It’s the least interesting to talk about in this context. But! It too is open source if you’d like to use it.
The process of maintaining all of this
At the beginning I mentioned defining and automating the process as a way of making it less difficult. We haven’t yet reached full automation at WSU, but our process is now well defined.
- Generate a private key and CSR using our WSUWP TLS plugin. This provides an interface in the main network admin to type in a domain name and generate the required files. The private key stays on the server and the CSR is available to copy so that it can be submitted to InCommon.
- Submit the CSR through the InCommon web interface. Wait.
- Upon receipt of the approval email, download the SSL certificate from the embedded link.
- Upload the SSL certificate through the WSUWP TLS interface. This verifies the certificate’s domain, places it on the server alongside the private key, and generates the server block for nginx.
- Deploy the private key, SSL certificate, and generated server block file. At the moment, this process involves the command line.
- Run
nginx -t
to test the configuration andservice nginx reload
to pull it into production. - In the WSUWP TLS plugin interface, verify the domain responds on HTTPS and remove it from the list.
Looking at the steps above, it’s not hard to imagine a completely automated process, especially if your certificate authority has a way of immediately approving request and responding with a certificate. And even without automation, having this process well defined allows several members of our team to generate, request, and deploy certificates.
I’d love to know what other ways groups are approaching this. I’ve often hoped and spent plenty of time searching for easier ways. Share your thoughts, especially if you see any holes! 🙂
Previously:
Responses and reactions
Replies
[…] blocks defined for hundreds of domains that pointed to a single WordPress multisite installation. I wrote this up previously, but each of these blocks was effectively the […]
thought I'd link to this re significance of number of names per SAN, though I haven't modeled this myself (yet)...
https://serverfault.com/questions/453475/how-do-san-certs-degrade-performance
my take away from that and other sources: there should be really no significant difference for most use cases between a cert with 10 names and a cert with 50 names --> meaning, just stay under the 100 name limit because the 'limit' has been essentially standardized at 100 to limit potential for performance issues... and that was back in the day even, we got generally more bandwidth now --> so, stay under the limit especially if you have long names (as addressed above), and all will be fine :)
edit: here is this I had forgotten about which discusses a practical limit if 25 san per cert...
https://cabforum.org/pipermail/performance/2014-May/000047.html
cheers :)
Do you have any performance metrics with the increasing amount of certificates in terms of memory+cpu utilization? Does the memory footprint stays the same or does it increase in a linear way with the amount of certificates?
Background: I'm building up something similar and I would like to use nginx as an ssl-offload-proxy and forward the requests to a cluster of application servers.
Thank you in advance!
Do you know if there's a limit to the number of server blocks that nginx can handle? How many server blocks have you had at the most?
I'm particularly interested in knowing if it would scale to say 1000 domains / server blocks.
Thanks for the article by the way, very informative.
I haven't run into a limit yet. We're now above 1000 different server names and almost 700 certificate/key pairs without any trouble.
The only requirement for your mention to be recognized is a link to this post in your post's content. You can update or delete your post and then re-submit the URL in the form to update or remove your response from this page.
Learn more about Webmentions.