Tagged nginx

Figuring out how to serve many SSL certificates, part 2.

0

I’ve been pretty happy over the last couple days with our A+ score at SSL Labs. I almost got discouraged this morning when it was discovered that LinkedIn wasn’t able to pull in the data from our HTTPS links properly when sharing articles.

Their bot, `LinkedInBot/1.0 (compatible; Mozilla/5.0; Jakarta Commons-HttpClient/3.1 +http://www.linkedin.com)`, uses an end of life HTTP client that happens to also be Java based. One of our warnings in the handshake simulation area was that clients using Java Runtime Environment 6u45 did not support 2048 DH params, something that we were using. I’m not entirely sure if LinkedIn has their JRE updated to 6u45, but I’m guessing that anything below that has the same issue.

I generated a new 1024 bit dhparams file to solve the immediate issue and reloaded nginx without changing any other configs. LinkedIn can now ingest our HTTPS links and we still have an A+ score. :)

Figuring out how to serve many SSL certificates, part 1.

0

In the process of figuring out how to configure SSL certificates for hundreds (maybe thousands) of domains in a single nginx configuration without a wildcard certificate, I decided it would be cool to use `server_name` as a variable in the nginx configuration:

`ssl_certificate /etc/nginx/ssl/$server_name.crt;`

Unfortunately, per this aptly named request on Server Fault—nginx use $server_name on ssl_certificate path—that’s not allowed.

Nginx docs explain it more:

Variables are evaluated in the run-time during the processing of each request, so they are rather costly compared to plain static configuration.

So with that, I’m going to have to generate a bunch of `server {}` blocks that point to the correct certificate and key files before including a common config. I can’t find any examples of this yet, so I’m still wondering if there’s a better way.

Clear nginx Cache in Vagrant

20

Fooled you. You think that cache is the problem, but it’s not.

Scenario 1… You installed Vagrant with VirtualBox on your local machine and have a sweet nginx setup going as your development environment. You made a few changes to a CSS file and the new style is not reflecting on the page. You try saving the file again in your text editor, no go. You look at the file on the server, it’s cool. You restart the nginx service, still no change. You restart the services for php5-fpm and memcached, maybe even mysql… no go.

Something has captured this file in cache and is not letting go!

Scenario 2… Same setup. You made a few changes to a JS file and the script doesn’t seem to be working. Must be a caching issue. You try saving the file again, look at the file on the server, restart nginx, restart everything. Finally look at the console in your browser and see some kind of random error.

Sooner or later, with one of these files, you open it up and see these:

�����������������

What the what? It’s an encoding issue? Not a caching issue? Or it’s a… wait, what?

Hopefully you haven’t spent too much time trying to figure this out before stumbling on a site like this one that tells you the only change necessary is a simple line in your nginx config file.

sendfile off;

Find the spot in your assorted nginx config files that says ‘sendfile on’ and change it to ‘sendfile off’.

Sendfile is used to ‘copy data between one file descriptor and another‘ and apparently has some real trouble when run in a virtual machine environment, or at least when run through Virtualbox. Turning this config off in nginx causes the static file to be served via a different method and your changes will be reflected immediately and without question – or black question mark diamond thing.

Hope that saves you a minute.

For further reading, consider those that have stumbled on the same problem before.

Or, even better – more detail about sendfile itself and other common nginx pitfalls:

Are nginx, Batcache and Memcached Working?

1

So you’ve done your due diligence and gone to great lengths to make sure that your WordPress server setup is top notch.

Nginx, PHP-FPM, and Memcached are all installed and process are running. Batcache and a Memcached PECL plugin are installed for WordPress.

How do you know it’s working, besides that things seem quick?

The obvious answer is to open an incognito or private window in your browser, visit the site in question, and then view source on the page load. In the <head> area, there should be a comment left by Batcache providing statistics on when and for how long it was generated.

Batcache Comments in page source

However, the easy answer is not always the most fun answer. And not every answer tells the full story. Checking the reponse headers of the HTTP request can also fill you in on some extra info.

Batcache by default is set to only start serving cached page views if a page has been accessed more than twice in a 120 second period. It also should only be serving these cached views to unauthenticated users. Before you’ll be able to see the entire package in action, you need to load whichever page you want to test a few times as a non authenticated user, and then check the headers. If you have a command prompt with curl installed, your easiest option is this:

curl http://mydomain.com/
curl http://mydomain.com/
curl http://mydomain.com/
curl -I http://mydomain.com/
curl -I http://mydomain.com/

Do these in quick succession, ignoring the page content that you receive after the first 3 commands. Hint, hint.. use the up arrow. Feel free to ignore me too, because right now I’m hitting it after one page view, so who knows what I did.

After the fourth command, issued with the -I flag that tells curl to only make a HEAD request, your should see output indicating that Batcache has caught the request and is attempting to work some magic.

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 10 Dec 2012 06:19:30 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.3.6-13ubuntu3.9
Vary: Cookie
X-Pingback: http://mydomain.com/wordpress/xmlrpc.php
Link: <http://little.shorty/2aYLe>; rel=shortlink
Last-Modified: Mon, 10 Dec 2012 06:19:30 GMT
Cache-Control: max-age=300, must-revalidate

The last two lines in this HEAD output are key. Cache-Control has been turned on, and the max-age of the request has been set to 300 seconds. Sweet! This means that at least one thing is doing something – Batcache.

Now, the second curl request made with the -I flag gives us almost the same information:

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 10 Dec 2012 06:42:45 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Last-Modified: Mon, 10 Dec 2012 06:42:43 GMT
Cache-Control: max-age=298, must-revalidate
X-Powered-By: PHP/5.3.6-13ubuntu3.9
Vary: Cookie
X-Pingback: http://mydomain.com/wordpress/xmlrpc.php
Link: <http://little.shorty/2aYLe>; rel=shortlink

You’ll notice here that the Cache-Control line has moved up a bit and the max-age of the request has been set to 298 seconds. This means the timer on the cache expiration has started to count down. If you were to keep on making curl -I requests at this point, you could expect that timer to count all the way to 0 before the page cache was regenerated.

The ordering of the lines in these examples may not always match, but if you do this curl -I request multiple times and max-age stays at 300, this is probably an indication that while Batcache is doing what it needs to do, there is no actual caching going on in the background. At this point, check to make sure that you have an object cache plugin installed and that Memcached is in fact running.

Of course, sometimes it isn’t as easy as just making sure everything is running. Batcache and Memcached may be running fine, but if there’s a PHP Session to be maintained, then the Cache-Control header will probably not be modified and you’ll see something similar to this:

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 10 Dec 2012 06:06:33 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
Last-Modified: Mon, 10 Dec 2012 06:03:29 GMT
X-Powered-By: PHP/5.3.6-13ubuntu3.9
Vary: Cookie
Set-Cookie: PHPSESSID=dpbnobn95jrgg5fhpfaa5sn707; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
X-Pingback: http://mydomain.com/wordpress/xmlrpc.php
Link: <http://little.shorty/12345>; rel=shortlink

At this point, you’ll need to go back to relying on the comment left by Batcache in the page source to determine if it is still generating things as intended. Though it may be work a search for ‘session_start()’ through your code base to see if you really need that PHP Session, as this could be negating some of what you are hoping to achieve through caching anyway.

Oh, and if nothing is turned on at all, expect something similar to this:

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 10 Dec 2012 06:21:48 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.3.6-13ubuntu3.9
X-Pingback: http://mydomain.com/wordpress/xmlrpc.php
Link: <http://little.shorty/2aYLe>; rel=shortlink

Notice no Cache-Control header at all when Batcache is out of the picture.

All of the above is intended to be taken with a grain of salt. I didn’t research too much of it thoroughly, and a lot is dependant on my specific environment. It may come in handy to a few though, and it’ll probably come in handy to myself again.

Server Setup: nginx 1.0.5 | Memcached PECL | WordPress 3.5 | Batcache | WordPress Memcached Backend