{"id":2080,"date":"2016-03-31T10:07:56","date_gmt":"2016-03-31T09:07:56","guid":{"rendered":"https:\/\/denbeke.be\/blog\/?p=2080"},"modified":"2016-06-02T08:05:04","modified_gmt":"2016-06-02T07:05:04","slug":"two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server","status":"publish","type":"post","link":"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/","title":{"rendered":"Two months ago I started to &#8220;Serve The Web Like It&#8217;s 2016&#8221;, and I&#8217;m still loving Caddy!"},"content":{"rendered":"<h2>Caddy?<\/h2>\n<p>Wooha, hold your horses, what is Caddy?! <a href=\"https:\/\/caddyserver.com\">Caddy<\/a> is a web server like Apache or Nginx, but different:<\/p>\n<ul>\n<li>Caddy is a modern web server (supporting HTTP\/2) with elegant and easy configuration. It comes with automated HTTPS (with <a href=\"https:\/\/letsencrypt.org\">Let&#8217;s Encrypt<\/a>) and a growing number of extensions (including Git support).<\/li>\n<li>It&#8217;s open source software, written in <a href=\"https:\/\/golang.org\">Go<\/a>, and driven by an awesome community.<\/li>\n<li>Well <a href=\"https:\/\/caddyserver.com\/docs\">documented<\/a><\/li>\n<li>Cross-platform: available for Linux, Mac OS X, FreeBSD, Windows, OpenBSD and Android.<\/li>\n<li>All this in just one binary executable!<\/li>\n<\/ul>\n<h2 id=\"caddyfile\"><a href=\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/attachment\/caddy-logo-2\/\" rel=\"attachment wp-att-2088\"><img loading=\"lazy\" class=\"size-medium wp-image-2088 aligncenter\" src=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo-300x65.png\" alt=\"Caddy logo\" width=\"300\" height=\"65\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo-300x65.png 300w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo-768x166.png 768w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo-1024x222.png 1024w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo.png 1200w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a>Caddyfile<\/h2>\n<p>Configuration for Caddy is done using a <em>Caddyfile<\/em>, which is a new language specifically for Caddy (ok, this seems odd at first sight). But by using a domain specific language, configuration becomes very simpel and to-the-point.<\/p>\n<p>Caddy is very powerful (and easy at the same time), which I will demonstrate with Caddyfile snippets for some of my real-world situations.<\/p>\n<p>Configuring Caddy can be very easy for most sites:<\/p>\n<pre><code>denbeke.be {\r\n    root sites\/denbeke.be\r\n}<\/code><\/pre>\n<p>Look, I just created the config for a static website with a document root. This site is automatically served over HTTPS, and HTTP traffic is automatically redirected to HTTPS<sup>1<\/sup>.<\/p>\n<p>Dynamic PHP websites are of course also supported. Simply use PHP-FPM as you would do with Nginx:<\/p>\n<pre><code>denbeke.be {\r\n    root sites\/denbeke\r\n    fastcgi \/ unix:\/var\/run\/php\/php7.0-fpm.sock php\r\n}<\/code><\/pre>\n<p>But Caddy is not only easy, it comes packed with a lot of features, which support a lot of use cases.<\/p>\n<p>My personal WordPress blog runs perfectly with only 12 lines of code:<\/p>\n<pre><code>www.denbeke.be {\r\n    redir https:\/\/denbeke.be{uri}\r\n}\r\n\r\ndenbeke.be {\r\n\r\n    root sites\/denbeke\r\n    log sites\/logs\/denbeke.be.access.log\r\n    errors sites\/logs\/denbeke.be.error.log\r\n\r\n    fastcgi \/ unix:\/var\/run\/php\/php7.0-fpm.sock php\r\n\r\n    # Routing for WordPress\r\n    rewrite \/blog {\r\n        to {path} {path}\/ \/blog\/index.php?{query}\r\n    }\r\n\r\n    gzip\r\n    header \/blog\/wp-content\/ Cache-Control \"max-age=2592000\"\r\n    header \/blog\/wp-includes\/js\/ Cache-Control \"max-age=2592000\"\r\n\r\n}<\/code><\/pre>\n<p>I have a redirect from <code>www.denbeke.be<\/code> to <code>denbeke.be<\/code>, redirect from HTTP to HTTPS (note that non-HTTPS traffic is automatically redirected to HTTPS with Caddy by default<sup>1<\/sup>), error and access logging, and PHP with routing for WordPress. I also compress all content with gzip and set caching headers to optimize used bandwidth.<\/p>\n<p>For my Git server, I have a reverse proxy to <a href=\"https:\/\/gogs.io\">Gogs<\/a>. Again, Caddy takes care of HTTPS&#8230; The Caddyfile for this is again trivial:<\/p>\n<pre><code>git.denbeke.be {\r\n    proxy \/ http:\/\/localhost:3000\r\n}<\/code><\/pre>\n<p>My last example is the website for a group project, where the complete website is put in a Git repo, so all contributors can edit the website. The following directive will clone the complete repo on initial setup, and pull changes every hour:<\/p>\n<pre><code>oakstrong.be {\r\n    root sites\/oakstrong\r\n    git https:\/\/bitbucket.org\/oakstrong\/oakstrong.be.git\r\n}<\/code><\/pre>\n<p>It&#8217;s all very easy, isn&#8217;t it?<\/p>\n<p>And this is just a subset of Caddy&#8217;s capabilities, Caddy supports a lot more, like <a href=\"https:\/\/blog.zenithar.org\/post\/2016\/01\/06\/automatisation-publication-hugo-avec-caddy\/\">automated Hugo publishing (French blogpost)<\/a>, <a href=\"https:\/\/github.com\/mholt\/caddy\/wiki\/Running-Caddy-on-Android\">running Caddy on Android<\/a>, or any other PHP CMS or static site generator. Caddy also has a growing number of add-ons\/modules, which add a variety of features to Caddy, like Prometheus metrics, IP filtering, search, Cross Origin Resource Sharing, JSONP, &#8230;<\/p>\n<h2 id=\"running-caddy-as-a-service...\">Running Caddy as a service&#8230;<\/h2>\n<p>&#8230; is easy! (and others, including myself, already made configuration files and tutorials about it)<\/p>\n<ul>\n<li><a href=\"https:\/\/denbeke.be\/blog\/servers\/running-caddy-server-as-a-service\/\" target=\"_blank\">Running Caddy as a service with upstart (Ubuntu &lt;= 14)<\/a><\/li>\n<li><a href=\"https:\/\/denbeke.be\/blog\/servers\/running-caddy-server-as-a-service-with-systemd\/\" target=\"_blank\">Running Caddy as a service with systemd (Ubuntu &gt;= 15)<\/a><\/li>\n<li><a href=\"https:\/\/www.davd.eu\/posts\/caddy-freebsd-init-script\/\" target=\"_blank\">Running Caddy as a service with rc.d system (FreeBSD)<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/r\/abiosoft\/caddy\/\" target=\"_blank\">Running Caddy in a Docker container<\/a><\/li>\n<li><a href=\"http:\/\/s.natalian.org\/2016-03-17\/caddy.service\" target=\"_blank\">Running the Caddy Docker container as a service with systemd<\/a><\/li>\n<li><a href=\"https:\/\/code.launchpad.net\/~hduran-8\/+archive\/ubuntu\/caddy\" target=\"_blank\">PPA for Ubuntu<\/a> (work in progress)<\/li>\n<\/ul>\n<h2 id=\"caddy-in-production-rock-solid\">Caddy in production: rock solid!<\/h2>\n<p>But have you tried running Caddy in production? Is this new and young web server stable enough? Doesn&#8217;t it sometimes crash?<br \/>\nSimple answer <strong>Yes<\/strong> it&#8217;s stable, and <strong>No<\/strong> it hasn&#8217;t crashed yet.<a href=\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/attachment\/pingdom-uptime-report-caddy-webserver\/\" rel=\"attachment wp-att-2081\"><br \/>\n<\/a><\/p>\n<p><a href=\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/attachment\/pingdom-uptime-report-caddy-webserver\/\" rel=\"attachment wp-att-2081\"><img loading=\"lazy\" class=\"aligncenter size-large wp-image-2081\" src=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Pingdom-Uptime-report-Caddy-webserver-1024x565.png\" alt=\"Pingdom Uptime report Caddy webserver\" width=\"640\" height=\"353\" srcset=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Pingdom-Uptime-report-Caddy-webserver-1024x565.png 1024w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Pingdom-Uptime-report-Caddy-webserver-300x165.png 300w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Pingdom-Uptime-report-Caddy-webserver-768x424.png 768w, https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Pingdom-Uptime-report-Caddy-webserver.png 1414w\" sizes=\"(max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>At the beginning of\u00a0February 2016 I made the switch from Nginx to Caddy (together with the switch from PHP 5 to PHP 7) on my home server and my production server. Two months later Caddy already served thousands of visitors on various websites.<sup>2<\/sup> Caddy hasn&#8217;t crashed ever since, and I currently have 100% uptime on my production server.<sup>3<\/sup><\/p>\n<p>Does this mean that Caddy is perfect and bug-free? Of course not!<br \/>\nI started using Caddy in production after a stupid FastCGI bug was fixed (which caused requests to block). While moving to production I submitted a few pull requests and issues on GitHub to fix some important and\u00a0less important bugs. But I can confirm Caddy now perfectly works with <a href=\"https:\/\/denbeke.be\/blog\/servers\/caddy-server-and-wordpress-php-fpm\/\">WordPress<\/a>, Piwik, <a href=\"https:\/\/denbeke.be\/blog\/webdevelopment\/serving-owncloud-with-caddy\/\">ownCloud<\/a>, Vanilla Forums, SMF, and all self-written PHP stuff.<\/p>\n<p>If you take a look at the issues, pull requests, or <a href=\"https:\/\/gitter.im\/mholt\/caddy\">Gitter<\/a>, you&#8217;ll quickly notice that Caddy is a very active project, in which bugs got fixed very swiftly by a growing community. Caddy currently has <del>67<\/del> 70 contributors.<\/p>\n<h2 id=\"conclusion\">Conclusion<\/h2>\n<p>Caddy is awesome! And getting better every day!<\/p>\n<hr \/>\n<ol style=\"list-style-type: decimal;\">\n<li>If you don&#8217;t want to use automated HTTPS certificates, you can specify your own certificates (or disable HTTPS) using the <code>tls<\/code> directive.<\/li>\n<li>I must admit that I&#8217;m not serving high traffic websites, but Matt Holt got this reply from &#8216;a guy&#8217;:<br \/>\n<blockquote><p><em>I got this email from a user that has sometimes has ~100 concurrent users on his site (that uses PHP), and switched from nginx to Caddy:<\/em><\/p>\n<blockquote><p><em>The server has been performing well and server resources are the most free that they&#8217;ve been in months.<\/em><\/p><\/blockquote>\n<\/blockquote>\n<\/li>\n<li>Something else to admit&#8230; right after I wrote this blogpost, my MySQL server crashed, so I can&#8217;t speak of a 100% uptime anymore. But this doesn&#8217;t change the fact that Caddy hasn&#8217;t caused any problems (yet).<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>Caddy? Wooha, hold your horses, what is Caddy?! Caddy is a web server like Apache or Nginx, but different: Caddy is a modern web server (supporting HTTP\/2) with elegant and easy configuration. It comes with automated HTTPS (with Let&#8217;s Encrypt) and a growing number of extensions (including Git support). It&#8217;s open source software, written in [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[227],"tags":[260,232,207,151,186],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v15.6.2 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Two months ago I started to &quot;Serve The Web Like It&#039;s 2016&quot;, and I&#039;m still loving Caddy! &ndash; DenBeke<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Two months ago I started to &quot;Serve The Web Like It&#039;s 2016&quot;, and I&#039;m still loving Caddy! &ndash; DenBeke\" \/>\n<meta property=\"og:description\" content=\"Caddy? Wooha, hold your horses, what is Caddy?! Caddy is a web server like Apache or Nginx, but different: Caddy is a modern web server (supporting HTTP\/2) with elegant and easy configuration. It comes with automated HTTPS (with Let&#8217;s Encrypt) and a growing number of extensions (including Git support). It&#8217;s open source software, written in [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/\" \/>\n<meta property=\"og:site_name\" content=\"DenBeke\" \/>\n<meta property=\"article:published_time\" content=\"2016-03-31T09:07:56+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2016-06-02T07:05:04+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo-300x65.png\" \/>\n<meta name=\"twitter:card\" content=\"summary\" \/>\n<meta name=\"twitter:creator\" content=\"@MthsBk\" \/>\n<meta name=\"twitter:site\" content=\"@MthsBk\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"5 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/denbeke.be\/blog\/#website\",\"url\":\"https:\/\/denbeke.be\/blog\/\",\"name\":\"DenBeke\",\"description\":\"Mathias Beke\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/denbeke.be\/blog\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-US\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/#primaryimage\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/denbeke.be\/blog\/wp-content\/uploads\/2016\/03\/Caddy-logo.png\",\"width\":1200,\"height\":260},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/#webpage\",\"url\":\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/\",\"name\":\"Two months ago I started to \\\"Serve The Web Like It's 2016\\\", and I'm still loving Caddy! &ndash; DenBeke\",\"isPartOf\":{\"@id\":\"https:\/\/denbeke.be\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/#primaryimage\"},\"datePublished\":\"2016-03-31T09:07:56+00:00\",\"dateModified\":\"2016-06-02T07:05:04+00:00\",\"author\":{\"@id\":\"https:\/\/denbeke.be\/blog\/#\/schema\/person\/386878f712fe3fe22227216f087772dc\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/denbeke.be\/blog\/servers\/two-months-ago-i-started-to-serve-the-web-like-its-2016-and-im-still-loving-caddy-migrating-from-nginx-to-caddy-server\/\"]}]},{\"@type\":\"Person\",\"@id\":\"https:\/\/denbeke.be\/blog\/#\/schema\/person\/386878f712fe3fe22227216f087772dc\",\"name\":\"Mathias Beke\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/denbeke.be\/blog\/#personlogo\",\"inLanguage\":\"en-US\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/015ba35e6ce4f5859e3888ca99807575?s=96&d=mm&r=g\",\"caption\":\"Mathias Beke\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","_links":{"self":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/2080"}],"collection":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/comments?post=2080"}],"version-history":[{"count":16,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/2080\/revisions"}],"predecessor-version":[{"id":2103,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/posts\/2080\/revisions\/2103"}],"wp:attachment":[{"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/media?parent=2080"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/categories?post=2080"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/denbeke.be\/blog\/wp-json\/wp\/v2\/tags?post=2080"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}