NOTE: Many of the commands used here are redundant or unnecessary. They are included to further illustrate what is happening behind the scenes.


  • CyanogenMod 10.1 on your remote device (build after May 12, 2013)
  • An SSH client on your local machine (such as OpenSSH or PuTTY)
  • A private SSH key. (If you don’t already have one, see this helpful article for information on how to make one.)
  • A means of running commands on your phone as root. This guide uses an adb connection to your device (see ADB intro for more information)

Setting up sshd

All command are executed from the adb root shell (su to root from adb shell), unless otherwise specified. Properly setting the file and directory permissions is critical for sshd to function as expected.

Setting up the directory structure

mkdir -p /data/ssh/empty
chmod 700 /data/ssh
chmod 700 /data/ssh/empty

/data/ssh holds the server’s host keys and configuration file. /data/ssh/empty is used for privsep.

NOTE: Both /data/ssh and /data/ssh/empty should have already existed. They are created here in case of previous accidental deletion.

Helpful Tip

Commands can be pasted into PuTTY by right-clicking or pressing Shift-Ins.

Creating the server configuration file

cat /system/etc/ssh/sshd_config | \
sed 's/#PermitRootLogin yes$/PermitRootLogin no/' | \
sed 's/#PubkeyAuthentication yes/PubkeyAuthentication yes/' | \
sed 's/#PasswordAuthentication yes/PasswordAuthentication no/' | \
sed 's/#PermitEmptyPasswords no/PermitEmptyPasswords no/' | \
sed 's/#ChallengeResponseAuthentication yes/ChallengeResponseAuthentication no/' | \
sed 's;/usr/libexec/sftp-server;internal-sftp;' > \
chmod 600 /data/ssh/sshd_config
  • PermitRootLogin no forbids root login (We’ll be logging in as shell.)
  • PubkeyAuthentication yes allows the public key authentication method
  • PasswordAuthentication no prevents the password authentication method
  • PermitEmptyPasswords no prevents submitting empty passwords (probably redundant, since we disabled password authentication *shrug*)
  • ChallengeResponseAuthentication no prevents the challenge response authentication method
  • Subsystem sftp internal-sftp allows sftp without the need for the sftp-server binary

NOTE: You could probably set a password for shell with passwd and use the password authentication method, but I am unsure of what, if any, effects this might have.

Helpful Tip

Lines that end in a \ continue the same command on the following line. This was done above improve readability of a long command.

Setting the Authorised Public Key

Upload your public key to your phone to /data/.ssh/authorized_keys in a text file on a single line. This file is a list of all the public keys that sshd will allow with one key per line. Since only your public key will be allowed, there will only be one line in it. First, make the directory where the public key will be stored, and grant it the correct permissions.

mkdir -p /data/.ssh
chmod 700 /data/.ssh
chown shell:shell /data/.ssh

Then upload your public key to your phone. (This one command is done on your computer.)

adb push your_public_key /data/.ssh/authorized_keys

Now, fix the permissions.

chmod 600 /data/.ssh/authorized_keys
chown shell:shell /data/.ssh/authorized_keys

NOTE: /data/.ssh should have already existed. As with, /data/ssh and /data/ssh/empty, it is created here in case of previous accidental deletion.

Helpful Tip

Some sftp clients may require the use of an SSH key agent to manage the key.

Starting sshd

There is a script already on the phone called start-ssh that will start sshd, but it requires modification:

mkdir -p /data/local/userinit.d
cat /system/bin/start-ssh | \
sed 's;/system/etc/ssh/sshd_config;/data/ssh/sshd_config;' > \
chmod 755 /data/local/userinit.d/99sshd
  • /system/etc/ssh/sshd_config is changed to /data/ssh/sshd_config so configuration changes are not lost after a /system flash

To start sshd, run /data/local/userinit.d/99sshd, the new version of start-ssh. It must be run as root. It will also get run automatically by /system/etc/init.d/90userinit on startup, along with any other scripts you put in /data/local/userinit.d.

Connecting and Usage

Once sshd has been started on the phone, you can connect to it with your favourite SSH client and the username shell. This is the same username adb shell gives you, so your permissions are the same until you choose to elevate them using su. You can connect as root (you’ll have to edit sshd_config to allow it), but that is highly inadviseable. Only using root when you have to puts you at a much smaller risk of accidentally wrecking things.

The shell user is pretty weak, so you might like to carve out a home folder, where shell has write access. There you can also keep settings for all your favourite shelly programs, like emacs, vim, and bash. The following is an example of just that.

Make the folder (as root, using su):

mkdir /data/home
chmod 755 /data/home
chown shell:shell /data/home

Everything else from here on in can be done as shell over SSH or with scp. Copy over some key config files (run on the computer):

scp .inputrc .bash_profile .bashrc .vimrc .screenrc shell@hostname:/data/home

Now, we’d like a fast way of configuring the home directory, since it gets ignored when we first log in. Put the following in /data/home/login:


exec bash --login

Then set its permissions to allow execution:

chmod 755 /data/home/login

Now, to switch to the new home directory when you log in, just type exec /data/home/login.

Android has made it so that the files and directories shell creates can only be accessed by itself by default. If you want to access the files you make with shell from your other apps, like file browsers, without root access, you’ll need to change the default file and directory creation permissions. Add the following to your .bash_profile on a line by itself to allow read-only access from all apps: umask 0022. To allow all apps read/write access, use umask 0000 instead.

To emulate sudo behaviour, you might like to put the following alias in your .bashrc: alias sudo='su root'.


  • Change # DEBUG=1 to DEBUG=1 in /data/local/userinit.d/99sshd to enable debug logging to logcat
  • Reboot remote device (or kill the sshd process and run 99sshd)
  • Run logcat | grep sshd to show the debug log
  • When in debug mode, sshd will quit after the first ssh session exits. Recomment the DEBUG=1 line and restart 99sshd for normal behavior.

NOTE: Most issues will be related to permissions.

Helpful Tip

Some devices may be sluggish with the screen locked. Try unlocking the screen to see if performance improves.


  • Find specific versions of CM where supported
  • Identify effects of setting password for shell user
  • Add more troubleshooting information
  • Add a section for client (PuTTY) setup; specifically, private key conversion (puttygen) and/or ssh-agent (pageant) usage (this may be more useful has a it’s own document)

Problem with SELinux

My solution for problem:

W/sshd type=1400 audit(0.0:16): avc: denied { open } for name="sshd_config"
  • Install SuperSu ([1])
  • create directory /system/su.d
  • modify file 99sshd and add/change
supolicy --live "allow sysinit self:capability setgid;allow sysinit system_data_file:file open;"
/system/bin/logwrapper /system/bin/sshd -f /data/ssh/sshd_config

Notice I removed the -D param. Because with it the sshd was killed.
And added the logwrapper, because sshd can generate an output when error.

  • put the file 99sshd into /system/su.d/ (remount rw)

I choosed this directory because the had problems (selinux) with running another scripts.

Allowing root login

Modify file /data/ssh/sshd_config

AuthorizedKeysFile      /data/.ssh/authorized_keys.%u
PermitRootLogin yes

and rename file /data/.ssh/authorized_keys to authorized_keys.root and

Content of this page is based on informations from, under CC BY-SA 3.0 licence.