How I Built a Windows Server 2022 Core Print Server Without a GUI

Introduction

Windows Server without a desktop environment? Why would anyone want to manage Windows Server with PowerShell only? Well, there is definitely some PowerShell involved and a little GUI involved as well.

In my career working on small to medium-sized business Windows environments, I have NEVER seen a single instance of Windows Server Core in production. Are the tradeoffs of a reduced attack surface and minimum system requirements worth the headache of managing it with PowerShell and other tools? Let’s find out.

In this blog, I will stand up two Windows Server 2022 Core VMs in Proxmox and join a laptop to Active Directory. One of the VMs will be a domain controller, and the other will be a print server. The goal of this lab is simply to sign in as a domain user and connect to a shared printer.

Lab Environment

In this lab, I will be using Proxmox installed on an HP business-class desktop machine, a spare Dell laptop, and a Dell micro workstation. If you are following along with this lab, you can use any virtualization platform you like. If you don’t have a spare workstation with Windows 11 installed, you can use a virtual machine with Windows 11! I will also be using my network printer, an HP LaserJet Pro MFP M426.

Step-by-Step: How to Set Up Windows Server 2022 Core Without a GUI

This blog will not cover creating my virtual machines, but I want to document the specs of each VM. What is cool about Windows Server Core is how little it needs. Below is the output of qm config <VM ID> for my two VMs in Proxmox. Each VM uses 2 CPU cores, 2 GB of RAM, 32 GB of storage, and other hardware.

root@pve1:~# qm config 105
agent: 1
bios: ovmf
boot: order=scsi0;ide2;ide0;net0
cores: 2
cpu: host
efidisk0: vmdisks-thin:vm-105-disk-0,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=4M
ide0: local:iso/virtio-win-0.1.271.iso,media=cdrom,size=709474K
ide2: local:iso/SERVER_EVAL_x64FRE_en-us.iso,media=cdrom,size=4925874K
machine: pc-q35-11.0+pve2
memory: 2048
meta: creation-qemu=11.0.2,ctime=1785806665
name: DC1
net0: virtio=BC:24:11:AD:88:86,bridge=vmbr0,firewall=1,tag=20
net1: virtio=BC:24:11:02:2E:43,bridge=vmbr0,firewall=1,tag=10
numa: 0
ostype: win11
scsi0: vmdisks-thin:vm-105-disk-1,discard=on,iothread=1,size=32G,ssd=1
scsihw: virtio-scsi-single
smbios1: uuid=f477ba11-9d75-44ed-b174-0d4249a4be2c
sockets: 1
tpmstate0: vmdisks-thin:vm-105-disk-2,size=4M,version=v2.0
vmgenid: ea9cf2e2-db67-4a85-805a-bc9c94fa26c1
root@pve1:~#
root@pve1:~#
root@pve1:~# qm config 106
agent: 1
bios: ovmf
boot: order=scsi0;ide2;ide0;net0
cores: 2
cpu: host
efidisk0: vmdisks-thin:vm-106-disk-0,efitype=4m,ms-cert=2023k,pre-enrolled-keys=1,size=4M
ide0: local:iso/virtio-win-0.1.271.iso,media=cdrom,size=709474K
ide2: local:iso/SERVER_EVAL_x64FRE_en-us.iso,media=cdrom,size=4925874K
machine: pc-q35-11.0+pve2
memory: 2048
meta: creation-qemu=11.0.2,ctime=1787133848
name: PRINT1
net0: virtio=BC:24:11:D5:C3:D8,bridge=vmbr0,firewall=1,tag=20
net1: virtio=BC:24:11:A9:4A:5D,bridge=vmbr0,firewall=1,tag=10
numa: 0
ostype: win11
scsi0: vmdisks-thin:vm-106-disk-1,discard=on,iothread=1,size=32G,ssd=1
scsihw: virtio-scsi-single
smbios1: uuid=7faa670d-5de5-4dbc-8819-7939820175b3
sockets: 1
tpmstate0: vmdisks-thin:vm-106-disk-2,size=4M,version=v2.0
vmgenid: 7469cfd0-365e-419a-92dd-d3f44e5bf5de

Step 1 – Initial Windows Server Core Configuration

The first step is doing the initial configuration of both servers.

After installing Windows Server Core and logging into the Administrator account, you will land in the SConfig tool. This nifty tool allows you to configure common settings without much fuss.

sconfig

With SConfig, I configured the following (mostly):

Hostname (Servers will be called DC1 and PRINT1)

  • Remote Management
  • Remote Desktop
  • Date and Time
  • Network Settings

With SConfig, you enter the number for the desired setting and follow the on-screen instructions to configure it. That’s it!

It’s important to note that, when enabling Remote Management (option 4), there are essentially two things to configure: enabling ping to the server and enabling WinRM (options 1 and 3 on the screen below).

sconfig remote management

Another thing I encountered when using SConfig was a small quirk. If you want to set up a static IP address for an interface with all the TCP/IP information, then SConfig is a suitable tool to use. However, if you have multiple interfaces, it is best practice not to configure multiple default gateways.

SConfig will not allow you to configure an interface without configuring a default gateway. If you find yourself in this situation, as I did, then PowerShell or netsh is the better tool. On my VMs, I have two interfaces: one for managing the server and one for server/client traffic. In my homelab, I try to isolate management traffic from other traffic.

Configuring Interfaces With PowerShell and netsh

First, you want to identify the interfaces:

Get-NetAdapter or Get-NetIPConfiguration will provide you with the name of the interface.

Get Net

Next, you have to disable DHCP:

Set-NetIPInterface -InterfaceAlias “Ethernet” -Dhcp Disabled

Finally, you can configure the IP address. Notice how there is no default gateway specified:

New-NetIPAddress -InterfaceAlias “Ethernet” -IPAddress 10.50.20.10 -PrefixLength 24

For the server/client traffic, I disabled DHCP and then set the IP address:

Set-NetIPInterface -InterfaceAlias “Ethernet 2” -Dhcp Disabled
New-NetIPAddress -InterfaceAlias “Ethernet 2” -IPAddress 10.50.50.9 -PrefixLength 24 -DefaultGateway 10.50.50.1

Then you have to set DNS:

Set-DnsClientServerAddress -InterfaceAlias "Ethernet 2" -ServerAddresses 10.50.50.9

When all the configuration is done, verify everything with Get-NetIPConfiguration.

Below is the same configuration but using the netsh tool.

Identify interfaces:

netsh interface ipv4 show interfaces

or 

netsh interface ipv4 show config
netsh interface ipv4 show

Configure management interface:

netsh interface ipv4 set address name="Ethernet" source=static address=10.50.20.10 mask=255.255.255.0 gateway=none

Configure server/client interface:

netsh interface ipv4 set address name="Ethernet 2" source=static address=10.50.50.9 mask=255.255.255.0 gateway=10.50.50.1

Configure DNS:

netsh interface ipv4 set dnsservers name="Ethernet 2" source=static address=10.50.50.9 register=primary

Verify:

netsh interface ipv4 show config

Step 2 – Configuring the Domain Controller

This might seem scary if you are used to installing Active Directory Domain Services with Server Manager, but it is surprisingly simple to do with PowerShell.

First install the role and then verify it was installed:

Install-WindowsFeature AD-Domain-Services -IncludeManagementTools
Get-WindowsFeature AD-Domain-Services

Promote the server to a domain controller and reboot. Replace the values of -DomainName and -DomainNetbiosName with your unique values. Running this command will also make a Windows Security window appear, requiring a new Safe Mode Administrator password:

Install-ADDSForest -DomainName <insert domain name> -DomainNetbiosName <NETBIOS NAME> -InstallDNS  -SafeModeAdministratorPassword (Read-Host -AsSecureString "Enter DSRM Password") -Force

After the reboot, check the DNS configuration and fix it if needed:

Verify:

Get-DnsClientServerAddress -AddressFamily IPv4
get dnsclientserveraddress

Configure:

Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses 10.50.50.9

Step 3: Domain Joining the Server and Laptop

Next, I needed to domain join PRINT1 and a Windows 11 laptop to Active Directory. With Windows Server Core, I used SConfig to do this; with the Windows 11 laptop, I opened System Properties.

Step 4: Installing RSAT

To manage Active Directory with ease, you can use traditional GUI tools remotely. From a dedicated Windows 11 workstation, I installed these features:

  • RSAT: Active Directory Domain Services and Lightweight Directory Services Tool
  • RSAT: Group Policy Management Tools
optional features
optional features view features
optional features see available
optional features see add

Step 5: Print Server Configuration

On PRINT1, I installed the Print Server role.

Install:

Install-WindowsFeature Print-Server

Verify:

Get-WindowsFeature -Name “*Print*”

Enable necessary firewall rules for managing this server role remotely:

Get-NetFirewallRule -DisplayName "File and Printer Sharing (Spooler Service - RPC)" | Enable-NetFirewallRule
Get-NetFirewallRule -DisplayName "File and Printer Sharing (Spooler Service - RPC-EPMAP)" | Enable-NetFirewallRule

Step 6: Install Print Driver & Share

Open Print Management on a Windows 11 workstation, and then add the print server:

print management
print management add

For this lab, I downloaded the HP Universal Print Driver:

HP Universal Print Driver Series for Windows Software and Driver Downloads | HP® Support

I installed the print driver and selected the .inf file below:

add driver

I added the port:

add port

I added the printer:

add printer

When adding the printer, you will be asked to share it. I selected that option and gave it the name “Home Printer.”

Below is the Share tab after the printer has been added:

share printer

Step 7: Connecting to the Shared Printer

While logged into a domain admin account, I am able to open File Explorer, navigate to \\PRINT1, and then connect to the share.

While logged into a standard user account, I am able to open File Explorer and see the share, but when I try to connect to the printer, I am prompted to enter administrator credentials.

For now, this lab has been successful. Next, I will focus on hardening the configuration and figuring out how to allow standard user accounts to install the print driver.

Conclusion

This post focused more on building and configuring the lab than on exploring the security implications of running the Print Server role on Windows Server 2022 Core. That deserves a deeper dive of its own.

Scroll to Top