Depot server
Overview
VCF requires binaries for installation. These can either be done by connecting the vcf-installer directly to the Broadcom, or, you can also create a depot server, in-case if you don’t have direct access to the Internet.
I’ve also configured the depot server to run unbound for DNS.
This page outlines the installation for both services.
depot VM
| Component | Value |
|---|---|
| Depot Server | depot.lab.fiveorange.net |
| IP Address | 192.168.200.5 |
| OS | Fedora 43 |
| Web Server | Apache (httpd) |
| Document Root | /var/www/html/depot |
| Depot Path | /var/www/html/depot (accessible at /) |
| Protocols | HTTP (80) and HTTPS (443) |
| Certificate | Wildcard *.lab.fiveorange.net |
| Auth Method | Basic Authentication (both HTTP and HTTPS) |
| Auth Username | vcfadmin |
| Access Methods | FQDN or IP address |
Creating the Depot VM
Run the following command from Promox
qm create 200 \
--name depot \
--memory 2048 \
--cores 1 \
--sockets 1 \
--cpu host \
--ostype l26 \
--net0 virtio,bridge=vmbr0 \
--scsihw lsi \
--boot order=sata0And add the Fedora boot ISO.
Once the VM is booted, the config of the vm should look something like this.
# qm config 200
boot: order=sata0
cores: 1
cpu: host
memory: 2048
meta: creation-qemu=10.1.2,ctime=1764884766
name: depot
net0: virtio=BC:24:11:EB:FD:1B,bridge=vmbr0
ostype: l26
scsi0: local-lvm:vm-200-disk-0,size=40G,ssd=1
scsihw: lsi
smbios1: uuid=b3998f04-3541-4f15-b277-fc76d2a38dec
sockets: 1
vmgenid: e8ad7143-8119-41fd-a80a-20b0e9da08a6Run lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 40G 0 disk
├─sda1 8:1 0 1M 0 part
├─sda2 8:2 0 2G 0 part /boot
└─sda3 8:3 0 38G 0 part
└─fedora-root 252:0 0 38G 0 lvm /
zram0 251:0 0 1.9G 0 disk [SWAP]Check the ip route
$ ip route
default via 192.168.200.1 dev ens18 proto static metric 100
192.168.200.0/24 dev ens18 proto kernel scope link src 192.168.200.5 metric 100Set selinux to permissive
# Set immediately
setenforce 0
# Make persistent across reboots
sed -i 's/^SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config
# Verify
getenforce
# Should show: PermissiveDisable systemd-resolved (conflicts with Unbound)
# Stop and disable systemd-resolved
sudo systemctl disable --now systemd-resolved
# Delete the symlink
sudo rm -f /etc/resolv.conf
# Add entries to /etc/resolv.conf
nameserver 192.168.200.1
search lab.fiveorange.net
# Prevent NetworkManager from overwriting resolv.conf
# Add the following to /etc/NetworkManager/NetworkManager.conf
[main]
dns=none
# Restart NetworkManager
sudo systemctl restart NetworkManager
# Check status
sudo systemctl status NetworkManagerUpdate the server
sudo dnf update -yReboot the server after updates
sudo rebootunbound
Installing unbound
sudo dnf install unbound -yConfigure unbound
# Change directory
cd /etc/unbound
# Take backup of the original file
sudo cp unbound.conf{,.orig}Edit the unbound.conf. This is my config
server:
# number of threads to create. 1 disables threading.
# num-threads: 1
interface: 0.0.0.0
access-control: 127.0.0.0/8 allow
access-control: 192.168.200.0/24 allow
access-control: 192.168.201.0/24 allow
access-control: 192.168.202.0/24 allow
access-control: 192.168.203.0/24 allow
include: /etc/unbound/local.d/*.conf
# Local zone for lab.fiveorange.net (forward lookups)
local-zone: "lab.fiveorange.net." static
# Forward DNS records (A records)
local-data: "depot.lab.fiveorange.net. IN A 192.168.200.5"
local-data: "proxmox.lab.fiveorange.net. IN A 192.168.200.10"
local-data: "esxi-mgmt-01.lab.fiveorange.net. IN A 192.168.200.21"
local-data: "esxi-mgmt-02.lab.fiveorange.net. IN A 192.168.200.22"
local-data: "esxi-mgmt-03.lab.fiveorange.net. IN A 192.168.200.23"
local-data: "vcf-installer.lab.fiveorange.net. IN A 192.168.200.49"
local-data: "sddc-manager.lab.fiveorange.net. IN A 192.168.200.51"
local-data: "vcenter.lab.fiveorange.net. IN A 192.168.200.52"
local-data: "nsxmgr.lab.fiveorange.net. IN A 192.168.200.53"
local-data: "nsxmgr-vip.lab.fiveorange.net. IN A 192.168.200.54"
# Reverse DNS records (PTR records)
local-data: "5.200.168.192.in-addr.arpa. IN PTR depot.lab.fiveorange.net."
local-data: "10.200.168.192.in-addr.arpa. IN PTR proxmox.lab.fiveorange.net."
local-data: "21.200.168.192.in-addr.arpa. IN PTR esxi-mgmt-01.lab.fiveorange.net."
local-data: "22.200.168.192.in-addr.arpa. IN PTR esxi-mgmt-02.lab.fiveorange.net."
local-data: "23.200.168.192.in-addr.arpa. IN PTR esxi-mgmt-03.lab.fiveorange.net."
local-data: "49.200.168.192.in-addr.arpa. IN PTR vcf-installer.lab.fiveorange.net."
local-data: "51.200.168.192.in-addr.arpa. IN PTR sddc-manager.lab.fiveorange.net."
local-data: "52.200.168.192.in-addr.arpa. IN PTR vcenter.lab.fiveorange.net."
local-data: "53.200.168.192.in-addr.arpa. IN PTR nsxmgr.lab.fiveorange.net."
local-data: "54.200.168.192.in-addr.arpa. IN PTR nsxmgr-vip.lab.fiveorange.net."
forward-zone:
name: "."
forward-addr: UPSTREAM.DNS.1
forward-addr: UPSTREAM.DNS.2Save and Exit and check the config for errors.
$ sudo unbound-checkconf
unbound-checkconf: no errors in /etc/unbound/unbound.confEnable and start unbound
sudo systemctl enable --now unboundCheck status
sudo systemctl status --now unboundUpdate local resolv.conf to use Unbound. Edit the /etc/resolv.conf with the following contents
nameserver 127.0.0.1
search lab.fiveorange.netTesting resolution
$ dig @127.0.0.1 vcenter.lab.fiveorange.net +short
192.168.200.52
$ dig @127.0.0.1 -x 192.168.200.52 +short
vcenter.lab.fiveorange.net.
$ dig @127.0.0.1 google.com +short
142.250.195.142Installing and configuring apache
dnf install -y httpdCreate the depot directory
sudo mkdir /var/www/html/depot
sudo chown -R apache:apache /var/www/html/depot/
sudo chmod -R 755 /var/www/html/depot/Configure httpd
# Create a new file /etc/httpd/conf.d/depot.conf with following contents
<Directory "/var/www/html/depot">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>Enable and start Apache
sudo systemctl enable --now httpd
sudo systemctl status httpdConfiguring firewalld
Add the following rules
# Add rules
sudo firewall-cmd --permanent --add-service=dns
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --reload
# Check
sudo firewall-cmd --list-all
services: dhcpv6-client dns http mdns sshTesting Apache
From the Mac, browse to http://192.168.200.5/depot/ and it should show listing. It will be blank for now.
Copying offline-depot-metadata
rsync the files to the Depot server
rsync -Pav VMware-VCSA-all-9.0.1.0.24957454.iso max@depot:~/Unzip the file at /var/www/html/depot
Create the following directories in /var/www/html/depot
/var/www/html/depot$ tree .
.
├── PROD
│ ├── COMP
│ │ ├── NSX_T_MANAGER
│ │ │ └── nsx-unified-appliance-9.0.1.0.24952114.ova
│ │ ├── SDDC_MANAGER_VCF
│ │ │ ├── Compatibility
│ │ │ │ └── VmwareCompatibilityData.json
│ │ │ └── VCF-SDDC-Manager-Appliance-9.0.1.0.24962180.ova
│ │ └── VCENTER
│ │ └── VMware-VCSA-all-9.0.1.0.24957454.isoAnd copy the .ova’s there.
Set the correct permissions
chown -R apache:apache /var/www/html/depot
chmod -R 755 /var/www/html/depotObtain the wildcard certificate
VCF installer requires valid wildcard certificate. Self-signed certificates don’t seem to work.
Since I have a domain name with Cloudflare, I’m using certbot.
sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.cloudflare/credentials.ini \
--dns-cloudflare-propagation-seconds 30 \
-d "*.lab.fiveorange.net" \
-d "lab.fiveorange.net" \
--email VALID@EMAIL \
--agree-tos \
--non-interactive
# You should get something like this
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Account registered.
Requesting a certificate for *.lab.fiveorange.net and lab.fiveorange.net
Waiting 30 seconds for DNS changes to propagate
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/lab.fiveorange.net/fullchain.pem
Key is saved at: /etc/letsencrypt/live/lab.fiveorange.net/privkey.pem
This certificate expires on 2026-03-07.
These files will be updated when the certificate renews.
Certbot has set up a scheduled task to automatically renew this certificate in the background.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
If you like Certbot, please consider supporting our work by:
* Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
* Donating to EFF: https://eff.org/donate-le
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -The certificates are stored here
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/lab.fiveorange.net/fullchain.pem
Key is saved at: /etc/letsencrypt/live/lab.fiveorange.net/privkey.pem
This certificate expires on 2026-03-07.Verify the certificates
$ sudo certbot certificates
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Found the following certs:
Certificate Name: lab.fiveorange.net
Serial Number: 6095e161478e882e436e4f35e929b031f2d
Key Type: ECDSA
Domains: *.lab.fiveorange.net lab.fiveorange.net
Expiry Date: 2026-03-07 05:26:10+00:00 (VALID: 89 days)
Certificate Path: /etc/letsencrypt/live/lab.fiveorange.net/fullchain.pem
Private Key Path: /etc/letsencrypt/live/lab.fiveorange.net/privkey.pem
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Install mod_ssl
# Install mod_ssl
sudo dnf install -y mod_ssl
# Verify mod_ssl is loaded
httpd -M | grep ssl
ssl_module (shared)Creating Basic Auth Password file
# Install httpd-tools if not already installed
sudo dnf install -y httpd-tools
# Create a user called vcfadmin
sudo htpasswd -c /etc/httpd/.htpasswd vcfadmin
New password:
Re-type new password:
Adding password for user vcfadminConfigure Apache SSL VirtualHost
# Create a new file called /etc/httpd/conf.d/depot-ssl.conf with the following contents
<VirtualHost *:443>
ServerName depot.lab.fiveorange.net
DocumentRoot /var/www/html
# SSL Configuration
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/lab.fiveorange.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/lab.fiveorange.net/privkey.pem
# Modern SSL settings
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
# Logging
ErrorLog /var/log/httpd/depot-ssl-error.log
CustomLog /var/log/httpd/depot-ssl-access.log combined
# Depot directory with basic auth
<Directory "/var/www/html/depot">
Options Indexes FollowSymLinks
AllowOverride None
# Basic Authentication
AuthType Basic
AuthName "VCF Offline Depot"
AuthUserFile /etc/httpd/.htpasswd
Require valid-user
</Directory>
</VirtualHost>Configure HTTP to HTTPS redirect
# Create a new file /etc/httpd/conf.d/depot-redirect.conf with following contents
<VirtualHost *:80>
ServerName depot.lab.fiveorange.net
# Redirect all HTTP traffic to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>Verify HTTPS and Basic auth
# Test HTTPS
$ curl -u vcfadmin https://depot.lab.fiveorange.net/depot/
Enter host password for user 'vcfadmin':
# You can also do this
curl -u vcfadmin -I https://depot.lab.fiveorange.net/depot/
Enter host password for user 'vcfadmin':
HTTP/1.1 200 OK
Date: Sun, 07 Dec 2025 06:47:36 GMT
Server: Apache/2.4.65 (Fedora Linux) OpenSSL/3.5.4
Content-Type: text/html;charset=ISO-8859-1Verify auto-renewal
# Check timer status
sudo systemctl status certbot-renew.timer
# If you want to list all timers
sudo systemctl list-timers
# Do a dry run of cert-bot
sudo certbot renew --dry-run
# You should get something like this
Saving debug log to /var/log/letsencrypt/letsencrypt.log
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Processing /etc/letsencrypt/renewal/lab.fiveorange.net.conf
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Account registered.
Simulating renewal of an existing certificate for *.lab.fiveorange.net and lab.fiveorange.net
Waiting 30 seconds for DNS changes to propagate
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations, all simulated renewals succeeded:
/etc/letsencrypt/live/lab.fiveorange.net/fullchain.pem (success)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Verify firewalld
# Ensure that you have done this
$ sudo firewall-cmd --list-services
dhcpv6-client dns http https mdns sshTrouble shooting - unbound
# Check config
unbound-checkconf
# Restart service
systemctl restart unbound
# View logs
journalctl -u unbound -f
# Test lookup
dig @127.0.0.1 <hostname>
dig @127.0.0.1 -x <ip>Trouble shooting - Apache
Test HTTPS via FQDN (certificate valid, no -k flag needed)
curl -u vcfadmin https://depot.lab.fiveorange.net/
# Test HTTPS via IP (requires -k flag for IP-based access)
curl -u vcfadmin -k https://192.168.200.5/
# Note: The `-k` flag is required for IP-based HTTPS access because the certificate is issued for `*.lab.fiveorange.net`, not the IP address.
# Test access to metadata (VCF Installer requests these paths)
curl -u vcfadmin https://depot.lab.fiveorange.net/PROD/metadata/manifest/v1/vcfManifest.json
curl -u vcfadmin https://depot.lab.fiveorange.net/PROD/metadata/productVersionCatalog/v1/productVersionCatalog.json
# Check config
apachectl configtest
# Restart service
systemctl restart httpd
# View logs
tail -f /var/log/httpd/access_log
tail -f /var/log/httpd/error_logConfiguring chronyd
This server is also going to be a NTP server. I’m using chrony instead of ntpd.
In Fedora 43, chronyd is already installed.
Take backup of original config
cd /etc
cp chrony.conf{,.orig}Now edit the chrony.conf
# Set the pool
pool 0.au.pool.ntp.org iburst
pool 1.au.pool.ntp.org iburst
pool 2.au.pool.ntp.org iburst
pool 3.fedora.pool.ntp.org iburst
# Backup sources (global, in case AU pool has issues)
server time.cloudflare.com iburst
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
# Allow the system clock to be stepped in the first three updates
# if its offset is larger than 1 second.
makestep 1.0 3
# Enable kernel synchronization of the real-time clock (RTC).
rtcsync
# Allow NTP client access from local network.
#allow 192.168.0.0/16
allow 127.0.0.0/8
allow 192.168.200.0/24
allow 192.168.201.0/24
allow 192.168.202.0/24
allow 192.168.203.0/24
# Serve time even if not synchronized to a time source.
local stratum 10
Save NTS keys and cookies.
ntsdumpdir /var/lib/chrony
# Set the TAI-UTC offset of the system clock.
leapseclist /usr/share/zoneinfo/leap-seconds.list
# Specify directory for log files.
logdir /var/log/chrony
# Select which information is logged.
log measurements statistics trackingEnable and Start the service
systemctl enable chronyd && systemctl start chronydConfigure firewall
firewall-cmd --add-service=ntp --permanent
firewall-cmd --reloadChecking Chrony
Checking sources
chronyc sources -vYou should get something like this
.-- Source mode '^' = server, '=' = peer, '#' = local clock.
/ .- Source state '*' = current best, '+' = combined, '-' = not combined,
| / 'x' = may be in error, '~' = too variable, '?' = unusable.
|| .- xxxx [ yyyy ] +/- zzzz
|| Reachability register (octal) -. | xxxx = adjusted offset,
|| Log2(Polling interval) --. | | yyyy = measured offset,
|| \ | | zzzz = estimated error.
|| | | \
MS Name/IP address Stratum Poll Reach LastRx Last sample
===============================================================================
^+ 159.196.178.7 1 6 377 28 -62us[ -62us] +/- 12ms
^- syd.clearnet.pw 3 6 377 30 +1627us[+1627us] +/- 68ms
^- bitburger.simonrumble.com 1 6 377 30 +7005us[+7005us] +/- 13ms
^+ 193.177.220.128 2 6 377 32 +184us[ +114us] +/- 4948us
^+ time.cloudflare.com 3 6 377 28 -443us[ -443us] +/- 6341us
^+ time.cloudflare.com 3 6 377 29 -505us[ -505us] +/- 6111us
^- 194-195-253-58.ip.linode> 4 6 377 30 +4989us[+4920us] +/- 62ms
^- 220-158-215-20.broadband> 2 6 377 7 -548us[ -548us] +/- 43ms
^- ap-southeast-2.clearnet.> 2 6 377 29 +208us[ +208us] +/- 42ms
^- 159-196-3-239.9fc403.mel> 2 6 377 28 +2856us[+2856us] +/- 13ms
^- ns2.rasp.sh 3 6 377 32 -309us[ -378us] +/- 47ms
^- ntp-mel.mansfield.id.au 2 6 377 31 -1502ns[ -71us] +/- 12ms
^+ time.bbmg.tech 5 6 377 29 -407us[ -407us] +/- 4605us
^- ntp2.ds.network 2 6 377 32 -159us[ -228us] +/- 6307us
^+ ntp1.ds.network 2 6 377 31 +80us[ +11us] +/- 10ms
^* smtp.juneks.com.au 1 6 377 30 -137us[ -207us] +/- 5106usCheck tracking
chronyc tracking
Reference ID : 77120625 (smtp.juneks.com.au)
Stratum : 2
Ref time (UTC) : Fri Jan 30 05:40:16 2026
System time : 0.000139529 seconds slow of NTP time
Last offset : -0.000043255 seconds
RMS offset : 0.000548189 seconds
Frequency : 4.411 ppm slow
Residual freq : -0.071 ppm
Skew : 0.825 ppm
Root delay : 0.009834820 seconds
Root dispersion : 0.000394668 seconds
Update interval : 64.9 seconds
Leap status : NormalThe Leap status should be Normal.
Checking clients - once they are configured
chronyc clients