Skip to content

HOWTO coldsetup 05_reverse_proxy

steveoro edited this page Apr 26, 2021 · 1 revision

HOW-TO: Cold Deploy Server step-by-step

References:

Assuming the SSL main domain (master-goggles.org) is already set up as outlined in the link above.

Part 5: Reverse Proxy setup

References:

(@ remote server)

Install Apache required modules:

$> sudo a2enmod proxy
$> sudo a2enmod proxy_http

# We need the headers mod to forward the headers:
$> sudo a2enmod headers

# In case we want to configure a balancer:
$> sudo a2enmod proxy_balancer

$> sudo a2enmod lbmethod_byrequests
$> sudo systemctl restart apache2

Given that the Apache server acts as both HTTP and HTTPS server, the reverse-proxy configuration must be placed in both the HTTP and HTTPS virtual hosts. Or, at least, use a rewrite rule to redirect all traffic to the actual HTTPS endpoint.

Edit Virtual Host config to enable the Reverse Proxy, for both ports (80 & 443).

Example configuration files:

$> sudo vi /etc/apache2/sites-available/goggles-prod.conf
<VirtualHost *:80>
  ServerAdmin [email protected]
  ServerName  master-goggles.org
  ServerAlias www.master-goggles.org

  # We will use a simple rewrite rule to redirect all traffic to the HTTPS port:
  RewriteEngine on
  RewriteRule   ^/(.*)$  https://%{HTTP_HOST}/$1  [redirect,last]

  ErrorLog  ${APACHE_LOG_DIR}/prod_error.log
  CustomLog ${APACHE_LOG_DIR}/prod_access.log combined

  ErrorLogFormat "[%{cu}t] [%-m:%-l] %-a %-L %M"
  LogFormat     "%h %{GEOIP_COUNTRY_CODE}e %u [%{%Y-%m-%d %H:%M:%S}t.%{usec_frac}t] \"%r\" %>s %b \
\"%{Referer}i\" \"%{User-Agent}i\" \"%{Content-Type}i\" %{remote}p %v %A %p %R \
%X \"%{cookie}n\" %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x \
%I %O %{ratio}n%% %D %{ApplicationTime}e" extended
</VirtualHost>

The reverse proxy will map connections from the SSL port to the running production container published port (8080), in & out.

$> sudo vi /etc/apache2/sites-enabled/goggles-prod-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
  ServerAdmin [email protected]
  ServerName  master-goggles.org
  ServerAlias www.master-goggles.org

  Include               /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile    /etc/letsencrypt/live/master-goggles.org/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/master-goggles.org/privkey.pem

  # Header protocol must be forwarded and config.force_ssl must be set to true in Rails:
  RequestHeader         set X-Forwarded-Proto https

  ProxyTimeout        	60
  ProxyPreserveHost 	  On
  ProxyPass 		        /   http://localhost:8080/
  ProxyPassReverse 	    /   http://localhost:8080/

  ErrorLog  ${APACHE_LOG_DIR}/prod_error.log
  CustomLog ${APACHE_LOG_DIR}/prod_access.log combined

  ErrorLogFormat "[%{cu}t] [%-m:%-l] %-a %-L %M"
  LogFormat     "%h %{GEOIP_COUNTRY_CODE}e %u [%{%Y-%m-%d %H:%M:%S}t.%{usec_frac}t] \"%r\" %>s %b \
\"%{Referer}i\" \"%{User-Agent}i\" \"%{Content-Type}i\" %{remote}p %v %A %p %R \
%X \"%{cookie}n\" %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x \
%I %O %{ratio}n%% %D %{ApplicationTime}e" extended
</VirtualHost>
</IfModule>

Check resulting config & restart:

$> sudo apache2ctl configtest

Enable site if not yet enabled:

$> sudo a2ensite goggles-prod goggles-prod-le-ssl

Restart:

$> sudo systemctl restart apache2
$> sudo systemctl status apache2

Basic Auth for staging back-end

References:

Install Apache utils to create a password file readable by Apache:

(@ remote server)

$> sudo apt update
$> sudo apt install apache2-utils
$> sudo htpasswd -c /etc/apache2/.htpasswd <TEST_USER1_NAME_1>
$> cat /etc/apache2/.htpasswd

# Add any other staging user without '-c':
$> sudo htpasswd /etc/apache2/.htpasswd <TEST_USER_NAME_2>
$> sudo htpasswd /etc/apache2/.htpasswd <TEST_USER_NAME_3>
# ...

Edit config:

Use a different port for the other back-end (i.e.: 444). We don't need to have a 80-ish port equivalent for this, given the internal nature of this back-end (no "plain -> SSL" redirection is needed).

The reverse proxy will map connections to the chosen port to the running staging container published port (9080), in & out.

$> sudo vi /etc/apache2/sites-enabled/goggles-staging.conf
<IfModule mod_ssl.c>
<VirtualHost *:444>
  ServerAdmin [email protected]
  ServerName  master-goggles.org
  ServerAlias www.master-goggles.org

  Include               /etc/letsencrypt/options-ssl-apache.conf
  SSLCertificateFile    /etc/letsencrypt/live/master-goggles.org/fullchain.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/master-goggles.org/privkey.pem

  # Header protocol must be forwarded and config.force_ssl must be set to true in Rails:
  RequestHeader         set X-Forwarded-Proto https

  ProxyTimeout      60
  ProxyPreserveHost	On
  ProxyPass         /   http://localhost:9080/
  ProxyPassReverse 	/   http://localhost:9080/

  <Proxy http://localhost:9080>
      Order deny,allow
      Allow from all
      Authtype Basic
      Authname "Restricted content"
      AuthUserFile /etc/apache2/.htpasswd
      Require valid-user
  </Proxy>

  ErrorLog  ${APACHE_LOG_DIR}/staging_error.log
  CustomLog ${APACHE_LOG_DIR}/staging_access.log combined

  ErrorLogFormat "[%{cu}t] [%-m:%-l] %-a %-L %M"
  LogFormat     "%h %{GEOIP_COUNTRY_CODE}e %u [%{%Y-%m-%d %H:%M:%S}t.%{usec_frac}t] \"%r\" %>s %b \
\"%{Referer}i\" \"%{User-Agent}i\" \"%{Content-Type}i\" %{remote}p %v %A %p %R \
%X \"%{cookie}n\" %{UNIQUE_ID}e %{SSL_PROTOCOL}x %{SSL_CIPHER}x \
%I %O %{ratio}n%% %D %{ApplicationTime}e" extended
</VirtualHost>
</IfModule>

Edit the ports:

$> sudo vi /etc/apache2/ports.conf
Listen 80

<IfModule ssl_module>
        Listen 443
        Listen 444
</IfModule>

<IfModule mod_gnutls.c>
        Listen 443
        Listen 444
</IfModule>

Set port visibility on internal firewall (ufw):

$> ufw allow 22/tcp
$> ufw allow 80/tcp
$> ufw allow 443/tcp
$> ufw allow 444/tcp

# "Just in case":
$> ufw deny 8080/tcp
$> ufw deny 9080/tcp

$> ufw status
$> ufw reload

Check resulting config & restart:

$> sudo apache2ctl configtest

Enable site if not yet enabled:

$> sudo a2ensite goggles-staging

Restart:

$> sudo systemctl restart apache2
$> sudo systemctl status apache2
Clone this wiki locally