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

Lego fails to bind to port 80 when obtaining certificates via security.acme #191794

Closed
Garmelon opened this issue Sep 18, 2022 · 1 comment · Fixed by #191861
Closed

Lego fails to bind to port 80 when obtaining certificates via security.acme #191794

Garmelon opened this issue Sep 18, 2022 · 1 comment · Fixed by #191861

Comments

@Garmelon
Copy link
Contributor

Garmelon commented Sep 18, 2022

Describe the bug

When using the security.acme module to obtain a certificate using listenHTTP = ":80";, lego fails to bind to the port because permission is denied.

Steps To Reproduce

  1. Configure acme:
  networking.firewall.allowedTCPPorts = [ 80 ];

  security.acme = {
    acceptTerms = true;

    certs."<domain>" = {
      email = "<email>";
      listenHTTP = ":80";
    };
  };
  1. nixos-rebuild switch
  2. journalctl -u acme-<domain>.service yields a result like the following:
Sep 18 12:10:52 taube acme-<domain>-start[58403]: + set -euo pipefail
Sep 18 12:10:52 taube acme-<domain>-start[58403]: + echo <domainhash>
Sep 18 12:10:52 taube acme-<domain>-start[58403]: + cmp -s domainhash.txt certificates/domainhash.txt
Sep 18 12:10:52 taube acme-<domain>-start[58403]: + lego --accept-tos --path . -d <domain> --email <email> --key-type ec256 --http --http.port :80 run
Sep 18 12:10:53 taube acme-<domain>-start[58419]: 2022/09/18 12:10:53 [INFO] [<domain>] acme: Obtaining bundled SAN certificate
Sep 18 12:10:54 taube acme-<domain>-start[58419]: 2022/09/18 12:10:54 [INFO] [<domain>] AuthURL: https://acme-v02.api.letsencrypt.org/acme/authz-v3/<...>
Sep 18 12:10:54 taube acme-<domain>-start[58419]: 2022/09/18 12:10:54 [INFO] [<domain>] acme: Could not find solver for: tls-alpn-01
Sep 18 12:10:54 taube acme-<domain>-start[58419]: 2022/09/18 12:10:54 [INFO] [<domain>] acme: use http-01 solver
Sep 18 12:10:54 taube acme-<domain>-start[58419]: 2022/09/18 12:10:54 [INFO] [<domain>] acme: Trying to solve HTTP-01
Sep 18 12:10:54 taube acme-<domain>-start[58419]: 2022/09/18 12:10:54 [INFO] Deactivating auth: https://acme-v02.api.letsencrypt.org/acme/authz-v3/<...>
Sep 18 12:10:54 taube acme-<domain>-start[58419]: 2022/09/18 12:10:54 Could not obtain certificates:
Sep 18 12:10:54 taube acme-<domain>-start[58419]:         error: one or more domains had a problem:
Sep 18 12:10:54 taube acme-<domain>-start[58419]: [<domain>] [<domain>] acme: error presenting token: could not start HTTP server for challenge: listen tcp :80: bind: permission denied
Sep 18 12:10:54 taube acme-<domain>-start[58403]: + echo Failed to fetch certificates. This may mean your DNS records are set up incorrectly. Selfsigned certs are in place and dependant services will still start.
Sep 18 12:10:54 taube acme-<domain>-start[58403]: Failed to fetch certificates. This may mean your DNS records are set up incorrectly. Selfsigned certs are in place and dependant services will still start.
Sep 18 12:10:54 taube acme-<domain>-start[58403]: + exit 10

Expected behavior

lego binds to port 80, serves challenge successfully and downloads certificates.

Additional context

CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
conditionally adds CAP_NET_BIND_SERVICE to CapabilityBoundingSet. The generated service file at /etc/systemd/system/acme-<domain>.service contains the line CapabilityBoundingSet=CAP_NET_BIND_SERVICE.

The port is reachable from the outside, as confirmed using nc/nc -l.

Nothing else is bound to the port, as confirmed using netstat -tulpn.

When using port 50080 instead of 80, everything works as expected and without errors.

Notify maintainers

@aanderse @andrew-d @arianvp @emilazy @flokli @m1cr0man

Metadata

  • system: "x86_64-linux"
  • host os: Linux 5.15.67, NixOS, 22.05 (Quokka), 22.05.3065.178fea1414a
  • multi-user?: yes
  • sandbox: yes
  • version: nix-env (Nix) 2.8.1
  • channels(root): "nixos-22.05"
  • nixpkgs: /nix/var/nix/profiles/per-user/root/channels/nixos
@m1cr0man
Copy link
Contributor

Hi, and thanks for the bug report. I wrote a test and was able to reproduce this :) It seems both CapabilityBoundingSet and AmbientCapabilities must be set for this to work. The systemd docs hint as to why, stating it is useful if you want to execute a process as a non-privileged user but still want to give it some capabilities. I think CapabilityBoundingSet simply limits what capabilities can be used, if allowed, not what ones are explicitly granted.

I'll hopefully have a PR for this and other things tonight.

m1cr0man added a commit to m1cr0man/nixpkgs that referenced this issue Sep 19, 2022
Fixes NixOS#191794

Lego threw a permission denied error binding to port 80.
AmbientCapabilities with CAP_NET_BIND_SERVICE was required.
Also added a test for this.
winterqt pushed a commit that referenced this issue Oct 6, 2022
Fixes #191794

Lego threw a permission denied error binding to port 80.
AmbientCapabilities with CAP_NET_BIND_SERVICE was required.
Also added a test for this.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants