[SOLVED] How to Configure Caddy in Docker Container (Getting Permission Denied)

As you would asume, I’m just starting to work with Docker and Caddy but I’m haven’t being able to run it since I’m getting the following error:

Could not start HTTPS server for challenge -> listen tcp :443: bind: permission denied

Here is the excerpt fo the docker-compose.yml:

webserver:
    image: jumanjiman/caddy
    depends_on:
      - parse-dashboard
      - loovus
    ports:
      - "80:8000"
      - "443:443"
    links:
      - parse-dashboard
      - parse-server
    volumes:
      - ./production:/prod/
      - ./dist/:/angular/
    command: -port 8000 -host 0.0.0.0 -conf /prod/Caddyfile

Caddyfile:

qa.loovus.mx:8000

tls contacto@loovus.mx

gzip {
  ext .js .css
}

root /angular

proxy /parse parse-server:1337

rewrite / {
  if {path} not_match /parse
  to {path} /index.html
}

If you can give me any hint, I would really appreciate it.

Thank you in advance!

Hi @Neoluis10, welcome to the Caddy community.

I’ve edited your post to format your config files for visibility.

It looks like the Docker maintainer may not have given the caddy user in his container the required privileges to bind to lower port numbers. Here was what I got from a quick test:

whitestrake at icarus in ~/caddytest
→ docker run --rm -v `pwd`:/etc/caddy jumanjiman/caddy -conf /etc/caddy/Caddyfile
Activating privacy features... done.
2017/06/01 00:12:28 listen tcp :80: bind: permission denied

With a simple Caddyfile:

whitestrake at icarus in ~/caddytest
→ cat Caddyfile
:80, :443
status 200 /

It might be necessary for you to build your image from his container to set the required privileges with setcap, or perhaps try a different container. I’m a fan of @abiosoft’s container here: Docker Hub

That said, your Caddyfile has no labels eligible for Automatic HTTPS, and none with :443 specified, so Caddy shouldn’t be trying to bind to :443 regardless. This might indicate that the incorrect Caddyfile is being picked up?

Hello,

I see he is setting

tls contacto@loovus.mx

and that should make Caddy aim for Let’s Encrypt setup, if I see it right.

About the :443 binding failing, I am using a different image and I guess I am not switching to a non-root user as I should, so I have no such issue.

But for you particular case, can you try to add

cap_add:
  - CAP_NET_BIND_SERVICE

to the docker-compose.yml, into the webserver service definition as per Overview | Docker Docs

Cheers,
///Pablo

Hi,
I have updated my docker-compose file with the suggested modification and I also commented the tls command from the Caddyfile but I’m still getting this message:

Please enter your email address so you can recover your account if needed. 6/1/2017 12:26:18 PMYou can leave it blank, but you'll lose the ability to recover your account. 6/1/2017 12:26:21 PM2017/06/01 17:26:21 [qa.loovus.mx] failed to get certificate: [qa.loovus.mx] error presenting token: Could not start HTTP server for challenge -> listen tcp :80: bind: permission denied

docker-compose file:

`webserver:
image: jumanjiman/caddy

depends_on:
  - parse-dashboard
  - loovus

expose:
  - "443"
ports:
  - "80:8000"
  - "443:443"
cap_add:
  - NET_BIND_SERVICE

links:
  - parse-dashboard
  - parse-server

volumes:
  - ./production:/prod/
  - ./dist/:/angular/
command: -port 8000 -host 0.0.0.0 -conf /prod/Caddyfile`

Thanks for any recommendation

Hi @Neoluis10,

You’ve added:

cap_add:
  - NET_BIND_SERVICE

But you need:

cap_add:
  - CAP_NET_BIND_SERVICE

As for this:

You might be right, although I don’t think tls [email] is the reason on its own - going off the docs, it technically meets all Automatic HTTPS requirements. Automatic HTTPS — Caddy Documentation

I guess I assumed that given Caddy is not being instructed to serve over :80 or :443, it wouldn’t logically need to manage certificates.

Hi @Whitestrake, I had to change the command since I was getting the following message when building the image from docker:

ERROR: for webserver Cannot start service webserver: linux spec capabilities: Unknown capability to add: "CAP_CAP_NET_BIND_SERVICE"

I assumed that docker already added the “CAP_” prefix. If I leave it as “NET_BIND_SERVICE”, everything seems to be better; although still not working the HTTPS; still getting:

Could not start HTTP server for challenge -> listen tcp :80: bind: permission denied

I’m a little bit desperate with this matter. I would appreciate if you have any other ideas

Huh, my bad. Docker docs say reference man 7 capabilities, which specifies CAP_, but I suppose Docker’s examples pretty clearly don’t have CAP_. It’d be nice if they mentioned that they add the prefix themselves.

I’m a little confused myself. cap_add: should be exactly what’s needed, but if it’s not working, my only other advice is to use a different container - abiosoft/caddy ignores this issue by not downgrading the user from root, so the Caddy binary has every capability by default.

Hi @Whitestrake, I have changed the container to use the abiosoft/caddy and it seems promising since I get the message:

Activating privacy features... done. https://qa.loovus.mx:8000 http://qa.loovus.mx

However, when I open my browser and use any of the previous URLs, I get a web page that says: This site can’t be reached. My Caddyfile and docker-compose file are pretty much the same that I posted originally.

Thank you for your great help!

I just curl'd those addresses and got no response over HTTPS on port 8000, and a very weird response over HTTP on port 80. Not sure what’s going on there, does qa.loovus.mx resolve to the IP address of your Caddy server?

Hi @Whitestrake, I finally got the HTTPS working for my site. At the end it was a matter of misunderstanding with the configuration between Caddyfile and docker-compose, specifically in the docker-compose where I was specifying the following line:

command: -port 8000 -host 0.0.0.0 -conf /prod/Caddyfile

I replaced it by:

command: -conf /prod/Caddyfile

and left the default ports (80 and 443)

The ending docker-compose file is:

webserver: image: abiosoft/caddy # Express dependency between services # https://docs.docker.com/compose/compose-file/#dependson depends_on: - parse-dashboard - loovus # Forwards the exposed port 8000 on the container to port 80 on the host machine. # Either specify both ports (HOST:CONTAINER) # https://docs.docker.com/compose/compose-file/#ports #expose: # - "443" # - "80" ports: - "80:80" - "443:443" cap_add: - NET_BIND_SERVICE # Link to containers in another service. Either specify both the service name and a link alias (SERVICE:ALIAS), or just the service name. links: - parse-dashboard - parse-server # Mount host paths or named volumes. # https://docs.docker.com/compose/compose-file/#volumes volumes: # Path on the host, relative to the Compose file - ./production:/prod/ - ./dist/:/angular/ command: -conf /prod/Caddyfile

Thank you very much for your help!

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