{"id":80255,"date":"2016-10-05T00:01:03","date_gmt":"2016-10-05T07:01:03","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/?p=80255"},"modified":"2019-02-18T09:10:26","modified_gmt":"2019-02-18T16:10:26","slug":"part-2-install-net-core-and-powershell-on-linux-using-dsc","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/part-2-install-net-core-and-powershell-on-linux-using-dsc\/","title":{"rendered":"Part 2 \u2013 Install .NET Core and PowerShell on Linux Using DSC"},"content":{"rendered":"<p><strong>Summary<\/strong>: Learn how to configure and use PowerShell, Bash, and desired state configuration (DSC) with Linux.<\/p>\n<p>Today, Cloud and Data Center MVP Stefan Roth returns for Part 2\u00a0of his three-part series about how to configure and use PowerShell, Bash, and desired state configuration (DSC) with Linux. Take it away Stefan \u2026<\/p>\n<p>My <a href=\"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2016\/09\/28\/part-1-install-bash-on-windows-10-omi-cim-server-and-dsc-for-linux\/\">previous post<\/a> installed the foundation for this second part. It installed the OMI CIM server and DSC on Linux. In this part, the goal is to run a DSC configuration on Linux to download and install .NET core libraries and Windows PowerShell for Linux.<\/p>\n<p>There is a multi-step process to get this done.<\/p>\n<ol>\n<li>Open firewall TCP port 5986 on the Linux machine<\/li>\n<li>Connect via CIM session to the OMI CIM server<\/li>\n<li>Install nx DSC module locally on your Windows 10 system<\/li>\n<li>Create MOF file locally on your Windows 10 system<\/li>\n<li>Copy and execute the DSC configuration (MOF file) on Linux<\/li>\n<\/ol>\n<p>Sounds cool? Yeah it is!<\/p>\n<p>Just to recap, my Ubuntu Bash is running on my client computer and a Linux server CentOS 7 x64. I think to test and develop a DSC configuration, which we want to run from Azure Automation, the best way is to write the configuration file locally and connect to the OMI CIM server via WinRM. By default, the OMI CIM server is listening on port 5986 for incoming traffic.<\/p>\n<p>You can figure this out by looking at the omiserver.conf file in the <em>\/etc\/opt\/omi\/conf\/ <\/em>directory.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-1.png\" alt=\"Contents of the omiserver.conf file\" width=\"604\" height=\"499\" class=\"alignnone size-full wp-image-80256\" \/><\/a><\/p>\n<p>Because my CentOS 7 server has a firewall running, you need to open the firewall TCP port 5986.<\/p>\n<p>To open TCP port 5986 (inbound), use the following commands:<\/p>\n<p style=\"padding-left: 60px\"><code>firewall-cmd --zone=public --add-port=5986\/tcp --permanent<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>firewall-cmd \u2013reload<\/code><\/p>\n<p>The next step is to use PowerShell on my Windows 10 system to connect to the OMI CIM server. For this, I use the <strong>New-CIMSession<\/strong> cmdlet. Because we do not use a valid certificate for https to successfully connect, we need to skip certificate authority (CA), certificate common name (CN) and revocation status check. So, the command looks like this.<\/p>\n<p>Connect via CIM session to OMI CIM server:<\/p>\n<p style=\"padding-left: 60px\"><code>$Credentials = Get-Credential -UserName:'root' -Message 'Enter Root Credentials'<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$CIMOptions = New-CimSessionOption -SkipCACheck -SkipCNCheck -UseSsl -SkipRevocationCheck<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>$CIMSession = New-CimSession -Credential $Credentials -ComputerName '192.168.32.18' -Port 5986 -Authentication Basic -SessionOption $CIMOptions<\/code><\/p>\n<p>If you look at the <strong>$CIMSession<\/strong> object, you will see the connection.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-2.png\" alt=\"The connection in the $CIMSession object\" width=\"400\" height=\"133\" class=\"alignnone size-full wp-image-80265\" \/><\/a><\/p>\n<p>The next step is to install the nx DSC module on your Windows 10 system. You need this module so you can develop and compile the managed object format (MOF) file locally on Windows 10. The nx DSC module has several included resources. You need nxArchive, nxScript, and nxPackage.<\/p>\n<p><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxbuiltinresources\">Built-in resources<\/a><\/p>\n<p>The following list of resources and links to topics describe the resources in detail.<\/p>\n<ul>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxarchiveresource\">nxArchive Resource<\/a>&#8211;Provides a mechanism to unpack archive (.tar, .zip) files at a specific path.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxenvironmentresource\">nxEnvironment Resource<\/a>&#8211;Manages environment variables on target nodes.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxfileresource\">nxFile Resource<\/a>&#8211;Manages Linux files and directories.<\/li>\n<li><a href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxfilelineresource\">nxFileLine Resource<\/a>&#8211;Manages individual lines in a Linux file.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxgroupresource\">nxGroup Resource<\/a>&#8211;Manages local Linux groups.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxpackageresource\">nxPackage Resource<\/a>&#8211;Manages packages on Linux nodes.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxscriptresource\">nxScript Resource<\/a>&#8211;Runs scripts on target nodes.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxserviceresource\">nxService Resource<\/a>&#8211;Manages Linux services (daemons).<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxsshauthorizedkeysresource\">nxSshAuthorizedKeys Resource<\/a>&#8211;Manages public secure shell (SSH) keys for a Linux user.<\/li>\n<li><a target=\"_blank\" href=\"https:\/\/msdn.microsoft.com\/en-us\/powershell\/dsc\/lnxuserresource\">nxUser Resource<\/a>&#8211;Manages local Linux users.<\/li>\n<\/ul>\n<p>To install the nx DSC module on Windows 10, just run one command, <strong>Install-Module<\/strong>. When you get prompted several times, just confirm and agree.<\/p>\n<p>To install the DSC module (nx), use the following command:<\/p>\n<p style=\"padding-left: 60px\"><code>Install-Module -Name nx<\/code><\/p>\n<p>After you install. the DSC module, we are ready to put some meat on the bone. I have created a DSC script that will install .NET Core and PowerShell on Linux.<\/p>\n<p>The first section of the DSC script defines the download paths for .NET Core and PowerShell.<\/p>\n<p style=\"padding-left: 60px\"><code># Set the configuration data\n$ConfigData = @{<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>AllNodes = @(<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>@{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>NodeName = \"192.168.32.18\"\n<\/code><code>DownloadPath = \"\/root\/Downloads\/\"\nNetCoreSource = \u201chttps:\/\/download.microsoft.com\/download\/1\/5\/2\/1523EBE1-3764-4328-8961-D1BD8ECA9295\/dotnet-dev-centos-x64.1.0.0-preview2-003121.tar.gz\u201d\nNetVersion = \"dotnet-dev-centos-x64.1.0.0-preview2-003121.tar.gz\"\nPowerShellSource = \"https:\/\/github.com\/PowerShell\/PowerShell\/releases\/download\/v6.0.0-alpha.8\/powershell-6.0.0_alpha.8-1.x86_64-centos.7-x64.rpm\"\nPowerShellVersion = \"powershell-6.0.0_alpha.8-1.x86_64-centos.7-x64.rpm\"<\/code><\/p>\n<p style=\"padding-left: 180px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>)<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}<\/code><\/p>\n<p>The DSC configuration part uses several DSC resources from the nx module. There is a two-step process in place. First, you download prerequisites and source for .NET Core and installed it. If this step is successful, you download PowerShell for Linux and run the installation. If everything succeeds, you just type <strong>powershell<\/strong>, and the prompt from PowerShell on Linux will appear.<\/p>\n<p>The DSC script has comments, so there is probably not much more to say.<\/p>\n<p style=\"padding-left: 60px\"><code># DSC configuration\nconfiguration DotNetPowerShell\n{<\/code><\/p>\n<p style=\"padding-left: 90px\"><code># Import the DSC module nx\nImport-DSCResource -Module nx<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>node 192.168.32.18\n{<\/code><\/p>\n<p style=\"padding-left: 120px\"><code># Use yum to install pre-requisites for .NET Core\nnxPackage PreNetCore\n{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>Name = \"libunwind libicu\"\nEnsure = \"Present\"\nPackageManager = \"Yum\"<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}\n# Download the .NET Core source from Microsoft\nnxFile DownloadNetCore\n{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>Ensure = \"Present\"\nSourcePath = $Node.NetCoreSource\nDestinationPath = $Node.DownloadPath + $Node.NetVersion\nType = \"File\"\nDependsOn = \"[nxPackage]PreNetCore\"<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}\n# Extract the .NET Core tarball\nnxArchive ExtractNetCore\n{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>SourcePath = $Node.DownloadPath + $Node.NetVersion\nDestinationPath = \u201c\/opt\/dotnet\u201d\nForce = $false\nDependsOn = \"[nxFile]DownloadNetCore\"<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}\n# .NET Core needs to have a symbolic link set, therefore we use the script resource\nnxScript Symlink{<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>GetScript = @\"\n#!\/bin\/bash\nll \/usr\/local\/bin\/dotnet\n\"@<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>SetScript = @\"\n<\/code><code>#!\/bin\/bash\nln -s \/opt\/dotnet\/dotnet \/usr\/local\/bin\n\"@<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>TestScript = @'\n<\/code><code>#!\/bin\/bash\nif [ -L \/usr\/local\/bin\/dotnet ]\nthen<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>exit 0<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>else<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>exit 1<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>fi\n'@<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>DependsOn = \"[nxArchive]ExtractNetCore\"\n}\n# Download the PowerShell for Linux source\nnxFile DownloadPowerShell\n{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>Ensure = \"Present\"\nSourcePath = $Node.PowerShellSource\nDestinationPath = $Node.DownloadPath + $Node.PowerShellVersion\nType = \"File\"<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}\n# Install the PowerShell for Linux package\nnxPackage PowerShell\n{<\/code><\/p>\n<p style=\"padding-left: 150px\"><code>Name = $Node.PowerShellVersion\nFilePath = $Node.DownloadPath +\u00a0 $Node.PowerShellVersion\nEnsure = \"Present\"\nPackageManager = \"Yum\"\nDependsOn = \"[nxFile]DownloadPowerShell\"<\/code><\/p>\n<p style=\"padding-left: 120px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 90px\"><code>}<\/code><\/p>\n<p style=\"padding-left: 60px\"><code>}<\/code><\/p>\n<p>The next step is to create the MOF file on your local Windows system and save it to a directory (C:\\MOF).<\/p>\n<p style=\"padding-left: 60px\"><code>DotNetPowerShell -ConfigurationData $ConfigData -OutputPath \"C:\\MOF\\\"<\/code><\/p>\n<p>Finally, we can connect and run the MOF file against the Linux server by using the CIM session and the following command.<\/p>\n<p style=\"padding-left: 60px\"><code>Start-DscConfiguration -CimSession $CIMSession\u00a0 -Wait -Verbose -Path \"C:\\MOF\\\"<\/code><\/p>\n<p>You should get an output like in this screenshot.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-3.png\" alt=\"Output of the MOF file run against the Linux server \" width=\"554\" height=\"201\" class=\"alignnone size-full wp-image-80275\" \/><\/a><\/p>\n<p>If you run simply the <strong>powershell<\/strong> command (yes, lowercase) in your Bash, PowerShell will start on Linux.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/hsg-10-5-16-4.png\" alt=\"Output of the the powershell command \" width=\"588\" height=\"485\" class=\"alignnone size-full wp-image-80285\" \/><\/a><\/p>\n<p><strong><u>Summary:<\/u><\/strong> Imagine what this post achieves. First, you connected via WSMan protocol (PowerShell remoting) to the OMI CIM server that\u2019s running on Linux. Then, you used DSC on Linux to install .NET Core and PowerShell (!) on Linux. Finally, you just ran <strong>Get-ChildItem<\/strong> on Linux to get the directories and files the same way they\u2019re available on Windows. Isn\u2019t this just awesome!?<\/p>\n<p>In my next post, you will have some fun with Azure Automation DSC and the OMS injection API. Stay tuned!<\/p>\n<p>Thank you Stefan.<\/p>\n<p>I invite you to follow me on <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> and <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a target=\"_blank\" href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a>, or post your questions on the <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. Also, check out my <a target=\"_blank\" href=\"https:\/\/blogs.technet.microsoft.com\/msoms\/\">Microsoft Operations Management Suite Blog<\/a>. Until then, peace.<\/p>\n<p><strong>Ed Wilson\n<\/strong>Microsoft Scripting Guy<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to configure and use PowerShell, Bash, and desired state configuration (DSC) with Linux. Today, Cloud and Data Center MVP Stefan Roth returns for Part 2\u00a0of his three-part series about how to configure and use PowerShell, Bash, and desired state configuration (DSC) with Linux. Take it away Stefan \u2026 My previous post installed [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[568,641],"tags":[698,56,3,699,45],"class_list":["post-80255","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hey-scripting-guy","category-windows-powershell","tag-bash","tag-guest-blogger","tag-scripting-guy","tag-stefan-roth","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to configure and use PowerShell, Bash, and desired state configuration (DSC) with Linux. Today, Cloud and Data Center MVP Stefan Roth returns for Part 2\u00a0of his three-part series about how to configure and use PowerShell, Bash, and desired state configuration (DSC) with Linux. Take it away Stefan \u2026 My previous post installed [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/80255","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=80255"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/80255\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=80255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=80255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=80255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}