Comments (8)
@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.
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.
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.
$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.
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.
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.
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.
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)
- Long DKIM Keys (or other long TXT record) lead to syntax error in bind9 HOT 1
- Have some tests HOT 1
- Support for unqualified domain names
- Use of `dns.nix` triggers infinite recursion HOT 5
- Is there a way to import this module to have it available in all imported files? HOT 3
- Provide more detailed examples
- "error: cannot coerce a set to a string" when eval lib.types HOT 3
- DMARC: add support for external destination verification
- provide a hostTTL function HOT 3
- Maintenance status HOT 3
- writeZone does not work when importing as flake HOT 4
- Expose defaults.ttl as an option HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from dns.nix.