nix-community / nix-on-droid

Nix-enabled environment for your Android device. [maintainers=@t184256,@Gerschtli]
https://nix-on-droid.unboiled.info
MIT License
1.29k stars 72 forks source link

modules/supervisord: init, modules/openssh: init #203

Open zhaofengli opened 2 years ago

zhaofengli commented 2 years ago

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.

Gerschtli commented 2 years ago

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 commented 2 years ago

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 commented 2 years ago

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.

zhaofengli commented 2 years ago

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.

Gerschtli commented 1 year ago

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

zhaofengli commented 1 year ago

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.

t184256 commented 1 year ago

Random idea, feel free to disregard:

login -> proot -> login-inner -> session
       \
        -> (supervisord overseeing process) -> proot -> login-inner -> supervisord
zhaofengli commented 1 year ago

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.

t184256 commented 1 year ago

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.

Gerschtli commented 1 year ago

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

zhaofengli commented 1 year ago

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.

diamondburned commented 1 year ago

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

Gerschtli commented 1 year ago

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 :)

diamondburned commented 1 year ago

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?

Gerschtli commented 1 year ago

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 :)

expenses commented 4 months ago

What's the status of this PR? I've been using it for some basic services and I'm pretty happy with it. Would be good to get it merged if possible.

bbigras commented 2 weeks ago

Another friendly ping. Any progress on this?