WordPress behind HAProxy with TLS termination

https://oxcrag.net/2017/04/30/wordpress-behind-haproxy-with-tls-termination/

TLS termination configuration

The problem with terminating TLS traffic before the web server, is that any good web application should be able to recognize that the client is coming from an insecure connection. Luckily, we can use HAProxy to tell WordPress that the connection was good up until the load balancer and to trust it the rest of the way. Be aware that this is an extremely bad idea if there is any way to reach the web server other than via your HAProxy:

/usr/share/wordpress/wp-config.php:

[...]
/** Make sure WordPress understands it's behind an SSL terminator */
define('FORCE_SSL_ADMIN', true);
define('FORCE_SSL_LOGIN', true);
if ($_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')
$_SERVER['HTTPS']='on';
[...]

/etc/haproxy/haproxy.cfg:

[...]
frontend web-https
    option http-server-close
    http-request set-header X-Forwarded-Proto https if { ssl_fc }
[...]

global
	log /dev/log	local0
	log /dev/log	local1 notice
	chroot /var/lib/haproxy
	stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
	stats timeout 30s
	user haproxy
	group haproxy
	daemon

	# Default SSL material locations
	ca-base /etc/ssl/certs
	crt-base /etc/ssl/private

	# modern configuration
	ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
	ssl-default-bind-options prefer-client-ciphers no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets

	ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
	ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tlsv12 no-tls-tickets


defaults
	log	global
	mode	http
	option	httplog
	option	dontlognull

	option forwardfor
	option http-server-close

        timeout connect 5000
        timeout client  50000
        timeout server  50000
	errorfile 400 /etc/haproxy/errors/400.http
	errorfile 403 /etc/haproxy/errors/403.http
	errorfile 408 /etc/haproxy/errors/408.http
	errorfile 500 /etc/haproxy/errors/500.http
	errorfile 502 /etc/haproxy/errors/502.http
	errorfile 503 /etc/haproxy/errors/503.http
	errorfile 504 /etc/haproxy/errors/504.http

frontend stats
        bind *:9000
        mode http
        log global
        maxconn 10

        stats enable
        stats refresh 10s
        stats show-node
        stats auth nguyen:Anne1021
        stats uri  /

frontend www-http
	bind *:80
	bind *:443 ssl crt /etc/haproxy/ssl/
	http-request set-header X-Forwarded-Proto https if { ssl_fc }

	# letsencryp validation path for cert request
	acl letsencrypt-acl path_beg /.well-known/acme-challenge/

	acl wp_site hdr(host) -i bebubi.com
        acl wp_site hdr(host) -i www.bebubi.com
        acl wp_site hdr(host) -i wp.bebubi.com
        acl wp_site hdr(host) -i bibube.com
        acl wp_site hdr(host) -i www.bibube.com
        acl wp_site hdr(host) -i wp.bibube.com

        acl nc_site hdr(host) -i nc.bibube.com
        acl nc_site hdr(host) -i nc.bebubi.com

	use_backend letsencrypt-backend if letsencrypt-acl
	use_backend wp-backend if wp_site
	use_backend nc-backend if nc_site


backend letsencrypt-backend
	server letsencrypt 127.0.0.1:8888

backend wp-backend
	server wp 192.168.0.201:80

backend nc-backend
	server nc 192.168.0.200:443 check ssl verify none

Installing Let’s Encrypt Client

sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install certbot

Obtaining a Certificate

Verify Port 80 is Open

Then
sudo certbot certonly --standalone --preferred-challenges http --http-01-port 80 -d bibube.com -d wp.bibube.com -d nc.bibube.com -d www.bibube.com

sudo certbot certonly --standalone --preferred-challenges http --http-01-port 80 -d bebubi.com -d wp.bebubi.com -d nc.bebubi.com -d www.bebubi.com

Automated renewal script

root@pi-haproxy:~# cat renewCerts
#!/bin/bash
certbot renew --force-renewal --standalone --preferred-challenges http --http-01-address 127.0.0.1:8888

# Loop through all Let's Encrypt certificates
for CERTIFICATE in `find /etc/letsencrypt/live/* -type d`; do

  CERTIFICATE=`basename $CERTIFICATE`

  # Combine certificate and private key to single file
  cat /etc/letsencrypt/live/$CERTIFICATE/fullchain.pem /etc/letsencrypt/live/$CERTIFICATE/privkey.pem > /etc/haproxy/ssl/$CERTIFICATE.pem

done
systemctl reload haproxy.service

Jenkins

Installation Steps for Ubuntu:

Installing the Default JRE/JDK
sudo apt install default-jdk

Example:
ptn@ptn-virtual-machine:~$ sudo apt install default-jdk
ptn@ptn-virtual-machine:~$ javac -version
javac 11.0.14.1

Installing Jenkins
wget -q -O - https://pkg.jenkins.io/debian-stable/jenkins.io.key | sudo apt-key add -

sudo sh -c 'echo deb http://pkg.jenkins.io/debian-stable binary/ > /etc/apt/sources.list.d/jenkins.list'

sudo apt install jenkins

htttp://localhost:8080
sudo cat /var/lib/jenkins/secrets/initialAdminPassword

References:
https://www.digitalocean.com/community/tutorials/how-to-install-jenkins-on-ubuntu-20-04

Install Docker
https://docs.docker.com/engine/install/ubuntu/

https://www.digitalocean.com/community/tutorials/how-to-set-up-continuous-integration-pipelines-in-jenkins-on-ubuntu-16-04