Local network privacy dialogue not triggered for bash script inside agent

Hi,

I'm trying to set up automated backups on my machine using a combination of restic, a wrapper script, and a launchd agent, but I think I'm hitting a problem with the local network privacy dialogue.

Basically, the script sets up the environment variables for Restic, which then tries to backup to a local REST server. Problem is, when trying to do that, I get the following error:

Fatal: unable to open config file: Head "https://X:X@X.X.X.network:8000/X/X.X.X.network/config": dial tcp 192.168.50.229:8000: connect: no route to host

So it resolves DNS just fine, but can't connect to the local server. I tried a couple of things, tools such as ping work and can ping the local server, but nothing I do fixes the issue with restic itself. After reading about the network privacy feature, which I loved by the way, I believe it's the culprit here.

This is the .plist file I'm using, which lives in ~/Library/LaunchAgents/com.james.local-backup.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>com.james.local-backup</string>
  <key>ProgramArguments</key>
  <array>
    <string>/Users/james/.local/bin/replicator</string>
    <string>--backup</string>
<string>rest:https://X.X.X.network:8000/X/X.X.X.network</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>PATH</key>
    <string>/opt/homebrew/opt/coreutils/libexec/gnubin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    <key>XDG_CONFIG_HOME</key>
    <string>/Users/james/.config</string>
  </dict>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key>
    <integer>13</integer>
    <key>Minute</key>
    <integer>0</integer>
  </dict>
  <key>StandardErrorPath</key>
  <string>/tmp/com.user.backup.err</string>
  <key>StandardOutPath</key>
  <string>/tmp/com.user.backup.out</string>
  <key>ProcessType</key>
  <string>Background</string>
</dict>
</plist>

The local network dialogue never shows up, so I can't give the wrapper script or restic access to the local network, which I assume is why it can't connect to the local server.

Any way I can solve this? I could build a proper Swift CLI that calls restic, but I assume I'd hit the same issue. Plus, it seems overkill for my needs.

Answered by DTS Engineer in 816979022
As a workaround …

That’s probably your best option here.

As I mentioned above, the system has hard time tracking the identity of a script. Most ‘real’ developers don’t care about because the user’s entry point to their product is their app. In your case, however, the script is everything; you don’t have a product that can become the responsible code for your script.

This workaround creates such a product by wrapping your script, and that’s a pretty reasonable way to get yourself out of this bind.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Local network privacy is heavily dependent on the concept of responsible code. I talk about this more in TN3179 Understanding local network privacy.

This responsible code concept is problematic when it comes to scripting, because there’s no good way for the system to track the identity of a script.

In your example, is /Users/james/.local/bin/replicator your “wrapper script”? That’s a shell script, right?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Created a new .plist file, this time calling restic directly, but the dialogue still doesn't show up.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>Label</key>
  <string>co.jamespond.local-backup</string>
  <key>ProgramArguments</key>
  <array>
    <string>/opt/homebrew/bin/restic</string>
    <string>backup</string>
    <string>--files-from</string>
    <string>/Users/james/.config/restic/include</string>
    <string>--exclude-file</string>
    <string>/Users/james/.config/restic/exclude</string>
    <string>--exclude-caches</string>
  </array>
  <key>EnvironmentVariables</key>
  <dict>
    <key>PATH</key>
    <string>/opt/homebrew/opt/coreutils/libexec/gnubin:/opt/homebrew/bin:/opt/homebrew/sbin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
    <key>RESTIC_REST_USERNAME</key>
    <string>X</string>
    <key>RESTIC_REST_PASSWORD</key>
    <string>X</string>
    <key>RESTIC_REPOSITORY</key>
    <string>X</string>
    <key>RESTIC_PASSWORD</key>
    <string>X</string>

  </dict>
  <key>StartCalendarInterval</key>
  <dict>
    <key>Hour</key>
    <integer>13</integer>
    <key>Minute</key>
    <integer>0</integer>
  </dict>
  <key>StandardErrorPath</key>
  <string>/tmp/com.user.backup.err</string>
  <key>StandardOutPath</key>
  <string>/tmp/com.user.backup.out</string>
  <key>ProcessType</key>
  <string>Background</string>
</dict>
</plist>

The error is the same as before, dial tcp 192.168.50.229:8000: connect: no route to host.

As a workaround, for now, I used https://github.com/sveinbjornt/Platypus to create a wrapper for the replicator script, and the dialogue showed up for that.

As a workaround …

That’s probably your best option here.

As I mentioned above, the system has hard time tracking the identity of a script. Most ‘real’ developers don’t care about because the user’s entry point to their product is their app. In your case, however, the script is everything; you don’t have a product that can become the responsible code for your script.

This workaround creates such a product by wrapping your script, and that’s a pretty reasonable way to get yourself out of this bind.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Local network privacy dialogue not triggered for bash script inside agent
 
 
Q