I want to launch an SSH server on Linux subsystem (Bash on Ubuntu on Windows) at windows startup. The problem is that all Linux processes are terminated when Bash window is closed.

Is there a way to make Linux process run permanently in background without bash window?


Found a tutorial for that by aseering:

This was originally discussed and sorted out by github users imjakey, fpqc, qris, therealkenc, Manouchehri, and aseering (myself) here:


Note that running sshd has security implications. Until WSL's security model has had longer to bake, you should assume that anyone who can ssh into your Windows box has permission to perform any command as the Windows user running sshd, regardless of Linux-level permissions. (Permissions are probably more restrictive than that in practice, but WSL's initial security model is not intended to be very sophisticated.)

Attempting to aggregate the instructions from github:

  • Generate SSH host keys by running sudo dpkg-reconfigure openssh-server in a bash shell
  • Run sudo nano /etc/ssh/sshd_config; edit the UsePrivilegeSeparation yes line to read UsePrivilegeSeparation no. (This is necessary because UsePrivilegeSeparation uses the chroot() syscall, which WSL doesn't currently support.)
  • While still editing /etc/ssh/sshd_config, you may choose to change PasswordAuthentication no to PasswordAuthentication yes. Otherwise you will have to set up SSH keys.
  • Save /etc/ssh/sshd_config and exit.
  • Run sudo visudo to edit the sudoers file. Add the line

    $USER ALL = (root) NOPASSWD: /usr/sbin/sshd -D

    replacing "$USER" with your Linux username. Save and exit. If visudo complains that your changes are invalid, fix them until it reports that they are valid; otherwise you can break sudo on your system!

  • On the Windows side, edit the Windows firewall (and any third-party firewalls that you might be running) to allow incoming traffic on port 22. Because this isn't a super-secure setup, I recommend only allowing incoming traffic from home (private) and domain networks, not from the public Internet.
  • Create a text file autostartssh.vbs in Windows containing the following:

    set ws=wscript.createobject("wscript.shell")
    ws.run "C:\Windows\System32\bash.exe -c 'sudo /usr/sbin/sshd -D'",0
    • Double-click on the script. It should start sshd; you should be able to ssh into your Windows machine.
    • Open Windows's Task Scheduler. Add a task that runs autostartssh.vbs on system boot. Use wscript.exe as the command to run and the VBS script location as the parameter.

And that's it -- your Windows computer should be running a Linux openssh server!

| improve this answer | |
  • The VBS script didn't do anything for me. sshd isn't showing up in resource monitor Network tab. – megamaiku Apr 13 '17 at 22:25
  • I wrote a a process dispatcher github.com/131/dispatcher that 'll allows you to spawn bash with no windows. – 131 Nov 1 '17 at 15:56
  • @megamaiku: I had the same problem. Turns out the little snipped to run sshd got stuck on the (invisible) password prompt because I didn't do the "visudo" part right. At first I added the NOPASSWD line somewhere in the middle of the sudoers file. It worked once I moved it to the bottom! – ltjax Dec 3 '17 at 12:21
  • 1
    It's currently working with UsePrivilegeSeparation = yes , except that one needs to also run sudo /bin/mkdir -p /var/run/sshd (to create the privilege separation directories) before starting sshd. Does WLS now support chroot(), is there a workaround in place in the openssh source, or is the = No setting more of a safety recommendation? Also, the windows task seems to only work for me if my user is logged in. – init_js Dec 11 '17 at 23:12
  • This worked excellently. I would suggest, to make things easier, move the port SSH is listening on, e.g. 3322, something random. Comment out the line in /etc/ssh/sshd_config that reads Port 22 and switch to Port 8822. One reason for this is Windows running some sort of SSH process on 22. I've seen suggestions saying there's no problem with disabling that, but I found it easiest to just switch the WSL SSH port. – knickum Apr 6 '18 at 14:48
  1. Create a file named wsl_setup.bat and add content as follow

    wsl -u root -e sudo service ssh start
    wsl -u root -e sudo service nginx start
  2. Add wsl_setup.bat file to windows startup folder windows-10-change-startup-apps

  3. Restart and log in your windows account (yes, you need to log in)

| improve this answer | |
  • This is best answer, We can change which distrib we want to run the command on by adding -d Debain where Debain can be replaced by any name of distro installed, which one can obtain by running wsl -l. – Animesh Sahu Jul 13 at 15:35

I've needed to do the same thing.

Here's how to boot the Ubuntu Linux subsystem with all of cron's services upon the Windows boot & provide a means to 'reboot' the Linux subsystem.

I'm successfully hosting the openssh-server, nginx & mariadb database on our server.

Install Linux Subsystem

  • Open Powershell as Administrator
  • Paste:

    Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
  • Install Ubuntu from Windows Store.

Remove sudo password prompt (required)

  • Open bash (Linux Subsystem installs this)
  • Paste:

    sudo sed -i "s/%sudo.*/%sudo ALL=(ALL:ALL) NOPASSWD:ALL/g" /etc/sudoers

Enable SSH password login (optional)

  • Open bash
  • Paste:

    sudo sed -i '/StrictModes yes/c\StrictModes no' /etc/ssh/sshd_config
    sudo sed -i '/ChallengeResponseAuthentication/c\ChallengeResponseAuthentication no' /etc/ssh/sshd_config
    sudo sed -i '/PasswordAuthentication/c\PasswordAuthentication yes' /etc/ssh/sshd_config

Windows autologin on start (required if you have a password or RDP in)

  • Open netplwiz
  • Untick 'Users must enter a username and password...'
  • Open regedit as Administrator
  • Browse to

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon
  • Create a new string DefaultPassword and write the user's password as value.

Run bash/cron loop on start

  • Create a file called linux.bat in shell:startup
  • Paste:

    C:\Windows\System32\bash.exe -c 'while [ true ]; do sudo /usr/sbin/cron -f; done'

Add apps/services to startup on cron

  • Open bash
  • sudo crontab -e
  • Select nano (or any editor you know how to save in)
  • Append startup apps such as openssh-server, nginx, mysql, php:

    @reboot . $HOME/.profile; /usr/sbin/sshd -D
    #@reboot . $HOME/.profile; service php7.1-fpm start # Uncomment for php7.1 fpm
    #@reboot . $HOME/.profile; service mysql start # Uncomment for mysql/mariadb
    #@reboot . $HOME/.profile; service nginx start # Uncomment for nginx
  • Save and exit: ctrlx, then press y and enter.

Reboot the Linux subsystem without rebooting Windows

  • Open bash or SSH in

    sudo service ssh restart
  • This will close the current instance and create a new one applying cron.

Extra - Install PHP 7.1 (not quite as straight forward)

  • Run the commands below for a pretty standard setup:

    mkdir /run/php && chmod -R 777 /run/php
    sudo add-apt-repository ppa:ondrej/php && sudo apt update
    PHPV=7.1 && sudo apt install --allow-unauthenticated -y php${PHPV}-fpm php${PHPV}-gd php${PHPV}-json php${PHPV}-mysqlnd php${PHPV}-curl php${PHPV}-intl php${PHPV}-mcrypt php${PHPV}-imagick php${PHPV}-zip php${PHPV}-xml php${PHPV}-mbstring
  • Run the command below for an 'OwnCloud' setup:

    PHPV=7.1 && apt install --allow-unauthenticated -y php${PHPV}-redis redis-server php${PHPV}-ldap php${PHPV}-smbclient

Extra - Install nginx webserver

  • Run the commands below for a base setup with PHP7.1:

    sudo add-apt-repository ppa:nginx/stable
    sudo apt update && sudo apt -y install nginx
    sudo sed -i 's:access_log /var/log/nginx/access.log;:access_log off;:g' /etc/nginx/nginx.conf
    sudo sed -i '/index index.html/c\\tindex index.html index.php index.htm index.nginx-debian.html;' /etc/nginx/sites-available/default
    STR='}\n\n\tlocation ~ \.php$ {\n\t\tinclude snippets\/fastcgi-php.conf;\n\t\tfastcgi_pass unix:\/var\/run\/php\/php7.1-fpm.sock;\n\t}'
    sudo sed -i "0,/}/s//$STR\n/" /etc/nginx/sites-available/default
    sudo service nginx restart

Extra - Install mariadb's mysql database

  • Run the commands below for a mysql database server:

    RELEASE=`lsb_release -a | tail -1 | cut -f2`
    sudo apt install software-properties-common
    sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
    sudo add-apt-repository "deb [arch=i386,amd64,ppc64el] https://mirrors.evowise.com/mariadb/repo/10.3/ubuntu $RELEASE main"
    sudo apt update && sudo apt --allow-unauthenticated -y install mariadb-server
  • When prompted, set a root database user password.

| improve this answer | |
  • That is very clever! and precise instructions, thanks. Is there a way to avoid skipping "sudo" password entirely? – greg Apr 13 '18 at 9:26
  • I don't recommend using the Linux subsystem anymore. The app compatibility sucks, it's unstable and the tools don't all work as well as they could - bash integration, etc. Instead use msys2, it provides you with a great bash shell and will allow you to install a lot of apps via its pacman package manager - Best of all, all of the apps are .exe's. All you need to do is add the bin directories to your environment variables in Windows. I use linux commands in windows and vice versa now. All of my Windows scripting is done in bash. – Nom Apr 28 '18 at 4:24

@Poma and @Hintron answers are great.

I would like to extend description of last point how to add ssh task in Windows Task Scheduler as it requires switching some options:

  • Run "Task Scheduler". On the left list select "Task Scheduler (Local)", then go to "Action" menu and "Create Task".
  • General tab:
    • Name: "ssh"
    • Select "Run whether user is logged on or not"
  • Triggers tab:
    • New
      • Begin the task: "At startup"
  • Actions tab:
    • New
      • Program/script: C:\Windows\System32\bash.exe
      • Add arguments (optional): -c "sudo /usr/sbin/service ssh start"
  • Conditions:
    • Unselect "Start the task only if the computer is on AC power
  • Settings
    • Unselect "Stop the task if it runs longer than

It is used direct bash invocation. There is no need to wrap it in vbs or powershell scripts.

I use service command for reasons that @Hintron explained. Additionally direct sshd invocation gives error

Missing privilege separation directory: /var/run/sshd

In such case it should be added this entry by sudo visudo command

ALL ALL = (root) NOPASSWD: /usr/sbin/service ssh *

Also notice that here all users (first column) can start or stop sshd. If your are only one user of this Windows machine, then it should be fine.

| improve this answer | |

@poma 's answer is very good, and is what my answer is based off of. I want to add some improvements to it, though:

  • Use service instead of calling sshd directly: 'sudo service ssh start' instead of 'sudo /usr/sbin/sshd -D'. That way, even if you call the script multiple times, there will only be at most one sshd process. Also, it's easy to kill it with another script that runs 'sudo service ssh stop'. In the sudoers file, you simply need to replace /usr/sbin/sshd -D with /usr/sbin/service.
  • If you are set on calling sshd directly, get rid of the -D option, because that will put a process in the foreground indefinitely. If you don't believe me, just do top and you will see an init and a sudo process for each time you called the script. Don't forget to remove the -D option in the sudoers file as well!
  • Use PowerShell instead of vbs! Create a file called autostartsshd.ps1 and paste in the following: bash -c 'sudo service ssh start'. To execute the script, right click it and click Run with PowerShell.

Another stack overflow question has similar steps: https://superuser.com/a/1114162/182590

Hope that helps someone :)

| improve this answer | |
  • Are you sure this will work? Running sshd in the foreground was intentional to keep bash session open (there will be no problems with multiple instances because duplicates will fail to start). If you just run sudo service ssh start and then close bash it will kill ssh daemon. At least that's what it did at the moment of writing my guide. – Poma May 28 '18 at 17:34
  • @Poma With the latest update to Windows 10, Linux applications can now run in the background, so I think this should work fine. – JacobTheDev May 29 '18 at 14:04

put bash -c "echo [password] | service ssh start" in Windows startup script, and use your own sudo password to substitute [password]

| improve this answer | |
  • You can't just pipe a password to a sudo prompt (not that your command even includes the necessary sudo keyword that your sentence implies). This just doesn't work. Not that you should ever store your password in plaintext anyways! – adam_0 Sep 17 '19 at 15:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.