Skip to content

Commit 2c45c8a

Browse files
committed
configure DNS on macOS runners
On macOS, `tailscaled` does not manage DNS. Configure it manually in the GitHub action to make sure MagicDNS name resolution works. Updates tailscale/corp#32821 Signed-off-by: Percy Wegmann <[email protected]>
1 parent d4729ea commit 2c45c8a

File tree

6 files changed

+113
-6
lines changed

6 files changed

+113
-6
lines changed

.github/workflows/test.yml

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,18 +59,26 @@ jobs:
5959
arch: arm64
6060
version: latest
6161

62-
# macOS intel
62+
# macOS 13 (AMD64)
6363
- os: macos-13
6464
runner-os: macOS
6565
arch: amd64
6666
version: latest
67-
ping: 100.99.0.2 # hostnames aren't resolving on MacOS, just ping IP lax-pve.pineapplefish.ts.net,lax-pve
67+
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
6868

69-
# macOS ARM
69+
# macOS 14 (ARM)
7070
- os: macos-14
7171
runner-os: macOS
7272
arch: arm64
7373
version: latest
74+
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
75+
76+
# macOS latest (ARM)
77+
- os: macos-latest
78+
runner-os: macOS
79+
arch: arm64
80+
version: latest
81+
ping: 100.99.0.2,lax-pve.pineapplefish.ts.net,lax-pve
7482

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

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

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

README.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ tailscale ping my-target.my-tailnet.ts.net
5353

5454
The `ping` option will wait up to to 3 minutes for a connection (direct or relayed).
5555

56-
> ⚠️ On macOS runners, one can only ping IP addresses, not hostnames.
57-
5856
## Tailnet Lock
5957

6058
If you are using this Action in a [Tailnet

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);
@@ -41750,6 +41757,28 @@ async function installCachedBinaries(toolPath, runnerOS) {
4175041757
}
4175141758
}
4175241759
}
41760+
async function configureDNSOnMacOS(status) {
41761+
if (!status.CurrentTailnet.MagicDNSEnabled) {
41762+
core.info("MagicDNS is disabled, not configuring DNS");
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

dist/logout/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25689,6 +25689,16 @@ const exec = __importStar(__nccwpck_require__(5236));
2568925689
async function logout() {
2569025690
try {
2569125691
const runnerOS = process.env.RUNNER_OS || "";
25692+
if (runnerOS === "macOS") {
25693+
// The below is required to allow GitHub's post job cleanup to complete.
25694+
core.info("Resetting DNS settings on macOS");
25695+
await exec.exec("networksetup", ["-setdnsservers", "Ethernet", "Empty"]);
25696+
await exec.exec("networksetup", [
25697+
"-setsearchdomains",
25698+
"Ethernet",
25699+
"Empty",
25700+
]);
25701+
}
2569225702
core.info("🔄 Logging out of Tailscale...");
2569325703
// Check if tailscale is available first
2569425704
try {

src/logout/logout.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,17 @@ async function logout(): Promise<void> {
88
try {
99
const runnerOS = process.env.RUNNER_OS || "";
1010

11+
if (runnerOS === "macOS") {
12+
// The below is required to allow GitHub's post job cleanup to complete.
13+
core.info("Resetting DNS settings on macOS");
14+
await exec.exec("networksetup", ["-setdnsservers", "Ethernet", "Empty"]);
15+
await exec.exec("networksetup", [
16+
"-setsearchdomains",
17+
"Ethernet",
18+
"Empty",
19+
]);
20+
}
21+
1122
core.info("🔄 Logging out of Tailscale...");
1223

1324
// Check if tailscale is available first

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);
@@ -799,4 +818,29 @@ async function installCachedBinaries(
799818
}
800819
}
801820

821+
async function configureDNSOnMacOS(status: tailscaleStatus): Promise<void> {
822+
if (!status.CurrentTailnet.MagicDNSEnabled) {
823+
core.info("MagicDNS is disabled, not configuring DNS");
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)