Reverse Proxy to allow VMs to share a IP
Go to file
Linus Sehn fa7a20ab5a
continuous-integration/drone/push Build is passing Details
Fix typo
2023-04-05 10:17:02 +02:00
group_vars add HSTS header before redirection 2021-07-20 13:01:26 +02:00
host_vars Fix typo 2023-04-05 10:17:02 +02:00
inventory@de8e53f300 bump inventory 2022-12-04 10:36:27 +01:00
templates Passthrough managesieve 2023-03-16 15:50:27 +01:00
.drone.yml adding drone CI for docs sync 2023-01-13 13:50:55 +01:00
.gitmodules initial commit for basic functionality for ports 80 and 443 2021-07-14 19:25:45 +02:00 added badge to the README 2023-01-13 13:52:45 +01:00
ansible.cfg initial commit for basic functionality for ports 80 and 443 2021-07-14 19:25:45 +02:00
playbook.yml reduce max. log time 2021-07-16 16:14:56 +02:00

Reverse Proxy for VMs

This is a reverse proxy using HAProxy to enable multiple VMs share the same IPv4 and IPv6. At the moment, it only tunnels TCP on port 443 (HTTPS), based on TLS SNI.

Deployment happens via Ansible.



A proxied VM still requires a dedicated IPv6. From that, the hostname and the IP of the host the service is hosted on have to be entered in the host_vars of the proxy on the cluster the VM is located on.

Example, e.g. in host_vars/, proxy the hostname to its IPv6:

webservers: 2a02:16d0:1004:5a00:f5f3::1

VM webserver configuration

The webservers behind this reverse proxy have to be slightly re-configured in order to work properly. That is because we use the proxy protocol to forward requests, and the real originating IP should be displayed correctly in the logs.

Attention: Although the reverse proxy internally forwards port 80 to 443, there is one exception: ACME challenges for Let's Encrypt. For certbot to be able to authenticate, you must not remove the vhost for port 80! However, you can make it absolutely minimal.


  1. Enable the required module: a2enmod remoteip

  2. In the virtual host config (e.g. /etc/apache2/sites-enabled/000-default.conf), add inside the vhost of port 443:

    RemoteIPProxyProtocol On
  3. In the Apache config, adapt the log format to show the real IP passed by the proxy. You have two options:

    1. Change the default combined LogFormat in apache2.conf:

      - LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
      + LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
    2. Add a new LogFormat in apache2.conf...

      LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined_proxy

      and use it in the virtual host config, e.g.:

      - CustomLog /var/log/apache2/yoursite-access.log combined
      + CustomLog /var/log/apache2/yoursite-access.log combined_proxy


Nginx has the required module included in Debian's default installation.

  1. Modify the following to the virtual host configuration (e.g. /etc/nginx/sites-enabled/default), again the port 443 config:

    -listen [::]:443 ssl ipv6only;
    -listen 443 ssl;
    +listen [::]:443 ssl ipv6only proxy_protocol;
    +listen 443 ssl proxy_protocol;
  2. Add in the same configuration:

    real_ip_header proxy_protocol;