Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running as the haproxy user in 2.4 leaved haproxy unable to start - cannot bind socket (Permission denied) [0.0.0.0:80] #160

Closed
akerr-CINC opened this issue Jun 8, 2021 · 10 comments

Comments

@akerr-CINC
Copy link

akerr-CINC commented Jun 8, 2021

This may not be best practice, but we bind to port 80 and 443.

2.3's dockerfile has:
no USER for backwards compatibility (to try to avoid breaking existing users)

2.4's dockerfile has:
USER haproxy

So when starting with my configuration I get:
[NOTICE] (1) : haproxy version is 2.4.0-6cbbecf
[ALERT] (1) : Starting frontend frontend-web80: cannot bind socket (Permission denied) [0.0.0.0:80]
[ALERT] (1) : Starting frontend frontend-web443: cannot bind socket (Permission denied) [0.0.0.0:443]
[ALERT] (1) : [haproxy.main()] Some protocols failed to start their listeners! Exiting.

Yes, I could bind to another port and map them, which is probably what I will do, but it would be convenient if there was a way to override this setting.

I imagine this might be related to #158 although I'm not sure.

@yosifkit
Copy link
Member

yosifkit commented Jun 8, 2021

If you have a new enough kernel (4.11), then adding --sysctl net.ipv4.ip_unprivileged_port_start=0 to the docker run should allow it to use "privileged" ports (moby/moby#8460).

If you have both a new enough kernel and new enough docker (20.10.x, moby/moby@dae652e), then it can just work: moby/moby#41030.

@akerr-CINC
Copy link
Author

Running in podman on centos8 stream (kernel 4.18.0-277.el8.aarch64) for the record. Changing the user it runs as also broke other permissions such as the pidfile which was set to /var/run/haproxy.pid.

I suppose you can close this and just look at the larger issue of changing from running as root to another user.

Certainly appreciate the container though, and wasn't hard to fix.

@saschaarthur
Copy link

If you have a new enough kernel (4.11), then adding --sysctl net.ipv4.ip_unprivileged_port_start=0 to the docker run should allow it to use "privileged" ports (moby/moby#8460).

Can confirm adding this to the host works.

If you have both a new enough kernel and new enough docker (20.10.x, moby/moby@dae652e), then it can just work: moby/moby#41030.

If i get it right, i should have never reached here.

root@lb-001 /p/docker # docker --version
Docker version 20.10.2, build 20.10.2-0ubuntu1~20.04.2

root@lb-001 /p/docker # uname -a
Linux lb-001 5.4.0-74-generic #83-Ubuntu SMP Sat May 8 02:35:39 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

haproxy-live | [ALERT] (16) : Starting frontend wwws-web: cannot bind socket (Permission denied) [0.0.0.0:444]
haproxy-live | [ALERT] (16) : Starting frontend wwws-web: cannot bind socket (Permission denied) [0.0.0.0:445]
haproxy-live | [ALERT] (16) : Starting frontend wwws-web: cannot bind socket (Permission denied) [0.0.0.0:446]

So this didnt seem to work out.

@surajthakur
Copy link

surajthakur commented Sep 3, 2021

@akerr-CINC We did find the same issue. We are running debian9, and so kernel version is 4.9.0-12-amd64., meaning cant use --sysctl net.ipv4.ip_unprivileged_port_start=0

So version 2.4.3 of haproxy didnt work for me and got same error.

Inside haproxy docker config file we were binding frontend on 80 and 443 and mapping host port 80>80 and 443->443.

Saw your idea of changing the ports in the haproxy config and doing port mapping host 80 and 443 to it. For example, 80 -> 8888 and 443-> 8889 port mapping. solves the purpose and able to run haproxy 2.4

Is it recommended to do so ? Did you find any issues on this approach ? Just wanted to get a feedback to decide whether to use this approach

Thanks

@surajthakur
Copy link

@yosifkit can you suggest on the above query I asked. Just wanted to be sure if it can lead to any complications
Thanks

@tianon
Copy link
Member

tianon commented Sep 7, 2021

If you have to stay on an older kernel, yes, you should probably use port numbers larger than 1024 and remap them via Docker's port mapping if you need them exposed externally on lower ports. Otherwise, you'll have to run the container as root (which comes at the cost of somewhat lower security).

In the future, these sorts of questions/requests would be more appropriately posted to a dedicated support forum, such as the Docker Community Forums, the Docker Community Slack, or Stack Overflow.

@surajthakur
Copy link

Thanks, @tianon. Appreciate your response. I will open any further questions on the forum.

@stevenmasci
Copy link

Leaving this here, this may help someone: #170 (comment)

@nsmosi
Copy link

nsmosi commented Apr 24, 2023

still this is an issue :(

@ghost
Copy link

ghost commented Jan 19, 2024

Currently solved through port mapping bypass.

root@deepin-1:~/nginx-cluster# docker-compose ps -a 
NAME                      IMAGE                 COMMAND                  SERVICE   CREATED              STATUS                        PORTS
nginx-cluster-haproxy-1   haproxy:alpine3.19    "docker-entrypoint.s…"   haproxy   About a minute ago   Up About a minute (healthy)   0.0.0.0:443->8443/tcp
nginx-cluster-nginx1-1    nginx:1.25.3-alpine   "/docker-entrypoint.…"   nginx1    About a minute ago   Up About a minute (healthy)   80/tcp
nginx-cluster-nginx2-1    nginx:1.25.3-alpine   "/docker-entrypoint.…"   nginx2    About a minute ago   Up About a minute (healthy)   80/tcp
root@deepin-1:~/nginx-cluster# 
root@deepin-1:~/nginx-cluster# cat docker-compose.yaml 
version: '3'
services:
  haproxy:
    image: haproxy:alpine3.19
    environment:
      TZ: ${TIMEZONE}
    volumes:
      - ./conf/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
      - ./certs:/etc/ssl/private:ro
      - /data/logs/haproxy:/var/log/haproxy:rw 
    ports:
      - "${PORT_SERVER}:8443"
    networks:
      - webnet
    privileged: true
    restart: unless-stopped
    healthcheck: 
      test: ["CMD", "haproxy", "-c", "-f", "/usr/local/etc/haproxy/haproxy.cfg"]
      interval: 30s
      timeout: 10s
      retries: 3
    logging: 
      driver: json-file
      options:
        max-size: "500m"
        max-file: "3"

  nginx1:
    image: nginx:${VERSION}
    environment:
      TZ: ${TIMEZONE}
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/ssl/private:ro
      - ./html:/usr/share/nginx/html
      - /data/logs/nginx1:/var/log/nginx:rw 
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "nginx -t && ps aux | grep '[n]ginx: master process' || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - webnet
    depends_on:
      - haproxy
    logging: 
      driver: json-file
      options:
        max-size: "300m"
        max-file: "3"

  nginx2:
    image: nginx:${VERSION}
    environment:
      TZ: ${TIMEZONE}
    volumes:
      - ./conf/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./certs:/etc/ssl/private:ro
      - ./html:/usr/share/nginx/html
      - /data/logs/nginx2:/var/log/nginx:rw 
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "nginx -t && ps aux | grep '[n]ginx: master process' || exit 1"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - webnet
    depends_on:
      - haproxy
    logging: 
      driver: json-file
      options:
        max-size: "300m"
        max-file: "3"

networks:
  webnet:
root@deepin-1:~/nginx-cluster# 
root@deepin-1:~/nginx-cluster# 
root@deepin-1:~/nginx-cluster# 
root@deepin-1:~/nginx-cluster# cat conf/haproxy.cfg 
global
    log stdout format raw local0
    # Tune SSL options for better performance
    tune.ssl.default-dh-param 2048

defaults
    log     global
    option  httplog
    option  dontlognull
    timeout connect 5000ms
    timeout client  50000ms
    timeout server  50000ms

# Frontend configuration
frontend https_in
    mode http
    bind *:8443 ssl crt /etc/ssl/private/localserver.com.pem
    redirect scheme https code 301 if !{ ssl_fc }
    default_backend   http_servers
    

# Backend configuration
backend http_servers
      mode http
      balance roundrobin
      option httpchk HEAD /
      http-response set-header X-Frame-Options SAMEORIGIN
      http-response set-header X-XSS-Protection 1;mode=block
      http-response set-header X-Content-Type-Options nosniff
      #default-server check maxconn 5000
      retries 5
      timeout connect 5s
      timeout server 30s
      timeout check 10s
      server nginx1 nginx1:443 ssl verify none check inter 10s fall 3 rise 2
      server nginx2 nginx2:443 ssl verify none check inter 10s fall 3 rise 2
root@deepin-1:~/nginx-cluster# cat .env
VERSION=1.25.3-alpine

TIMEZONE=Asia/Shanghai

PORT_SERVER=443

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants