Skip to content

Commit 3357f78

Browse files
committed
Experimenting with macOS MagicDNS
Signed-off-by: Percy Wegmann <percy@tailscale.com>
1 parent 2ee2add commit 3357f78

3 files changed

Lines changed: 142 additions & 54 deletions

File tree

.github/workflows/test.yml

Lines changed: 68 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -16,61 +16,69 @@ jobs:
1616
fail-fast: false
1717
matrix:
1818
include:
19-
# Linux tests (AMD64)
20-
- os: ubuntu-latest
21-
runner-os: Linux
22-
arch: amd64
23-
version: latest
24-
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
25-
26-
# Try unstable too
27-
- os: ubuntu-latest
28-
runner-os: Linux
29-
arch: amd64
30-
version: unstable
31-
32-
# Try a pinned version
33-
- os: ubuntu-latest
34-
runner-os: Linux
35-
arch: amd64
36-
# leave version blank to fall back to default
37-
38-
# Linux tests (ARM64)
39-
- os: ubuntu-24.04-arm
40-
runner-os: Linux
41-
arch: arm64
42-
version: latest
43-
44-
# Windows tests (AMD64)
45-
- os: windows-latest
46-
runner-os: Windows
47-
arch: amd64
48-
version: latest
49-
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
50-
51-
- os: windows-latest
52-
runner-os: Windows
53-
arch: amd64
54-
version: unstable
55-
56-
# Windows tests (ARM64)
57-
- os: windows-11-arm
58-
runner-os: Windows
59-
arch: arm64
60-
version: latest
61-
62-
# macOS intel
63-
- os: macos-13
64-
runner-os: macOS
65-
arch: amd64
66-
version: latest
67-
ping: 100.99.0.2 # hostnames aren't resolving on MacOS, just ping IP lax-pve.pineapplefish.ts.net,lax-pve
68-
69-
# macOS ARM
70-
- os: macos-14
19+
# # Linux tests (AMD64)
20+
# - os: ubuntu-latest
21+
# runner-os: Linux
22+
# arch: amd64
23+
# version: latest
24+
# ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
25+
26+
# # Try unstable too
27+
# - os: ubuntu-latest
28+
# runner-os: Linux
29+
# arch: amd64
30+
# version: unstable
31+
32+
# # Try a pinned version
33+
# - os: ubuntu-latest
34+
# runner-os: Linux
35+
# arch: amd64
36+
# # leave version blank to fall back to default
37+
38+
# # Linux tests (ARM64)
39+
# - os: ubuntu-24.04-arm
40+
# runner-os: Linux
41+
# arch: arm64
42+
# version: latest
43+
44+
# # Windows tests (AMD64)
45+
# - os: windows-latest
46+
# runner-os: Windows
47+
# arch: amd64
48+
# version: latest
49+
# ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
50+
51+
# - os: windows-latest
52+
# runner-os: Windows
53+
# arch: amd64
54+
# version: unstable
55+
56+
# # Windows tests (ARM64)
57+
# - os: windows-11-arm
58+
# runner-os: Windows
59+
# arch: arm64
60+
# version: latest
61+
62+
# # macOS 13 intel
63+
# - os: macos-13
64+
# runner-os: macOS
65+
# arch: amd64
66+
# version: latest
67+
# ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
68+
69+
# # macOS 14 ARM
70+
# - os: macos-14
71+
# runner-os: macOS
72+
# arch: arm64
73+
# version: latest
74+
# ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
75+
76+
# macOS 15 ARM
77+
- os: macos-15
7178
runner-os: macOS
7279
arch: arm64
7380
version: latest
81+
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
7482

7583
runs-on: ${{ matrix.os }}
7684

@@ -83,7 +91,7 @@ jobs:
8391
with:
8492
node-version: "24"
8593
cache: "npm"
86-
94+
8795
- name: Install Dependencies
8896
run: npm ci
8997

@@ -104,6 +112,13 @@ jobs:
104112
retry: 3
105113
ping: "${{ matrix.ping }}"
106114

115+
# Look up names
116+
- name: Look up unqualified name
117+
run: nslookup lax-pve
118+
119+
- name: Look up qualified name
120+
run: nslookup lax-pve.pineapplefish.ts.net
121+
107122
# Test Tailscale status command
108123
- name: Check Tailscale Status
109124
if: steps.tailscale-oauth.outcome == 'success'

dist/index.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41244,6 +41244,9 @@ async function run() {
4124441244
core.debug(`Tailscale status: ${JSON.stringify(status)}`);
4124541245
if (status.BackendState === "Running") {
4124641246
core.info("✅ Tailscale is running and connected!");
41247+
if (runnerOS === runnerMacOS) {
41248+
await configureDNSOnMacOS(status);
41249+
}
4124741250
await pingHostsIfNecessary(config);
4124841251
// Explicitly exit to prevent hanging
4124941252
process.exit(0);
@@ -41255,6 +41258,10 @@ async function run() {
4125541258
}
4125641259
catch (err) {
4125741260
core.warning(`Failed to get Tailscale status: ${err}`);
41261+
if (runnerOS === runnerMacOS) {
41262+
core.setFailed(`❌ Tailscale status is required in order to configure macOS`);
41263+
process.exit(2);
41264+
}
4125841265
// Still exit successfully since the main connection worked
4125941266
core.info("✅ Tailscale daemon is connected!");
4126041267
await pingHostsIfNecessary(config);
@@ -41665,6 +41672,7 @@ async function connectToTailscale(config, runnerOS) {
4166541672
`--authkey=${finalAuthKey}`,
4166641673
`--hostname=${hostname}`,
4166741674
"--accept-routes",
41675+
"--accept-dns",
4166841676
...platformArgs,
4166941677
...config.args.split(" ").filter(Boolean),
4167041678
];
@@ -41750,6 +41758,27 @@ async function installCachedBinaries(toolPath, runnerOS) {
4175041758
}
4175141759
}
4175241760
}
41761+
async function configureDNSOnMacOS(status) {
41762+
if (!status.CurrentTailnet.MagicDNSEnabled) {
41763+
return;
41764+
}
41765+
core.info(`Setting system DNS server to 100.100.100.100 and searchdomains to ${status.CurrentTailnet.MagicDNSSuffix}`);
41766+
try {
41767+
await exec.exec("networksetup", [
41768+
"-setdnsservers",
41769+
"Ethernet",
41770+
"100.100.100.100",
41771+
]);
41772+
await exec.exec("networksetup", [
41773+
"-setsearchdomains",
41774+
"Ethernet",
41775+
status.CurrentTailnet.MagicDNSSuffix,
41776+
]);
41777+
}
41778+
catch (e) {
41779+
throw Error(`Failed to configure DNS on macOS: ${e}`);
41780+
}
41781+
}
4175341782
run();
4175441783

4175541784

src/main.ts

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,18 @@ interface TailscaleConfig {
4747
pingHosts: string[];
4848
}
4949

50+
type tailnetInfo = {
51+
MagicDNSSuffix: string;
52+
MagicDNSEnabled: boolean;
53+
};
54+
55+
type tailscaleStatus = {
56+
BackendState: string;
57+
CurrentTailnet: tailnetInfo;
58+
};
59+
5060
// Cross-platform Tailscale local API status check
51-
async function getTailscaleStatus(): Promise<any> {
61+
async function getTailscaleStatus(): Promise<tailscaleStatus> {
5262
const platform = os.platform();
5363

5464
if (platform === platformWin32) {
@@ -171,6 +181,9 @@ async function run(): Promise<void> {
171181
core.debug(`Tailscale status: ${JSON.stringify(status)}`);
172182
if (status.BackendState === "Running") {
173183
core.info("✅ Tailscale is running and connected!");
184+
if (runnerOS === runnerMacOS) {
185+
await configureDNSOnMacOS(status);
186+
}
174187
await pingHostsIfNecessary(config);
175188
// Explicitly exit to prevent hanging
176189
process.exit(0);
@@ -180,6 +193,12 @@ async function run(): Promise<void> {
180193
}
181194
} catch (err) {
182195
core.warning(`Failed to get Tailscale status: ${err}`);
196+
if (runnerOS === runnerMacOS) {
197+
core.setFailed(
198+
`❌ Tailscale status is required in order to configure macOS`
199+
);
200+
process.exit(2);
201+
}
183202
// Still exit successfully since the main connection worked
184203
core.info("✅ Tailscale daemon is connected!");
185204
await pingHostsIfNecessary(config);
@@ -686,6 +705,7 @@ async function connectToTailscale(
686705
`--authkey=${finalAuthKey}`,
687706
`--hostname=${hostname}`,
688707
"--accept-routes",
708+
"--accept-dns",
689709
...platformArgs,
690710
...config.args.split(" ").filter(Boolean),
691711
];
@@ -799,4 +819,28 @@ async function installCachedBinaries(
799819
}
800820
}
801821

822+
async function configureDNSOnMacOS(status: tailscaleStatus): Promise<void> {
823+
if (!status.CurrentTailnet.MagicDNSEnabled) {
824+
return;
825+
}
826+
827+
core.info(
828+
`Setting system DNS server to 100.100.100.100 and searchdomains to ${status.CurrentTailnet.MagicDNSSuffix}`
829+
);
830+
try {
831+
await exec.exec("networksetup", [
832+
"-setdnsservers",
833+
"Ethernet",
834+
"100.100.100.100",
835+
]);
836+
await exec.exec("networksetup", [
837+
"-setsearchdomains",
838+
"Ethernet",
839+
status.CurrentTailnet.MagicDNSSuffix,
840+
]);
841+
} catch (e) {
842+
throw Error(`Failed to configure DNS on macOS: ${e}`);
843+
}
844+
}
845+
802846
run();

0 commit comments

Comments
 (0)