Hints for Securing Ubuntu on a VPS

Digital Ocean and Godaddy Pro are nice VPS providers. However, it’s important to update the security of any box you create ASAP. It took under 24 hours for one of my boxes to be hacked and turned into a DoS! Therefore, when you create your box, make sure to add a firewall immediately.

  1. Add an SSH key to the box so you can log into it without passwords. This can sometimes be a real pain in the ars, but it’s worth it. Remember, the server needs an “authorized_keys” file, and the client needs an agent, either Pageant or ‘eval $(ssh-agent)’.
  2. Turn off passwords for SSH. After adding a key–and making sure that it works–turn off password prompting. Note: if you mess this up and can’t login without password prompting, you are totally screwed!
    1. vi /etc/ssh/sshd_config, uncomment “PasswordAuthentication”, and change “PasswordAuthentication” from “yes” to “no”.
  3. Install UFW (the “Uncomplicated Firewall”). Set up which ports that are exposed. For now, allow SSH (port 22).
sudo apt-get install ufw
sudo ufw default deny incoming
sudo ufw allow ssh
# set up ssh before enabling ufw!
sudo ufw --force enable
sudo ufw status
  1. Install Fail2ban. Fail2ban keeps track of hackers trying to get into the machine, and sets up blocks accordingly.
    1. sudo apt-get update
    2. sudo apt-get install fail2ban
    3. Install any additional rules you want.
      1. sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
      2. vi /etc/fail2ban/jail.local
        1. Add in rules, e.g., ‘^%(__prefix_line)sReceived disconnect from <HOST>: 11: (Bye Bye)? \[preauth\]$’.
      3. To test it with fail2ban-regex or egrep, you can just strip off the ^%(__prefix_line)s from the beginning. Add this line to the failregex variable in your /etc/fail2ban/filter.d/sshd.conf.
  2. Check logs periodically. Look for strange happenings.
    1. grep sshd.\*Failed /var/log/auth.log | less
    2. grep sshd.*Did /var/log/auth.log | less
  3. Do not expose Redis, Mongo DB, or other unsafe programs directly past the firewall:
    1. http://redis.io/topics/security
  4. Install nethogs to see what’s going on with the network.
    1. sudo apt-get install nethogs
    2. sudo nethogs eth0
    3. creating socket failed while establishing local IP – are you rootwget -c https://github.com/raboof/nethogs/archive/v0.8.1.tar.gz
    4. wget -c https://github.com/raboof/nethogs/archive/v0.8.1.tar.gz
    5. tar xf v0.8.1.tar.gz
    6. cd ./nethogs-0.8.1/
    7. sudo apt-get install libncurses5-dev libpcap-devsudo apt-get install make
    8. sudo apt-get install make
    9. sudo apt-get install build-essential g++
    10. make && sudo make install
    11. nethogs
  5. Run netstat occasionally to see what ports are open.
    1. netstat -tnp
    2. netstat -tulpn
  6. Amazon’s AWS has firewalls built in around the machine when you create a VPS. You don’t need to set up these programs, but it’s a good thing to do.

Resources

https://www.digitalocean.com/community/tutorials/an-introduction-to-securing-your-linux-vps

https://apps.ubuntu.com/cat/applications/fail2ban/

https://www.digitalocean.com/community/tutorials/how-to-protect-ssh-with-fail2ban-on-ubuntu-14-04

https://dodwell.us/security/ufw-fail2ban-portscan/

http://antirez.com/news/96

 

Getting a C# Server Working with Dokku and Vagrant

Developing a self-hosted web server in C# to run on Linux is like solo climbing a mountain: not a lot of people will be accompanying you; and the route will be unmarked, unmaintained, and often dangerous. In the digital world, there are two groups of programmers: people who use Node.js, Java, Ruby, etc. hosted on Linux; and people who use C# hosted on Windows. Building a C# server to run on Linux isn’t usually done because there is a perception that Mono is buggy. Most of those arguments are from experiences over 5 years ago, and Mono has come a long way. Of course, there is always room for improvement.

In particular, if you are a developer that wants to create services without focusing on all the crap associated with deployment, then Dokku is the way to go. I definitely prefer a command-line deployment rather than working with IDEs and browsers. Dokku, modeled after Heroku, is a PAAS model whereby the deployment of the server is simply a “git push.”  Unfortunately, the problem with Dokku and C# programming is that the easy “git push” deployment is offset by the difficulty in setting up the environment.

With that in mind, my goal was:

Prerequisites

Dokku requires you to work with SSH (both client and server), so you need to understand SSH very well. It is likely you have to understand how to configure your DHCP router, as I could not get Vagrant to send the DHCP router the name of the virtual machine. Also, if you aren’t familiar with Heroku, you might like to give that a spin with the Java example in order to understand some of the concepts.

Method

  1. Create a vanilla Ubuntu virtual machine, 20 GB disk space, 2048 memory, user “ubuntu”.
    1. Download the latest Ubuntu release from http://www.ubuntu.com.
    2. Start Virtualbox, and create a new virtual machine with a unique virtual_box_name running Ubuntu.
    3. Note: use the 64-bit “desktop” version of the OS. Make sure you have enough disk space for the large ISO file. You will also need at least 10GB of free disk space for the virtual machine itself.
    4. Install Ubuntu. Add user, e.g., “ubuntu”. Note: The Dokku installation scripts create user “dokku”. In order to login, you will want another account other than dokku.
    5. Restart the virtual machine.
    6. Install the VirtualBox Guest Additions.
    7. Restart the virtual machine.
    8. Start a terminal command-line interface in the virtual machine.
    9. sudo apt-get install openssh-server
    10. sudo visudo
      1. Add user ALL=(ALL) NOPASSWD: ALL to the file. This updates user with superuser rights so you don’t have to give a password for every sudo command.
    11. Shutdown the virtual machine.
  2. Create a Vagrant package of the vanilla Ubuntu virtual machine.
    vagrant box remove my-box
    vagrant init my-box
    vagrant package --base virtual_box_name
    vagrant box add my-box package.box
  3. Start the Vagrant virtual machine.
    1. Get a copy of my ‘kukku’ vagrant setup files at https://ken_domino@bitbucket.org/ken_domino/kukku.git
    2. cd kukku
    3. In the Vagrantfile, note the lines for setting up the user id and password for signing into the virtual machine, etc. Make sure they are in agreement with the names you gave in setting up the virtual machine.
      # -*- mode: ruby -*-
      # vi: set ft=ruby :
      # encoding: UTF-8
      
      BOX_NAME = ENV["BOX_NAME"] || "my-box"
      DOKKU_DOMAIN = ENV["DOKKU_DOMAIN"] || "kukku.home"
      # DOKKU_IP = ENV["DOKKU_IP"] || "10.0.0.2"
      PUBLIC_KEY_PATH = "#{Dir.home}/.ssh/id_rsa.pub"
      
      Vagrant.configure(2) do |config|
      
        # Set the name of the vagrant image file.
        config.vm.box = BOX_NAME
      
        # Display the Virtualbox GUI.
        config.vm.provider "virtualbox" do |v|
          v.gui = true
        end
      
        # Declare the name of the VM folder.
        config.vm.provider "virtualbox" do |v|
          v.name = "kukku-fun"
        end
      
        # Set the network to use bridge adapter, with a static IP, and known MAC.
        # My router does not handle the name of the guest correctly, so this bypasses
        # the problem by fixing it all. Note, in the router, I create an entry for
        # "whack" because the name isn't being broadcasted from the guest to the router.
        config.vm.network "public_network", ip: "192.168.1.33", :mac => "080027EA2F24"
        
        # Tell Vagrant to not muck around with the .ssh/authorized_hosts file.
        # It should not exist, or if it does, it should be empty. This is make sure
        # Dokku ssh works.
        config.ssh.insert_key = false
        config.ssh.private_key_path = File.expand_path("../.ssh/vagrant", __FILE__)
      
        # Define user id and password for login.
        config.ssh.username = "ubuntu"
        config.ssh.password = "ubuntu"
        
        # Provision the box with Dokku.
        config.vm.provision "shell", inline: >>-SHELL
      
          wget https://raw.githubusercontent.com/dokku/dokku/v0.4.14/bootstrap.sh
          sudo DOKKU_TAG=v0.4.14 bash bootstrap.sh
      
        SHELL
      end
      
      
    4. vagrant up
  4. Set up Dokku, and run the C# server.
    1. In the virtual machine…open a browser, and enter the address “localhost/”. It should be the Dokku set up screen.
    2. In the setup screen, enter the contents of your ~/.ssh/id_rsa.pub file, and set the name of the box to ‘whack’ or what ever machine you set for the machine. Click the button to set up Dokku.
    3. In the host machine…
      1. Verify that you see the help screen for Dokku via ‘ssh dokku@whack’. Otherwise, the ~dokku/.ssh/authorized_keys file on the virtual machine has the wrong entry. Edit that file, or type cat ~/.ssh/id_rsa.pub | ssh dokku@whack "sudo sshcommand acl-add dokku foobar"
      2. ssh dokku@whack apps:create fun
      3. ssh dokku@whack config:set fun BUILDPACK_URL=https://github.com/AdamBurgess/heroku-buildpack-mono
        1. Note: Adam Burgess’ C# buildpack is the only buildpack that seems to work. There are at least 4 others which I tried and don’t work. This buildpack uses xbuild for the build process.
      4. Get a copy of my “Hello World!” https://ken_domino@bitbucket.org/ken_domino/hn.git
        1. Note, you can substitute your program, but it should be an http server, and it must access the environmental variable PORT for the port to open. Dokku monitors that port to verify that the program is operating.
      5. cd hn
      6. git remote add foo dokku@whack:fun
      7. git push foo master
      8. Note: you should see output like the following.
        Ken@Win8-GAZ77X /cygdrive/c/Users/Ken/Documents/hn
        $ git push foo master
        Counting objects: 32, done.
        Delta compression using up to 4 threads.
        Compressing objects: 100% (25/25), done.
        Writing objects: 100% (32/32), 916.64 KiB | 0 bytes/s, done.
        Total 32 (delta 3), reused 0 (delta 0)
        -----> Cleaning up...
        -----> Building fun from herokuish...
        -----> Adding BUILD_ENV to build environment...
        -----> Fetching custom buildpack
        -----> .NET app detected
        -----> Installing mono version 636c0c95cc78-minimal
        -----> Downloading https://github.com/AdamBurgess/heroku-buildpack-mono/releases/download/636c0c95cc78/mono-minimal.tar.xz
        -----> Installing SSL certificates
        -----> Installing NuGet packages
               Installing 'Nancy.Hosting.Self 1.4.1'.
               Installing 'Nancy 1.4.3'.
               Successfully installed 'Nancy.Hosting.Self 1.4.1'.
               Successfully installed 'Nancy 1.4.3'.
        -----> Compiling .NET application
               XBuild Engine Version 14.0
               Mono, Version 4.3.3.0
               Copyright (C) 2005-2013 Various Mono authors
        
               Build started 03/04/2016 19:07:53.
               __________________________________________________
               Project "/tmp/build/hn.sln" (default target(s)):
               Target ValidateSolutionConfiguration:
               Building solution configuration "Release|Any CPU".
               Target Build:
               Project "/tmp/build/hn.csproj" (default target(s)):
               Target PrepareForBuild:
               Configuration: Release Platform: AnyCPU
               Created directory "obj/Release/"
               Target CopyFilesMarkedCopyLocal:
               Copying file from '/tmp/build/packages/Nancy.1.4.3/lib/net40/Nancy.dll' to '/tmp/build/Nancy.dll'
               Copying file from '/tmp/build/packages/Nancy.Hosting.Self.1.4.1/lib/net40/Nancy.Hosting.Self.dll' to '/tmp/build/Nancy.Hosting.Self.dll'
               Target GenerateSatelliteAssemblies:
               No input files were specified for target GenerateSatelliteAssemblies, skipping.
               Target CoreCompile:
               Tool /tmp/build/mono/lib/mono/4.5/mcs.exe execution started with arguments: /noconfig /debug:pdbonly /optimize+ /out:obj/Release/hn.exe Program.cs Properties/AssemblyInfo.cs obj/Release/.NETFramework,Version=v4.5.AssemblyAttribute.cs /target:exe /define:TRACE /nostdlib /platform:AnyCPU /reference:packages/Nancy.1.4.3/lib/net40/Nancy.dll /reference:packages/Nancy.Hosting.Self.1.4.1/lib/net40/Nancy.Hosting.Self.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.Xml.Linq.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.Data.DataSetExtensions.dll /reference:/tmp/build/mono/lib/mono/4.5-api/Microsoft.CSharp.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.Data.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.Net.Http.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.Xml.dll /reference:/tmp/build/mono/lib/mono/4.5-api/System.Core.dll /reference:/tmp/build/mono/lib/mono/4.5-api/mscorlib.dll /warn:4
               Program.cs(41,17): warning CS0162: Unreachable code detected
               Target _CopyAppConfigFile:
               Copying file from '/tmp/build/App.config' to '/tmp/build/hn.exe.config'
               Target DeployOutputFiles:
               Copying file from '/tmp/build/obj/Release/hn.exe.mdb' to '/tmp/build/hn.exe.mdb'
               Copying file from '/tmp/build/obj/Release/hn.exe' to '/tmp/build/hn.exe
               Done building project "/tmp/build/hn.csproj".
               Done building project "/tmp/build/hn.sln".
        
               Build succeeded.
        
               Warnings:
        
               /tmp/build/hn.sln (default targets) ->
               (Build target) ->
               /tmp/build/hn.csproj (default targets) ->
               /tmp/build/mono/lib/mono/xbuild/14.0/bin/Microsoft.CSharp.targets (CoreCompile target) ->
        
               Program.cs(41,17): warning CS0162: Unreachable code detected
        
               1 Warning(s)
               0 Error(s)
        
               Time Elapsed 00:00:00.4912070
        -----> Discovering process types
               Procfile declares types -> web
        -----> Releasing fun (dokku/fun:latest)...
        -----> Deploying fun (dokku/fun:latest)...
        -----> DOKKU_SCALE file not found in app image. Generating one based on Procfile...
        -----> New DOKKU_SCALE file generated
        =====> web=1
        -----> Running pre-flight checks
               For more efficient zero downtime deployments, create a file CHECKS.
               See http://dokku.viewdocs.io/dokku/checks-examples.md for examples
               CHECKS file not found in container: Running simple container check...
        -----> Waiting for 10 seconds ...
        -----> Default container check successful!
        =====> fun container output:
               http://localhost:5000/
        =====> end fun container output
        -----> Running post-deploy
        =====> renaming container (d6dc5cffa4c9) nauseous_yonath to fun.web.1
        -----> Setting config vars
               DOKKU_NGINX_PORT: 80
        -----> Creating http nginx.conf
        -----> Running nginx-pre-reload
               Reloading nginx
        -----> Setting config vars
               DOKKU_APP_RESTORE: 1
        =====> Application deployed:
               http://dokku:32769 (container)
               http://dokku:80 (nginx)
        
        To dokku@dokku:fun
         * [new branch]      master -> master
        
        Ken@Win8-GAZ77X /cygdrive/c/Users/Ken/Documents/hn
        
    4. In a browser, type ‘whack/’. You should see “Hello world!”.

    Further Information

     

    An Important Side Note

    Part of the motivation for me was to re-examine what is available in website hosting. Currently, I use GoDaddy.com . After years of enduring GoDaddy ads that employ sophomoric humor, themes of misogyny, homophobia, and animal cruelty take on another light when juxtaposed by the actions of the son of Republican GoDaddy founder. It’s particularly important for me because I started a non-profit called “Hikers and Climbers Against Domestic Violence,” which tries to bring attention to the violence some women endure. While GoDaddy does offer good services at a low price, perceptions matter, and I’m shopping around to see what are my best options.

Self-hosting a C# Nancy Server on Linux

Sinatra is a popular and wonderful web application framework that has spawned a number of copycat frameworks. You can write large websites or REST servers with it. While it is a framework only for Ruby, there are alternatives for other languages, Spark Java for Java, Lavarel for PHP, etc. For C#, Nancy is the choice, and you can avoid using ASP.NET if you’d like. This post shows how to set up a “Hello world!” Nancy project that will build and run on Ubuntu and Windows.

Prerequisites:

Method:

  1. In your Windows host machine, start Visual Studio.
  2. In Visual Studio:
    1. Create a new C# console application “hn” within the mapped directory for the virtual machine.
    2. Replace the contents of Program.cs with the following code:
      using System;
      using System.Collections.Generic;
      using Nancy;
      using Nancy.Hosting.Self;
      
      namespace hn
      {
          public class SampleModule : Nancy.NancyModule
          {
              public SampleModule()
              {
                  Get["/"] = _ => "Hello World!";
              }
          }
      
          class Program
          {
              static void Main(string[] args)
              {
                  var uri = new Uri("http://localhost:80");
                  List list_uri = new List();
                  list_uri.Add(uri);
      
                  HostConfiguration hostConfigs = new HostConfiguration()
                  {
                      UrlReservations = new UrlReservations() { CreateAutomatically = true }
                  };
      
                  using (NancyHost host = new NancyHost(new DefaultNancyBootstrapper(), hostConfigs, list_uri.ToArray()))
                  {
                      host.Start();
                      foreach (Uri u in list_uri)
                          Console.WriteLine(u);
                      Console.WriteLine("Press any [Enter] to close the host.");
                      Console.ReadLine();
                  }
              }
          }
      }
      
      
    3. In order for this to compile, you will need to add two packages using the Package Manager.
      1. Start the Package Manager in Visual Studio.
      2. At the prompt, type Install-Package Nancy and Install-Package Nancy.Hosting.Self.
    4. Compile and run.
    5. In a browser, type in “http://localhost/”.
      1. Verify that your browser displays “Hello world!”.
  3. In the virtual machine guest:
    1. Open a Terminal.
    2. cd <mapped-directory>/<project-directory>
      1. Make sure the directory is mapped and you see the new project.
    3. xbuild
    4. mono bin/Debug/<project-executable>
    5. In a browser, type in “http://localhost/”.
      1. Verify that your browser displays “Hello world!”.

 

dokku@kukku:/vagrant/hn$ ls
App.config  bin  hn.csproj  hn.sln  obj  packages  packages.config  Program.cs  Properties
dokku@kukku:/vagrant/hn$ xbuild /target:Clean
XBuild Engine Version 12.0
Mono, Version 4.2.2.0
Copyright (C) 2005-2013 Various Mono authors

Build started 2/24/2016 10:20:58 AM.
__________________________________________________
Project "/vagrant/hn/hn.sln" (Clean target(s)):
	Target ValidateSolutionConfiguration:
		Building solution configuration "Debug|Any CPU".
	Target Clean:
		Project "/vagrant/hn/hn.csproj" (Clean target(s)):
/vagrant/hn/hn.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.
			Target CoreClean:
				Deleting file '/vagrant/hn/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttribute.cs'
				Deleting file '/vagrant/hn/obj/Debug/hn.exe'
				Deleting file '/vagrant/hn/obj/Debug/hn.exe.mdb'
				Deleting file '/vagrant/hn/obj/Debug/hn.csproj.FilesWrittenAbsolute.txt'
		Done building project "/vagrant/hn/hn.csproj".
Done building project "/vagrant/hn/hn.sln".

Build succeeded.

Warnings:

/vagrant/hn/hn.sln (Clean) ->
(Clean target) ->
/vagrant/hn/hn.csproj (Clean) ->

	/vagrant/hn/hn.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.

	 1 Warning(s)
	 0 Error(s)

Time Elapsed 00:00:00.5218600
dokku@kukku:/vagrant/hn$ xbuild
XBuild Engine Version 12.0
Mono, Version 4.2.2.0
Copyright (C) 2005-2013 Various Mono authors

Build started 2/24/2016 10:21:05 AM.
__________________________________________________
Project "/vagrant/hn/hn.sln" (default target(s)):
	Target ValidateSolutionConfiguration:
		Building solution configuration "Debug|Any CPU".
	Target Build:
		Project "/vagrant/hn/hn.csproj" (default target(s)):
/vagrant/hn/hn.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.
			Target PrepareForBuild:
				Configuration: Debug Platform: AnyCPU
			Target GenerateSatelliteAssemblies:
			No input files were specified for target GenerateSatelliteAssemblies, skipping.
			Target CoreCompile:
				Tool /usr/lib/mono/4.5/mcs.exe execution started with arguments: /noconfig /debug:full /debug+ /optimize- /out:obj/Debug/hn.exe Program.cs Properties/AssemblyInfo.cs obj/Debug/.NETFramework,Version=v4.5.AssemblyAttribute.cs /target:exe /define:"DEBUG;TRACE" /nostdlib /platform:AnyCPU /reference:packages/Nancy.1.4.3/lib/net40/Nancy.dll /reference:packages/Nancy.Hosting.Self.1.4.1/lib/net40/Nancy.Hosting.Self.dll /reference:/usr/lib/mono/4.5/System.dll /reference:/usr/lib/mono/4.5/System.Xml.Linq.dll /reference:/usr/lib/mono/4.5/System.Data.DataSetExtensions.dll /reference:/usr/lib/mono/4.5/Microsoft.CSharp.dll /reference:/usr/lib/mono/4.5/System.Data.dll /reference:/usr/lib/mono/4.5/System.Net.Http.dll /reference:/usr/lib/mono/4.5/System.Xml.dll /reference:/usr/lib/mono/4.5/System.Core.dll /reference:/usr/lib/mono/4.5/mscorlib.dll /warn:4
			Target _CopyAppConfigFile:
			Skipping target "_CopyAppConfigFile" because its outputs are up-to-date.
			Target DeployOutputFiles:
				Copying file from '/vagrant/hn/obj/Debug/hn.exe.mdb' to '/vagrant/hn/bin/Debug/hn.exe.mdb'
				Copying file from '/vagrant/hn/obj/Debug/hn.exe' to '/vagrant/hn/bin/Debug/hn.exe'
		Done building project "/vagrant/hn/hn.csproj".
Done building project "/vagrant/hn/hn.sln".

Build succeeded.

Warnings:

/vagrant/hn/hn.sln (default targets) ->
(Build target) ->
/vagrant/hn/hn.csproj (default targets) ->

	/vagrant/hn/hn.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.

	 1 Warning(s)
	 0 Error(s)

Time Elapsed 00:00:01.0865300
dokku@kukku:/vagrant/hn$ mono bin/Debug/hn.exe

Unhandled Exception:
System.Net.Sockets.SocketException: Access denied
  at System.Net.Sockets.Socket.Bind (System.Net.EndPoint local_end)  in :0 
  at System.Net.EndPointListener..ctor (System.Net.IPAddress addr, Int32 port, Boolean secure)  in :0 
  at System.Net.EndPointManager.GetEPListener (System.String host, Int32 port, System.Net.HttpListener listener, Boolean secure)  in :0 
  at System.Net.EndPointManager.AddPrefixInternal (System.String p, System.Net.HttpListener listener)  in :0 
  at System.Net.EndPointManager.AddListener (System.Net.HttpListener listener)  in :0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.Net.Sockets.SocketException: Access denied
  at System.Net.Sockets.Socket.Bind (System.Net.EndPoint local_end)  in :0 
  at System.Net.EndPointListener..ctor (System.Net.IPAddress addr, Int32 port, Boolean secure)  in :0 
  at System.Net.EndPointManager.GetEPListener (System.String host, Int32 port, System.Net.HttpListener listener, Boolean secure)  in :0 
  at System.Net.EndPointManager.AddPrefixInternal (System.String p, System.Net.HttpListener listener)  in :0 
  at System.Net.EndPointManager.AddListener (System.Net.HttpListener listener)  in :0 
dokku@kukku:/vagrant/hn$ sudo mono bin/Debug/hn.exe
http://localhost/
Press any [Enter] to close the host.

2016-02-24 (1)

 

Code for this example:

For more information:

 

Getting C# on Friggin’ Linux Working

If you like C#, and want to program using it across all platforms–including Linux–it’s easy using the Mono runtime! The details of the Mono project I won’t go into detail here, but rather only show how to set up a “Hello world!” project that will build and run on Ubuntu. Note: MonoProject is an IDE for Mono projects. I highly recommend you install that.

Prerequisites:

There are three options you can use to get the source project onto the virtual machine: (1) Use Visual Studio to create a Hello World program, then set up a mapped folder in VirtualBox that contains the project. (2) Use Visual Studio to create a Hello World program, then use Git to clone the repository onto the guest machine. If you’d like, you can skip this step, and use the example at https://bitbucket.org/ken_domino/hw/overview. (3) Use MonoProject to create a Hello World program from scratch on Ubuntu.

Method:

  1. In your Windows host machine, start Visual Studio.
  2. In Visual Studio:
    1. Create a new C# console application within the mapped directory for the virtual machine.
    2. Add System.Console.WriteLine(“Hello world!”); to the main method.
    3. Compile and run to verify that it works.
  3. Let’s set up Mono on the guest machine. In the virtual machine:
    1. Open a Terminal.
    2. cd <mapped-directory>/<project-directory>
      1. Make sure the directory is mapped and you see the new project.
    3. sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
      1. You are creating a package repository for Mono.
      2. These instructions are from the Mono Project install for Ubuntu.
    4. echo "deb http://download.mono-project.com/repo/debian wheezy main" | sudo tee /etc/apt/sources.list.d/mono-xamarin.list
    5. sudo apt-get update
    6. sudo apt-get install mono-complete
  4. Let’s now build the Hello World program. Use one of the three methods I mentioned above. Then…
    1. xbuild
      1. xbuild” is Mono’s version of “msbuild“.
    2. mono bin/Debug/<project-executable>
      1. You should see the “Hello world!” in the terminal.
  5. Install the MonoDevelop application if you want to have an IDE for C# on Linux. It is similar to Xamarin Studio. You can then open the project in MonoDevelop.
    1. sudo apt-get install monodevelop
  6. Install the XSP4 server if you want to write ASP.NET projects.
    1. sudo apt-get install mono-xsp4

 

dokku@kukku:/vagrant/hw$ which mono
/usr/bin/mono
dokku@kukku:/vagrant/hw$ mono --version
Mono JIT compiler version 4.2.2 (Stable 4.2.2.30/996df3c Mon Feb 15 17:30:30 UTC 2016)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	LLVM:          supported, not enabled.
	GC:            sgen
dokku@kukku:/vagrant/hw$ which mono
/usr/bin/mono
dokku@kukku:/vagrant/hw$ mono --version
Mono JIT compiler version 4.2.2 (Stable 4.2.2.30/996df3c Mon Feb 15 17:30:30 UTC 2016)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
	TLS:           __thread
	SIGSEGV:       altstack
	Notifications: epoll
	Architecture:  amd64
	Disabled:      none
	Misc:          softdebug 
	LLVM:          supported, not enabled.
	GC:            sgen
dokku@kukku:/vagrant/hw$ xbuild /target:Clean
XBuild Engine Version 12.0
Mono, Version 4.2.2.0
Copyright (C) 2005-2013 Various Mono authors

Build started 2/24/2016 9:11:49 AM.
__________________________________________________
Project "/vagrant/hw/hw.sln" (Clean target(s)):
	Target ValidateSolutionConfiguration:
		Building solution configuration "Debug|Any CPU".
	Target Clean:
		Project "/vagrant/hw/hw.csproj" (Clean target(s)):
/vagrant/hw/hw.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.
			Target CoreClean:
				Deleting file '/vagrant/hw/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttribute.cs'
				Deleting file '/vagrant/hw/bin/Debug/hw.exe.config'
				Deleting file '/vagrant/hw/bin/Debug/hw.exe.mdb'
				Deleting file '/vagrant/hw/bin/Debug/hw.exe'
				Deleting file '/vagrant/hw/obj/Debug/hw.exe'
				Deleting file '/vagrant/hw/obj/Debug/hw.exe.mdb'
				Deleting file '/vagrant/hw/obj/Debug/hw.csproj.FilesWrittenAbsolute.txt'
		Done building project "/vagrant/hw/hw.csproj".
Done building project "/vagrant/hw/hw.sln".

Build succeeded.

Warnings:

/vagrant/hw/hw.sln (Clean) ->
(Clean target) ->
/vagrant/hw/hw.csproj (Clean) ->

	/vagrant/hw/hw.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.

	 1 Warning(s)
	 0 Error(s)

Time Elapsed 00:00:00.5173490
dokku@kukku:/vagrant/hw$ ls -R
.:
App.config  bin  hw.csproj  hw.sln  obj  Program.cs  Properties

./bin:
Debug

./bin/Debug:
hw.pdb  hw.vshost.exe  hw.vshost.exe.config  hw.vshost.exe.manifest

./obj:
Debug

./obj/Debug:
DesignTimeResolveAssemblyReferencesInput.cache  TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs  TempPE
hw.csproj.FileListAbsolute.txt                  TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs
hw.csprojResolveAssemblyReference.cache         TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs

./obj/Debug/TempPE:

./Properties:
AssemblyInfo.cs
dokku@kukku:/vagrant/hw$ xbuild /target:Rebuild
XBuild Engine Version 12.0
Mono, Version 4.2.2.0
Copyright (C) 2005-2013 Various Mono authors

Build started 2/24/2016 9:12:19 AM.
__________________________________________________
Project "/vagrant/hw/hw.sln" (Rebuild target(s)):
	Target ValidateSolutionConfiguration:
		Building solution configuration "Debug|Any CPU".
	Target Rebuild:
		Project "/vagrant/hw/hw.csproj" (Rebuild target(s)):
/vagrant/hw/hw.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.
			Target PrepareForBuild:
				Configuration: Debug Platform: AnyCPU
			Target GenerateSatelliteAssemblies:
			No input files were specified for target GenerateSatelliteAssemblies, skipping.
			Target CoreCompile:
				Tool /usr/lib/mono/4.5/mcs.exe execution started with arguments: /noconfig /debug:full /debug+ /optimize- /out:obj/Debug/hw.exe Program.cs Properties/AssemblyInfo.cs obj/Debug/.NETFramework,Version=v4.5.AssemblyAttribute.cs /target:exe /define:"DEBUG;TRACE" /nostdlib /platform:AnyCPU /reference:/usr/lib/mono/4.5/System.dll /reference:/usr/lib/mono/4.5/System.Xml.Linq.dll /reference:/usr/lib/mono/4.5/System.Data.DataSetExtensions.dll /reference:/usr/lib/mono/4.5/Microsoft.CSharp.dll /reference:/usr/lib/mono/4.5/System.Data.dll /reference:/usr/lib/mono/4.5/System.Net.Http.dll /reference:/usr/lib/mono/4.5/System.Xml.dll /reference:/usr/lib/mono/4.5/System.Core.dll /reference:/usr/lib/mono/4.5/mscorlib.dll /warn:4
			Target _CopyAppConfigFile:
				Copying file from '/vagrant/hw/App.config' to '/vagrant/hw/bin/Debug/hw.exe.config'
			Target DeployOutputFiles:
				Copying file from '/vagrant/hw/obj/Debug/hw.exe.mdb' to '/vagrant/hw/bin/Debug/hw.exe.mdb'
				Copying file from '/vagrant/hw/obj/Debug/hw.exe' to '/vagrant/hw/bin/Debug/hw.exe'
		Done building project "/vagrant/hw/hw.csproj".
Done building project "/vagrant/hw/hw.sln".

Build succeeded.

Warnings:

/vagrant/hw/hw.sln (Rebuild) ->
(Rebuild target) ->
/vagrant/hw/hw.csproj (Rebuild) ->

	/vagrant/hw/hw.csproj:  warning : Project has unknown ToolsVersion '14.0'. Using the default tools version '4.0' instead.

	 1 Warning(s)
	 0 Error(s)

Time Elapsed 00:00:01.1014250
dokku@kukku:/vagrant/hw$ ls -l bin/Debug/hw.exe
-rwxrwxrwx 1 dokku dokku 4096 Feb 24 09:12 bin/Debug/hw.exe
dokku@kukku:/vagrant/hw$ mono !$
mono bin/Debug/hw.exe
Hello world!
dokku@kukku:/vagrant/hw$ 

 

For more information:

 

Getting SSH/Git Clients on Friggin’ Windows Working

 

Secure Shell (SSH) is a network protocol used ubiquitously, e.g., github.com, bitbucket.com, etc. If you use Git or Hg, it’s nice to set up SSH because you can avoid having to re-enter your user id and password every time you clone the repository. (Or, if you are really desperate, encode the user id and password in the URI for the repository.) While there may be a lot of information (e.g., here and here) on how to set this up, it’s almost always Linux-centric, using ssh, ssh-add, ssh-keygen commands. Cygwin has an implementation which looks just like the Linux toolset, but Putty is the SSH system most use on Windows. Unfortunately, Git checks the environmental variables, and special cases the connection (see the kludges in git_connect in connect.c). So, if you try Git from Cygwin, it may not use the same SSH system in some other environment, like SourceTree. (If you look for “git.exe” in your PC, it’s sprinkled throughout.) If you didn’t know that and use Windows, God help you because you can spend days trying to figure out why things don’t work while sifting through the mountains of useless information! This protocol outlines the steps involved to set up SSH for both Cygwin and Putty.

Prerequisites:

  • Cygwin installed
  • Account on Github.com
  • Git installed (https://git-scm.com/downloads)
  • Git GUI (https://git-scm.com/downloads/guis). I recommend SourceTree (https://www.sourcetreeapp.com/).

Method:

    1. Open a Cygwin Terminal, and execute the following commands in order presented…
    2. which ssh
      1. Note: Verify that you have SSH installed for Cygwin. If not, go to http://cygwin.com, download the installer, run it and install SSH.
    3. I HIGHLY recommend you use Pageant. Place in your ~/.bashrc file eval $(/usr/local/bin/ssh-pageant -ra $TEMP/.ssh-pageant)., See https://github.com/cuviper/ssh-pageant.
      1. If you don’t plan on using Pageant, eval `ssh-agent -s`; ssh-add -L
      2. Note: look at the output to see if there are any keys added. There may or may not, it doesn’t matter because you’re going to generate and add a new key here.
    4. cd ~/.ssh
      1. Note: If you don’t have the directory, execute cd, then mkdir .ssh to create one, then cd .ssh.
    5.  ssh-keygen -t rsa
    6. On the prompts, you can just return for each thing prompted for.
    7. ls
      1. Note: Verify you have id_rsa, id_rsa.pub (or the file name you entered above) generated.
    8. cat id_rsa.pub # (or the file you entered above)
      1. Verify the key is not empty.
    9. ssh-add
      1. Note: You should see output from ssh-add indicating it added the keys in the ~/.ssh directory. If not, it may have been already added.
    10. ssh-add -L
      1. Note: Verify you have the key you just created added.
    11. In an editor like Notepad, open the .PUB file and copy the text into the clipboard.
    12. In a browser, log into github.com (or create an account).
    13. In Github.com, to the the upper-right corner, and click on the icon for the user, and then settings in the pulldown.
      1. Add a key. See https://help.github.com/articles/adding-a-new-ssh-key-to-your-github-account/ for more info.
    14. Back in the Cygwin Terminal started in step 1 …
    15. ssh -v git@github.com
      • When it prompts for “do you want to continue?”, enter yes.
      • The output should look like this:

 

$ ssh -v git@github.com
OpenSSH_7.1p1, OpenSSL 1.0.2d 9 Jul 2015
debug1: Connecting to github.com [192.30.252.129] port 22.
debug1: Connection established.
debug1: identity file /home/Ken/.ssh/id_rsa type 1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_rsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_dsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_dsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_ecdsa type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_ecdsa-cert type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_ed25519 type -1
debug1: key_load_public: No such file or directory
debug1: identity file /home/Ken/.ssh/id_ed25519-cert type -1
debug1: Enabling compatibility mode for protocol 2.0
debug1: Local version string SSH-2.0-OpenSSH_7.1
debug1: Remote protocol version 2.0, remote software version libssh-0.7.0
debug1: no match: libssh-0.7.0
debug1: Authenticating to github.com:22 as 'git'
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: server->client chacha20-poly1305@openssh.com <implicit> none
debug1: kex: client->server chacha20-poly1305@openssh.com <implicit> none
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: Server host key: ssh-rsa SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8
The authenticity of host 'github.com (192.30.252.129)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,192.30.252.129' (RSA) to the list of known hosts.
debug1: SSH2_MSG_NEWKEYS sent
debug1: expecting SSH2_MSG_NEWKEYS
debug1: SSH2_MSG_NEWKEYS received
debug1: Roaming not allowed by server
debug1: SSH2_MSG_SERVICE_REQUEST sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
debug1: Authentications that can continue: publickey
debug1: Next authentication method: publickey
debug1: Offering RSA public key: /home/Ken/.ssh/id_rsa
debug1: Server accepts key: pkalg ssh-rsa blen 279
debug1: Authentication succeeded (publickey).
Authenticated to github.com ([192.30.252.129]:22).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
PTY allocation request failed on channel 0
debug1: client_input_channel_req: channel 0 rtype exit-status reply 0
Hi kaby76! You've successfully authenticated, but GitHub does not provide shell access.
debug1: channel 0: free: client-session, nchannels 1
Connection to github.com closed.
Transferred: sent 3388, received 1796 bytes, in 0.1 seconds
Bytes per second: sent 42231.9, received 22387.4
debug1: Exit status 1
      1. git clone git@github.com:heroku/ruby-rails-sample.git
        1. Note: This verifies that command-line Git works. If it doesn’t then you should probably use ssh-pageant because git is not using the right agent.
      2. Note: If you use SourceTree (or other Git clients), verify they work too. This is because they use a damn separate authentication tool: pageant.exe. You can tell if you see in the lower-right corner the Pageant server icon.
      3. Find the Pageant server, and open it
      4. 2016-02-18 (4)
      5. In SourceTree, go to menu item “Tools | Create or Import SSH Keys”.
      6. In the dialog box, click on “Load” button, and find the file id_rsa (or the file name you entered above). You will have to type it in explicitly, or remove the stupid filter for the open file dialog box. Save the key, both public and private (generates a PPK file that’s compatible with Pageant).
      7. In Pageant, “Add Key”, using the .PPK generated above by SourceTree utility.
      8. Execute plink.exe in the Atlassian/SourceTree installation directory from Cygwin Terminal or Cmd.
      9. plink git@github.com
      10. In SourceTree, In SourceTree, clone the above Ruby sample. If it hangs, use plink.exe from the Cygwin Terminal.
$ plink git@github.com
Hi kaby76! You've successfully authenticated, but GitHub does not provide shell access.
Using username "git".
Server refused to allocate pty

Additional Information

Order-Independent Tree Comparison Using X-Diff

I am interested in the testing of regressions of a program that I am modifying. What is unique about this regression test is that I want to check for differences after modifications of the internal data structures using XML or JSON. As an example, suppose I am working on a C# compiler. The compiler works by parsing C# programs, then constructs an abstract syntax tree. Let’s assume that I’ve written some simple C# programs that are valid, and the compiler before modifications is correct. I now modify the compiler to use a new parser, and now want to check for regressions in the data structures after the parser. To test for regressions, I compare the XML or JSON representations of the abstract syntax tree of a program, before and after modifications to the compiler.

X-Diff

What is it?

X-Diff is a program that determines the set of changes between two XML documents. X-Diff assumes an unordered tree comparison model, whereby order of elements is not important (i.e., the trees are isomorphic). The command-line program takes two input file names containing XML (or JSON, in the C# port/extension).

Who wrote it?

http://pages.cs.wisc.edu/~yuanwang/xdiff.html

Wang, Yuan, David J. DeWitt, and Jin-Yi Cai. “X-Diff: An effective change detection algorithm for XML documents.” Data Engineering, 2003. Proceedings. 19th International Conference on. IEEE, 2003. DOI: 10.1109/ICDE.2003.1260818.

C++ and Java source.

How does it work?

Note: It is difficult to relate the code to the algorithms described in the paper, with many special case code percolated throughout. Below is an overview of what the code does.

  1. Input two XML files with XParser.parse(). The code intermingles parsing with attribute analysis, so it can be somewhat difficult to understand. In Java, the Xerces XML parser is used (http://xerces.apache.org/). In the C# port, the Microsoft “LINQ to XML” library is used instead. “LINQ to XML” does not provide a SAX-like interface for parsing, so I’ve added a pre-order tree walker (XParser.preorder) to XParser as a drop-in substitute. During parsing, a hash value is computed for each node in the XML document. The value is recursively defined: hash(N) = DES(N) + \sum^c[hash(c)]^2\text{, where c = child of N}. Notes: (a) the hash value for node N is order independent because addition is commutative. (b) I don’t understand why the authors square the hash value–except when a node has a single child. I don’t know why. (c) The Data Encryption Standard (DES) is used to obtain the hash value of tags, attributes, and text: DES(N). It isn’t clear why DES is used as opposed to Cyclic Redundency Check (CRC).
  2. In a top-down manner, each node in one tree is matched to a node is the second tree. The result of is a list of pairs that are matched.
    1. xdiff(node1, node2)–node1 and node2 are two nodes which are to be matched. The result is a matching, defined by table matched.
      1. If the hash value of child c1 of node1 and c2 of node2 are equal, they are removed from further comparison, and placed in matched += (c1, c2).
      2. If there is no match for c1, c2, then c1 and c2 are added to unmatched1, unmatched2, respectively.
      3. The sets unmatched1 and unmatched2 are now examined: Find an optimal matching of nodes in unmatched, matchList(unmatched1, unmatched2). Note: matchList is a recursive function defined below.
    2. matchList(unmatched1, unmatched2)–unmatched lists are of unmatched nodes in the two trees.
      1. For all n1 in unmatched1
        1. For all n2 in unmatched2
          1. Compute the optimal “distance” d = distance(n1, n2). Note: distance() is a recursive function that finds the optimal number of changes to convert node n1 to node n2. Distance should also compute the cost of creating a tree (i.e., distance(null, n2)) or deleting a tree (i.e., distance(n1, null)).
      2. Find the optimal bipartite complete matching by picking the list of weighted pairs (n1, n2) such that n1 is in unmatched1 (or null), n2 is in unmatched2 (or null): searchNCC().
      3. For each pair in optimal match, xdiff(p1, p2).

Port to C#

I have ported the code to C#; it is available in a git repository (https://bitbucket.org/ken_domino/xdiff).

A Short, Practical Review of Foreign Function Calls in Java, C#, C++

Android is a popular platform for smartphones, with ten of thousands of applications developed for it every year. For coding an Android app, there are a number of programming languages, but Java is the most popular. However, Xamarin provides tools for writing applications in C# if you prefer. If you use Xamarin, but sometimes want to use an open-source library written in Java, you still can. The state of currently used, practical Foreign Function Interfaces (FFI) on most platforms is similar. Of course, the difficulty is in the details.

Generally, there are two ways for code in one language to call another: use a native function to call the foreign function; or, use reflection to call the foreign function. A bindings interface offers native functions to the whole foreign API.

Java Native Interface (JNI) provides a native interface to call non-Java code from Java. It also provides an API for use in C++ to invoke Java code, structured like Java’s reflection API.

There are a number of tutorials on how to use JNI, but they are somewhat out of date. This article brings it forward–if only to a small degree, with “how to” explanations.

Continue reading “A Short, Practical Review of Foreign Function Calls in Java, C#, C++”

An OpenCL.NET Program for Device Information

There was an interesting question on Gamedev.net today asking about whether there is an API in C# for querying information about the GPUs installed. Apparently, GPU-Z uses the CUDA API to get information about an NVIDIA GPU, and GPUPerfAPI for the AMD GPU. However, a good alternative to those APIs is OpenCL, a platform independent framework to gather information about the computing devices in a PC. For C#, OpenCL.NET works quite well.

The following program queries and outputs the device information from OpenCL. It comes in handy when you need to know some basic properties of the computer you are using when you don’t want to use GPU-Z or CPU-Z.

Synchronization Using Barrier for Tasks in the .NET Task Parallel Library

Lately I have been converting some GPGPU algorithms from CUDA into C# and the Task Parallel Library, e.g., tiled reduction. However, I noticed a significant problem in the efficiency of the System.Threading.Barrier class for task synchronization. This problem was also noted by Andrea Esuli here, who proposed an incomplete solution.

As stated in the documentation, “[Barrier] enables multiple tasks to cooperatively work on an algorithm in parallel through multiple phases.” Although it does work with System.Threading.Tasks.Task, when the participant count for the Barrier is more than four–the number of cores in my CPU–the method SignalAndWait() blocks with a time out of one second, probably because Barrier blocks a thread serving multiple task. The example below illustrates the problem using Barrier and Task with a large number of tasks spawned. Notwithstanding the efficiency, Barrier.SignalAndWait() is correct.

As noted by Esuli, a solution is to try to coerce each task to be in its own thread using TaskCreationOptions.LongRunning during construction. Unfortunately, this seems to only work outside a debugging session, or for problems with a participant count up to 8 when debugging the program. This limits its use. Esuli also notes to use ManualResetEvent instead of Barrier. Unfortunately, that solution isn’t correct because ManualResetEvent.Set() does not block the execution of the code following the Set() in a task the same way as Barrier.

The best solution I came up with is a task-level barrier, implemented as follows. (1) Replace “SignalAndWait();” in each task with “await Task.Yield();”. (2) Create a custom task scheduler that maintains a special queue for the execution of the asynchronous continuation tasks. The scheduler examines the context of the call to QueueTask(Task task). If the call is for a continuation, place the task on a special queue to be executed after all “normal” tasks. (3) When the final continuation task has been queued, transfer the continuation tasks the the normal queue. (4) Wait for all normal tasks to complete using Task.WaitAll(…). (5) Complete all continuation tasks using RunSynchronously().

 

Windows 10 on VirtualBox

The Windows 10 preview has been out for several months, but it still doesn’t work well in VirtualBox: the VirtualBox graphics driver crashes with “Windows cannot initialize the device driver for this hardware. (Code 37)” or “Windows has stopped this device because it has reported problems. (Code 43)”. This means you cannot use “auto-resize Guest Display”. Fortunately, I saw in 4sysops.com this nice work around. In your host machine, add a custom video mode for the monitor size you will use in fullscreen mode. While VirtualBox is not running, execute the command “/cygdrive/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe setextradata vs2013-win10 CustomVideoMode1 1440x900x32“, where “vs2013-win10” is the name of the virtual machine, and “1440x900x32” is the screen resolution of the monitor you plan on using. Then, start VirtualBox, and log into Windows 10. Right click on the desktop, select “screen resolution” for the monitor you want to use, then enter fullscreen mode.

As you use Windows 10, “Windows Update” will be performed periodically. Occasionally, the updates, which typically involves most files of the OS during this pre-release period, may not install due to disk space of your VDI disk image. That can be fixed using /cygdrive/c/Program\ Files/Oracle/VirtualBox/VBoxManage.exe modifyhd YOUR_HARD_DISK.vdi –resize SIZE_IN_MB.

Note: After extending the size of a VDI using VBoxManager, you will need to extend the partition within the VirtualBox guest OS so that the guest uses the extra space. For example, for a Windows 10 NTFS partition, go to File Explorer | This PC / right-click | Manage -> Disk Management -> left-click the partition -> Extend Volume.