Running wordpress on virtualmin setup http only behind bunkerweb reverse proxy

SYSTEM INFORMATION
OS type and version Ubuntu 24.04.3
Webmin version 2.610
Virtualmin version 8.0.0
Webserver version 2.4.58
Related packages Apache

Hi I tried to setup virtualmin behind Bunkerweb reverse proxy https works perfectly fine for the webmin/virtualmin backend but when I create a website and point the reverse proxy to port 80 I get 500 internal server error.
Curl command though from the same virtualmin server shows the website content.

I used this command: curl -v -H “Host: example.comhttp://127.0.0.1/

If I go to the servers up adress and port I get the example page.

I did disable Apache SSL website because I thought that might cause an issue.

I also read there might be a too many redirects that could cause it or maybe missing headers, Auto redirect by virtualmin.

I have used virtualmin for a long time at my home network but mainly only with https via the proxy.

But it might only work at my home network and not my isp because at home i have a certain dns setup.

My VPS setup which has this issue is like this:

VPS1 - Bunkerweb WAF and Reverse Proxy
||
VPS2 - Virtualmin (isolated from the internet, only allowed to connect with vps1 and established connections to apt repos)

As for might be misconfigured reverse proxy I did disable all features to only use the reverse proxy no other features like crowd sec or anti bot stuff like that.

My home network is setup like this:

PFSENSE
||
BUNKERWEB
||
VIRTUALMIN

Domains point to the Pfsense firewall which also manages dns and dhcp.
DNS records for domains are set to the bunkerweb instances ip adress.
Bunkerweb points to the Virtualmin servers port 80.
In the past I also used to create virtual ip addresses in my network and added them to virtualmin then I had a unique ip for every website.
But the latest instance I ran had only one and it worked over https fine I haven’t tested http only.

To clarify ssl certificate is managed in every cenario by bunkerweb not virtualmin it’s self.

I am totally clueless what to do.
I would appreciate some advice and help.

There is no such thing as “auto redirect by Virtualmin”.

There are some redirects on subdomain names Virtualmin creates for some admin/webmail related services (admin.domain.tld and webmail.domain.tld), but the domain itself has no redirect or proxy, by default. And, Virtualmin is not involved in serving web requests, it creates a configuration for your chosen web server, which services web requests. You can literally stop Virtualmin/Webmin and continue to serve web requests.

That’s only an issue when trying to get TLS certs, since validation usually breaks when you have a proxy in front. But no harm, if the proxy in front is providing TLS termination.

We need to see the actual server errors. Your browser has no clue what is going wrong. A 500 error can be literally anything.

Thank you for you’re response.
In the console i see this:
GET

[HTTP/1.1 500 Internal Server Error 622ms]

GET

Status
500
Internal Server Error
VersionHTTP/1.1
Transferred70.95 kB (69.47 kB size)
Request PriorityHighest
DNS ResolutionSystem

Cache-Control
	no-cache, no-store, must-revalidate
Connection
	close
Content-Security-Policy
	default-src 'none'; script-src 'strict-dynamic' 'nonce-6UhsHICFCXwwm7Mpu97B6y844oAKvR5g'; style-src 'nonce-zEVbrDKtS2eEiAV5G3SFX62etaNaRvrA'; frame-ancestors 'none'; base-uri 'none'; img-src data:; font-src data:; require-trusted-types-for 'script';
Content-Type
	text/html; charset=utf-8
Date
	Tue, 27 Jan 2026 06:02:51 GMT
Host
	$host
Permissions-Policy
	accelerometer=(), ambient-light-sensor=(), attribution-reporting=(), autoplay=(), battery=(), bluetooth=(), browsing-topics=(), camera=(), compute-pressure=(), display-capture=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), identity-credentials-get=(), idle-detection=(), local-fonts=(), magnetometer=(), microphone=(), midi=(), otp-credentials=(), payment=(), picture-in-picture=(), publickey-credentials-create=(), publickey-credentials-get=(), screen-wake-lock=(), serial=(), speaker-selection=(), storage-access=(), usb=(), web-share=(), window-management=(), xr-spatial-tracking=(), interest-cohort=()
Referrer-Policy
	strict-origin-when-cross-origin
Transfer-Encoding
	chunked
X-Content-Type-Options
	nosniff
X-DNS-Prefetch-Control
	off
X-Forwarded-For
	$proxy_add_x_forwarded_for
X-Forwarded-Host
	$host
X-Forwarded-Proto
	http
X-Frame-Options
	SAMEORIGIN
	
Accept
	text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Encoding
	gzip, deflate
Accept-Language
	en-US,en;q=0.9
Connection
	keep-alive
Host
	example.com
Priority
	u=0, i
Upgrade-Insecure-Requests
	1
User-Agent
	Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0

Content-Security-Policy: Couldn’t process unknown directive ‘require-trusted-types-for’

That is still the client side. The client has no useful information.

You always need to look at the logs on the server.

The only logs that have an entry is apache access log but i don’t think that its useful because it only shows entries from webmin accessing it trough the preview i think!: 57.129.118.37 - - [26/Jan/2026:22:04:01 +0100] “GET /wp-admin/images/spinner-2x.gif HTTP/1.0” 200 7796 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:01 +0100] “GET /wp-admin/images/wordpress-logo.svg?ver=20131107 HTTP/1.0” 200 1784 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1 HTTP/1.0” 200 13867 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-admin/js/language-chooser.min.js?ver=6.9 HTTP/1.0” 200 710 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-includes/js/jquery/jquery.min.js?ver=3.7.1 HTTP/1.0” 200 87844 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-includes/css/buttons.min.css?ver=6.9 HTTP/1.0” 200 6343 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-admin/css/l10n.min.css?ver=6.9 HTTP/1.0” 200 3481 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-admin/css/install.min.css?ver=6.9 HTTP/1.0” 200 5322 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-includes/css/dashicons.min.css?ver=6.9 HTTP/1.0” 200 59287 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:04:00 +0100] “GET /wp-admin/css/forms.min.css?ver=6.9 HTTP/1.0” 200 28384 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:03:59 +0100] “GET /wp-admin/setup-config.php HTTP/1.0” 200 13527 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:22:03:58 +0100] “GET / HTTP/1.0” 302 246 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:41 +0100] “GET /wp-admin/images/wordpress-logo.svg?ver=20131107 HTTP/1.0” 200 1784 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:41 +0100] “GET /wp-admin/images/spinner-2x.gif HTTP/1.0” 200 7796 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-admin/js/language-chooser.min.js?ver=6.9 HTTP/1.0” 200 710 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1 HTTP/1.0” 200 13867 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-includes/js/jquery/jquery.min.js?ver=3.7.1 HTTP/1.0” 200 87844 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] "GET /wp-admin/css/install.min.css?ver=6.9 12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-admin/css/forms.min.css?ver=6.9 HTTP/1.0” 200 28384 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-includes/css/buttons.min.css?ver=6.9 HTTP/1.0” 200 6343 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-admin/css/l10n.min.css?ver=6.9 HTTP/1.0” 200 3481 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:40 +0100] “GET /wp-includes/css/dashicons.min.css?ver=6.9 HTTP/1.0” 200 59287 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:48:39 +0100] “GET /wp-admin/setup-config.php HTTP/1.0” 200 13495 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:34 +0100] “GET /wp-admin/images/spinner-2x.gif HTTP/1.0” 200 7796 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:33 +0100] “GET /wp-admin/images/wordpress-logo.svg?ver=20131107 HTTP/1.0” 200 1784 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-admin/js/language-chooser.min.js?ver=6.9 HTTP/1.0” 200 710 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1 HTTP/1.0” 200 13867 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-includes/js/jquery/jquery.min.js?ver=3.7.1 HTTP/1.0” 200 87844 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-admin/css/l10n.min.css?ver=6.9 HTTP/1.0” 200 3481 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-admin/css/install.min.css?ver=6.9 HTTP/1.0” 200 5322 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-includes/css/buttons.min.css?ver=6.9 HTTP/1.0” 200 6343 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-admin/css/forms.min.css?ver=6.9 HTTP/1.0” 200 28384 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:31 +0100] “GET /wp-includes/css/dashicons.min.css?ver=6.9 HTTP/1.0” 200 59287 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:30 +0100] “GET /wp-admin/setup-config.php HTTP/1.0” 200 13527 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:29 +0100] “GET / HTTP/1.0” 302 246 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:06 +0100] “GET /wp-admin/setup-config.php HTTP/1.0” 200 13527 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:17:05 +0100] “GET / HTTP/1.0” 302 246 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:54 +0100] “GET /wp-includes/js/dist/i18n.min.js?ver=c26c3dc7bed366793375 HTTP/1.0” 200 5603 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:54 +0100] “GET /wp-admin/js/password-toggle.min.js?ver=6.9 HTTP/1.0” 200 1134 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:54 +0100] “GET /wp-includes/js/dist/hooks.min.js?ver=dd5603f07f9220ed27f1 HTTP/1.0” 200 5950 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:54 +0100] “GET /wp-admin/setup-config.php?step=1 HTTP/1.0” 200 4713 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:52 +0100] “POST /wp-admin/setup-config.php?step=0 HTTP/1.0” 200 3060 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:42 +0100] “GET /wp-admin/images/spinner-2x.gif HTTP/1.0” 200 7796 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:42 +0100] “GET /wp-admin/images/wordpress-logo.svg?ver=20131107 HTTP/1.0” 200 1784 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-includes/js/jquery/jquery-migrate.min.js?ver=3.4.1 HTTP/1.0” 200 13867 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-admin/js/language-chooser.min.js?ver=6.9 HTTP/1.0” 200 710 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-includes/js/jquery/jquery.min.js?ver=3.7.1 HTTP/1.0” 200 87844 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-includes/css/buttons.min.css?ver=6.9 HTTP/1.0” 200 6343 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-admin/css/install.min.css?ver=6.9 HTTP/1.0” 200 5322 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-includes/css/dashicons.min.css?ver=6.9 HTTP/1.0” 200 59287 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-admin/css/forms.min.css?ver=6.9 HTTP/1.0” 200 28384 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:39 +0100] “GET /wp-admin/css/l10n.min.css?ver=6.9 HTTP/1.0” 200 3481 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:38 +0100] “GET /wp-admin/setup-config.php HTTP/1.0” 200 13527 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:37 +0100] “GET / HTTP/1.0” 302 246 “-” “Webmin”
12.122.122.12 - - [26/Jan/2026:21:16:36 +0100] “GET / HTTP/1.0” 302 246 “-” “Webmin”

Log seem to be present: ubuntu@ubuntu:~$ ls -l /var/log/virtualmin/example.com_error_log
-rw-r----- 1 root adm 0 Jan 27 22:42 /var/log/virtualmin/example.com_error_log

If you don’t see any requests in the log, then the request is not reaching the web server (or it’s reaching it on the wrong domain). Check the log for the first domain configured (the “default” domain) in Apache. If the headers from your proxy are messed up in some way, you might be asking the wrong VirtualHost to answer.

PHP log seem t be too: ubuntu@ubuntu:~$ sudo ls -l /home/lunaterramartis/logs/php_log
-rw-r–r-- 1 exampleexample 0 Jan 26 21:01 /home/example/logs/php_log

Ok i’ll check that.

OK, you could look at those logs. But, if you don’t see anything in the access_log, I don’t think there could be any errors or PHP log entries, either. The access_log will show every request including failed requests. If there’s nothing there, your proxy is not requesting anything in that VirtualHost.

Ok, and is the virtualmins domain counted as first domain because it’s not natively listed as virtual server yesterday i had a trick to get into that’s settings where it lists him as virtual server but i forgot how i did it. If it does not count then the first domain is the one i am posting about cirrently i have only one configured yet apart fro virtualmins own one.

If you browse to your Virtualmin server IP address, whatever domain shows is the default domain. The automatically created hostname domain is not necessarily the default domain. You can choose what the default domain will be in Virtualmin, which just makes sure the VirtualHost is the first one in Apache’s configuration (which makes it the one Apache settles on when a request that matches the IP comes in).

It seems that the only service i created example . com is the default IP.

Any advise what i need to setup in the proxy what virtualmin needs for vhost to resolve correctly?

Virtualmin doesn’t need anything. It is not the web server. It is not involved in any way in serving web requests.

Apache is the web server. Generally with proxies, you need to make sure your proxy is setting the host header correctly. I have no familiarity with the proxy you’re using.

But, you really need to figure out what is actually happening with your requests. I don’t know how to say look at the logs in more ways than I already have. You need to make sure the request is hitting your server somehow.

You can test to be sure Apache is answering appropriately by adding the name and IP to your hosts file and browsing to the domain for testing. If you see that working, then you know the problem is with your proxy configuration and nothing you do in Virtualmin or Apache can help.

The proxy is based on nginx host is based on one of the contributors being delivered to the proxy source.
Wouldn’t curl command not confirm it must be proxy caused, because it seem to resolve totally fine if i use it?:
C:\Users\simns>curl -v -H “Host: example . com” http://12.122.12.12

  • Trying 12.122.12.12:80…
  • Connected to 12.122.12.12 (12.122.12.12) port 80
  • using HTTP/1.x

GET / HTTP/1.1
Host: example . com
User-Agent: curl/8.13.0
Accept: /

  • Request completely sent off
    < HTTP/1.1 302 Found
    < Date: Tue, 27 Jan 2026 23:28:47 GMT
    < Server: Apache
    < Upgrade: h2,h2c
    < Connection: Upgrade
    < Location: http://example . com/wp-admin/setup-config.php
    < Content-Length: 0
    < Content-Type: text/html; charset=UTF-8
    <
  • Connection #0 to host 12.122.12.12 left intact

If WordPress (unconfigured) is what you expect to see on that domain, then yes, you’ve proven the Apache side is working.

So, your proxy is doing something wrong.

Yeah wordpress is unconfigured and preview in virtualmin shows it fine too.

And the host header is the only one needed from the proxy to be forwarded or another one or so i have to pay attention to? The reverse proxy is also a WAF but nginx based it should support nearly all nginx features.