Giter Site home page Giter Site logo

Comments (8)

catern avatar catern commented on June 21, 2024 1

@m1cr0man Wow, awesome change! That's much better!

Though, I still like that my approach avoids a secret key entirely in favor of Unix permissions on a Unix socket, and so is totally stateless. Regrettably, PowerDNS's HTTP API doesn't support going over a Unix socket: PowerDNS/pdns#8677
and the API in PowerDNS which can go over a Unix socket (which is not the HTTP API), doesn't support changing DNS records.

from dns.nix.

kirelagin avatar kirelagin commented on June 21, 2024

Just to be clear, by “authentication”, do you mean the DNS-01 challenge used to prove the control of the domain? In this case, no, I don’t use it. The reason is that ACME is already supported by NixOS in a fully automatic way via the HTTP-01 challenge and I don’t see an easy way to have DNS-01 supported automatically.

However, I would love to know more about the specific difficulties that you are having. I was under the impression that fulfilling a DNS-01 challenge boils down to creating a TXT record requested by Let’s Encrypt, so I would expect it to be rather straightforward with dns.nix?

from dns.nix.

catern avatar catern commented on June 21, 2024

Yes, I mean DNS-01. Yes, it seems tricky (although not impossible) to have DNS-01 supported automatically (although I don't think the HTTP challenge support is perfect - the automated support can be broken by something as simple and common as setting documentRoot)

My difficulty is this:

  • if I include my DNS records (with dns.nix and nsd) and lego (with security.acme) in my configuration.nix, then when lego runs, I don't have a chance to modify my dns.nix records to add the TXT record based on the Let's Encrypt challenge.
  • However, if I move lego out and run it manually, I don't have the normal NixOS integration. (and it's actually kind of painful to do, especially because I can't just copy out the lego command from the unit generated by NixOS, because it uses various custom systemd directives for sandboxing, for better or for worse)

From searching around it looks like some people solve this by modifying zone files with various custom scripts, invoked by lego/certbot/etc. I think from a NixOS perspective, the ideal would be to have a file that lego could just overwrite with the TXT record, and then poke the DNS server to load/reload that file. I guess this is what I will try next, although the first way to do that that comes to mind would be to stick an $INCLUDE in the zonefile, and dns.nix doesn't support $INCLUDE it looks like.

from dns.nix.

catern avatar catern commented on June 21, 2024

$INCLUDE is going to be a bit tricky since I'd need to let nsd break out of its sandbox, or bind mount a file in...

Maybe there's a DNS server that allows RFC2136 updates to be applied to a separate zone file from the main zone file? So the main zone file could be generated by dns.nix and then the Let's Encrypt updates could be done with RFC2136 in another zone file that is overlayed on the main one.

from dns.nix.

catern avatar catern commented on June 21, 2024

OK, I eventually settled on an approach of completely overwriting a separate _acme-challenge zonefile, and then triggering a reload in the DNS server. I used powerdns because it's the only DNS server that I could find which has a Unix-socket-based control tool (everything else is localhost TCP with private keys).

Here's what I did:

  services.powerdns = {
    enable = true;
    extraConfig = let
      catern.com = pkgs.writeText "catern.com" (dns.lib.toString "catern.com" (with dns.lib.combinators; {
         my_domain_config
      }));
    in
      ''
    launch=bind
    bind-config=${pkgs.writeText "named.conf" ''
      zone "catern.com" { file "${catern.com}"; };
      zone "_acme-challenge.catern.com" { file "/var/db/bind/_acme-challenge.catern.com."; };
      ''}
    '';
  };
  systemd.services.pdns.serviceConfig.ExecStartPost = "${pkgs.coreutils}/bin/chmod g+w /var/run/pdns/pdns.controlsocket";
  security.acme = {
    acceptTerms = true;
    email = "[email protected]";
    certs."catern.com" = let
      update_script = pkgs.writeScript "acme_update_dns.sh" ''
        #!/bin/sh
        set -o errexit -o nounset
        mode="$1"
        record="$2"
        token="$3"
        if test "$mode" = "present";
        then cat >/var/db/bind/$record <<EOF
        $record IN 86400 SOA catern.com. spencerbaugh.gmail.com. ($(date +'%s') 86400 600 864000 60)
        $record IN 10 TXT "$token"
        EOF
        else echo >/var/db/bind/$record;
        fi
        ${pkgs.powerdns}/bin/pdns_control bind-reload-now _acme-challenge.catern.com
        '';
    in {
      domain = "catern.com";
      group = "wwwrun";
      dnsProvider = "exec";
      credentialsFile = pkgs.writeText "conf" "EXEC_PATH=${update_script}";
      dnsPropagationCheck = false;
    };
  };
  users.users.acme.extraGroups = ["pdns"];

This actually works really well. There's no setup required outside the NixOS configuration; no need to create things manually (well, I created /var/db/bind manually but that's a simple tmpfiles snippet).

I think this could be viably integrated into upstream NixOS, so that DNS-based challenges could be supported by NixOS completely automatically in the same way HTTP challenges are supported. I filed NixOS/nixpkgs#138478 about one of the prerequisites for that.

from dns.nix.

m1cr0man avatar m1cr0man commented on June 21, 2024

Hey @catern I saw NixOS/nixpkgs#138478 but not this ticket, and I figured I would follow up.

If you are using PowerDNS you should be able to configure Lego to use the PDNS API as a DNS backend as per the lego docs. Following this part of the NixOS manual, you would set your dnsProvider to pdns, and then set the appropriate environment variables in the credentialsFile (as per lego's docs). In this sense, DNS challenges are completely automated without extra scripting required 😃 Lego's vast DNS backend support is one of the main reasons we chose it.

I imagine this solves your request? It would be interesting to know if this works for you. You would still need your external zonefile, and that bit might be a worthy candidate for a PR to the pdns module. Personally I use Bind with RFC2136 to do wildcard certificates for my own domains. I have not tried using PowerDNS.

from dns.nix.

catern avatar catern commented on June 21, 2024

Thanks for the heads up @m1cr0man

I looked into that before, but I didn't want to use the PDNS HTTP API because it requires generating a secret key and allocating a TCP port to the HTTP API. The same goes for the approach outlined in the NixOS manual: It requires generating a secret key.

The nice thing about my current approach is that there's no secret key required and no need to allocate a TCP port (since it's using a Unix socket). This allows it to be completely stateless.

from dns.nix.

m1cr0man avatar m1cr0man commented on June 21, 2024

Hey @catern I took that as some feedback and I have updated the NixOS docs in NixOS/nixpkgs#147784 . The DNS-01 section now includes an example service which will generate the DNS keys on start rather than requiring manual intervention. As far as I know, you could totally configure lego to use a unix socket for the API too since I think the Go layers will handle that fine. I too prefer a system that is stateless and can be deployed on multiple hosts. :)

from dns.nix.

Related Issues (13)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.