Home Lab: Active Directory, Network & Monitoring

Overview

I built a small simulated company network from scratch in VirtualBox — an identity layer (Active Directory), a network layer (a segmented, firewalled network behind pfSense), and an observability layer (Prometheus and Grafana) — to get hands-on practice with the tools help desk, sysadmin, and network admin roles use daily. Each layer builds on the last: the network layer controls what can reach what, the identity layer controls what's allowed to be done once you're there, and the monitoring layer tells you whether any of it is actually healthy.


Environment: 1x Windows Server 2022 VM promoted to a Domain Controller for lab.local, 2+ Windows 11 client VMs joined to the domain, a pfSense VM acting as router/firewall between two segmented internal networks — Servers (192.168.60.0/24) and Workstations (192.168.70.0/24) — with remote VPN access, and an Ubuntu Server VM running Prometheus and Grafana to monitor it all.

Tags: Windows Server 2022 Active Directory Group Policy pfSense Network Segmentation OpenVPN DNS / DHCP Linux Prometheus Grafana VirtualBox

Phase 1 — Identity & Access

Domain Controller setup

Installed Windows Server 2022, configured a static IP, and promoted it to a Domain Controller running AD DS and DNS for a new forest, lab.local.

Organizational Units and Group Policy

Created two OUs — IT and Sales — each with a test user account. I built a Group Policy Object scoped only to the IT OU that pushes a custom desktop wallpaper, and confirmed with gpresult /r and side-by-side login tests that the policy applied to the IT user and correctly did not apply to the Sales user.

Active Directory Domain Services Configuration Wizard showing new forest setup for lab.local
Promoting the server to a domain controller for a new forest, lab.local
gpresult output confirming the IT Desktop Background GPO applied to the IT user
gpresult /r confirming the "IT - Desktop Background" GPO applied correctly, scoped only to the IT OU

Security groups and file share permissions

Created IT-Group and Sales-Group security groups, separate from the OUs — OUs organize and apply policy, groups grant access. Set up a shared folder with a nested subfolder, and configured distinct Share and NTFS permissions so each group could access the shared folder, but only IT-Group could access the IT-specific subfolder.

Phase 2 — Network Infrastructure

Router/firewall setup

Installed pfSense as a virtual router and firewall, with a WAN interface (NAT, simulating an ISP connection) and a LAN interface fronting my existing lab network. Created and tested a targeted firewall rule blocking ICMP from a specific host, verified it took effect with a failed ping and a matching entry in the firewall logs, then removed the test rule.

pfSense firewall rule list showing a block rule for ICMP traffic above the default allow rule
A targeted block rule correctly ordered above the default allow rule — proven active by its non-zero packet count

Network segmentation

Split the lab into two segments — Servers and Workstations — each with its own pfSense interface, rather than one flat network. VirtualBox's Internal Network adapters don't support real 802.1Q VLAN tagging, so instead of tagging traffic on a single NIC, I gave pfSense a dedicated virtual NIC per segment — a practical adaptation that achieves the same isolation goal.

By default, Workstations couldn't reach Servers at all — true network-level isolation, not just an AD permission boundary. I then added narrow, deliberate exceptions: Workstations can reach the AD server on SMB (445) and LDAP (389) only, with everything else to that subnet explicitly blocked. This is the same default-deny-with-exceptions pattern real enterprise networks use.

pfSense Interface Assignments showing Servers and Workstations mapped to dedicated network adapters
Servers and Workstations assigned to their own dedicated virtual NICs, each acting as an isolated segment
pfSense firewall rules on the Workstations interface allowing only LDAP and SMB to the AD server
Workstations can reach the AD server only on LDAP and SMB — everything else to that subnet is blocked

DNS forwarding and DHCP

Configured a DNS Domain Override on pfSense so any query for lab.local forwards straight to the AD server (the actual authority for that domain), while pfSense resolves everything else itself. Enabled DHCP on the Workstations segment and confirmed a fresh client could pull a correct address, DNS, and domain name automatically with no manual network configuration.

Remote access VPN

Set up an OpenVPN remote-access server on pfSense: created a Certificate Authority and server certificate, configured user authentication, and scoped the VPN's allowed routes to both internal subnets. Exported a client profile and confirmed a device could authenticate, tunnel in, and reach the internal network.

pfSense OpenVPN server configuration showing Remote Access SSL/TLS + User Auth mode
OpenVPN server configured for remote access with certificate and user authentication

Phase 3 — Monitoring & Observability

Added a Prometheus + Grafana monitoring stack on a new Ubuntu Server VM — my first Linux server in the lab, managed entirely over SSH — to get visibility into whether the infrastructure I'd built was actually healthy, not just running.

Prometheus, installed and run as a proper Linux service

Rather than using a shortcut package, I installed Prometheus manually: downloaded the binary, created a dedicated prometheus system user, and wrote the systemd unit file by hand. This is the same binary + systemd unit + config pattern used by a huge number of Linux services, so it's a transferable skill beyond Prometheus specifically.

systemd service file for Prometheus viewed with systemctl cat
The systemd unit file for Prometheus — this is where a duplicate flag name caused the service to fail on first boot

Exporters and cross-network scraping

Installed windows_exporter on the AD server to expose CPU, memory, and system metrics, then configured Prometheus to scrape it across the network. Confirmed data flowing end to end in Prometheus's own web UI before layering visualization on top.

Prometheus targets page showing the ad-server target as down with a context deadline exceeded error
The AD server target initially failed to scrape — a missing Windows Firewall rule for the exporter's port, separate from the SMB/LDAP rules from the network phase

Grafana dashboards and alerting

Connected Grafana to Prometheus as a data source and built a dashboard tracking available memory and CPU usage over time for the AD server. Added an alert rule on the built-in up metric that fires when the server stops responding, and verified it correctly transitions from Normal → Pending → Firing by stopping the exporter service and watching it trigger.

Documenting the troubleshooting was, honestly, more valuable than the happy path:

PowerShell output showing Get-NetAdapter with status Not Present
Get-NetAdapter showing the virtual network adapter as "Not Present" — the root cause of a string of downstream errors

What This Demonstrates