<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Nginx on ma.ttias.be</title><link>https://ma.ttias.be/categories/nginx/</link><description>Recent content in Nginx on ma.ttias.be</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><managingEditor>mattias@ma.ttias.be (Mattias Geniar)</managingEditor><webMaster>mattias@ma.ttias.be (Mattias Geniar)</webMaster><lastBuildDate>Tue, 02 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://ma.ttias.be/categories/nginx/index.xml" rel="self" type="application/rss+xml"/><item><title>Serving HTTP/2 and HTTP/3 with Nginx in 2026</title><link>https://ma.ttias.be/serving-http2-http3-nginx-2026/</link><pubDate>Tue, 02 Jun 2026 00:00:00 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/serving-http2-http3-nginx-2026/</guid><description>&lt;p&gt;Back in 2016 I &lt;a href="https://ma.ttias.be/run-nginx-proxy-docker-container-http2/"&gt;wrapped nginx in a Docker container&lt;/a&gt;
just to get HTTP/2 working. Not because I love Docker, but because the server&amp;rsquo;s OpenSSL was too old to do ALPN, and the cleanest way to borrow a modern OpenSSL was to lift one out of an Alpine container. It worked, but it was a hack, and I knew it at the time.&lt;/p&gt;</description></item><item><title>Nginx: add_header not working on 404</title><link>https://ma.ttias.be/nginx-add_header-not-working-on-404/</link><pubDate>Fri, 07 Jun 2019 09:41:28 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-add_header-not-working-on-404/</guid><description>&lt;p&gt;I had the following configuration block on an Nginx proxy.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-nginx" data-lang="nginx"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;X-Robots-Tag&lt;/span&gt; &lt;span class="s"&gt;noindex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kn"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="err"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The idea was to add the &lt;code&gt;X-Robots-Tag&lt;/code&gt; header on all requests being served. However, it didn&amp;rsquo;t work for 404 hits.&lt;/p&gt;</description></item><item><title>Deploying laravel-websockets with Nginx reverse proxy and supervisord</title><link>https://ma.ttias.be/deploying-laravel-websockets-with-nginx-reverse-proxy-and-supervisord/</link><pubDate>Tue, 04 Dec 2018 22:18:57 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/deploying-laravel-websockets-with-nginx-reverse-proxy-and-supervisord/</guid><description>&lt;p&gt;There is a new PHP package available for Laravel users called &lt;a href="https://github.com/beyondcode/laravel-websockets" target="_blank" rel="noopener noreferrer"&gt;laravel-websockets&lt;/a&gt;
that allows you to quickly start a websocket server for your applications.&lt;/p&gt;</description></item><item><title>Nginx adds support for HTTP/2 Server-Side Push</title><link>https://ma.ttias.be/nginx-adds-support-http2-server-side-push/</link><pubDate>Tue, 13 Feb 2018 08:34:01 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-adds-support-http2-server-side-push/</guid><description>&lt;p&gt;Looks like they&amp;rsquo;ll be implementing it based on the &lt;code&gt;Link&lt;/code&gt; header, which should make it trivial to implement from a developer point of view.&lt;/p&gt;</description></item><item><title>cron.weekly issue #97: kernel 4.13, TLS, LLVM, Yarn, Vagrant, AWX, Nginx &amp; more</title><link>https://ma.ttias.be/cron-weekly-issue-97-kernel-4-13-tls-llvm-yarn-vagrant-awx-nginx/</link><pubDate>Mon, 11 Sep 2017 07:30:04 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/cron-weekly-issue-97-kernel-4-13-tls-llvm-yarn-vagrant-awx-nginx/</guid><description>&lt;p&gt;Quite the packed issue, I&amp;rsquo;m very happy with how this one turned out.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Welcome to cron.weekly issue #97 for Sunday, September 10th, 2017.&lt;/p&gt;</description></item><item><title>RHEL &amp; CentOS 7.4 restores HTTP/2 functionality on Nginx</title><link>https://ma.ttias.be/rhel-centos-7-4-restores-http2-functionality-nginx/</link><pubDate>Tue, 01 Aug 2017 18:01:45 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/rhel-centos-7-4-restores-http2-functionality-nginx/</guid><description>&lt;p&gt;Red Hat Enterprise Linux 7.4 &lt;a href="https://www.redhat.com/en/about/press-releases/red-hat-bridges-hybrid-multi-cloud-deployments-latest-version-red-hat-enterprise-linux-7" target="_blank" rel="noopener noreferrer"&gt;has just been released&lt;/a&gt;
, and with it, a much-awaited (at least by me) update to OpenSSL, bringing it to version 1.0.2k.&lt;/p&gt;</description></item><item><title>How to enable TLS 1.3 on Nginx</title><link>https://ma.ttias.be/enable-tls-1-3-nginx/</link><pubDate>Tue, 02 May 2017 06:45:29 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/enable-tls-1-3-nginx/</guid><description>&lt;p&gt;&lt;a href="https://nginx.org/en/CHANGES" target="_blank" rel="noopener noreferrer"&gt;Since Nginx 1.13&lt;/a&gt;
, support has been added for TLSv1.3, the latest version of the TLS protocol. Depending on when you read this post, chances are you&amp;rsquo;re running an older version of Nginx at the moment, which doesn&amp;rsquo;t yet support TLS 1.3. In that case, consider &lt;a href="https://ma.ttias.be/run-nginx-proxy-docker-container-http2/"&gt;running Nginx in a container&lt;/a&gt;
for the latest version, or compiling Nginx from source.&lt;/p&gt;</description></item><item><title>Nginx might have 33% market share, Apache isn’t falling below 50%</title><link>https://ma.ttias.be/nginx-might-33-market-share-apache-isnt-falling-50/</link><pubDate>Tue, 11 Apr 2017 19:51:41 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-might-33-market-share-apache-isnt-falling-50/</guid><description>&lt;p&gt;This is a response to a post published by W3 Techs titled &amp;ldquo;&lt;a href="https://w3techs.com/blog/entry/nginx_reaches_33_3_percent_web_server_market_share_while_apache_falls_below_50_percent" target="_blank" rel="noopener noreferrer"&gt;Nginx reaches 33.3% web server market share while Apache falls below 50%&lt;/a&gt;
&amp;rdquo;. It&amp;rsquo;s gotten &lt;a href="https://news.ycombinator.com/item?id=14078589" target="_blank" rel="noopener noreferrer"&gt;massive upvotes on Hacker News&lt;/a&gt;
, but I believe it&amp;rsquo;s a fundamentally flawed post.&lt;/p&gt;</description></item><item><title>Run Nginx proxy in Docker container for HTTP/2</title><link>https://ma.ttias.be/run-nginx-proxy-docker-container-http2/</link><pubDate>Sun, 30 Oct 2016 14:02:30 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/run-nginx-proxy-docker-container-http2/</guid><description>&lt;p&gt;This is a really quick write-up on how I&amp;rsquo;ve been running HTTP/2 on my server for the last 2 months, despite &lt;a href="https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/"&gt;having an OS that doesn&amp;rsquo;t support OpenSSL 1.0.2&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>The day Google Chrome disables HTTP/2 for nearly everyone: May 31st, 2016</title><link>https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/</link><pubDate>Sat, 14 May 2016 12:28:56 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/day-google-chrome-disables-http2-nearly-everyone-may-31st-2016/</guid><description>&lt;p&gt;If you&amp;rsquo;ve been reading this blog for a while (or have been &lt;a href="https://twitter.com/mattiasgeniar" target="_blank" rel="noopener noreferrer"&gt;reading my rants on Twitter&lt;/a&gt;
), you&amp;rsquo;ll probably know this was coming already. If you haven&amp;rsquo;t, here&amp;rsquo;s the short version.&lt;/p&gt;</description></item><item><title>Nginx 1.10 brings HTTP/2 support to the stable releases</title><link>https://ma.ttias.be/nginx-1-10-brings-http2-support-stable-releases/</link><pubDate>Tue, 26 Apr 2016 19:24:03 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-1-10-brings-http2-support-stable-releases/</guid><description>&lt;p&gt;A very small update was sent to the &lt;a href="https://marc.ttias.be/nginx-announce/2016-04/msg00002.php" target="_blank" rel="noopener noreferrer"&gt;nginx-announce&lt;/a&gt;
mailing list today. And I do mean very small:&lt;/p&gt;</description></item><item><title>nginx-1.9.13: no longer retry non-idempotent upstream requests by default</title><link>https://ma.ttias.be/nginx-1-9-13-no-longer-retry-non-idempotent-upstream-requests-default/</link><pubDate>Tue, 29 Mar 2016 17:16:10 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-1-9-13-no-longer-retry-non-idempotent-upstream-requests-default/</guid><description>&lt;p&gt;Release 1.9.13 of Nginx, just out a couple of hours ago, fixes a &lt;a href="https://trac.nginx.org/nginx/ticket/488#comment:4" target="_blank" rel="noopener noreferrer"&gt;long standing bug&lt;/a&gt;
: non-idempotent requests could be resent to another upstream, potentially causing multiple form submits, multiple deletes, &amp;hellip;&lt;/p&gt;</description></item><item><title>Nginx Proxy: upstream sent too big header while reading response header from upstream</title><link>https://ma.ttias.be/nginx-proxy-upstream-sent-big-header-reading-response-header-upstream/</link><pubDate>Fri, 11 Mar 2016 21:30:20 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-proxy-upstream-sent-big-header-reading-response-header-upstream/</guid><description>&lt;p&gt;If you&amp;rsquo;re running an Nginx proxy configuration, you can run into the following error in your logs.&lt;/p&gt;</description></item><item><title>Chrome drops NPN support for HTTP/2, ALPN only</title><link>https://ma.ttias.be/chrome-drops-npn-support-for-http2-alpn-only/</link><pubDate>Mon, 16 Nov 2015 13:11:01 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/chrome-drops-npn-support-for-http2-alpn-only/</guid><description>&lt;p&gt;&lt;strong&gt;&lt;del&gt;Update 23/11/2015: Chrome reverted the change, NPN is allowed again!&lt;/del&gt; &lt;a href="#update"&gt;More details below.&lt;/a&gt;
&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 14/02/2016: Chrome will, as of May 15th 2016, only support HTTP/2 via ALPN. NPN supported is dropped (&lt;a href="http://blog.chromium.org/2016/02/transitioning-from-spdy-to-http2.html" target="_blank" rel="noopener noreferrer"&gt;source&lt;/a&gt;
).&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Update 11/05/2015: We&amp;rsquo;re still doomed, Chrome is scheduled to release a new update on May 15th 2016 that switches from NPN to ALPN, requiring OpenSSL 1.0.2 in order to further support HTTP/2. More details below.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If this cryptic title doesn&amp;rsquo;t mean much to you, let me rephrase it in more words: Chrome is switching to the newer Application-Layer Protocol Negotiation (ALPN) extension for TLS negotiation. ALPN requires at least OpenSSL 1.0.2. Right now, Red Hat Enterprise Linux, CentOS, Ubuntu and Debian only support up to OpenSSL 1.0.1.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Basically, Chrome just made it damn near impossible to run HTTP/2 on a Linux server without some serious OpenSSL hackery.&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>Nginx: Cannot assign requested address for upstream</title><link>https://ma.ttias.be/nginx-cannot-assign-requested-address-for-upstream/</link><pubDate>Mon, 02 Nov 2015 20:42:59 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-cannot-assign-requested-address-for-upstream/</guid><description>&lt;p&gt;A few days ago, I ran into the following interesting Nginx error message.&lt;/p&gt;</description></item><item><title>Enable Keepalive connections in Nginx Upstream proxy configurations</title><link>https://ma.ttias.be/enable-keepalive-connections-in-nginx-upstream-proxy-configurations/</link><pubDate>Tue, 27 Oct 2015 20:17:00 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/enable-keepalive-connections-in-nginx-upstream-proxy-configurations/</guid><description>&lt;p&gt;A very common setup to see nowadays is to have an Nginx SSL proxy in front of a Varnish configuration, that handles all the SSL configurations while Varnish still maintains the caching abilities.&lt;/p&gt;</description></item><item><title>Enable HTTP/2 in Nginx</title><link>https://ma.ttias.be/enable-http2-in-nginx/</link><pubDate>Tue, 22 Sep 2015 18:46:10 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/enable-http2-in-nginx/</guid><description>&lt;p&gt;As of &lt;a href="http://nginx.org/en/CHANGES" target="_blank" rel="noopener noreferrer"&gt;nginx 1.9.5&lt;/a&gt;
, there is &lt;em&gt;experimental&lt;/em&gt; support for HTTP/2. This article will show you how to enable HTTP/2 support in your Nginx configuration. This can be enabled or disabled per vhost, it does not have to be enabled server-wide.&lt;/p&gt;</description></item><item><title>Nginx SSL Certificate Errors: PEM_read_bio_X509_AUX, PEM_read_bio_X509, SSL_CTX_use_PrivateKey_file</title><link>https://ma.ttias.be/nginx-ssl-certificate-errors-pem_read_bio_x509_aux-pem_read_bio_x509-ssl_ctx_use_privatekey_file/</link><pubDate>Thu, 13 Aug 2015 19:28:04 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-ssl-certificate-errors-pem_read_bio_x509_aux-pem_read_bio_x509-ssl_ctx_use_privatekey_file/</guid><description>&lt;p&gt;When configuring your SSL certificates on Nginx, it&amp;rsquo;s not uncommon to see several errors when you try to reload your Nginx configuration, to activate the SSL Certificates.&lt;/p&gt;</description></item><item><title>Increasing Nginx Performance With Thread Pooling</title><link>https://ma.ttias.be/increasing-nginx-performance-with-thread-pooling/</link><pubDate>Thu, 18 Jun 2015 20:00:18 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/increasing-nginx-performance-with-thread-pooling/</guid><description>&lt;p&gt;&lt;a href="https://www.f5.com/company/blog/nginx/thread-pools-boost-performance-9x" target="_blank" rel="noopener noreferrer"&gt;Fascinating stuff&lt;/a&gt;
.&lt;/p&gt;</description></item><item><title>Nginx Open Sources TCP Load Balancing</title><link>https://ma.ttias.be/nginx-open-sources-tcp-load-balancing/</link><pubDate>Mon, 20 Apr 2015 16:22:19 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-open-sources-tcp-load-balancing/</guid><description>&lt;p&gt;A move we can only applaud.&lt;/p&gt;</description></item><item><title>Nginx HTTP/2 Support Coming Late 2015</title><link>https://ma.ttias.be/nginx-http2-support-coming-late-2015/</link><pubDate>Tue, 14 Apr 2015 18:14:42 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-http2-support-coming-late-2015/</guid><description>&lt;p&gt;As anticipated.&lt;/p&gt;</description></item><item><title>Nginx Getting JavaScript Scripting Engine</title><link>https://ma.ttias.be/nginx-getting-javascript-scripting-engine/</link><pubDate>Tue, 14 Apr 2015 18:11:33 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-getting-javascript-scripting-engine/</guid><description>&lt;p&gt;I missed the original hint in &lt;a href="http://web.archive.org/web/20190105141026/https://www.infoworld.com/article/2838008/javascript/nginx-has-big-plans-for-javascript.html" target="_blank" rel="noopener noreferrer"&gt;October 2014&lt;/a&gt;
, so this came as a surprise to me.&lt;/p&gt;</description></item><item><title>Nginx sets HTTP 200 OK on PHP-FPM parse errors</title><link>https://ma.ttias.be/nginx-sets-http-200-ok-php-fpm-parse-errors/</link><pubDate>Mon, 19 Jan 2015 16:42:48 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/nginx-sets-http-200-ok-php-fpm-parse-errors/</guid><description>&lt;p&gt;Here&amp;rsquo;s an interesting bit of behaviour. When a PHP error occurs in a PHP-FPM pool, nginx can still reply with a HTTP 200 status code &amp;ndash; indicating everything is OK &amp;ndash; if the PHP script returns output.&lt;/p&gt;</description></item><item><title>Architecting Websites For The HTTP/2 Era</title><link>https://ma.ttias.be/architecting-websites-http2-era/</link><pubDate>Tue, 06 Jan 2015 21:07:41 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/architecting-websites-http2-era/</guid><description>&lt;p&gt;&lt;p&gt;
&lt;img src="https://ma.ttias.be/wp-content/uploads/2015/01/http2_logo-300x162.png" alt="http2_logo" width="300" height="162" loading="lazy" /&gt;
&lt;/p&gt;
&lt;/p&gt;
&lt;p&gt;The arrival of HTTP/2 will require &lt;a href="https://ma.ttias.be/undoing-years-optimisations-http2/"&gt;a bit of re-thinking how we handle websites (and webservers)&lt;/a&gt;
. This makes it a good time to reflect on what those changes can bring.&lt;/p&gt;
&lt;p&gt;This post is based entirely &lt;a href="http://http2.github.io/" target="_blank" rel="noopener noreferrer"&gt;on theory (the HTTP2 spec)&lt;/a&gt;
, as HTTP/2 is hard to test today. &lt;a href="#when"&gt;Major browsers support HTTP/2&lt;/a&gt;
, but very little servers do. And often, it&amp;rsquo;s unclear which draft of the HTTP/2 spec they &lt;em&gt;do&lt;/em&gt; support.&lt;/p&gt;
&lt;p&gt;The entire &lt;a href="https://github.com/http2/http2-spec" target="_blank" rel="noopener noreferrer"&gt;HTTP/2 Spec&lt;/a&gt;
is available for reading on Github and is highly recommended. It covers a lot more edge-cases than this article does.&lt;/p&gt;
&lt;p&gt;And if you&amp;rsquo;re up for a bit more reading, &lt;a href="http://www.w3.org/Protocols/rfc2616/rfc2616.html" target="_blank" rel="noopener noreferrer"&gt;the HTTP/1.1 spec is also worth it&lt;/a&gt;
, if only for comparisons&amp;rsquo; sake.&lt;/p&gt;</description></item><item><title>Undoing Years of Optimisations With HTTP/2</title><link>https://ma.ttias.be/undoing-years-optimisations-http2/</link><pubDate>Fri, 26 Dec 2014 08:25:53 +0000</pubDate><author>mattias@ma.ttias.be (Mattias Geniar)</author><guid>https://ma.ttias.be/undoing-years-optimisations-http2/</guid><description>&lt;p&gt;Someone just released an HTTP server &lt;a href="http://blog.kazuhooku.com/2014/12/ann-initial-release-of-h2o-and-why.html" target="_blank" rel="noopener noreferrer"&gt;called H2O, which is significantly faster than Nginx&lt;/a&gt;
(especially for small files). This in itself is an accomplishment, but the reason for this development is even more important.&lt;/p&gt;</description></item></channel></rss>