1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
# Make tailscaled wait for the network before it takes over DNS.
#
# tailscaled claims /etc/resolv.conf *exclusively* through resolvconf: it drops
# a `9999999 tailscale` file into /run/resolvconf/exclusive/, which suppresses
# every other resolver, including the nameservers dhcpcd learns over DHCP.
#
# If tailscaled starts before the machine has a working network, it cannot
# reach the coordination server, so it never learns any upstream resolvers.
# It still installs the exclusive claim, and /etc/resolv.conf ends up listing
# only MagicDNS (100.100.100.100) — which has nothing to forward to. The result
# is a machine where no public name resolves at all. When DHCP finishes moments
# later its nameservers are ignored, because the exclusive claim outranks them,
# so the system never repairs itself; it takes a manual `systemctl restart
# tailscaled` to recover.
#
# That is not hypothetical: on legosi tailscaled started at 22:12:37 logging
# "network is unreachable" against every bootstrap DERP, dhcpcd only leased at
# 22:12:44, and nginx then failed to start because a `proxyPass` upstream could
# not be resolved at config-test time.
#
# The nixpkgs module only guards against this when NetworkManager is in use
# (it orders tailscaled after NetworkManager-wait-online.service), which leaves
# dhcpcd-based servers unprotected. Ordering after network-online.target covers
# both, since dhcpcd's wait-online reaches that target only once a lease exists.
{ config, lib, ... }:
let
cfg = config.profpatsch.services.tailscaleDnsOrdering;
in
{
###### interface
options = {
profpatsch.services.tailscaleDnsOrdering = {
enable = lib.mkOption {
type = lib.types.bool;
default = config.services.tailscale.enable;
defaultText = lib.literalExpression "config.services.tailscale.enable";
description = ''
Delay tailscaled until the network is actually up, so that it does
not install an exclusive, empty DNS configuration that breaks name
resolution for the whole machine until it is restarted by hand.
'';
};
};
};
###### implementation
config = lib.mkIf cfg.enable {
systemd.services.tailscaled = {
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
};
};
}
|