My Server gives 502 and Caddy says header_upstream

Hello,

I have a problem with following:
I wanted to move from my old host to a new dedicated server using Docker and Caddy as a web server. I wanted to move my WordPress site with my following configs:


docker-compose.yaml

version: '2'

services:

   caddy:
      container_name: 'Caddy'
      image: abiosoft/caddy:latest
      volumes:
        - ~/.caddy:/etc/caddycerts
        - ./Caddyfile:/etc/Caddyfile
      ports:
        - "80:80"
        - "443:443"
      restart: always
      environment:
        - CADDYPATH=/etc/caddycerts

   mysql:
     container_name: mysql
     image: mysql:5.7
     volumes:
       - ./mysql:/var/lib/mysql
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: blabla123

   wordpress:
     container_name: wordpress
     depends_on:
       - mysql
     image: wordpress:fpm
     volumes:
      - ./wordpress/httpdocs:/var/www/html
     restart: always
     environment:
       WORDPRESS_DB_NAME: wordpress
       WORDPRESS_DB_HOST: mysql:3306
       WORDPRESS_DB_PASSWORD: blabla123

volumes:
    Caddyfile:
    mysql:

Caddyfile

domain.com {  
    fastcgi / wordpress:9000 php {
        ext .php
        index index.php
    }
    proxy / wordpress:80 {
        proxy_header Host {host}
        proxy_header X-Real-IP {remote}
        proxy_header X-Forwarded-Proto {scheme}
    }
    tls me@domain.com
}

I get a 502 Bad Gateway when starting up the Caddy Docker Container and the log says following:

2016/12/07 23:27:39 [INFO] www.domain.com - No such site at :80 (Remote: 84.123.12.187, Referer: https://www.google.es/)
Activating privacy features... done.
WARNING: proxy_header is deprecated and will be removed soon; use header_upstream instead.
https://domain.com
http://domain.com
Activating privacy features... done.
WARNING: proxy_header is deprecated and will be removed soon; use header_upstream instead.
https://domain.com:2015

As you can see it has a problem with the proxy and switches to port 2015, but I really can’t find the solution.

I run Debian Jessie.

Please help me!

Thanks in advance.

René

Hi René, when you start Caddy using that Caddyfile without any Docker stuff (don’t worry about WordPress for the time being), does it still act like this?

Hi Matt,

thanks for reply. I will try that this evening (in around 10 hours) and will give you results.

Hello Matt,

this makes no sense to start the Caddy without Docker, since the proxy is forwarding to a Docker Container.

Okay, so just accept for the purposes of experimentation the fact that proxying won’t work when you make a request, but does Caddy start as you would expect without Docker? If so, then it’s probably a misconfiguration of your Docker setup.

Also, use header_upstream instead of proxy_header. :wink:

Hey Matt,

my Caddy is running correctly when starting right from the host. I also changed to header_upstream (why is that needed?) and it does not give the proxy error in the container as well.

What else can be so error?

Thanks!

Hey Matt,

I get this error now when accessing the server from caddy:

2016/12/08 18:14:50 http: TLS handshake error from 188.138.105.23:4976: tls: client offered an unsupported, maximum protocol version of 301

The server responses No such site at :443 now at https and also at :80

Hey Matt,

I got everything working! The reason why it did not work is the proxy header => header_upstream and also I needed to add a rewrite to access the php-files:

    rewrite {
        if {path} not_match ^\/wp-admin
        to {path} {path}/ /index.php?_url={uri}
    }

Is there also another way to strictly redirect to www.domain.com? I used this now:

domain.com {
    redir https://www.domain.com{uri}
}

Thank you very much!

Yours,
René

Oh god. I was thinking it works now, but my DNS was not flushed… :confused: I have 502 Bad Gateway now… and I really don’t get why. I really need a solutions for this

Interestingly enough, lately I have been working on exactly what you’re trying to achieve. Some thoughts:

  • There is no need for the ext and index declarations in your fastcgi block, the php preset handles this (see docs for fastcgi). You can simply remove them as redundant.
  • The entire fastcgi block can be removed anyway, as the WordPress image is based on PHP, which is preconfigured with Apache. Caddy will only ever receive a post-PHP result from upstream, no need for a block to pass it back again.
  • You can clean up the proxy statement a bit, too - the following does exactly what you’ve written, and will handle the proxy headers correctly (see docs for proxy):
proxy / wordpress {
    transparent
}
  • I’d highly recommend using MariaDB instead of MySQL as a drop-in replacement which is widely regarded to be the superior option. It uses identical Docker configuration, too, just change the image to mariadb:latest and reap the benefits (see MariaDB on Docker Hub).
  • You’ve specified WORDPRESS_DB_HOST and WORDPRESS_DB_NAME, but you’ve specified their default values. These can be removed from your compose file. This is true whether you use MySQL or MariaDB (identical configuration).

Consider the following configuration I have successfully deployed:

version: '2'

services:
  caddy:
    image: zzrot/alpine-caddy:latest
    volumes:
      - ./Caddyfile:/etc/Caddyfile
      - ./certs:/root/.caddy
      - ./sites:/srv
    environment:
      CLOUDFLARE_EMAIL: # Redacted
      CLOUDFLARE_API_KEY: # Redacted
    ports:
      - 80:80
      - 443:443
    restart: always

  wordpress:
    image: wordpress:latest
    environment:
      WORDPRESS_DB_PASSWORD: # Sneaky date|md5sum goes here
    volumes:
      - ./wordpress:/var/www/html
    restart: always

  mysql:
    image: mariadb:latest
    environment:
      MYSQL_ROOT_PASSWORD: # Sneaky date|md5sum goes here
    volumes:
      - ./mysql:/var/lib/mysql
    restart: always

And the following configuration in my Caddyfile (you can ignore the TLS blocks, I set this up behind a load balancer):

domain.com {
    redir / https://www.domain.com{uri}
    tls {
        dns cloudflare
    }
}

www.domain.com {
    proxy / wordpress {
        transparent
    }
    tls {
        dns cloudflare
    }
}

I did it mostly because I was tinkering with CloudFront, and the site was previously hosted on a shared host behind CloudFlare, and CloudFront does NOT like CloudFlare’s SSL (I think, I could not quite pinpoint the issue past HTTPS). Putting my site on DigitalOceanAWS (DO don’t have a DC near me :cry:) saved me about 5 seconds off my page load, though, so I feel like it might be time to benchmark some other shared hosting providers…

Anyway, all of the above is tested live and working 100% right now. I did make some minor changes (it was split across two compose projects and the networks were joined, so I removed all that to post a single compose file here), but there should be no issues if you were to use this exact setup, I think.

2 Likes

Hey Matthew,

thanks for your great explanation!

Do you use php7 as well? Because latest does use php 5.6 if I did see right.
I also want to compose multiple projects with Docker and Caddy on the same host.

I will try that out and post my results here.

Big thanks!

1 Like

Sharp eye, my version uses PHP 5.6. Have a look at the wordpress:php7.0 tag, you should be able to drop it right in instead of wordpress:latest, let me know how it works out.

As for composing multiple projects - my main network/proxy compose project is stored in /opt/whitestrake for the time being - so the network created is whitestrake_default. I add the following snippet to the bottom of the compose file of any project I want to attach to this network:

networks:
  default:
    external:
      name: whitestrake_default

All services in both compose projects can then immediately access each other via their service name, which is very useful. You might want instead to specifically define a proxy and a backend network instead and specify for each container, but I just override the default. I also simply double check to make sure the proxy is composed up before starting attached projects, because they will throw errors if the network doesn’t exist yet, so look out for that.