Changing ssh-agent private key timeout

  • 1. Edit /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist
  • 2. Add the two options
<string>-t</string>
<string>1800</string>

to

<key>ProgramArguments</key>

N.B. The flag -t and the value 1800 have to be seperate elements (apparently).

  • 3. Quit Terminal, log out & log in, restart Terminal, done

Removing or adding a service from launchd as user

  • 1. Find the service, try launchctl list or launchctl <service>
  • 2. Unload and disable with
$ launchctl unload -w <plist file path>

This unloads (and stops) the specific service. -w tells launchd to disable the service as well.

  • 3. Log out and log in, done

To add the service again

  • 4. Load the service with launchctl:
$ launchctl load -w <plist file path>
  • 5. Log out and log in

Adding a launch service as user

Here we stop the system default ssh-agent service and add our own in our own directory.

  • 1. Unload the system-wide service:
$ launchctl unload -w /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist
  • 2. Copy the file to your own homedir:
$ cp /System/Library/LaunchAgents/org.openbsd.ssh-agent.plist ~/Library/LaunchAgents/
  • 3. Edit some settings, such as the ssh-agent timeout
$ vim ~/Library/LaunchAgents/org.openbsd.ssh-agent.plist
  • 4. Load the new service as user
$ launchctl load -w ~/Library/LaunchAgents/org.openbsd.ssh-agent.plist
  • 5. Verify it is indeed loaded
$ launchctl list | grep ssh
-       0       org.openbsd.ssh-agent

This means launchctl knows about this service. Column 1 is the PID (none), col 2 is the last exit status (not started). Column 3 is the service name.

More information is gained by querying the service itself:

$ launchctl list org.openbsd.ssh-agent
{
        "Label" = "org.openbsd.ssh-agent";
        "LimitLoadToSessionType" = "Aqua";
        "OnDemand" = true;
        "LastExitStatus" = 0;
        "PID" = 4978;
        "TimeOut" = 30;
        "ProgramArguments" = (
                "/usr/bin/ssh-agent";
                "-l";
                "-t";
                "1800";
        );
        "EnableTransactions" = true;
        "TransactionCount" = 0;
        "Sockets" = {
                "Listeners" = (
                        file-descriptor-object;
                );
        };
};
;
  • 6. Quit terminal, log out & in, start terminal, ssh somewhere:
$ ssh <server>

This will start the ssh-agent and you will be greeted with a familiar Keychain login (Leopard and higher). ssh-agent now runs with your (custom) options:

$ ps ax | grep ssh-agent
3140   ??  S      0:00.03 /usr/bin/ssh-agent -l -t 1800
  • 7. Rejoice!

Reload new configuration parameters without loggin out

  • 1. Stop the service
$ launchctl unload Library/LaunchAgents/org.openbsd.ssh-agent.plist
  • 2. Re-load the service
$ launchctl load Library/LaunchAgents/org.openbsd.ssh-agent.plist
  • 3. Check the settings
$ launchctl list org.openbsd.ssh-agent
  • 4. Start the service manually
$ launchctl start org.openbsd.ssh-agent

This is approximately how far I got, everything seems to work except the environment variable SSH_AUTH_SOCK. Here are some things that look right but don't work properly:

  • 5. Unset SSH_AUTH_SOCK variable
$ launchctl unsetenv SSH_AUTH_SOCK
  • 6. Re-set SSH_AUTH_SOCK manually (system wide)
$ launchctl setenv SSH_AUTH_SOCK $(launchctl getenv SSH_AUTH_SOCK)
$ export SSH_AUTH_SOCK=$(launchctl getenv SSH_AUTH_SOCK)
  • 7. Rejoice!

N.B. Somehow this still does not properly work, you have to run export for all Terminal sessions. SSH_AUTH_SOCK is set to the previous value otherwise. I don't know why or where this is configured.

Some other things I found out, background information

  • launchctl controls launchd
FILES
     ~/Library/LaunchAgents         Per-user agents provided by the user.
     /Library/LaunchAgents          Per-user agents provided by the adminis-
                                    trator.
     /Library/LaunchDaemons         System wide daemons provided by the admin-
                                    istrator.
     /System/Library/LaunchAgents   Mac OS X Per-user agents.
     /System/Library/LaunchDaemons  Mac OS X System wide daemons.

  • launchctl is user-specific, i.e.
$ sudo launchctl list

gives a different output than

$ launchctl list
  • launchctl load and launchctl unload load a certain service into launchd. This does not mean it will be started immediately, some services are on-demand.

- load and unload have a -w flag that disabled loading, this is stored elsewhere on disk (overrides.plist (?)), possibly in

/private/var/db/launchd.db/com.apple.launchd/overrides.plist

or

private/var/db/launchd.db/com.apple.launchd.peruser.<number>/overrides.plist
  • Some services create sockets (?) in /tmp/ that listen to connections. In the case of ssh-agent, this can for example be /tmp/launch-oEZ3J9/Listeners. launchd sets the environment variable SSH_AUTH_SOCK to this location. When ssh is issued, lauchd detects somebody wants to use ssh-agent and starts this.
  • Manually setting SSH_AUTH_SOCK to the right listener also 'works'.
  • launchctl getenv SSH_AUTH_SOCK gives the right socket
  • Restarting Terminal or applications in general might be necessary to reload updated launchd information
  • My launchctl list org.openbsd.ssh-agent output (after tampering and restoring):
[tim@Saturn] LaunchAgents% launchctl list org.openbsd.ssh-agent
{
        "Label" = "org.openbsd.ssh-agent";
        "LimitLoadToSessionType" = "Aqua";
        "OnDemand" = true;
        "LastExitStatus" = 512;
        "PID" = 917;
        "TimeOut" = 30;
        "ProgramArguments" = (
                "/usr/bin/ssh-agent";
                "-l";
        );
        "EnableTransactions" = true;
        "TransactionCount" = 0;
        "Sockets" = {
                "Listeners" = (
                        file-descriptor-object;
                );
        };
};

Some unresolved issues

  • After loading/unloading with launchctl as user and as root, SSH_AUTH_SOCK did not seem to be generated properly anymore. Why?
  • For ssh-agent does it matter if you load the service as root or user?
  • Are load and unload operations persistent over reboots? If so, where is this stored?

References

On the -w flag and disabling services permanently