🚀 Best Practices and Security Hardening – Getting Your Environment Ready for VCF 9.0

Picking Up Where We Left Off

If you’ve been following along with the Zero to VCAP series, we just wrapped up configuring eight Cisco UCS B200 blades with direct-attached Fibre Channel storage from the NetApp ASA A30 — a full FlexPod Cisco Validated Design (CVD) build leveraging NetApp ASA A30 all-flash storage. The blades are racked, zoned, booted, and ESXi is up across all eight hosts.

That part always feels good.

But before you let the VCF 9.0 installer touch your hosts, there’s one step that will either save your deployment… or quietly break it.

Security hardening, time synchronization, and consistent DNS across every host in the environment.

Skip this, and you’re not failing fast — you’re failing halfway through bring-up when it hurts the most.

Why This Step Matters

This isn’t optional for me.

Whether it’s a customer engagement, a lab build, or part of my Zero to VCAP journey, every ESXi host gets the same baseline before anything else touches them.

  • Consistent DNS
  • Consistent NTP
  • Consistent security configuration

If even one host drifts, you’ll find out at the worst possible time.

⚠️ Real-world lesson learned

I’ve seen VCF deployments fail mid-bring-up because:

  • One host had incorrect DNS
  • Another had NTP drift
  • A third didn’t meet security baseline

Everything looked fine… until it didn’t.

The Script: BestPractices_Security_Hardening.ps1

This is the script I use to enforce a clean, repeatable ESXi baseline before VCF deployments.

This version combines:

  • DNS configuration
  • NTP configuration
  • Advanced ESXi security hardening

All into a single workflow.

This is not a “nice to have” script — this is a baseline.

Consistency across hosts isn’t optional. It’s the difference between a smooth deployment and chasing issues later.

What the Script Actually Does

This script standardizes your entire ESXi host baseline in a single run.

🔹 1. NTP Configuration

  • Prompts for NTP servers (defaults provided)
  • Removes existing entries
  • Applies consistent NTP across all hosts
  • Ensures service is running and set to start automatically

👉 Eliminates time drift issues that break VCF bring-up

🔹 2. DNS Configuration

  • Prompts for DNS servers and domain name
  • Applies consistent DNS configuration to all hosts
  • Ensures all hosts resolve correctly

👉 Prevents certificate and validation failures

🔹 3. Advanced Security Hardening (14 Settings)

Applies and verifies key ESXi advanced settings including:

  • Account lockout policies
  • Password complexity
  • Shell timeout controls
  • Memory salting
  • MOB disablement
  • TLS / protocol hardening
  • Execution restrictions

👉 Aligns with CIS Benchmark and VMware Security Configuration Guide

🔹 4. Dry Run Mode (This is Huge)

Before making any changes, the script runs in dry mode.

  • Shows current vs desired state
  • Makes zero changes
  • Lets you validate everything first

👉 This is your safety net

🔹 5. Verification + API Fallback

After applying settings:

  • Script reads values back to confirm success
  • Falls back to API methods if needed

👉 Ensures nothing silently fails

🔹 6. HTML + CSV Reporting

Every run generates:

  • HTML dashboard with KPI summary
  • Per-host results table
  • CSV export for tracking

👉 This becomes your documentation

Running the Script (Real Example)

From VS Code:

cd .\VMware\ESXi\PowerShell\Hardening\
.\BestPractices_Security_Hardening.ps1

Step 1 — Safety Notice and Dry Run Prompt

The script starts with a safety notice and recommends running in dry mode first.

Say yes.

Step 2 — Connection Selection

You are prompted to select how to target hosts:

  1. vCenter
    • Target all hosts or a specific cluster
  2. Standalone ESXi host(s)
    • Enter one or multiple hosts (comma-separated)
  3. hosts.csv file
    • Provide a CSV with hosts listed in a Host column

For this deployment, I’m using Option 2 — Standalone ESXi host(s).

At this stage, there is no vCenter deployed yet, so I’m connecting directly to each ESXi host.

In my environment, the ESXi hosts follow a consistent naming convention:

dc3-hst-esxi01 – dc3-hst-esxi08

Since the script expects a comma-separated list, I enter them like this:

dc3-hst-esxi01,dc3-hst-esxi02,dc3-hst-esxi03,dc3-hst-esxi04,dc3-hst-esxi05,dc3-hst-esxi06,dc3-hst-esxi07,dc3-hst-esxi08

This allows the script to run across all hosts in a single pass and ensures a consistent baseline before VCF bring-up begins.

💡 Pro Tip

Using consistent host naming conventions like this makes automation significantly easier and reduces the risk of targeting the wrong systems during deployment.

Step 3 — Log Directory

Choose where logs and reports will be stored.

Step 4 — NTP Configuration Prompt

Enter your NTP servers or use defaults.

Step 5 — DNS Configuration Prompt

Enter:

  • Primary DNS
  • Optional secondary DNS
  • Domain name

Step 6 — Credentials

Provide credentials for ESXi hosts.

Step 7 — Host Discovery

The script connects to each host and builds the working list.

Step 8 — Dry Run Output

The script evaluates all hosts and compares current vs desired state.

Step 9 — Review HTML Report

Review before applying changes.

Step 10 — Apply Mode

Run again in apply mode to enforce settings.

Step 11 — Final HTML Report

Final validation and documentation output.

How This All Fits Together

Before moving into final validation, here’s the flow I follow every time.

At a High Level

  1. Build ESXi hosts
  2. Run script (dry run)
  3. Review report
  4. Run script (apply)
  5. Validate output
  6. Proceed to VCF bring-up

Pre-VCF 9.0 Checklist

ItemExpected State
NTPConsistent
DNSForward + reverse working
SecurityApplied
HostsNo drift
ReportsClean

Advanced Security Settings — What They Do and Why They Matter

The advanced settings applied by the script are based on VMware / Broadcom security guidance and the CIS Benchmark for ESXi. These settings are designed to reduce attack surface, enforce secure access, and ensure consistent behavior across all hosts before VCF bring-up.

🔐 Account Lockout and Access Control

  • Security.AccountLockFailures = 5
    Locks a local account after five failed login attempts, helping prevent brute-force attacks.
  • Security.AccountUnlockTime = 900
    Automatically unlocks accounts after 15 minutes, balancing usability and security.

🔑 Password Policy

  • Security.PasswordHistory = 5
    Prevents reuse of recent passwords, enforcing proper credential rotation.
  • Security.PasswordQualityControl
    Enforces strong password policies, including minimum length and complexity rules.

🧠 Memory and VM Security

  • Mem.ShareForceSalting = 2
    Prevents memory sharing attacks by isolating memory pages between virtual machines.

🔒 Host Access and Interfaces

  • Config.HostAgent.plugins.solo.enableMob = false
    Disables the Managed Object Browser to reduce exposure of internal APIs.

🖥️ Shell and Session Controls

  • UserVars.ESXiShellTimeOut
    Automatically disables the ESXi shell after inactivity.
  • UserVars.ESXiShellInteractiveTimeOut
    Logs out inactive shell sessions.
  • UserVars.DcuiTimeOut
    Logs out inactive console sessions.

📡 Logging and Visibility

  • Config.HostAgent.log.level = info
    Provides balanced logging for troubleshooting without excessive log growth.

🔐 Protocol and Execution Hardening

  • UserVars.ESXiVPsDisabledProtocols
    Disables insecure or legacy protocols.
  • VMkernel.Boot.execInstalledOnly = true
    Ensures only trusted, signed binaries are executed.

📊 Telemetry and UI Behavior

  • UserVars.HostClientCEIPOptIn = 2
    Disables telemetry data collection.
  • UserVars.SuppressShellWarning = 1
    Suppresses UI warnings during automation workflows.

Flexible Execution — Automated or Manual

By default, the script applies all recommended settings automatically to enforce a consistent baseline quickly.

However, I’ve built in logic to run the advanced settings section in manual mode, allowing you to:

  • Review each setting individually
  • Compare current vs recommended values
  • Choose whether to apply or override

This is especially useful when working with security teams, compliance requirements, or testing configurations in a lab.

👉 You get the best of both worlds — automation for consistency and speed, and manual control when needed

Final Thoughts

When everything is green, you’re not just ready.

You’re setting yourself up for a clean VCF bring-up.

And that’s the difference between:

  • A smooth deployment
  • And chasing issues later

This is how I do it across all environments.

Teaching to fish. 🎣

Get the Script

Humbledgeeks Github

https://github.com/humbledgeeks/infra-automation

What’s Next

Next up: VCF 9.0 Cloud Builder and bring-up JSON.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top