(This is a guest post by Antoni Sawicki aka Tenox)
While everybody is busy buzzing about Windows 11, I wanted to commemorate the finest operating system ever made by Microsoft – Nano Server.
For most of people Nano Server was esoteric, distant and unapproachable. It had a rather high entry barrier, requiring you to build it on a Windows Server 2016 host using PowerShell magic spells. You couldn’t just simply download and run it. Even if you managed to get it running, there wasn’t anything you could actually do with it for fun. People didn’t bother to even check it out. My goal is to demystify this a bit, lower the entry bar and made it easy for people to hack it.
Background info (you can skip it)
Nano Server was an interesting attempt at creating a datacenter grade OS that’s not managed via local GUI, keyboard and mouse, but rather full automation, remote tooling and code. It went one step further than Server Core or Windows PE by completely removing GUI components and local shell. Hence it’s not actually called “Windows” or “Windows Nano” but rather simply “Nano Server”. Rumor has it, it started as MinWin. The OS has a rudimentary text mode console with functionality similar of VMware ESXi console. However Nano was much more than a bare metal hypervisor. It was a fully fledged operating system. Unlike ESXi you can develop and install services/apps for it and hypervisor wasn’t even it’s default role.
Ever since I first saw a demo on Microsoft Ignite (previously known as TechEd) I wanted to run aclock on the text console. Much like the WinNT BSOD edition. This article started around my efforts to run (or port if needed) aclock to this platform. At the time of writing, the technology has been dead for several years now. However all the artifacts and documentation are still available on Microsoft’s website. Probably not for long, so a good moment to do it now, before everything gets deleted in to oblivion.
How to quickly deploy Nano Server and run command line apps on the console
The hard way: you need to download Windows 2016 Server (eval) and run a PowerShell command to produce a bootable VHD file.
Microsoft provides (soon to be deleted) Nano Server Quick Start. However the steps are trivial so you can totally skip that and just do this:
- Launch PowerShell terminal window on the WS2016 host.
- Run:
Import-Module D:\NanoServer\NanoServerImageGenerator -Verbose
(D:\ drive being where Windows Server CDROM is mounted) - Run:
New-NanoServerImage -DeploymentType Guest -Edition Standard -MediaPath d:\ -BasePath c:\nano -TargetPath c:\nano.vhdx -ComputerName nano -Development
(c:\nano folder and c:\nano.vhdx image will be created for you)
Done! This will build a .vhdx image that can be run under Hyper-V as “Gen-2” VM. For Gen-1 or to run it on any other hypervisor change .vhdx to .vhd in -TargetPath
while running the PowerShell command.
The easy way: you can just download a pre-built VM image from here. There are VHD for Hyper-v Gen-1 and VHDX for Hyper-v Gen-2 and OVA for everything else.
First Boot
Once you boot it up you will be greeted with a PowerShell prompt. Just like that! You can type cmd
to launch the good old cmd.exe shell. MS-DOS 2016?
Keep in mind, this is a developer mode (see -Development flag). Normally you would be greeted with a login prompt and a boring menu that allows to change some networking settings and not much beyond that. In production mode you need to resort to hacks (or this) to get stuff running, fortunately nothing like that needed here.
So what can you run on it?
Firstly in order to get some external utilities going, you can mount a SMB share using net use
in cmd or New-SMBMapping
in PS world. Nano being a server and all, you can also share out a folder via net share
or use C$
(you may need to create a user by using either net user /add
in cmd or New-LocalUser
in PS). Alternatively you can install Posh-SSH and use SCP to transfer files. If you don’t have working network you can just shut it down, mount the vhd image on the host and copy stuff in to the image then detach the VHD.
Aclock worked on the first run, no issues, using standard win64 exe:
Wow! So looks like Nano console does have basic terminal controls. That opens quite a lot of possibilities. But can you run more complex apps? Text editors? Web browsers? GAMES?
Well, yes…, but likely not, but it really depends – on dependencies (read: DLLs).
From all the editors I tried XVI is probably the best:
Everything else has a variety of issues:
- The font is lacking line drawing characters. Some editors like YEdit allow to use ASCII drawing characters fortunately.
- There is no reverse video. This manifests mostly in menus, etc. however it also applies to the cursor.
- There is no cursor, or rather the cursor is an underscore and not transparent cell. Moving arrow left in the CLI doesn’t actually move the cursor it erases characters. There is no line editing.
- Also related to reverse video, it appears Nano console has some weird issues with colors.
- Missing DLLs. Nano Server not being a “Windows” OS is missing a lot of Windows DLLs and it has its own nano DLL hell. This has actually been acknowledged in MinWin. As such a lot of apps will not launch due to dependencies.
For example YEdit works remarkably well except for the menus, which use reverse video:
Update: Malcolm has fixed it in latest version of YEdit! Thank you!
Update: thanks to Ron Yorston you can also run BusyBox on Nano! All you need to do is get the 64bit version and before you run it set an environmental variable to disable ANSI emulation. In CMD set BB_SKIP_ANSI_EMULATION=0
in PS $env:BB_SKIP_ANSI_EMULATION=0
. Done!
You even get ls colors and vi
editor works flawlessly! Unix shell on Nano, thats awesome!
So what about games?
Initially nothing worked as expected. Either due to line drawing, colors or previously mentioned DLL hell. There was one game that actually worked – PowerShell adaptation of snake:
But I wanted something better. I had high hopes for ascii-patrol, which is pure text mode and they build it for win64. Unfortunately the game requires a bunch of multimedia / sound DLLs from Windows which are not present in Nano.
Thankfully Neozeed has stepped in, took the source code, amputated all the multimedia stuff, borrowed the Unix clock code and gettimeofday, and used an older Visual Studio to build it. But he managed to produce a fully working and playable version!!!! Truly amazing stuff!
The binary is available here. To play the game scroll down one screen to start a mission. If you enter profile customization simply press ESC to get out. Thanks again Neozeed!
I’m hoping readers can find more text mode/ascii apps and games that will work on the console. Please comment and send links!
In another dimension, having a working text editor, Yori shell, smb/scp, maybe with help of mingw64, sdk tools or borrowed compilers from Visual Studio, one could have a self hosted developer workstation with this.
For now please just download the pre-build image, or make one yourself and run it in your favorite hypervisor and have some fun with it!
With this, goodbye Nano Server! You will be always remembered. I know folks at Redmond tried really hard to make it such beautiful gem.
Thanks for the nudge.
I ignored this when it was launched because it seemed like a big contradiction to say “compact Windows image” and then say “which uses Powershell and .NET for administration.” That was before Yori, and now it seems like a good time to revisit and see if the potential of Nano can really be fulfilled. Replacing Powershell with Yori as a boot shell enabled it to boot on 128Mb RAM. I need to do some trial-and-error to see what services can be disabled – most of them are network related and I don’t have an operational network so it looks like a lot of them can go.
It has plenty of quirks and loose edges. It has winhttp.dll but not wininet.dll, which is what ypm was using for updates. It doesn’t have user32.dll which makes sense given it’s trying to be GUI-less and user32 contains a lot of Window handling code, but it also contains things like clipboard code or even the simplest way to reboot and shutdown. The terminal appears to have VT support, but doesn’t implement everything and Yori by default spews the current directory to the console (it’s trying to hint to Terminal where it is but Nano doesn’t know what to do with that.) And I really need to figure out how to debug the thing, given it doesn’t have an operating network – use kd for everything?
In terms of reverse video, it looks like the foreground color can be set to anything but the background color must be black. That breaks a whole pile of things, like the cursor (as you mentioned.) I think what I need to do with YEdit is create a central color table system, so rather than controls specifying their colors they query from a system palette. From there, it needs to detect display capabilities and fall back to something primitive. It’s not just the menus that are off – the dialogs are unusable, the status bar is hidden, the scroll bar is busted, etc.
In more amusing news, it has 8.3 names enabled. So here we are with a 64-bit only edition, no 32 bit support let alone 16 bit support, and DOS compatibility lives on.
Thanks for a quick response! Wow if you could replace PS with Yori shell and make YEdit work a little better that would make a pretty awesome and useable OS! I’m also thinking that perhaps instead of working around quirks of the default console a better video driver could be build?
I’ve been working on changes for this and will push them momentarily. It feels very Win9x like where things are just missing and/or broken.
As far as fixing the console, it’s not exactly a video driver. The “normal” console goes via condrv.sys, which generates events that are pumped by a usermode conhost.exe which turns around and calls GDI to render things. Here, condrv appears basically in tact, but messages are pumped by conkbd.dll which is hosted in csrss.exe (everything old is new again!) I’m sure you’re right that it’d be possible to replace this sucker with a “better” version that can display a cursor or background colors without horking.
However, that’s only one layer. The other strange thing in Nano is that kernel32.dll isn’t fully there – parts of it are, and some exports that have existed since Windows NT 4.0 are just gone. Yori happens to work because it’s designed to run on NT 3.1 so it’s trying to degrade gracefully when things are missing, but the missing things here are just a bit strange. For example, the normal console manages aliases which are exposed via AddConsoleAlias et al. Those exports are gone. So even if conkbd.dll were replaced with something that implemented them, there’s no way for applications to access that functionality without adding back the missing exports into kernel32.
Something that really gave me Win95 flashbacks is ENABLE_WRAP_AT_EOL_OUTPUT . By default this is on, and conkbd doesn’t support it being turned off. Win9x was similar, so sdir (which ran on Win95 once) has to count to see if a line is long enough to trigger an implicit line wrap, and if not generate one explicitly. More, which is newer, just turned this off so it can display a line and move to the next line unconditionally. But on condrv, this moves by two lines, not one. So I need to port all of the sdir crap into more so it works correctly.
Anyway, here are fixes so far:
* Don’t display the current directory via VT sequences since conkbd just displays it as text.
* Use 7-bit ascii line drawing by default in sdir and libwin (aka edit, co, history.)
* A cut down palette for libwin. I’m using yellow for selection, green for titles. This makes edit usable, but somebody more artistic than me could do better.
* Accelerator characters are always highlighted since pressing “Alt” by itself doesn’t trigger a keypress from conkbd.
Changes that I think would be good:
* Do something with the cursor, but all options suck. Conkbd is effectively not displaying the character the cursor is on. I can do that too but use a giant yellow block or something, but without a background color, keeping the character displayed is only possible by changing the foreground color only, which is lame.
* Yedit should detect the lack of clipboard and always disable those options. Somewhat later, it should build its own single process fallback clipboard.
* Fix Yori (shell) selection color, similar to libwin. This is hard to invoke without a mouse, but it’s still there.
* Ymore line wrapping issue mentioned above.
* Ypm could fall back to winhttp when wininet is not available. It looks like the instructions for Nano include an extra switch to generate an image with OEM drivers, which seems like something I should use to have networking support.
* Yshutdn should fall back to something when user32’s shutdown is gone.
There’s probably a lot more, but as of now things kind of work. Here’s what yedit looks like:
http://www.malsmith.net/edit/nano.png
To use Yori instead of Powershell:
reg add “HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon” /v Shell /t REG_SZ /d “C:\Yori\OneYori.exe” /f
There’s also the x86 win 8.1 era minwin builds intended for Intel Galileo (but worked in VMs), of which there were a few images of. No idea if any are still around. I still have the Galileo board MS sent me, but no microsd…
OK, this link is still up, might want to mirror: https://mega.co.nz/#!VwQnkRJC!RtLwdzo-hD_PN3M5emzylAGL3Hcxr4ia9edrU9ZbDhs
Okay, after much frustration trying to update this thing, looks like I missed an important memo:
https://docs.microsoft.com/en-us/lifecycle/products/windows-server-2016-nano-server-installation-option
Normal servers are supported for 10 years; this one was supported for less than two. Trying to install updates after 2018, including servicing stack updates, fails claiming they’re inapplicable.
I’m actually curious if any Microsoft product was supported for less time.
Yeah this was actually quite disappointing. Everybody was so hyped about Nano and a lot of vendors were making software more compatible with it. I seen a few pilot deployments on Nano. Then it just died all out of the sudden. I would like to learn the internal story some day. Do people really prefer regular server core over nano? Or do they run it with full desktop experience and tiles showing random websites around the web? Do people really run Windows containers? And even if they do, doesn’t it make sense to use more full featured base image than nano for regular apps? All of this stuff is backward and really doesn’t make any sense to me.
Interesting. I maintain a WIN32 port of BusyBox (https://frippery.org/busybox). Back in 2016 I had a PR from John Howard at Microsoft (https://github.com/rmyorston/busybox-w32/pull/70) to provide support for nanoserver. I was fairly dismissive at the time though I did eventually add the requested feature.
The current release of busybox-w32 appears to work in nanoserver. At least, the BusyBox testsuite gives results in the same ballpark as on proper Windows systems.
It needs an environment variable to be set for correct console emulation (from PowerShell: $env:BB_SKIP_ANSI_EMULATION=0) then just run ‘busybox sh -l’ to get a BusyBox shell. No further set up is needed.
Thanks for commenting on! I actually did try busybox-w32 but wasn’t too impressed. Commands worked but vi and line editing didn’t. I wasn’t aware of the environment variable. I will try that if it works I will update the article of course or maybe slap a new one. Again thanks for pointing this out!
Indeed, it is a pure gem.
Adding Packages to an already installed Nano Server instance, is a really an interesting question.
I can think about adding :
– WSA packages : https://github.com/yarnpkg/yarn/issues/3999
– Windows Nano Server packages shipped by Microsoft on Windows Server 2016 ISO.
https://mehic.se/2017/02/02/how-to-implement-packages-roles-and-features-on-nano-server/
https://www.javydekoning.com/fixing-signature-nanoserverpackage-cat-not-match-hash/
Create you own edition according to fit your specific needs and nothing more than a really basic sustainable principle in 2023!