Deploying .NET applications with the Nix package manager

36
Deploying .NET applications with the Nix package manager Sander van der Burg Delft University of Technology, EEMCS, Department of Software Technology Philips Healthcare, Philips Informatics Infrastructure (PII), Best June 15, 2010 Sander van der Burg Deploying .NET applications with the Nix package manager

description

Presentation given at Philips Healthcare about deploying .NET applications with Nix

Transcript of Deploying .NET applications with the Nix package manager

Page 1: Deploying .NET applications with the Nix package manager

Deploying .NET applications with the Nix packagemanager

Sander van der Burg

Delft University of Technology, EEMCS,Department of Software Technology

Philips Healthcare, Philips Informatics Infrastructure (PII),Best

June 15, 2010

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 2: Deploying .NET applications with the Nix package manager

Nix deployment system

Nix is a package manager, with some distinct features:

Stores components in isolation from each other

Allows using multiple variants/versions safely next to eachother

Builds components from declarative specifications

Reproducibility

Supports atomic upgrades and rollbacks

Garbage collection

Safely removes obsolete components

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 3: Deploying .NET applications with the Nix package manager

Nix deployment system

About 2500 open-source/free software packages are supported(Nixpkgs)

Used as a basis for the NixOS GNU/Linux distribution

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 4: Deploying .NET applications with the Nix package manager

Hydra

Continuous build & integration server

Built upon the Nix package manager

Used at TU Delft for building, integration and testing ofseveral projects on multiple platforms

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 5: Deploying .NET applications with the Nix package manager

Disnix

Distributed deployment extension for Nix

Manages inter-dependencies

Builds, distributes, activates services in a network of machines

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 6: Deploying .NET applications with the Nix package manager

The Nix store

All components are stored in isolation in a Nix store

In Nix every component name consists of a hash code andcomponent name:

/nix/store/30v58jznlaxnr4bca3hiz64wlb43mgpx-hello-2.5

Hash is generated from all the input arguments of the buildfunction: compilers, libraries, build scripts etc.

Multiple variants/versions can be kept safely next to eachother

Can be used for any type of component

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 7: Deploying .NET applications with the Nix package manager

The Nix store

/nix/store

44ef921582e840dae...-glibc-2.9

lib

libc.so

a1v58jz2la6nr7bcr...-glibc-2.11.1

lib

libc.so

30v58jznlaxnr4bca...-hello-2.5

bin

hello

0a4d829298227c98c...-hello-2.5

bin

hello

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 8: Deploying .NET applications with the Nix package manager

Global Assembly Cache (GAC)

.NET Global Assembly Cache (GAC) only supports strong-namedlibrary assemblies (DLLs):

Other types of components are not supported (executables,native DLLs, compilers)

Strong name is created from name, version, culture andsigning with a public-private key pair

Creating strong-names is sometimes painful

Possible to produce a different assembly with samestrong-name

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 9: Deploying .NET applications with the Nix package manager

Nix expressions

{stdenv, fetchurl}:

stdenv.mkDerivation {

name = "hello-2.5";

src = fetchurl {

url = ftp://ftp.gnu.org/gnu/hello/hello-2.5.tar.gz;

sha256 = "0in467phypnis2ify1gkmvc5l2fxyz3s4xss7g74gwk279ylm4r2";

};

meta = {

description = "A program that produces a familiar, friendly greeting";

homepage = http://www.gnu.org/software/hello/manual/;

license = "GPLv3+";

};

}

Specifies how the hello component should be built.

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 10: Deploying .NET applications with the Nix package manager

Nix expressions

rec {

stdenv = ...

curl = ...

openssl = ...

fetchurl = import ../build-support/fetchurl {

inherit curl openssl;

};

hello = import ../applications/misc/hello {

inherit stdenv fetchurl;

};

}

The hello build function is called with its arguments

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 11: Deploying .NET applications with the Nix package manager

Nix expressions

To build the Hello package:

$ nix-build all-packages.nix -A hello

Will recursively build hello and its dependencies and produces helloin:

/nix/store/30v58jznlaxnr4bca3hiz64wlb43mgpx-hello-2.5

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 12: Deploying .NET applications with the Nix package manager

Runtime dependencies

Nix detects runtime dependencies of a build

Nix scans all files of a component for hash-codes of adependency, e.g. RPATH defined in a ELF header

Uses a notion of closures to guarantee completeness:

If a specific component needs to be deployed, all its runtimedependencies are deployed first

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 13: Deploying .NET applications with the Nix package manager

Runtime dependencies

/nix/store

44ef921582e840dae...-glibc-2.9

lib

libc.so

a1v58jz2la6nr7bcr...-glibc-2.11.1

lib

libc.so

30v58jznlaxnr4bca...-hello-2.5

bin

hello

0a4d829298227c98c...-hello-2.5

bin

helloSander van der Burg Deploying .NET applications with the Nix package manager

Page 14: Deploying .NET applications with the Nix package manager

Supporting .NET applications with Nix

Nix is designed for use on UNIX like systems, e.g. GNU/Linux,FreeBSD, Mac OS X

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 15: Deploying .NET applications with the Nix package manager

Requirements

Buildtime support:

Compile Visual Studio solutions and produce assemblies

Invoke MSBuild.exe with right parameters

The build process must find its buildtime dependencies

Runtime support:

Assemblies must find its runtime dependencies

Integrate .NET CLR dependency resolver with Nix

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 16: Deploying .NET applications with the Nix package manager

Windows support

Nix is supported on Windows through Cygwin:

Offers UNIX implementation on top of Windows

Allows combining UNIX and Windows utilities

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 17: Deploying .NET applications with the Nix package manager

Windows support

Several Cygwin utilities map Windows concepts to UNIX conceptsand vica versa:

Can be used to glue UNIX tooling to Windows processes

cygpath, UNIX path names <=> Windows path names

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 18: Deploying .NET applications with the Nix package manager

Implementing build support

A .NET Nix build function dotnetenv.buildSolution isimplemented:

Takes source code of a Visual Studio C# solution

Produces output of the solution into a unique store path,based on the input arguments of this function

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 19: Deploying .NET applications with the Nix package manager

Build function implementation

{stdenv, dotnetfx}:

{ name, src, slnFile, targets ? "ReBuild"

, options ? "/p:Configuration=Debug;Platform=Win32"

, assemblyInputs ? []

}:

stdenv.mkDerivation {

inherit name src;

buildInputs = [ dotnetfx ];

installPhase = ’’

for i in ${toString assemblyInputs}; do

windowsPath=$(cygpath --windows $i)

AssemblySearchPaths="$AssemblySearchPaths;$windowsPath"

done

export AssemblySearchPaths

ensureDir $out

outPath=$(cygpath --windows $out)\\

MSBuild.exe ${slnFile} /nologo /t:${targets} \

/p:OutputPath=$outPath ${options} ...

’’;

}

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 20: Deploying .NET applications with the Nix package manager

Example usage

{dotnetenv, MyAssembly1, MyAssembly2}:

dotnetenv.buildSolution {

name = "My.Test.Assembly";

src = /path/to/source/code;

slnFile = "Assembly.sln";

assemblyInputs = [

dotnetenv.assembly20Path

MyAssembly1

MyAssembly2

];

}

Specifies how a Visual Studio solution should be built.

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 21: Deploying .NET applications with the Nix package manager

Example usage

rec {

dotnetfx = ...

stdenv = ...

dotnetenv = import ../dotnetenv {

inherit stdenv dotnetfx;

};

MyAssembly1 = import ../MyAssembly1 {

inherit dotnetenv;

};

MyAssembly2 = import ../MyAssembly1 {

inherit dotnetenv;

};

MyTestAssembly = import ../MyTestAssembly {

inherit dotnetenv MyAssembly1 MyAssembly2;

};

}

The MyTestAssembly function is called with its arguments

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 22: Deploying .NET applications with the Nix package manager

Example usage

To build the My.Test.Assembly component:

$ nix-build all-packages.nix -A MyTestAssembly

Recursively builds My.Test.Assembly and its dependencies, i.e.MyAssembly1, MyAssembly2, MyTestAssembly and producesoutput in:

/nix/store/ri0zzm2hmwg01w2wi0g4a3rnp0z24r8p-My.Test.Assembly

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 23: Deploying .NET applications with the Nix package manager

Implementing runtime support

.NET runtime locaties assemblies:

Determines the correct version of the assembly (strong-namedassemblies only)

Checks whether the assembly has been bound before(strong-named assemblies only)

If so, it uses this versionShares same assemblies in memory between applications

Checks the Global Assembly Cache (GAC) (strong-namedassemblies only)

Probes the assembly

Checking the <codebase> element in the application .config

Probing heuristics

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 24: Deploying .NET applications with the Nix package manager

Assembly probing

A <codebase> element in the application .config file can specifyits own assembly references:

Private assemblies can only reside in the directory or asubdirectory of the executable

Strong-named assemblies can be invoked from an arbitrarylocation, including remote locations

Referenced assembly is cached, therefore a strong-name isrequired

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 25: Deploying .NET applications with the Nix package manager

Implementing runtime support in Nix

Not very trivial, 3 options:

Copy dependent assemblies into the same Nix store path asthe executable

Generate an application .config file with <codebase>

section

Symlink dependent assemblies into the same Nix store path asthe executable

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 26: Deploying .NET applications with the Nix package manager

Copy dependent assemblies

Copy dependent assemblies into the same Nix store path as theexecutable:

Essentially static linking

Expensive in terms of disk space

Expensive in terms of memory usage

Works with private and strong-named assemblies

Works on Windows 2000, XP

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 27: Deploying .NET applications with the Nix package manager

Copy dependent assemblies

/nix/store

99bed1970e5e459bc...-My.Assembly1

My.Assembly1.dll

f4e5d4c96f95c5887...-My.Assembly2

My.Assembly2.dll

ri0zzm2hmwg01w2wi...-My.Test.Assembly

My.Assembly1.dll

My.Assembly2.dll

My.Test.Assembly.exe

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 28: Deploying .NET applications with the Nix package manager

Generate an application config file

Generate an application config file with <codebase> section:

References assemblies in other Nix store paths

Nix scans and detects runtime dependencies due to uniquestore paths

Cheap in terms of disk space

Allows efficient upgrading of a system (i.e. only replacingupdated parts)

Only works with strong-named assemblies

Cheap in terms of memory usage (sharing in memory)

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 29: Deploying .NET applications with the Nix package manager

Generate an application config file

/nix/store

99bed1970e5e459bc...-My.Assembly1

My.Assembly1.dll

f4e5d4c96f95c5887...-My.Assembly2

My.Assembly2.dll

ri0zzm2hmwg01w2wi...-My.Test.Assembly

My.Test.Assembly.exe

My.Test.Assembly.exe.config

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 30: Deploying .NET applications with the Nix package manager

Symlink dependent assemblies

Symlink dependent assemblies into the same Nix store path as theexecutable:

References assemblies in other Nix store paths

Nix scans and detects runtime dependencies due to uniquestore paths

Cheap in terms of disk space

Works with private and strong-named assemblies

Allows efficient upgrading of a system (i.e. only replacingupdated parts)

Expensive in terms of memory usage (no sharing)

NTFS symlinks are only supported in Windows Vista+,Windows Server 2008+

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 31: Deploying .NET applications with the Nix package manager

Symlink dependent assemblies

/nix/store

99bed1970e5e459bc...-My.Assembly1

My.Assembly1.dll

f4e5d4c96f95c5887...-My.Assembly2

My.Assembly2.dll

ri0zzm2hmwg01w2wi...-My.Test.Assembly

My.Assembly1.dll

My.Assembly2.dll

My.Test.Assembly.exe

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 32: Deploying .NET applications with the Nix package manager

Result

With this implementation we can build and run .NET softwarewith Nix, some caveats:

.NET framework and Visual Studio tools are not managed byNix

.NET framework has dependencies which must be in the GACand registry

Registry is not managed

Do not use of registry for configuration settings

Some UNIX properties are not enforced when invoking nativeWindows processes:

e.g. chrootMakes it slightly harder to guarantee purity

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 33: Deploying .NET applications with the Nix package manager

Possible applications

Use Nix for deployment of .NET applications

Offers the benefits of Nix (e.g. atomic upgrading) for .NETapplicationsAllows the deployment of complete systemsNo need to create your own installers

Hydra, http://nixos.org/hydra

Continuous integration & testing of .NET applicationsBuild and test components for multiple architectures

Disnix, http://nixos.org/disnix

Distributed deployment of .NET services into a network ofmachines

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 34: Deploying .NET applications with the Nix package manager

References

Nix, Nixpkgs, Hydra, NixOS, Disnix, http://nixos.org

Cygwin, http://www.cygwin.com

Demystifying the .NET Global Assembly Cache, http://www.codeproject.com/kb/dotnet/demystifygac.aspx

Common MSBuild Project Properties, http://msdn.microsoft.com/en-us/library/bb629394.aspx

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 35: Deploying .NET applications with the Nix package manager

References

How the Runtime Locates Assemblies,http://msdn.microsoft.com/en-us/library/yx7xezcf%

28VS.71%29.aspx

Locating the Assembly through Codebases or Probing,http://msdn.microsoft.com/en-us/library/15hyw9x3%

28VS.71%29.aspx

Assembly Searching Sequence, http://msdn.microsoft.com/en-us/library/aa374224%28VS.85%29.aspx

Sander van der Burg Deploying .NET applications with the Nix package manager

Page 36: Deploying .NET applications with the Nix package manager

Questions

Sander van der Burg Deploying .NET applications with the Nix package manager