As part of setting up my “vms from anywhere” system, I wanted to be able to access my ESXi web consoles over the web. If you read my post about reverse proxies, you know I have a basic NGINX server running on my LAN that proxies the rest of my web applications out over HTTPS based on request subdomains.
I’m going to preface these notes with a warning: there’s a bunch of security issues with opening up an ESXi portal to the internet in production (or honestly, even in a home lab). Bad actors can very quickly lock you out via DDOS on the root account login – which will keep you out of your entire ESXi host for as long as they want. Leaving the portal open to the web is also begging for brute forcing, and exposes details of your infrastructure that would probably be better if closely held. That said, I felt like addressing these at a later date since nothing I’m hosting is mission critical at the moment. Once I’m less pressed for time, I’ll likely have another post where I’m working on making this setup secure sometime down the road. In other words – I’m making a bad (temporary) decision, and its fine. Just don’t blindly copy things unless you accept the limitations.
Naively, I decided I’d start by just plugging in my ESXi management address as a basic server block (just like I did for my iLo portals):
server{
listen 443;
server_name esxi.dupuis.xyz;
ssl on;
ssl_certificate /etc/letsencrypt/live/dupuis.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrpyt/live/dupuis.xyz/privkey.pem;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto https;
proxy_redirect off;
proxy_http_version 1.1;
proxy_pass https://192.168.1.15;
}
}
This setup allowed me to access the ESXi web interface, but none of the remote console services worked (either in the browser or on my machine via VMWare Remote Console):
Turning to Google, I found Damion Brown’s BasicAuth recommended setup for ESXi proxies on GitHub. Damion fixes some of the ESXi insecurity by hiding the management proxy behind a basic auth login. I didn’t feel like dealing with double login screens on my setup, so I skipped that part of his code and basically just adopted a bunch of his header forwarding options and proxy timeout settings, since he’d already tuned them for ESXi. The result was the following server configuration block:
server {
listen 443
server_name esxi.dupuis.xyz;
ssl on;
ssl_certificate /etc/letsencrypt/live/dupuis.xyz/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/dupuis.xyz/privkey.pem;
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "";
proxy_redirect off;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Origin "";
proxy_pass_header X-XSRF-TOKEN;
proxy_pass https://192.168.1.15;
proxy_send_timeout 300;
proxy_read_timeout 300;
send_timeout 300;
client_max_body_size 1000m;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
This got me most of the way there – I could use the HTML5 remote console, but was still getting certificate mismatch errors from both Chrome and ESXi. The desktop Remote Console application also wouldn’t connect, giving me “HTTP Error 401 Unauthorized” after the console started to load. I figured that the easiest way to fix what appeared to be a certificate mismatching error would be to just install the actual site certificates on ESXi – that way, the reverse proxy wouldn’t be stripping anything out, and both the client and server sides would be looking at the same keys with the same domain information.
Thankfully, VMware has docs about replacing default certificates from the ESXi shell. I started by renaming the old certificate and key as a backup. I then ran a remote copy of my SSH full chain certificate and key using scp from my Ubuntu network management VM to my ESXi server, and renamed the new certificates the match what ESXi is expecting:
mv rui.crt orig.rui.crt
mv rui.key orig.rui.key
scp /etc/vmware/ssl user@remoteserver:/etc/letsencrypt/live/dupuis.xyz/fullchain.pem
scp /etc/vmware/ssl user@remoteserver:/etc/letsencrypt/live/dupuis.xyz/privkey.pem
mv fullchain.pem rui.crt
mv privkey.pem rui.key
At this point, I rebooted my ESXi server – I probably didn’t have to, but it felt like a good measure to get everything to a stable point. Following the reboot, I was able to connect to a Remote Console from the desktop application successfully, and there were no more certificate errors in the browser:
I’m really pleased with the setup, aside from the glaring security holes – but we’ll patch those later. For now, I’m able to fully control my VMs from anywhere in the world, and that’s enough for me!
Hopefully this post is useful to configure ESXi on your remote proxy setup – if you have a question, or if there’s something I did wrong/could do better, leave a comment and I’ll get back to you as soon as I have a second. Thanks for reading!
Won’t you have to jump through the same hoop (replacing the cert on ESXi) every 90 days or however often Letsencrypt certs expire?
I suppose you could probably automate that somehow with scp and a script…
Like!! Thank you for publishing this awesome article.
This work for Esxi host. Can you share nginx conf file for Vcenter
I Just wanted to post that I only needed a portion of this to work with my “nginx proxy manager” install for both esxi console and proxmox console.
I installed nginx proxy manager as a docker container on an ubuntu VM. From there, the conf files were in ~/Proxy/data/nginx/proxy_host/
all of the configs for all of the proxy’d servers you set up in the gui, were listed as 1.conf, 2.conf, 3.conf…
For both my proxmox conf (1.conf in my case) and esxi (2.conf), all I had to do was copy and paste ONLY that top section of your above example under location. And copy it EXACTLY the same in both configs. I didn’t need any of the rest of it. in fact, when I tried copying the rest of it, it actually completely broke ALL of my proxy’d servers until I copied my backup file over the edited config.
So while your method is probably geared towards nginx native install. only a portion is needed for “nginx proxy manager”.
location / {
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization “”;
proxy_redirect off;
Anyway – I typed all of this out hoping that if somebody else googles it specifically for proxy manager, I’m hoping they will come across my response and be helped.
And thank you so much.
OOPS – I forgot a very big BUT here. I was ONLY trying to get the html5 console working – which this helped me do. this did NOT help me getting the standalone VMRC app connected. But I didn’t need that, as my goal was to be able to access it from any system, even if VMRC wasn’t installed.