Connecting a virtual server to Docker

SYSTEM INFORMATION
OS type and version Debian Linux 12
Virtualmin version 7.50.0 Professional

I’ve already read quite a bit online, and basically it can’t be that difficult.
I have a Docker stack (Mastodon) running on my server. It can be accessed via port 1234. The Dockers in the stack can communicate with each other.

Now I wanted to connect port 1234 to a subdomain abc.test.com via proxy. So I went to ‘Edit Proxy Website’ and entered ‘http://127.0.0.1:1234’. The container is also addressed, which I can see in the container log. However, the request is blocked because 127.0.0.1, just like localhost, is one of the ‘blocked hosts’.

So I need to somehow tell Virtualmin to pass on the request, but not with 127.0.0.1 or localhost, but preferably with the actual subdomain abc.test.com so that the container works correctly externally.
I just can’t get it to work. Has anyone else done this configuration before and can help me or give me the right tip?

Thx a lot

What is “blocked hosts” in this context? Who is blocking localhost? Why?

I check the log of the container with the published port, which should be accessible via the subdomain abc.test.com. The log shows a message stating that the host 127.0.0.1 or the host localhost is included in the list of blocked hosts.
This depends on the target of the proxy configuration: http://127.0.0.1:1234 or http://localhost:1234.
The container expects my request to come from the subdomain stored in the container configuration. In other words, a request from http://abc.test.com:1234.
What is missing here is a kind of translation or conversion of the requesting address, and that is where I am failing.

Maybe post the log, localhost is never blocked normally, you need to find the source of the blocking.

It sounds kinda like your application is expecting the HOST header to be something other than localhost. But, that won’t happen in a proxied connection. The HOST header will be the local address, and is expected to be that, while there may be a Forwarded or X-Forwarded-For header that contains the original destination host.

Thanks for the reply´s.

It’s very frustrating…
Previously in Plesk, I simply initialized the Docker stack and forwarded the subdomain to the corresponding port of the Docker.
I assumed I could do exactly the same thing with the proxy functions in Virtualmin.
I have now already configured my proxy with

ProxyPassReverse / http://localhost:3005/
ProxyPass / http://localhost:3005/
RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
RequestHeader set X-Forwarded-Host abc.test.com
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteRule ^/?(.*) “ws://localhost:3005/$1” [P]

extended.
When I start the Docker stack (docker-compose up) and look at the log, every reload in the browser to the actual subdomain (abc.test.com) is logged with:

web_1        | E, [2025-11-15T16:46:39.203850 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: localhost:3005
web_1        | E, [2025-11-15T16:46:39.945245 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: localhost:3005
web_1        | E, [2025-11-15T16:46:40.132301 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: localhost:3005
web_1        | E, [2025-11-15T16:46:40.196862 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: localhost:3005

Maybe it’s just a minor thing, but I can’t figure it out.

I suspect it’s due to the host that is transferred to Docker via the proxy. It’s a Mastodon server. Apparently, it locks up if the correct address is not transferred from outside.
I have two other containers running that work perfectly.

Blocked host? Is this log from within the container? Like it won’t accept a remote localhost connection because localhost is used internally and it assumes a remote localhost is a ‘bad thing’?

I have had cases where 127.0.0.1 works but localhost does not for some reason.

I have been trying for several days now to get my old Docker stack, on which I ran a Mastodon server, up and running again. I can get it to run, because the individual containers in the stack start up and can communicate with each other.

On my old server (with Plesk), I directed the domain via proxy to a port on the Docker stack, and it ran flawlessly for several years.

When I switched, I copied all Docker volumes to the new server (Virtualmin).

The Virtualmin installation is a Grade A+ system with all features. But it’s just Apache and not Nginx, as was previously the case with Plesk in combination.
That’s the only difference I can see.

After adjusting the configuration hundreds of times using docker-compose down removed and restarting Docker with docker-compose up to see if the changes to the configuration had the desired effect, I am slowly giving up.

I also can’t imagine that Apache as a reverse proxy should be less capable than Nginx and that this could be the cause.

My current status is:

/etc/apache2/sites-available/abc.test.com.conf
ProxyPassReverse / http://127.0.0.1:3000/
ProxyPass / http://127.0.0.1:3000/
RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
RequestHeader set X-Forwarded-Host abc.test.com
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:3000/$1" [P]

It is the standard comnpose file from mastodon.

Changed production.rb in

config/environments/production.rb

with added code:

  config.hosts = [
    IPAddr.new("0.0.0.0/0"), # All IPv4 addresses.
    IPAddr.new("::/0"), # All IPv6 addresses.
    "localhost" # The localhost reserved domain.
  ]

But nothing has changed. Whenever I call up the subdomain in the browser, the following error appears in the log output (docker compose up):

web_1        | E, [2025-11-16T16:29:04.355258 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: 127.0.0.1:3000
web_1        | E, [2025-11-16T16:29:04.645156 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: 127.0.0.1:3000
web_1        | E, [2025-11-16T16:29:04.663109 #17] ERROR -- : [ActionDispatch::HostAuthorization::DefaultResponseApp] Blocked hosts: 127.0.0.1:3000

This is the last project. Once I finish it, I will have successfully migrated everything from Plesk to Virtalmin.

try commenting out.

some googling also seems to suggest LOCAL_DOMAIN=[My mastodon FQDN] in .env to try.

maybe play with

ProxyPreserveHost On

1 Like

If Plesk ran both they were probably using Nginx as a Proxy. Loads of Discourse posts recommended that setup. But yeah getting Apache set up wasn’t as straight forward as it should have been as I recall. :frowning:

This is a bit from a working config and this is the first I’ve seen of the balancer so not sure WHERE/HOW/WHEN that got added. Also the SSL stuff drove me nuts as Discourse has its’ own Lets’s encrypt setup. :

 <Proxy balancer://root>
        BalancerMember http://localhost:8082/
        SSLProxyCheckPeerName off
        SSLProxyCheckPeerCN off
        SSLProxyCheckPeerExpire off
    </Proxy>
    ProxyPass / balancer://root/
    ProxyPassReverse / balancer://root/
    SSLProxyEngine on
1 Like

Damn it, that was the solution!

I already saw my online career in Mastodon going down the drain :sweat_smile:

Now everything is back online and ready to go. Thank you a thousand times!

As a result, here’s a quick summary of what got Docker up and running. Nothing actually needs to be changed in the Docker configurations, when you migrate from plesk. As I suspected, it’s the connection via the virtualserver.
The post by lawk provided the decisive clue here. For those who will have the same problem. Frist set up proxy forwarding for the virtual host (Web Configuration > Edit Proxy Website).

http://127.0.0.1:3000/

Second edit the proxy settings (Configure SSL Website > Edit Directives). There should be

ProxyPass / http://127.0.0.1:3000/
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:3000/$1" [P]

Change it to:

ProxyPreserveHost On
ProxyPassReverse / http://127.0.0.1:3000/
ProxyPass / http://127.0.0.1:3000/
RequestHeader set X-Real-IP expr=%{REMOTE_ADDR}
RequestHeader set X-Forwarded-Proto expr=%{REQUEST_SCHEME}
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade [NC]
RewriteRule ^/?(.*) "ws://127.0.0.1:3000/$1" [P]

The entry ProxyPreserveHost On and the removal of X-Forwarded-Host caused the knot to burst for me.
Thanks again to everyone for their support!

4 Likes

This topic was automatically closed 8 days after the last reply. New replies are no longer allowed.