SSH server on CyanogenMod 10.1

Updated Sunday, January, 24 2013, trying to address all issues raised in the comments below.

I have used Android QuickSSHd in the past to connect my Android devices with my Linux desktop. Since I installed CyanogenMod 10.1 nighty builds on them, none of the known SSH apps seem to work anymore. The Cyanogen wiki has a page about how to setup the Dopbear SSH daemon, but also states that since CynogenMod 9.x it is no longer included.

Apparently the original OpenSSH_6.0p1 is included with Android 4.2.1 (JellyBean) although it is not configured and support for sftp is missing. Here is what I did to have it up and running.

Download the sftp-server Android binary from this comment on Google code.

On my desktop I created a SSH daemon configuration file sshd_config.

# Minimal OpenSSH daemon configuration for CyanogenMod 10.1+
AuthorizedKeysFile /data/.ssh/authorized_keys
ChallengeResponseAuthentication no
PasswordAuthentication no
PermitRootLogin without-password
Subsystem sftp internal-sftp
pidfile /data/ssh/

Copy the created configuration file and my SSH public key to the Android device in the appropriate directories:

adb root
adb remount
adb push sshd_config /data/ssh/
adb push ~/.ssh/ /data/.ssh/authorized_keys

Create host keys and adjust file permissions on the device:

adb shell ssh-keygen -A
adb shell chmod 600 /data/.ssh/authorized_keys
adb shell chmod 644 /data/ssh/sshd_config

Its time to do a connection-test.

Find out the current IP address of the Android device:

adb shell ip addr show|grep 'inet '
    inet scope host lo
    inet brd scope global wlan0

Start the SSH daemon in debug mode on the Android device:

adb shell /system/bin/sshd -d

… then connect your SSH and SFTP clients in verbose mode:

ssh -v root@
sftp -v root@

If all works out, we tell the Android device to start the SSH-daemon automatically as service on boot. For this we first need to create a service-script called on our Desktop computer:


umask 077


# Generate rsa1, rsa, dsa and ecdsa host keys, if not already existing
ssh-keygen -A

if [ "1" == "$DEBUG" ] ; then
# run sshd in debug mode and capture output to logcat
/system/bin/logwrapper /system/bin/sshd -D -d
# don't daemonize - otherwise we can't stop the sshd service
/system/bin/sshd -D

Let’s install our service script on the Android device:

adb push /data/ssh/
adb shell chmod 755 /data/ssh/
adb shell mkdir -p /data/local/userinit.d
adb shell ln -s /data/ssh/ /data/local/userinit.d/90sshd

Sourcecode for OpenSSH in Android CyanogenMod is found here.

22 thoughts on “SSH server on CyanogenMod 10.1

  1. Unfortunately some of it will be lost after system updates. To get it back:
    adb root
    adb remount
    adb push sshd_config /system/etc/ssh/
    adb push sftp-server /system/bin/
    adb shell chmod 755 /system/bin/sftp-server

  2. This works fine for me as long as I am root and using ssh keys from root on on the connecting machine. For any other user I can’t get it to work. Anything obvious I’m overlooking here?

  3. That reads more like a SSH configuration problem on your connecting device to me.
    The Android device does not care, who is connecting to it as long as the supplied SSH key does match the root user on the Android device.
    My line “adb push ~/.ssh/ /data/ssh/authorized_keys” above implies that you already have existing SSH keys as a user (not as root) in your personal home-directory. If not you can create them as follows on your connecting system (not as root!):

    user@host:~$ ssh-keygen
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/user/.ssh/id_rsa):[Enter]
    user@host:~$ cat ~/.ssh/*.pub >> ~/.ssh/authorized_keys

    Make sure all the files in your personal .ssh directory are owned by your own userprofile and group (not root).
    user@host:~$ cd ~
    user@host:~$ sudo chown -R user:user .ssh

    Make sure that only your user has read and write access to your private keys (not even root) and others (including root) have only read access to your public keys.
    user@host:~$ chmod -R 600 ~/.ssh
    user@host:~$ chmod 644 ~/.ssh/*.pub

    Hope this helps. If not check the ssh and ssh-keygen manpages.

  4. Thanks for this nice solution. Works great!

    But how do you remount /system rw for SFTP? If i use apps like ‘root explorer’ to remount (like i did on previous Android versions) it doesn’t work for SSH/SFTP anymore. Somehow the remount is “user-bound” (to UID) now or something like this…

    If i do a ‘mount -o remount,rw /system’ it is only rw mounted for the shell, not for other apps like ‘root explorer’ or SSH/SFTP. The only global remount seems to be ‘adb remount’ but that’s too much hassle. There must be an easier way…

    Do you know any solution?

  5. Did not test it, but first thing that comes to my mind is wrapping the sftp binary in a shell script which does the remount before calling the sftp binary. Then change the subsystem line in the sshd.conf to point to that shell-script. The drawback is that it will always be remounted, no more read-only access at all.

  6. This is a great tutorial. I noticed in the first comment Alain stated that you will lose somethings after a system update. This can be resolved with a simple script being placed in /system/addon.d . This is how gapps are kept after a system update. There is another great tutorial located here for more information.

  7. Ahoy, I followed your guide with CM 10.1 nightlies, and I found that I needed to put the sshd_config in /data/ssh/ (where ssh-keygen puts its keys). When i did this sshd then started up and worked for ssh, but not sftp, so I copied sshd_config to /system/etc/ssh and then both worked.  So it looks like the config needs to be in both places :/ I’ve noticed that Android’s filesystem structure is pretty convoluted.

  8. Convoluted it is, especially this SSH stuff. Things are spread over /system/etc/ssh, /data/ssh, /data/.ssh and /data/ssh_client. And looking at the last commits things, are still in flux. I guess they haven’t made up their minds yet.
    From my observation, the current binary (OpenSSH_6.0 on cm-10.1-20130223-NIGHTLY) expects sshd_config and host-keys in /data/sshd/.
    However, the script /system/bin/start-ssh who starts the service, which I have linked to above overrides this to /system/etc/ssh/sshd_config via command-line paramter -F.
    Since I don’t like that start-script anyways (complicated key-setup, which would be done automatically anyways on first start, while not creating ECDSA keys, which are considered default) and I had no success with the suggestions from Trent Watkins for upgrade-survival (my addon.d script disappeared on one device and was not working on another one), lets do this again.

  9. You can get it to work without a sftp-server binary by changing:

    Subsystem sftp /usr/libexec/sftp-server


    Subsystem sftp internal-sftp

  10. #
    # At least on CyanogenMod 10.1.3-jfltespr
    # CyanogenMod already has sftp.

    # Then put your configs and keys here

  11. There seems to be a typo in your post. In your sshd_config it says /data/.ssh/authorized_keys, put you push a file to /data/ssh/authorized_keys.

  12. I wanted to thank you for the tutorial, it helped me a lot to get sshd running without any of these apps. However, I have some remarks:
    First, it seems as if there is still a typo, a missing dot:
    adb shell chmod 600 /data/.ssh/authorized_keys
    Should be the directory chmod 700 as well as it is required for others systems, where the keys file is silently ignored otherwise?

    Finally I don’t understand why the sshd should not run as daemon in the startup-script? At least my system was hanging during boot at this point. Without option -d everything is running fine (CyanogenMod-10-20130421)

  13. Thanks for that great guide.

    I would join lada04: why not start sshd as daemon


    To stop the service, just look up the pid in  /data/ssh/  or using  ps | grep sshd  and  kill  it.

  14. @Alain: Thanks for the guide
    @lada04: Thanks for your comment
    My system (CyanogenMod/FreeXperiaProject cm-10-20131224-FXP) was hanging during boot too. When I delete option -d it’s works.

  15. Nice tutorial worked for me.

    But I had a bad ass issue. After rebooting my Galaxy Nexus it got stuck at the google splash screen and nothing worked.

    I was still able to boot clockworkMod and then I removed all files mentionned in this tutorial again using adb shell.

    Then the phone booted again. I checked permissions and owners before removing the files and all were root:root. I guess a file was not accessible by the system boot process and this prevented the boot from going on.


    I’m not sure which file exactly caused the prob (maybe /data/ssh/ or /data/local/userinit.d/90sshd) but I think by setting the right user the device would boot  even with the files in place.

    Should it be system:system for the files?



  16. Hi guys

    This is all too techy for me.

    I have a rooted Android 4.4.2 (Galaxy S5). I want root explorer for ssh/sftp. I’ve tried using many of the ssh/sftp servers but none of them have root access (to the elusive /data/data/ folder).


    Please can someone write in layman terms the easiest way to get ssh/sftp root access please.



  17. Pingback: [Q] init scripts in 4.4? | Open Education usa

  18. If you don’t get a simple description like this one, leave it and don’t shoot yourself in the foot.

  19. Works nicely with CM 10.2 as well, but it makes no sense to run sshd in the foreground. You can either lsof (ps ax doesn’t work) and grep for the sshd PID, then kill it. Or you simply kill it with pkill sshd.

  20. Alain,

    Very nice work!  Thanks very much for documenting this so well, then subsequently editing in response to comments.  It took me a while to get a general idea of how the pieces fit together and how the Android differs from other systems, but the delays were my attempts to interpret your clear directions in the context of other systems I’ve worked on.



Leave a Reply

Your email address will not be published. Required fields are marked *

You can encrypt your comment so that only Alain Wolf can read it.

This site uses Akismet to reduce spam. Learn how your comment data is processed.