{"version":"https://jsonfeed.org/version/1.1","title":"Vic Demuzere - NGINX","home_page_url":"https://vic.demuzere.be/articles/tags/nginx/","feed_url":"https://vic.demuzere.be/articles/tags/nginx/feed.json","description":"Blog posts tagged NGINX by Vic Demuzere","language":"en","items":[{"id":"https://vic.demuzere.be/articles/nginx-outdated-content-being-served/","content_html":"<p>While updating one of my websites I noticed that a CSS file wasn't being updated.</p>\n<p>As I'm using Cloudflare to cache my website my first guess was that the cache on their side wasn't being cleared.\nPushed the clear cache button multiple times without any effect. It's clearly broken!\nA direct request to my webserver cleared any blame on Cloudflare though: my server was <strong>replying with an old version</strong> of my CSS file.</p>\n<p>Then it must be rsync! I'm using rsync to push the new versions of my website from my development machine to the server.\nA few retries later the funny looking webpages suggested the CSS was still wrong.\nChecking the file on my server confirmed that <strong>rsync had actually replaced the CSS</strong>, retrying the upload was useless.</p>\n<p>Why was nginx still serving the old CSS? Turns out it was my configuration.</p>\n<h2 id=\"sendfile\">Sendfile<a href=\"#sendfile\" aria-label=\"Link to heading 'Sendfile'\" data-heading-content=\"Sendfile\" class=\"anchor\"></a></h2>\n<p>As recommended by most optimization guides my nginx configuration allows using sendfile.\nThis option is especially useful for static websites like mine, as every single page can be served right from the filesystem.</p>\n<pre><code>http {\n  sendfile on;\n  tcp_nopush on;\n}\n</code></pre>\n<p>But what does it do exactly?</p>\n<p>The nginx documentation <a href=\"https://nginx.org/en/docs/http/ngx_http_core_module.html#sendfile\" title=\"documentation on the sendfile nginx configuration option\">explains the <code>sendfile</code> option</a> as:</p>\n<blockquote>\n<p>Enables or disables the use of sendfile().</p>\n</blockquote>\n<p>That's exactly what I would expect from a boolean option!\nSendfile is actually a Linux system call executed by nginx, for more information we have to resort to the man pages.</p>\n<blockquote>\n<p>sendfile() copies data between one file descriptor and another.\nBecause this copying is done within the kernel, sendfile() is more\nefficient than the combination of read(2) and write(2), which would\nrequire transferring data to and from user space.</p>\n</blockquote>\n<p>So basically nginx just asks the kernel to copy the contents of a file to the connection with the visitor's browser.\nThis makes serving static files a lot faster, as it eliminates the step where nginx copies the file into its own buffers. Yay!</p>\n<h2 id=\"open-file-cache\">Open file cache<a href=\"#open-file-cache\" aria-label=\"Link to heading 'Open file cache'\" data-heading-content=\"Open file cache\" class=\"anchor\"></a></h2>\n<p>Another optimization I've been using is the <code>open_file_cache</code> options:</p>\n<pre><code>http {\n  open_file_cache max=1000 inactive=20s;\n  open_file_cache_errors on;\n  open_file_cache_min_uses 2;\n  open_file_cache_valid 30s;\n}\n</code></pre>\n<p>When we turn to the nginx documentation again, what we should know about <a href=\"https://nginx.org/en/docs/http/ngx_http_core_module.html#open_file_cache\" title=\"documentation on the open_file_cache nginx configuration option\">the open file cache</a> is that it contains information about files being served from the filesystem:</p>\n<ul>\n<li>open file descriptors, their sizes and modification times</li>\n<li>information on existence of directories</li>\n<li>file lookup errors</li>\n</ul>\n<p>This cache is quite useful as the modification time allows nginx to reply to <code>If-Modified-Since</code> requests without actually opening the file.\nAnother situation that happens quite frequently is a non-existing file being requested multiple times.\nThe best known example is the <code>favicon.ico</code> that most browsers request whenever you visit a website.\nAs nginx already knows that the file is not actually there, it can simply reply with a 404 response right away.</p>\n<p>Great, huh?</p>\n<p>Remember how <code>sendfile</code> copies data <em>from one file descriptor to another</em>?\nIf the file on disk was replaced (not just modified) then this causes nginx to <strong>keep sending data from the old file</strong> instead of the new one.\nThis can be very confusing if you also have a web cache (Varnish, or a service like Cloudflare for example) as you'll be blaming the cache first.</p>\n<p>Looks like there is no way to clear the open file cache.\nAs I don't want to restart nginx every time I update my website I have modified my configuration to no longer cache files for 30s.</p>\n<h2 id=\"rsync\">Rsync<a href=\"#rsync\" aria-label=\"Link to heading 'Rsync'\" data-heading-content=\"Rsync\" class=\"anchor\"></a></h2>\n<p>As an extra: rsync <a href=\"https://rsync.samba.org/how-rsync-works.html\" title=\"rsync documentation\">is the reason why my files were replaced</a>.</p>\n<blockquote>\n<p>After the temp-file has been completed, its ownership and permissions and modification time are set. It is then renamed to replace the basis file.</p>\n</blockquote>\n<p>This means the existing file is not modified. It is actually replaced by a new file, to make sure we don't end up with only half of the contents in case transfer fails.</p>\n<div class=\"footer\"><hr><p>Thanks for subscribing to my feed!</p><p>Feel free to e-mail comments or corrections to <a href=\"mailto:vic@demuzere.be?subject=RE%3A%20Outdated%20files%20being%20served%20by%20nginx\">vic@demuzere.be</a>.</p></div>","url":"https://vic.demuzere.be/articles/nginx-outdated-content-being-served/","date_published":"2019-12-05T15:35:00Z","date_modified":"2023-11-28T19:55:32Z","language":"en"},{"id":"https://vic.demuzere.be/articles/combining-traditional-configuration-management-with-docker/","content_html":"<p>Configuration management systems like Ansible, Chef, Salt and Puppet are the <em>traditional</em> and proven way to automate server management.\nUsing a tool like one of these has a lot of benefits over manual configuration: Setting up a new server (for new projects or to replace a broken server) can be performed faster and more accurately than we could do manually.\nIt also makes sure that servers and individual services are configured exactly the same when you're doing it multiple times.\nNo doubt about the benefits of configuration management systems.</p>\n<h2 id=\"hello-docker\">Hello Docker!<a href=\"#hello-docker\" aria-label=\"Link to heading 'Hello Docker!'\" data-heading-content=\"Hello Docker!\" class=\"anchor\"></a></h2>\n<p>Then Docker came and brought a new way to manage services.\nWith the <strong>Dockerfile</strong> it introduced a standardized way to describe exactly what should be running inside a container.\nWhile containers were nothing new, the easy to use of the Docker toolchain changed everything.</p>\n<p>If you're just managing a few servers and are not planning to scale using Kubernetes or similar orchestration tools, <strong>using docker can make managing your services harder</strong>.\nKeeping containers up to date means you have to manage another package manager and configuration depends on whatever the image maintainer decided to add to the image.\nHaving a bit more flexibility in the software you're running is awesome, though!\nThat's why I decided to <strong>combine services running inside Docker containers with traditional configuration management</strong>.</p>\n<h2 id=\"hybrid-configuration\">Hybrid configuration<a href=\"#hybrid-configuration\" aria-label=\"Link to heading 'Hybrid configuration'\" data-heading-content=\"Hybrid configuration\" class=\"anchor\"></a></h2>\n<p>Since I want to use my existing Ansible code to manage nginx and its configuration, I need to be able to:</p>\n<ul>\n<li>Start, stop and reload my nginx service using systemd</li>\n<li>Configure nginx in <code>/etc/nginx</code></li>\n<li>View and cycle logs in <code>/var/log/nginx</code></li>\n<li>Connect to local services outside the container (<code>php-fpm</code>, Go webservices, ..)</li>\n<li>Publish websites with document roots in <code>/var/www</code></li>\n</ul>\n<p>But I also want features that I can't get on my standard debian system like TLS 1.3 and brotli compression.</p>\n<h2 id=\"managing-a-containerized-nginx-service-with-systemd\">Managing a containerized nginx service with systemd<a href=\"#managing-a-containerized-nginx-service-with-systemd\" aria-label=\"Link to heading 'Managing a containerized nginx service with systemd'\" data-heading-content=\"Managing a containerized nginx service with systemd\" class=\"anchor\"></a></h2>\n<p>First step was to create an <a href=\"https://hub.docker.com/r/sorcix/nginx/\">nginx docker image</a> with support for everything I want.\nThe systemd unit below takes care of downloading and starting the container on my server.\nVolumes are mounted on every important path listed above to make sure I can configure everything as if the nginx service was installed using the default Debian package.</p>\n<pre><code>[Unit]\nDescription=Nginx\nAfter=docker.service\nRequires=docker.service\n\n[Service]\nTimeoutStartSec=0\nRestart=always\nExecStartPre=/usr/bin/docker pull sorcix/nginx:latest\nExecStart=/usr/bin/docker run --net=host --name nginx --rm -v /etc/nginx:/etc/nginx:ro -v /var/log/nginx:/var/log/nginx:rw -v /etc/ssl:/etc/ssl:ro -v /var/www:/var/www sorcix/nginx:latest\nExecReload=/usr/bin/docker exec nginx nginx -s reload\nExecStop=/usr/bin/docker exec nginx nginx -s quit\n\n[Install]\nWantedBy=multi-user.target\n</code></pre>\n<h3 id=\"networking--security\">Networking &amp; security<a href=\"#networking--security\" aria-label=\"Link to heading 'Networking &amp; security'\" data-heading-content=\"Networking &amp; security\" class=\"anchor\"></a></h3>\n<p>The <code>--net=host</code> part makes the container use host networking instead of the separate docker network that is usually created for containers.\nForwarding ports 80 and 443 is not required (which actually makes traffic handling a little faster) and we can connect to services running on the host.\nNote that this also means that the additional security that containers usually provide is now missing.\nThat's fine with me as I'm using this as a drop in replacement for the default Debian nginx package which does not provide containerization at all.</p>\n<h3 id=\"updates\">Updates<a href=\"#updates\" aria-label=\"Link to heading 'Updates'\" data-heading-content=\"Updates\" class=\"anchor\"></a></h3>\n<p>The <code>ExecStartPre</code> command downloads new versions of the <code>sorcix/nginx</code> container every time I restart nginx.\nAs I manage the container image myself this isn't really an issue, but you should disable this when using images created by others.</p>\n<div class=\"footer\"><hr><p>Thanks for subscribing to my feed!</p><p>Feel free to e-mail comments or corrections to <a href=\"mailto:vic@demuzere.be?subject=RE%3A%20Combining%20traditional%20configuration%20management%20with%20Docker\">vic@demuzere.be</a>.</p></div>","url":"https://vic.demuzere.be/articles/combining-traditional-configuration-management-with-docker/","date_published":"2018-10-15T18:23:00Z","date_modified":"2023-11-28T19:55:32Z","language":"en"}]}