nix-on-droid icon indicating copy to clipboard operation
nix-on-droid copied to clipboard

modules/supervisord: init, modules/openssh: init

Open zhaofengli opened this issue 1 year ago • 15 comments

This PR adds support for running services with supervisord as well as an OpenSSH module. I wanted to run an SSH server (#32, #156) that gets automatically launched when Nix-on-Droid starts, complete with process supervision.

The supervisord.programs.<name> options are designed to resemble systemd.services.<name>:

{ pkgs, ... }:
{
  supervisord.programs.sshd = {
    path = [ pkgs.openssh ];
    autoRestart = true;
    script = ''
      ssh-keygen ...

      exec ${pkgs.openssh}/bin/sshd -D -f /etc/ssh/sshd_config
    '';
  };
}

Fixes #54.

zhaofengli avatar Sep 21 '22 09:09 zhaofengli

For completion, it would be great to have native options to add ssh pub keys in /etc/ssh/authorized_keys.d. But could be done in a separate PR, however you like :)

Gerschtli avatar Sep 21 '22 20:09 Gerschtli

Tested it on device: Running supervisorctl stop sshd does not stop the sshd process when there is an active ssh session.. Does not look like that would be expected behaviour.

Gerschtli avatar Sep 21 '22 21:09 Gerschtli

It's expected behavior because sshd forks a separate process to handle each connection. You can try by stopping sshd on NixOS (or any other distro): Existing sessions keep running but you can't establish new ones.

Okay, but there is still a sshd process running even after the last ssh connection is closed when the sshd was stopped while session where open.

Gerschtli avatar Sep 22 '22 20:09 Gerschtli

There is another UX issue with the current approach. Currently proot waits for all traced processes to terminate, so the first Nix-on-Droid session which starts supervisord won't terminate after exiting the shell. If this isn't desirable, we can start supervisord in a separate proot invocation.

zhaofengli avatar Oct 01 '22 21:10 zhaofengli

Why not detach the process from the invoking session with e.g. disown?

Gerschtli avatar Oct 11 '22 19:10 Gerschtli

Why not detach the process from the invoking session with e.g. disown?

Sadly this can't work because proot needs to ptrace all processes in the session to perform its hooking, so it has to be there as long as any child processes exist. There doesn't appear to be an option to have proot itself fork into the background if the "main process" exits.

zhaofengli avatar Oct 11 '22 20:10 zhaofengli

Random idea, feel free to disregard:

login -> proot -> login-inner -> session
       \
        -> (supervisord overseeing process) -> proot -> login-inner -> supervisord

t184256 avatar Oct 11 '22 20:10 t184256

Random idea, feel free to disregard:

login -> proot -> login-inner -> session
       \
        -> (supervisord overseeing process) -> proot -> login-inner -> supervisord

That's what I meant by "start supervisord in a separate proot invocation." If this is desired I'll implement it later this week.

zhaofengli avatar Oct 11 '22 20:10 zhaofengli

I still somehow thought that meant starting it from proot with extra precautions. Sorry for the noise then.

As for desireability, I'm not sure. Sounds rather involved to me wrt starting/stopping it (via signals?). If you figure out some alternative that simplifies things at the expense of, say, some support from the app, I'm open for discussing it further.

t184256 avatar Oct 11 '22 20:10 t184256

Hey @zhaofengli , is there anything where I could support you with this PR? :)

Gerschtli avatar Nov 05 '22 22:11 Gerschtli

Sorry, got distracted and forgot about this :/ Termux does appear to have a special type of session for background tasks:

Termux notification with background tasks active

One integration is implemented in Termux:Widgets, where you can drop a shell script in ~/.shortcuts/tasks and add a shortcut that launches the script in the background. We should look into whether it's possible to start such a task with /system/bin/am start or similar outside PRoot. If so, then things should be cleaner with the user still having a persistent notification even with no interactive sessions active.

zhaofengli avatar Nov 07 '22 06:11 zhaofengli

Is there a way to test this PR without rebuilding the fork? Maybe a way to patch these modules into the config?

diamondburned avatar Jan 07 '23 08:01 diamondburned

Yes, either use @zhaofengli's fork as channel/flake input or create your own fork of nix-on-droid and rebase his branch onto latest master to keep all changes that were merged in the meantime. No need for a new bootstrap zip because there were no changes :)

Gerschtli avatar Jan 07 '23 09:01 Gerschtli

create your own fork of nix-on-droid and rebase his branch onto latest master to keep all changes that were merged in the meantime

Sorry for being off-topic; how would I do this, exactly? I'm currently not using Flakes. Do I swap the Nix channel with one that points to this commit?

diamondburned avatar Jan 07 '23 11:01 diamondburned

nix-channel --list shows you the current nix-on-droid url. That's a url with repo owner, repo name and rev (probably master or release-22.11). Replace owner and rev and set within .nix-channels, afterwards run nix-channel --update and nix-on-droid switch :)

Gerschtli avatar Jan 07 '23 11:01 Gerschtli