Merge nucleic/vivid-glass-urchin-xoym into main
This commit is contained in:
+27
-5
@@ -612,7 +612,7 @@ adopting it would require per-slot saved states and a careful look at DHCP lease
|
||||
reuse — not a drop-in optimization.
|
||||
|
||||
**16. macOS 15+ Local Network privacy can block host→guest connections, and
|
||||
there is no reliable way to grant it interactively here.** Per
|
||||
granting it interactively takes deliberate work.** Per
|
||||
[TN3179](https://developer.apple.com/documentation/technotes/tn3179-understanding-local-network-privacy)
|
||||
it is not TCC — the check is a Network Extension packet filter, so it is absent
|
||||
from `TCC.db`, cannot be queried, cannot be reset, and it "uses your main
|
||||
@@ -628,8 +628,30 @@ rebuild.
|
||||
(`com.apple.network.local-network`, keys `AllowedEthernetLocalNetworkAddresses`
|
||||
and `AllowedWiFiLocalNetworkAddresses`), which is keyed on the network rather
|
||||
than the app and is read at boot — so it needs a reboot, not a service restart.
|
||||
`Doctor.checkLocalNetwork` reads those keys and requires coverage of
|
||||
`LocalNetworkPolicy` owns the arithmetic and requires coverage of
|
||||
`192.168.64.0/18`, not a single /24, because the NAT subnet is chosen at runtime
|
||||
and slides to the next free /24. `SSHExec.localNetworkHint` appends the same
|
||||
guidance to connection failures, since errno 65 gives the operator nothing to go
|
||||
on by itself.
|
||||
and slides to the next free /24; `Doctor.localNetworkNote` and
|
||||
`SSHExec.localNetworkHint` both report against it, since errno 65 gives the
|
||||
operator nothing to go on by itself.
|
||||
|
||||
→ *Consequence:* both routes are commands rather than documentation.
|
||||
`permissions grant` writes the allowlist and verifies it read back (`sudo
|
||||
defaults write` lands in root's or the invoking user's preferences depending on
|
||||
whether sudo preserved `HOME`, so where it went is not assumable).
|
||||
`permissions grant --method prompt` addresses the attribution problem head-on:
|
||||
launching the installed bundle through LaunchServices (`open -n -b …`) makes the
|
||||
app its **own** responsible process, so the prompt and the Settings row belong to
|
||||
it rather than to Terminal — and because the LaunchAgent runs the same signed
|
||||
identity, the grant carries. That only became worth building once the bundle was
|
||||
Developer ID signed; under ad-hoc signing the UUID churn withdraws it on the next
|
||||
rebuild, which is why `permissions status` reports code identity alongside the
|
||||
allowlist.
|
||||
|
||||
→ *Consequence:* the prompt route is best-effort and says so. Observed on a host
|
||||
where the decision was already recorded: `UserEventAgent` resolves the flow to
|
||||
the bundle ID on every attempt — so the attribution works — but presents no
|
||||
alert, because macOS asks once per app identity and then answers from that
|
||||
record, silently, forever. There is no supported reset. So `--method prompt`
|
||||
verifies by *probing* rather than by trusting the launch, and on a denial says
|
||||
plainly that it did not take and points at the allowlist, which is not subject
|
||||
to the per-app check at all. The allowlist stays the recommendation.
|
||||
|
||||
+48
-29
@@ -441,6 +441,11 @@ disabling sleep (`sudo pmset -a sleep 0 disablesleep 1`) so the Mac comes back i
|
||||
after a power event without a human present. This does mean the disk is effectively unlocked at
|
||||
boot — appropriate for a dedicated CI machine, not for a shared workstation.
|
||||
|
||||
On a terminal, `service install` also asks whether to configure Local Network access (§2.6) when it
|
||||
is not already, defaulting to no. It never blocks: a scripted install with no terminal prints a
|
||||
pointer and carries on. `--grant-local-network allowlist|prompt|none` decides it up front instead of
|
||||
being asked.
|
||||
|
||||
`service uninstall` removes the LaunchAgent; it does not delete images or config.
|
||||
|
||||
### 2.6 macOS 15+ Local Network privacy prompt
|
||||
@@ -449,32 +454,41 @@ Starting with macOS 15, a process that contacts other hosts on the local network
|
||||
one-time Local Network permission prompt. A LaunchAgent that is denied (or that never gets a human
|
||||
to click Allow) cannot reach the guest's NAT address, so VMs boot but SSH never connects.
|
||||
|
||||
**On a CI host, use the subnet allowlist.** It is the only deterministic option — no prompt, no GUI
|
||||
session, and nothing to redo after a rebuild:
|
||||
`service install` offers to configure this, and it can also be done at any time:
|
||||
|
||||
```sh
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedEthernetLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedWiFiLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
gitea-macos-runner permissions status # what is configured, and what to do about it
|
||||
gitea-macos-runner permissions grant # configure it
|
||||
```
|
||||
|
||||
Then **reboot** — these are read at boot, so restarting the service alone is not enough.
|
||||
`grant` has two methods. Both are one command; neither needs anything pasted.
|
||||
|
||||
**Do not pin this to a single /24.** Virtualization.framework's NAT starts at `192.168.64.0/24` but
|
||||
picks the subnet at runtime and steps to the next free one when that range is already in use, so the
|
||||
same host can hand out `192.168.65.x` tomorrow. An allowlist naming only `192.168.64.0/24` then
|
||||
looks configured while silently blocking every guest — the failure surfaces as `No route to host`
|
||||
(errno 65) on the SSH connection, not as a permission error. The `/18` above spans
|
||||
`192.168.64.0`–`192.168.127.255`, which covers the drift; if you would rather not think about
|
||||
ranges at all, the RFC 1918 set `"10.0.0.0/8" "172.16.0.0/12" "192.168.0.0/16"` also works. `doctor`
|
||||
reports `local network access` as a **pass** once it sees an allowlist that covers that span, and as
|
||||
a **warning** when an allowlist exists but does not. Both keys are documented by Apple in
|
||||
[TN3179](https://developer.apple.com/documentation/technotes/tn3179-understanding-local-network-privacy)
|
||||
and are the workaround [Tart's FAQ](https://tart.run/faq/) recommends for the same problem.
|
||||
**`--method allowlist` (the default) is what a CI host wants.** It writes a subnet allowlist — the
|
||||
one deterministic option: no prompt, no GUI session, and nothing to redo after a rebuild. It asks
|
||||
for your sudo password, reports which preferences file the write actually landed in, and then offers
|
||||
to **reboot**, which is required: these values are read at boot, so restarting the service alone is
|
||||
not enough. Pass `--no-reboot` to defer that.
|
||||
|
||||
**Why not just approve the prompt?** Because on this host there is usually nothing able to show it,
|
||||
and when something does, it is attributed to the wrong program.
|
||||
The default grant is all of RFC 1918 — `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` — the same
|
||||
set [Tart](https://tart.run/faq/) and orchard use. Narrow it with `--subnet`, repeatable, but **do
|
||||
not pin it to a single /24**: Virtualization.framework's NAT starts at `192.168.64.0/24` but picks
|
||||
the subnet at runtime and steps to the next free one when that range is already in use, so the same
|
||||
host can hand out `192.168.65.x` tomorrow. An allowlist naming only `192.168.64.0/24` then looks
|
||||
configured while silently blocking every guest — and the failure surfaces as `No route to host`
|
||||
(errno 65) on the SSH connection, not as a permission error. `192.168.64.0/18` spans
|
||||
`192.168.64.0`–`192.168.127.255`, which is the narrowest entry that covers the drift. `doctor`
|
||||
reports `local network access` as a **pass** once it sees an allowlist covering that span, and as a
|
||||
**warning** when an allowlist exists but does not. Both keys are documented by Apple in
|
||||
[TN3179](https://developer.apple.com/documentation/technotes/tn3179-understanding-local-network-privacy).
|
||||
|
||||
**`--method prompt` takes effect immediately, with no reboot**, and is the better choice on a Mac
|
||||
you are sitting in front of. It launches the installed `.app` through LaunchServices — which is what
|
||||
makes the app its own responsible process — provokes the real system alert, and reports whether the
|
||||
grant took. It needs `make install` to have run, a GUI session to show the alert in, and a Developer
|
||||
ID signature for the grant to survive the next rebuild; `permissions status` reports that last one.
|
||||
|
||||
**Why the prompt needs that much machinery.** Left to itself, on this host there is usually nothing
|
||||
able to show it, and when something does, it is attributed to the wrong program.
|
||||
|
||||
An app appears under **System Settings → Privacy & Security → Local Network** only *after* it has
|
||||
attempted a connection to a guest, so an empty list on a fresh install is expected and means
|
||||
@@ -490,14 +504,19 @@ miss:
|
||||
approving it there does not carry over to the LaunchAgent. (If you are hunting for a row that
|
||||
seems missing, look for Terminal rather than for "Gitea macOS Runner".)
|
||||
|
||||
> **And under ad-hoc signing it is not durable anyway.** Local Network privacy does not use TCC; per
|
||||
> TN3179 it "uses your main executable UUID as part of its implementation", and the linker mints a
|
||||
> fresh `LC_UUID` on essentially every rebuild. So `make install` after a code change presents as a
|
||||
> new app that must be approved again — and macOS offers no way to reset a Local Network decision
|
||||
> back to undetermined, so stale entries accumulate. Signing with a Developer ID certificate fixes
|
||||
> the churn (see [Code signing](#code-signing)); the subnet allowlist above, keyed on the network
|
||||
> rather than on the app, sidesteps the whole mechanism and is the recommendation for an unattended
|
||||
> machine either way.
|
||||
`permissions grant --method prompt` exists to thread that needle: it starts the app through
|
||||
LaunchServices rather than from the shell, so the app is its own responsible process and the
|
||||
decision is recorded against *its* identity — the same identity the LaunchAgent runs under.
|
||||
|
||||
> **Under an ad-hoc signature it is not durable anyway.** Local Network privacy does not use TCC;
|
||||
> per TN3179 it "uses your main executable UUID as part of its implementation", and the linker mints
|
||||
> a fresh `LC_UUID` on essentially every rebuild. So `make install` after a code change presents as
|
||||
> a new app that must be approved again — and macOS offers no way to reset a Local Network decision
|
||||
> back to undetermined, so stale entries accumulate. A Developer ID signature fixes the churn, since
|
||||
> the identity is then anchored to the certificate rather than to the binary (see
|
||||
> [Code signing](#code-signing)) — that is what makes `--method prompt` worth using at all. The
|
||||
> subnet allowlist, keyed on the network rather than on the app, sidesteps the whole mechanism and
|
||||
> remains the recommendation for an unattended machine.
|
||||
|
||||
---
|
||||
|
||||
@@ -531,7 +550,7 @@ The checks, in order:
|
||||
| `runner download url` | The `gitea-runner` release asset is reachable |
|
||||
| `token file permissions` | Warns — not fails — when a token file is group- or world-readable |
|
||||
| `guest ssh` | Reachability of the most recent guest lease, when there is one. Warns on a timeout, which is most often a stale 24-hour lease for a guest that is already gone |
|
||||
| `local network access` | Passes when a subnet allowlist covers `192.168.64.0/18`; warns when an allowlist exists but is scoped too narrowly; otherwise an informational note about the macOS 15+ Local Network prompt (§2.6) |
|
||||
| `local network access` | Passes when a subnet allowlist covers `192.168.64.0/18`; warns when an allowlist exists but is scoped too narrowly; otherwise an informational note about the macOS 15+ Local Network prompt. Fix either with `permissions grant` (§2.6) |
|
||||
|
||||
If the config file is missing or invalid, the host checks still run and the rest
|
||||
are skipped — which is exactly the state a first-time operator is in. Resolve
|
||||
|
||||
+59
-46
@@ -23,12 +23,12 @@ gitea-macos-runner service status
|
||||
| --- | --- | --- |
|
||||
| VM won't start; entitlement / `com.apple.security.virtualization` error | Running an unsigned binary, or one outside the signed `.app` bundle | `make sign` (or re-run `make install`); invoke the installed bundle, never `.build/release/…` |
|
||||
| `virtualMachineLimitExceeded` at boot | macOS allows at most **2** concurrent macOS VMs | Set `scheduler.maxConcurrentVMs` ≤ 2; kill stray VMs from earlier runs |
|
||||
| VM boots but never gets an IP | DHCP lease not yet written, or Local Network privacy denial (macOS 15+) | Check `/var/db/dhcpd_leases`; grant Local Network permission or pre-authorize the subnet |
|
||||
| Runner not listed under Privacy & Security → Local Network | Expected — the list is populated only after the app first attempts a local connection, and a run started from a shell is attributed to Terminal, not to the app | Allowlist the subnet with `defaults write com.apple.network.local-network` and reboot; the interactive grant does not reach the LaunchAgent |
|
||||
| VM boots but never gets an IP | DHCP lease not yet written, or Local Network privacy denial (macOS 15+) | Check `/var/db/dhcpd_leases`; `gitea-macos-runner permissions grant` |
|
||||
| Runner not listed under Privacy & Security → Local Network | Expected — the list is populated only after the app first attempts a local connection, and a run started from a shell is attributed to Terminal, not to the app | `gitea-macos-runner permissions grant` (allowlist, then reboot), or `--method prompt` to raise the alert as the app rather than as Terminal |
|
||||
| SSH times out on a freshly built image | Guest macOS < 27, so provisioning options were ignored and Setup Assistant is waiting | Rebuild the image from a macOS **27+** IPSW |
|
||||
| VMs boot in a loop; every teardown says `reason=cancelled` and nothing is logged between the lease and the teardown | `scheduler.bootTimeoutSeconds` is below the guest's *worst-case* boot on a contended host, so each clone is killed while still starting — and each replacement makes the next one slower | Raise `scheduler.bootTimeoutSeconds` (default 900) and reduce the number of concurrent guests; see [The daemon boots VMs forever](#the-daemon-boots-vms-forever-and-every-teardown-says-reasoncancelled) |
|
||||
| `ssh failed: cannot connect … No route to host) (errno: 65)` part-way through provisioning | macOS 15+ Local Network privacy blocking the app — the grant is keyed on the executable's UUID, so `make install` withdraws it | Allowlist the subnet (`192.168.64.0/18`) and **reboot**; see [SSH fails with "No route to host" mid-run](#ssh-fails-with-no-route-to-host-errno-65-mid-run) |
|
||||
| Allowlist is set but guests are still unreachable | It names `192.168.64.0/24` while the NAT has moved to `192.168.65.x` | Widen it to `192.168.64.0/18` and reboot; `doctor` now warns about too-narrow allowlists |
|
||||
| `ssh failed: cannot connect … No route to host) (errno: 65)` part-way through provisioning | macOS 15+ Local Network privacy blocking the app — the grant is keyed on the executable's UUID, so `make install` withdraws it | `gitea-macos-runner permissions grant`, then **reboot**; see [SSH fails with "No route to host" mid-run](#ssh-fails-with-no-route-to-host-errno-65-mid-run) |
|
||||
| Allowlist is set but guests are still unreachable | It names `192.168.64.0/24` while the NAT has moved to `192.168.65.x` | `gitea-macos-runner permissions grant` (defaults to all of RFC 1918) and reboot; `doctor` warns about too-narrow allowlists |
|
||||
| `SecKeyCreateRandomKey` / "Interaction is not allowed" | `login.keychain` is locked — no GUI session | Run as a LaunchAgent in an unlocked GUI session; enable auto-login |
|
||||
| Job stays queued forever | Label mismatch, or the daemon isn't running/reaching Gitea | Use bare label names in `runs-on`; match `runner.labels`; check daemon logs |
|
||||
| `actions/checkout` fails instantly | Node.js missing from the guest image | `gitea-macos-runner image provision <name>` |
|
||||
@@ -105,26 +105,24 @@ prompt**: a LaunchAgent that was never granted permission (or was denied) cannot
|
||||
An entry with a recent `lease` timestamp and the guest's MAC means networking is fine and the
|
||||
problem is timing — raise `scheduler.bootTimeoutSeconds`.
|
||||
|
||||
2. No entry at all: pre-authorize the VM subnet, then **reboot** (these are read at boot):
|
||||
2. No entry at all: check and fix the permission.
|
||||
|
||||
```sh
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedEthernetLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedWiFiLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
gitea-macos-runner permissions status
|
||||
gitea-macos-runner permissions grant # then reboot when it offers
|
||||
```
|
||||
|
||||
The `/18` is deliberate: the NAT subnet is chosen at runtime and slides to the next free /24
|
||||
(192.168.65.x, .66.x, …) when one is taken, so a pinned `192.168.64.0/24` breaks the day it
|
||||
moves. `doctor` reports `local network access` as a pass once it sees an allowlist covering that
|
||||
span. This is the deterministic fix for an unattended host —
|
||||
see [Local Network: the app is not listed in System Settings](#local-network-the-app-is-not-listed-in-system-settings)
|
||||
for why the interactive grant is not.
|
||||
`grant` pre-authorizes the VM subnets and offers to reboot, which is required — the allowlist is
|
||||
read at boot. It grants all of RFC 1918 by default; `--subnet` narrows it, but nothing narrower
|
||||
than `192.168.64.0/18` is safe, because the NAT subnet is chosen at runtime and slides to the next
|
||||
free /24 (192.168.65.x, .66.x, …) when one is taken, so a pinned `192.168.64.0/24` breaks the day
|
||||
it moves. `doctor` reports `local network access` as a pass once it sees an allowlist covering
|
||||
that span.
|
||||
|
||||
Do not reach for the interactive grant instead. Booting a VM by hand from a Terminal makes the
|
||||
prompt (and the **System Settings → Privacy & Security → Local Network** row) belong to
|
||||
*Terminal* rather than to this app, and approving it there does not carry over to the
|
||||
LaunchAgent.
|
||||
This is the deterministic fix for an unattended host. On a Mac with someone in front of it,
|
||||
`permissions grant --method prompt` applies immediately with no reboot —
|
||||
see [Local Network: the app is not listed in System Settings](#local-network-the-app-is-not-listed-in-system-settings)
|
||||
for what it does and why granting the prompt by hand does not work.
|
||||
|
||||
---
|
||||
|
||||
@@ -156,23 +154,36 @@ gitea-macos-runner vm boot --image default
|
||||
prompt and the Settings row belong to Terminal, and allowing it there does **not** carry over to the
|
||||
LaunchAgent, which is the process that actually needs it. Meanwhile the LaunchAgent itself has no UI
|
||||
to show a prompt in, so from it the connection is denied outright and surfaces as `No route to host`
|
||||
(errno 65) rather than as a permission error. Between the two, there is no reliable way to grant
|
||||
this interactively on an unattended host.
|
||||
(errno 65) rather than as a permission error.
|
||||
|
||||
**Fix — deterministic, and what to use on any host running the LaunchAgent.** Allowlist the VM
|
||||
subnet instead. It is keyed on the network rather than on the app, so no prompt is involved, and
|
||||
nothing needs redoing:
|
||||
subnets instead. The allowlist is keyed on the network rather than on the app, so no prompt is
|
||||
involved and nothing needs redoing:
|
||||
|
||||
```sh
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedEthernetLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedWiFiLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
gitea-macos-runner permissions grant
|
||||
```
|
||||
|
||||
Reboot afterwards. `doctor` then reports `local network access` as a **pass**. Both keys are
|
||||
Apple's, documented in TN3179; the same pair is what [Tart's FAQ](https://tart.run/faq/) recommends
|
||||
for this exact problem on CI hosts.
|
||||
That asks for your sudo password, writes both of Apple's keys (documented in TN3179 — the same pair
|
||||
[Tart's FAQ](https://tart.run/faq/) recommends for this exact problem on CI hosts), reports which
|
||||
preferences file the write landed in, and offers to reboot. Reboot is required: the values are read
|
||||
at boot. `doctor` then reports `local network access` as a **pass**.
|
||||
|
||||
**On a Mac you are sitting at,** `permissions grant --method prompt` is the alternative, and it
|
||||
needs no reboot. It launches the installed `.app` through LaunchServices instead of exec'ing it from
|
||||
the shell, which is exactly what makes the app its own responsible process — so the alert, and the
|
||||
Settings row it creates, belong to the app rather than to Terminal, and the decision applies to the
|
||||
LaunchAgent. It requires `make install` to have run, a GUI session, and a Developer ID signature to
|
||||
be durable (see below); `permissions status` reports all three.
|
||||
|
||||
**If `--method prompt` reports "still blocked" and you never saw an alert,** macOS most likely
|
||||
already has a decision on file for the app. It prompts exactly once per app identity and then
|
||||
answers from that record forever — silently, with `EHOSTUNREACH`, and with no supported way to reset
|
||||
it back to undetermined. The app *is* being evaluated under its own identity at that point (you can
|
||||
confirm with `log show --last 2m --predicate 'subsystem == "com.apple.networkextension"'`, which
|
||||
names the bundle ID on every attempt); the system simply is not asking. Switch the row on in
|
||||
**System Settings → Privacy & Security → Local Network**, or use the allowlist, which bypasses the
|
||||
per-app check entirely.
|
||||
|
||||
> **And an ad-hoc signed bundle cannot hold the grant anyway.** TN3179 notes that "local network
|
||||
> privacy uses your main executable UUID as part of its implementation". An ad-hoc signature has no
|
||||
@@ -636,27 +647,29 @@ Two details make it look intermittent rather than like a permission problem:
|
||||
responsible process, so the app's own identity is not what is being evaluated when you launch it
|
||||
by hand — and a grant given to Terminal does nothing for the LaunchAgent.
|
||||
|
||||
**Fix.** Allowlist the subnet — it is keyed on the network, not on the app, so no rebuild can
|
||||
withdraw it and no prompt has to be answered:
|
||||
**Fix.** Allowlist the subnets — the allowlist is keyed on the network, not on the app, so no
|
||||
rebuild can withdraw it and no prompt has to be answered:
|
||||
|
||||
```sh
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedEthernetLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
sudo defaults write com.apple.network.local-network \
|
||||
AllowedWiFiLocalNetworkAddresses -array "192.168.64.0/18"
|
||||
sudo reboot
|
||||
gitea-macos-runner permissions grant
|
||||
```
|
||||
|
||||
The values are only read at boot, so **the reboot is not optional** — until it happens, `defaults
|
||||
read com.apple.network.local-network` shows the new setting while the filter still behaves as
|
||||
before.
|
||||
It writes both of Apple's keys with sudo, verifies the values read back, and offers to reboot. The
|
||||
values are only read at boot, so **the reboot is not optional** — until it happens, `defaults read
|
||||
com.apple.network.local-network` shows the new setting while the filter still behaves as before.
|
||||
|
||||
Use `/18`, not `/24`. Virtualization.framework's NAT starts at `192.168.64.0/24` but chooses the
|
||||
subnet at runtime and steps to the next free /24 when that one is in use, so hosts drift to
|
||||
`192.168.65.x` and beyond. An allowlist naming a single /24 that the NAT has since moved off is the
|
||||
worst case: it reads as configured, `doctor` used to call it a pass, and every guest connection
|
||||
still fails with errno 65. `doctor` now warns instead when the allowlist does not cover
|
||||
`192.168.64.0`–`192.168.127.255`.
|
||||
The default grant is all of RFC 1918. If you narrow it with `--subnet`, use `/18`, not `/24`.
|
||||
Virtualization.framework's NAT starts at `192.168.64.0/24` but chooses the subnet at runtime and
|
||||
steps to the next free /24 when that one is in use, so hosts drift to `192.168.65.x` and beyond. An
|
||||
allowlist naming a single /24 that the NAT has since moved off is the worst case: it reads as
|
||||
configured, `doctor` used to call it a pass, and every guest connection still fails with errno 65.
|
||||
`doctor` now warns instead when the allowlist does not cover `192.168.64.0`–`192.168.127.255`, and
|
||||
`permissions grant` warns at the point you ask for something that narrow.
|
||||
|
||||
**If you are at the machine and would rather not reboot,** `permissions grant --method prompt`
|
||||
launches the installed app through LaunchServices so the system alert is attributed to the app
|
||||
rather than to Terminal, and takes effect immediately. It needs a GUI session and a Developer ID
|
||||
signature to stick across rebuilds.
|
||||
|
||||
**Verifying.** After the reboot, `gitea-macos-runner doctor` should show `local network access` as a
|
||||
pass naming the range. Re-run the command that failed; nothing else needs redoing, and
|
||||
|
||||
Reference in New Issue
Block a user