Using Caddy on a Fresh Magento 2.2.3 CE install

ok, you guys ready?

I’ve been trying to get Magento 2 to work with caddy instead of nginx or apache and looks like the biggest issue im having is converting the rewrite rules to work with caddy.

I know this isn’t anywhere near correct or complete yet but this is what I have so far.

I’ve been playing around with different configs to test the rewrite rules and I can get the home page to display correctly with js and css, but as soon as you click on something I either get a 403, or a not found.

then I can get all the links and everything to work right (mostly) but no js or css throughout the site.

Could really use some help with this.

Thanks

1 Like

To be a bit more specific, here are some things that i have questions on.

  1. errors - In the documentation, it states that you can specify an html page for an error code. Magento specifies a couple php files. I take it that means I will not be specifying those with caddy under that directive.

  2. A couple of these nginx location blocks within the nginx.conf file I linked to specify “fastcgi_pass fastcgi_backend;” Would that translate into specifying another fastcgi directive / block within my Caddyfile?

  3. Can headers be specified within a rewrite block?

Ill be putting together a few others as well, but can start here i think.

thanks

Correct, currently only static HTML files can be used for error pages (because what to do if there’s an error rendering a PHP page?). The errors directive could use some enhancements.

Yes, I think so, for the location block that applies to it in the nginx.conf. So, the one in location ~ ^/setup/index.php I think just means fastcgi /yoursiteroot/setup/index.php your_backend php and location ~ (index|get|static|report|404|503|health_check)\.php$ is basically fastcgi /index.php your_backend php basically.

No, but in the future we’re planning for the Caddyfile to support if blocks (against my better judgment, but oh well) that you could put directives into. However, there is a way to do this with rewrite, usually. That’s a lot of rewrites though! (Between you and me – on this public forum – I really hate it when web apps are designed like this, so that the web server has to do all the heavy lifting. It invites a LOT of problems. No reason it has to be like this. Sigh.)

Thanks for checking this out Matt, Magento has always been a pain in the ass… I know that if things arent just quite right, theres usually major issues. Whether performance or otherwise.

They are so ingrained with Apache or Nginx that I’m not surprised I havent found a shred of documentation out there regarding someone attempting to convert over to Caddy.

Good news, I was able to make SOME headway and get some rendering going with Magento and Caddy, even with a partial translation.

https://example.com {
    root /var/www/magento/pub

    gzip {
        ext .txt .css .less .js .jsonp .json .xml .rss .svg .svgz
        level 6
    }

    tls webmaster@example.com

    log stdout

    fastcgi / unix:/run/php-fpm/php-fpm.sock php {
        connect_timeout 600s
        read_timeout 600s
        ext .php .js .css .less .xml
    }

    rewrite / {
      to {path} {path}/ /index.php{query}
    }
    rewrite /media {
        ext .ico .jpg .jpeg .png .gif .svg .js .css .swf .eot .ttf .otf .woff .woff2
        to {path} {path}/ /get.php{query}
    }
    rewrite /static {
        ext .ico .jpg .jpeg .png .gif .svg .js .css .swf .eot .ttf .otf .woff .woff2
        r ^/?(.*)$
        to {path} {path}/ /static.php{query}
    }

   errors /var/log/caddy/errors.log

    push

    # MIME Types used
    mime {
        .txt text/plain
        .css text/css
        .less text/css
        .js application/javascript
        .jsonp text/javascript
        .json application/json
        .xml text/xml
        .rss application/xml+rss
        .svg image/svg+xml
        .svgz image/svg+xml
    }

    # Header for /pub path
    header / X-Frame-Options "SAMEORIGIN"
    header /media X-Frame-Options "SAMEORIGIN"

    # Header for /static
    header /static Cache-Control "public"
    header /static X-Frame-Options "SAMEORIGIN"
}

Now, It would be awesome to know if im at least heading down the right path here???
I’m not a server guy and it took me about 4-5 days just to get to this point. I have a magento2 install up already, the server is mostly configured the same way except it uses Apache instead of Caddy and i literally get mad trying to work with it because its sooooo slow.

With this partial config, I’ve got Magento up, some things definitely not working right due to the half a job, but its a LOT faster than what ive seen for a base magento install.

I even setup the sampledata to see if there was any difference… and the only other thing I did was to enable the Magento cache.

This just tells me its imperitive! that I can get Caddy to fully work and integrate with Magento.

with the simple config and speed, Caddy will blow it out of the water!

Any help on putting together a full translation would be appreciated. I cant seem to figure out some of the rewrite issues… It is up on a domain and vps that has nothing else on it right now besides this install so if you would like for me to post the link. Just beware, I will be continuing to work on it and it may be down if anyone goes to check it out.

1 Like

I hereby summon @whitestrake who is expert at Caddy rewrites! :slight_smile: I suspect this could be helpful to future searchers as well.

Thanks Matt! lets show Apache and Nginx what Caddy can do!

1 Like

It’s slow because Magento 2.2 is slow out of the box regardless of web server used. I am new to Magento 2.2 as well and did my first Magento 2.2 install on Centmin Mod based Nginx server and found it very very slow due to how Magento 2.2 is written. Only way you will speed it up is enabling Redis caching for backend/sessions + putting Varnish Cache Full Page Caching if you use Apache or Nginx or switch to Litespeed web server with LiteMage Caching.

I wrote up my first time Magento 2.2 install and benchmarking experience with Redis vs Varnish Caching at GitHub - centminmod/centminmod-magento2: Magento 2.2.2 Install Guide For Centmin Mod Nginx LEMP Stacks

  1. Magento 2 Redis Benchmarks
  2. Magento 2 File Based Caching Benchmarks
  3. Magento 2 Varnish Cache Config & Benchmarks
  4. Varnish Cache Benchmark Test Results

Pretty sure Caddy isn’t going to help given that performance scaling of Caddy is well behind Nginx already https://community.centminmod.com/threads/caddy-http-2-server-benchmarks-part-2.12873/. Or jump straight to the Caddy + Varnish HTTP/2 HTTPS benchmarks too.

Hope this info helps. Looking forward to how you fair - keep us updated :slight_smile:

edit: some wrk tool HTTP/1.1 HTTPS benchmarks from Nginx based Magento 2.2.2 with

Redis Unix socket caching of backend + full page caching + session caching

domain=https://magento.domain.com
wrk-cmm -t2 -c2 -d10s --breakout -H 'Accept-Encoding: gzip' -s scripts/setup.lua --latency $domain
thread 1 created
thread 2 created
Running 10s test @ https://magento.domain.com
  2 threads and 2 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    29.77ms    9.12ms 134.42ms   96.97%
    Connect     9.30ms    4.76ms  12.67ms  100.00%
    TTFB       29.46ms    9.08ms 134.08ms   96.97%
    TTLB      306.88us  212.53us   2.83ms   97.51%
    Req/Sec    34.26      6.07    40.00     97.47%
  Latency Distribution
     50%   28.09ms
     75%   30.42ms
     90%   33.51ms
     99%   75.62ms
  684 requests in 10.05s, 4.84MB read
Requests/sec:     68.04
Transfer/sec:    493.39KB
thread 1 made 342 requests and got 340 responses
thread 2 made 345 requests and got 344 responses

Compared to warmed up Magento 2.2.2 + Varnish Cache full page caching + redis backend + session caching

wrk-cmm -t2 -c2 -d10s --breakout -H 'Accept-Encoding: gzip' -s scripts/setup.lua --latency $domain
thread 1 created
thread 2 created
Running 10s test @ https://magento.domain.com
  2 threads and 2 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.99ms    0.90ms  13.00ms   91.47%
    Connect     7.28ms    5.85ms  17.71ms   52.00%
    TTFB        1.46ms  679.66us  12.54ms   81.05%
    TTLB      505.80us  583.70us   6.74ms   91.19%
    Req/Sec   508.07    126.29   720.00     66.50%
  Latency Distribution
     50%    1.49ms
     75%    2.49ms
     90%    2.76ms
     99%    5.49ms
  10124 requests in 10.01s, 70.53MB read
Requests/sec:   1011.06
Transfer/sec:      7.04MB
thread 1 made 5153 requests and got 5151 responses

Benchmarks are using my wrk forked version wrk-cmm for HTTP/1.1 HTTPS based load testing. For HTTP/2 HTTPS load testing use h2load.

If you want to scale Magento on any web server, you will need to use Varnish Caching for Magento full page caching due to the way Magento has been coded - everything is fed through php index.php - even the native Redis full page caching so of limited usefulness.

Hi George,

Thanks for the in-depth reply!

I’ve actually been working with magento in one form or another for about 8 years and even when we were working with 1.x, performance was always an issue.

When you say

I take it you have already attempted to run Magento 2.2 on Caddy?

In order to get to a point on a server where you can even install Magento, you have to have all the pre-reqs taken care of first. PHP, MySQL, Web Server.

My issue is that if you have already made it to this point, why cant you have a decent, working install that you can start setting up and configuring from within the admin panel?

I consider myself pretty technically inclined and with time can figure out pretty much anything, but I look at your post and all I see is about another week of research, messing around issues and configs and that much more of a delay before I can even start using it.

I really do appreciate the in depth response and will be looking into it, but I think that there might be an opportunity here where say a small business owner can come in, take a pre-configured Caddyfile, plug in their domain, un-comment additional settings if they want and get up and running with a fresh install quickly and painlessly.

I tell you what, I’d like a second opinion here. I have a “working” Caddyfile config that is doing AWESOME for me right now, as long as you install magento via cli. I havent gotten the web-setup to work yet, and theres still a lot left I have to figure out but if you know how to install Magento 2.2.3 via composer and have all your pre-requisites setup, I’d love to hear how the experience is for you vs setting up with Apache or Nginx.

https://example.com {

    root /var/www/magento2/pub
    
    gzip {
        ext .txt .css .less .js .jsonp .json .xml .rss .svg .svgz .html
        level 6
        min_length 1100
    }

    tls webmaster@example.com

    log stdout

    fastcgi / unix:/run/php-fpm/php-fpm.sock php {
        root /var/www/magento2/pub
        index index.php
        connect_timeout 600s
        read_timeout 600s
        ext .php .html .js .css .less .ico ## Are there any restrictions here?
    }
    
    errors /var/log/caddy/errors.log ## Plan on expanding this out a bit more
        
    push ## For now, I'm not sure if this is helping or hurting? or anything really at all? 

    # MIME Types used

    mime {
        .txt text/plain
        .css text/css
        .less text/css
        .js application/javascript
        .jsonp text/javascript
        .json application/json
        .xml text/xml
        .rss application/xml+rss
        .svg image/svg+xml
        .svgz image/svg+xml
    }

        ## internal links only, these paths are listed as Deny All

        internal /media/customer/
        internal /media/downloadable/
        internal /media/import/

	## Tried a couple different configurations and the web setup wizard would not work.  I adjusted the root directive so it pointed to my docroot and could use some fresh ideas.

       # rewrite {
       #     r ^/setup($|/)
       #     to {path} {path}/ ^/setup/index.php {uri} {uri}/ /index.php{uri}
       # }

       # header ^/setup/pub/ X-Frame-Options "SAMEORIGIN"

	## I stopped messing with the update blocks because I couldnt figure out where within the code this actually existed. Besides in just the nginx.conf.sample file.

       # rewrite {
       # r ^/update($|/)
       # to {path} {path}/ ^/update/index.php {uri} {uri}/ /index.php{uri}
       # }

	## Apparently it doesnt like my regex on the if lines, Guess im doing this wrong, any ideas?

        rewrite {
       #     if {file} not_match ^/media/theme_customization/.*\.xml
            r ^/media/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$
       #     if {file} match ^/media/\.(zip|gz|gzip|bz2|csv|xml)$
            to {path} {path}/ /get.php /get.php?{query}
        }

        header /media X-Frame-Options "SAMEORIGIN"
       # header /media/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ Cache-Control "public"
       # header /media/\.(zip|gz|gzip|bz2|csv|xml)$ Cache-Control "no-store"

	## Taking the Version number out actually works! Instead of setting 'php bin/magento config:set dev/static/sign 0' Not good having unversioned files floating around in cache?

        rewrite {
            r ^/static/(version\d*/)?(.*)$
            to /static/{2}
        }

	## Yea, no worky here either.  I have a feeling that some of these things have to be getting taken care of via one of ym other rewrites?

       # rewrite {
       #     ext .ico .jpg .jpeg .png .gif .svg .js .css .swf .eot .ttf .otf .woff .woff2
       #     r ^/static/?(.*)$
       #     to /static.php?resource={1}
       # }

       # rewrite {
       #     ext .zip .gz .gzip .bz2 .csv .xml
       #     r ^/static/?(.*)$
       #     to /static.php?resource={1}
       # }

	## Can regex be used with the header directive? otherwise how would the headers here, and up higher in the file, accomplish what this is supposed to? 
	
        header /static X-Frame-Options "SAMEORIGIN"
       # header /static/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ Cache-Control "public"
       # header /static/\.(zip|gz|gzip|bz2|csv|xml)$ Cache-Control "no-store";

	## Maybe I could get a little help with an explanation on this rewrite if possible please? Why does this work without the regex?  Im a bit lost here.

        rewrite {
       #     r (index|get|static|report|404|503|health_check)\.php$
            to {path} {path}/ /index.php /index.php?{query}
        }

        header / {
            X-Content-Type-Options "nosniff" ## Get around to adding making sure headers get set correctly
        }

	## How can you specify "off" for those files? or +1y or any of the other crazy things I've seen specified looking around?

        expires {
            match ^/static/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ 1y
            match ^static/\.(zip|gz|gzip|bz2|csv|xml)$ 0s
            match ^/media/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ 1y
            match ^/media/\.(zip|gz|gzip|bz2|csv|xml)$ 0s
        }

}

Soooo… to recap. With the below configs, Magento 2.2.3 is up and running with no errors in my logs and pretty good performance.

https://example.com {
    root /var/www/magento2/pub    
    gzip {
        ext .txt .css .less .js .jsonp .json .xml .rss .svg .svgz .html
        level 6
        min_length 1100
    }
    tls webmaster@example.com
    log stdout
    fastcgi / unix:/run/php-fpm/php-fpm.sock php {
        root /var/www/magento2/pub
        index index.php
        connect_timeout 600s
        read_timeout 600s
        ext .php .html .js .css .less .ico
    }    
    errors /var/log/caddy/errors.log        
    push 
    mime {
        .txt text/plain
        .css text/css
        .less text/css
        .js application/javascript
        .jsonp text/javascript
        .json application/json
        .xml text/xml
        .rss application/xml+rss
        .svg image/svg+xml
        .svgz image/svg+xml
    }
    internal /media/customer/
    internal /media/downloadable/
    internal /media/import/
    rewrite {
        r ^/media/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$
        to {path} {path}/ /get.php /get.php?{query}
    }
    header /media X-Frame-Options "SAMEORIGIN"
    rewrite {
        r ^/static/(version\d*/)?(.*)$
        to /static/{2}
    }
    header /static X-Frame-Options "SAMEORIGIN"
    rewrite {
        to {path} {path}/ /index.php /index.php?{query}
    }
    header / {
        X-Content-Type-Options "nosniff"
    }
    expires {
        match ^/static/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ 1y
        match ^/static/\.(zip|gz|gzip|bz2|csv|xml)$ 0s
        match ^/media/\.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ 1y
        match ^/media/\.(zip|gz|gzip|bz2|csv|xml)$ 0s
    }
}

Unfortunately I’m pretty sure that I’ve not configured everything in here correctly and the stuff thats commented out in the top example are a lot of what I still have questions on. @matt @Whitestrake Could use your input here on this conversion so far. Any ideas or suggestions?

Thanks!

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.