Windows And Linux – Just Married

Introduction

I’ve been using Linux for years now and I really like it. I wouldn’t want to work without it. If I had to work in a Windows-only environment I’d just go mad.

But some Linux-related things have been bothering me lately. Among other things these are:

  1. I’ve just got a shiny new notebook with a docking stations having two displays attached to it. I’d like to use the two external displays and the internal display simultaneously. And when I push the undock button on the docking station I want my notebook to switch to mobile mode automatically and back when I re-dock it. Currently docking, undocking and running nvidia optimus in Linux is a pain.
  2. This is stretches the term “lately” a bit: I work with some Windows programswhich don’t run properly under wine. I currently run these in a Windows virtual machine.
  3. I’ve upgraded to ubuntu 11.10 … I don’t like the way gnome – my window manager of choice – is going.

So, I’ve decided to give Windows as host a try, i.e. try having a Windows running on the laptop, running a Linux within a VM inside Windows and try to make them work together as seamlessly as possible.

Now I’m running a Windows 7 as host and a Ubuntu 11.10 in a VM. I can start Linux programs from within Windows with X11 forwarding. [Win]+[C] starts my gnome-terminal, [Win]+[X] starts the application starter gmrun, etc.. I have Linux programs in my Windows start menu. And each running program has its place in the task bar.
Oh, and everything is neatly responsive and fast.

Of course not everything is working seamlessly (yet?), but maybe I can get it running some day. For example Linux system tray icons don’t appear in the windows system tray.

I believe I’m not the first one having a setup like this, but since I had to gather my information from several different sources, I’d like to describe my whole setup.

Feel free to post any comments, questions or improvement ideas (!), but please don’t tell me how bad a person I am for using Windows. I know that already.

Let’s begin …

Base Setup

As I mentioned before I have a Lenovo T420 with Windows 7 running on it. I enabled the Intel virtualization features in the BIOS, installed the Lenovo update tool, joined our company’s windows domain and installed all the needed updates.
Afterwards I installed TrueCrypt and encrypted my entire disk.
Pretty basic.

Now we get to the fun part … hopefully …

The Fun Part … there we go

I assume you know Linux and Windows (at least a bit), ssh, X11 and the concept of virtual machines.

I also assume that you’ve used VirtualBox before. If not, please consult the documentation, since this won’t be a VirtualBox tutorial. Neither will it be a Cygwin tutorial.

If you like to save time, I recommend beginning to download Cygwin (setup.exe), VirtualBox and you favorite Linux ISO first. I use ubuntu 11.10, despite Unity and Gnome3. I won’t be seeing the window manager them much anyway. Afterwards I’d begin the installation of Cygwin since it will take quite a while to compile all the packages you need. The rest of the steps shouldn’t take too long to complete.

1. Install Linux In A VirtualBox VM

1.1. Install VirtualBox

We’ll run the VM within VirtualBox, so download VirtualBox and the Extension Pack from https://www.virtualbox.org/wiki/Downloads and install both of them.

1.2. Prepare The VM

  1. Create a new machinenamed “internal linux” with Linux / Ubuntu 64bit (if you want to use ubuntu).
    1. Set the “Base Memory Size” to whatever you think is necessary. I’ve set it to 1GB.
    2. Setup a new “Virtual Hard Disk” as “Start-Up Disk”. I’ve created a 8GB, VDI, Fixed size. It’s “only” 8GB, because I will add other dynamic disks and use a shared volume later.
  2. Adjust the following settings
    1. In “System -> Acceleration” enable “VT-x/AMD-V” and “Nested Paging” if your system supports this features. You might have to enable them in your BIOS first.
    2. Set “Network -> Adapter 1″ as “attached to” “Host-only Adapter”
    3. Enable the “Adapter 2″ and attach it to “NAT”.
    4. Open “Shared Folders” and add your Windows home (or whatever you like) as “internal_share”. Don’t forget the “Auto-mount” option.

Mount your favorite Linux ISO in “Storage -> IDE Controller -> the little CD-ROM symbol -> Choose a virtual CD/DVD disk file …” and start your VM.

1.3. Install Linux

Install Linux on the VM, apply the updates.

Login and install “OpenSSH Server”, “gmrun” and the “VirtualBox Guest Utils”.

internal> sudo aptitude install openssh-server gmrun virtualbox-guest-utils

For your user to be able to use the shared storage, add him/her to the group vboxsf, for example via adduser:

internal> adduser <your user> vboxsf

The newly added overlay scroll bars won’t work properly using X11 forwarding, so remove them if you like:

internal> sudo apt-get remove --purge overlay-scrollbar liboverlay-scrollbar-*

Reboot.

Maybe you want to link or adjust the mount point of the shared storage to a directory within your home.

We’ll now configure the ssh server.

1.4. Configure The OpenSSH Server

Add the following line to /etc/ssh/sshd_config and restart the ssh server:

UseDNS no

That way it won’t try to reverse-resolve your IP, thus saving connection time. (Thanks to my colleague Christoph for that hint).

Generate ssh-keypair (using ssh-keygen) without passphrase (use this only for your internal VM). Alternatively you can setup the key pair with a passphrase and use an ssh-agent in Cygwin or use a different authentication method. But since I only allow ssh access from my host-only adapter and only use this key for the internal VM, I think it’s okay.

Copy the private key to the internal_share. You’ll need it on the host system.

Copy the public key to ~/.ssh/authorized_keys.

We’ll test the connection later. We don’t have a windows ssh client, yet.

2. Prepare Windows

2.1. Install Cygwin/X

Download the setup.exe from cygwin.com and start the setup.
Select “Install from Internet“, set the root directory to %HOME%\cygwin and set the download directory to %HOME%\Downloads\cygwin.
Select the “X11” section to be installed. Also search “openssh“, select it and continue to the actual installation. This will take some time.

After the installation is finished we’ll try to connect via ssh to our VM.

You might also want to move the Cygwin setup.exe to your \Path\To\cygwin\ and put a link to that file into your Cygwin start menu folder.

Let’s test ssh.

2.2. Test The SSH Connection

Start a Cygwin Bash, which should be linked into your start menu or desktop.

cygwin> mkdir ~/.ssh

Move the ssh private key you’ve created earlier to ~/.ssh/ and adjust the rights, so only your user can use the file:

cygwin> chmod go-rwx id_rsa

Get the IP of the host-only adapter of your VM:

internal> ifconfig eth0 | grep -o -e "inet addr:\S*"

Mine is 192.168.56.101

Try to connect to your system:

cygwin> ssh internal@192.168.56.101

You should be connected to your internal VM now.

We’ll now run the XWin Server for the first time and try to run an X11 application.

2.3. Start An XWin Server

Start “Cygwin/X -> XWin Server” from your start menu. Once it’s started go back to your bash and type:

cygwin> DISPLAY=127.0.0.1:0.0 ssh -X internal@192.168.56.101

Again you should be connected to your VM. Type

cygwin> xclock

and get the xclock in your windows.

We’re finished with the basic setup. Now we’ll add some convenience add-ons to it.

3. Convenience Add-ons

3.1. run_internal.bat

Create a batch file called “run_internal.bat” somewhere, like %HOME%\bin\run_internal.bat for instance.
Add the following line and adjust the path, the user and the address according to your settings:

set DISPLAY=127.0.0.1:0.0
start /b C:\Users\MyUser\cygwin\bin\run.exe ssh -X internal@192.168.56.101 %*

We’ll use this batch file to start Linux programs with arguments – represented by the %* – tunneled through ssh using X11 forwarding.

3.2. Set Up AutoHotkey

Download, install and run AutoHotkey_L from autohotkey.com.

You should see a green H in your system tray. Right-click and click “Edit This Script“. To the script add the following lines, after adjusting your paths of course.

#x::Run, "C:\Users\MyUser\bin\run_internal.bat" "gmrun"
#c::Run, "C:\Users\MyUser\bin\run_internal.bat" "gnome-terminal"

These lines will let your system run gmrun when pressing [Win][X] and gnome-terminal when pressing [Win][C].

Right-click AutoHotkey again and click “Reload This Script“.

Try it by pressing [Win]+[X] and entering “xclock [Enter]“, which should bring up xclock again.

3.3. Add The Shutdown Script

We don’t want to click our way to saving the VM before, so we’ll add a shutdown hotkey to AutoHotkey:

#s::
{
  MsgBox, 1, Shutdown, Press [OK] to shutdown
  IfMsgBox, OK
  {
    SplashTextOn, 300, 50, Saving VM, Waiting for VM to be saved
    Run, "C:\Program Files\Oracle\VirtualBox\VBoxManage" "controlvm" "internal linux" savestate

    SetTitleMatchMode, 1
    DetectHiddenWindows, On
    WinWaitClose, internal linux, , 300	; Wait for VM to close

    SplashTextOff
    Shutdown, 8	; Shut down and power down
  }
}
return

It would be even nicer to hook into the shutdown process of windows. But I don’t know how, yet. Anybody?

4. Windows – Start-Up

To have all of this setup after your windows has started:

  1. Go to the VirtualBox Manager, right-click the VM and click “Create Shortcut on Desktop”
  2. Open the start menu -> all programs and right-click startup to “explore”.
  3. Move the links to the VM, AutoHotkey and XWin Server to the start-up folder.

5. One More Add-on – ssh-agent

Since I will use my Linux as environment to connect to the world via ssh, I only setup an ssh-agent there. I wouldn’t know how to do this on windows anyway.
This is a bit tricky, since I won’t enter a gnome-session, but just connect via ssh to the box.

5.1. PermitUserEnvironment

We’ll use ssh’s feature to be able to set environment variables for ssh sessions.

Add the following line to your /etc/ssh/sshd_config

PermitUserEnvironment yes

and restart sshd:

internal> service ssh restart

This will allow us to put environment variables into ~/.ssh/environment, thus populating SSH_AUTH_SOCK and SSH_AGENT_PID once we start ssh-agent.

5.2. Some Preparation: ~/bin

Create a home bin folder, if you like:

internal> mkdir $HOME/bin

Add the following line to your ~/.bashrc (adjust paths):

export PATH=$HOME/bin:$PATH

5.3. Create ~/bin/auto-start-ssh-agent

The following script will

  • check if there $SSH_AUTH_SOCK is set and a socket and otherwise try to recover it from ~/.ssh/environment
  • afterwards check if there the ssh-agent is running
  • if it can’t find an ssh-agent it will start one and export the needed environment variables to ~/.ssh/environment and the context the script is run in

This script should start a new ssh-agent and export the needed information, but only when needed.

Note to self: I should check if an actual ssh-agent is bound to that socket. It’s very probable though. :)

Here’s the code (~/bin/auto-start-ssh-agent):

#!/bin/bash

SSHAGENT=/usr/bin/ssh-agent
ENVFILE=$HOME/.ssh/environment

# assumptions
agent_running=0
do_export_envs=0

# check if ssh environment variables are set
if [ ! -S "$SSH_AUTH_SOCK" ]; then
        SSH_AUTH_SOCK=`grep -o -e '^SSH_AUTH_SOCK=\(.*\)$' $ENVFILE | sed 's/SSH_AUTH_SOCK=//'`
        SSH_AGENT_PID=`grep -o -e '^SSH_AGENT_PID=\(.*\)$' $ENVFILE | sed 's/SSH_AGENT_PID=//'`
	do_export_envs=1
fi

# check if agent is running
if [ -S "$SSH_AUTH_SOCK" -a -n "$SSH_AGENT_PID" ]; then
	proc_found=`ps -fp $SSH_AGENT_PID | grep "$SSHAGENT" -c`
	if [ $proc_found -eq 1 ]; then
		agent_running=1
	fi
fi

# start a new agent if none is found
if [ $agent_running -eq 0 ]; then
	if [ -x "$SSHAGENT" ]; then
		eval `$SSHAGENT`

		# replace the environment variables in ENVFILE
		sed -i "s@^\(SSH_AUTH_SOCK\)=\(.*\)\$@\1=$SSH_AUTH_SOCK@" $ENVFILE
		sed -i "s@^\(SSH_AGENT_PID\)=\(.*\)\$@\1=$SSH_AGENT_PID@" $ENVFILE

		do_export_envs=1
	else
		echo 'no valid ssh-agent found'
	fi
fi

# export ssh environment variables if needed
if [ $do_export_envs -eq 1 ]; then
	export SSH_AUTH_SOCK=$SSH_AUTH_SOCK
	export SSH_AGENT_PID=$SSH_AGENT_PID
fi

Make it executable:

internal> chmod +x auto-start-ssh-agent

5.4. ~/bin/gssh

The following script will execute the auto-start-ssh-agent script to ensure there is a running ssh-agent.
It will then use ssh-add to check if the identity file as already added to the agent and otherwise let you add it.
Finally it will continue to connect via ssh using the given identity file.

So only the first time, you run gssh you should have to put in your passphrase.

Here’s the code (adjust paths) (~/bin/gssh):

#!/bin/bash
IDENTITYFILE=/path/to/private/key

. auto-start-ssh-agent

key_found=`ssh-add -l | grep $IDENTITYFILE -c`

if [ $key_found -eq 0 ]; then
	ssh-add $IDENTITYFILE
fi

ssh -i $IDENTITYFILE "$@"

Make it executable:

internal> chmod +x gssh

5.5. ssh alias (optional)

Add this to ~/.bash_aliases (or to ~/.bashrc), if you like:

alias ssh='gssh'

6. Odds And Ends

  • After updating VirtualBox the host-only adapter was missing. I had to add it in the global network configuration again and set the IP to 192.168.56.1 (host system)
  • After installing the nvidia NVS drivers instead of the Lenovo drivers, I had to reinstall X11 for Cygwin

7. Open Issues

  • The run_internal.bat-way is not very elegant, since a box flashes every time
  • The VM should be minimized to system tray

The End. Thank you for your attention!

Dieser Beitrag wurde unter Development veröffentlicht. Setze ein Lesezeichen auf den Permalink.

3 Antworten auf Windows And Linux – Just Married

  1. Frank Birzle sagt:

    Ever thought about giving OS X a try? I did the switch several months ago and I don’t regret it at all. Most of the software that runs on Windows also runs on Mac (except for Minesweeper and Paint, maybe) and you don’t have to worry about stuff like display settings anymore. Very interesting article, though! Best regards from Berlin :)

  2. I tried OS X and was positively amused but not entirely persuaded. I wrote an article on my first impression.

  3. Bjoern Kortuemm Bjoern Kortuemm sagt:

    Yes, I have. I’ve been using Mac OS X on a private Laptop for about 1.5 years now, actually.
    It’s fine for personal use, but …
    … I can’t connect more than one external display at the screen resolution I’m using.
    … I still need to run some windows programs, like Enterprise Architect.
    … I still want to have a linux. I have to admit macports cover a lot of linux utils, though.