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?

up vote 21 down vote accepted

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:

https://github.com/Microsoft/BashOnWindows/issues/612

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!

  • 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
  • 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 at 14:48

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:

    PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
    @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.

  • That is very clever! and precise instructions, thanks. Is there a way to avoid skipping "sudo" password entirely? – greg Apr 13 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 at 4:24

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

  • 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 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 at 14:04

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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