% Reverse Proxy

# Introduction

Voir [Infrastructure du réseau sur serveur Kimsufi OVH](../proxmox/infrastructure-ovh.md)

POUR GÉRER CORRECTEMENT LES CHAMPS DNS: [Gestion du DNS OVH](dns-ovh.md)

# Installation letsencrypt

cf [Certbot Instructions | Certbot](https://certbot.eff.org/instructions?ws=nginx&os=pip)

## Dépendances

```bash
sudo apt update && sudo apt install python3 python3-venv libaugeas0
```

## Installation de `certbot`

```bash
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install certbot certbot-nginx
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
```

# Installation des sous-domaines

## Domaines à installer

On prépare une liste des services et de leur sous-domaine associé. Par exemple, voir cette page: [Services](../../../organisation-technique/services.html)

## Configuration de `nginx`

### Chargement dans les sous-dossiers

Édition de `/etc/nginx/nginx.conf`

Remplacer la ligne:

```conf
include /etc/nginx/sites-enabled/*;
```

Par:

```conf
include /etc/nginx/sites-enabled/*/*;
```



## Script

Je crée un script d'installation qui génère automatiquement chaque fichier de configuration `nginx` pour les sous-domaines listés dans un fichier (ici par exemple: `subdomains.txt`) :

```bash
$ cat ~/subdomains.txt 
nu.aezi.fr        
cloud.aezi.fr     
git.aezi.fr       
wallabag.aezi.fr  
appflowy.aezi.fr  
rustdesk.aezi.fr  
sync.aezi.fr      
pihole.aezi.fr    
hedgedoc.aezi.fr  
dessin.aezi.fr
```

### Script  `install-subdomains`

**IMPORTANT**: script inspiré de ce gist: [How to use nginx as a reverse-proxy with letsencrypt · GitHub](https://gist.github.com/gmolveau/5e5b0bd2773100d85d9302d0fa96632d)

**ATTENTION**: si le script ne fonctionne pas, voir la variante en dessous.


```bash
#!/bin/bash

set -euo pipefail

if [ $EUID != 0 ]
then
	echo "You must be root" >&2
	exit 1
fi


available_sites_dir=/etc/nginx/sites-available

subdomains_list="${1:-}"
if [ -z "${subdomains_list:-}" ]
then
	echo "Please give me a subdomain list"
	exit 2
fi
shift


create_subdomain(){
	local base_directory=$2
	local subdomain_name=$1
	local target_ip=$3
	local main_domain=$4
	if [ ! -f "$base_directory/$subdomain_name" ]
	then
		echo "Creating '$base_directory/$subdomain_name'"
		cat > $base_directory/$subdomain_name <<EOF
server {
    server_name $subdomain_name;

    listen 80;
    listen [::]:80;

    location / {
        proxy_pass  https://$target_ip:443;
        proxy_redirect                      off;
        proxy_set_header  Host              \$http_host;
        proxy_set_header  X-Real-IP         \$remote_addr;
        proxy_set_header  X-Forwarded-For   \$proxy_add_x_forwarded_for;
        proxy_set_header  X-Forwarded-Proto \$scheme;
        proxy_read_timeout                  900;
    }
}
EOF
	fi
}

while read subdomain
do
	subdomain=$(echo $subdomain | xargs)

	if [ -n "$subdomain" ]
	then
		echo "subdomain='$subdomain'"
		domain_name=${subdomain#*.}
		domain_dir=${available_sites_dir}/${domain_name}
		if [ ! -d ${domain_dir} ]
		then
			echo "Creating dir '${domain_dir}'"
			mkdir -p ${domain_dir}
		fi
		create_subdomain $subdomain ${domain_dir} 10.1.0.14 nu.aezi.fr
	fi
done < ${subdomains_list}
```


#### Variante

Ajouter le code suivant dans la section `server` sous la section `listen 80;    listen [::]:80;` :

```bash
    # HTTP to HTTPS
    if ($scheme != "https") {
        return 301 https://$host$request_uri;
    } # managed by Certbot
```

## Activation des fichiers de configuration

Après avoir généré les fichiers avec le le script précédent (et fait les modifications indiquées dans `nginx.conf` au paragraphe précédent), on active les configurations des sites:

```bash
cd /etc/nginx/sites-enabled/aezi.fr
ls ../../sites-available/aezi.fr/ | xargs -i{} sudo ln -s ../../sites-available/aezi.fr/{}
```

## Installation du certificat

L'installation du certificat se fait en lançant :

```bash
sudo certbot --nginx
```

Puis en sélectionnant la liste des certificats en sélectionnant le premier comme principal (ici : `nu.aezi.fr`).

(en cas de mauvaise manipulation voir [Dépannage](#depannage))

Donc on saisit `5` pour mettre nu.aezi.fr en premier puis les autres numéros:

```
5 1 2 3 4 6 7 8 9
```

Ce qui donne:

```bash
$ sudo certbot --nginx
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Which names would you like to activate HTTPS for?
We recommend selecting either all domains, or all domains in a VirtualHost/server block.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: appflowy.aezi.fr
2: dessin.aezi.fr
3: git.aezi.fr
4: hedgedoc.aezi.fr
5: nu.aezi.fr
6: pihole.aezi.fr
7: rustdesk.aezi.fr
8: sync.aezi.fr
9: wallabag.aezi.fr
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 
```

Une fois que c'est prêt, normalement tout devrait fonctionner

# Synchronisation des certificats

Pour permettre à OnlyOffice de fonctionner avec Nextcloud, on doit avoir des certificats.

Je choisis d'utiliser les mêmes entre mes VM. Pour ça => synchronisation

## Sur le reverse proxy

```
sudo adduser --shell /usr/sbin/nologin copycert
sudo setfacl -R -m u:copycert:rX /etc/letsencrypt/live/
sudo setfacl -d -R -m u:copycert:rX /etc/letsencrypt/live/
sudo setfacl -R -m u:copycert:rX /etc/letsencrypt/archive/
sudo setfacl -d -R -m u:copycert:rX /etc/letsencrypt/archive/
sudo apt install rsync
```

# Dépannage{#depannage}

## Modifier le domaine principal

Il faut le mettre en premier et utiliser `--force-renewal`:

```bash
./certbot --apache -d domaine-principal.fr -d www.domaine-principal.fr -d mysql.domaine-principal.fr --force-renewal
```

Voir: [cette réponse à "Change base domain name for Lets Encrypt SSL certificate"](https://stackoverflow.com/a/38268048/1011366)

## Notes supplémentaires

* [reverse proxy - Nginx http to http redirect 400 The plain HTTP request was sent to HTTPS port - Server Fault](https://serverfault.com/questions/1115189/nginx-http-to-http-redirect-400-the-plain-http-request-was-sent-to-https-port)
* [NGINX Error: The plain HTTP request was sent to HTTPS port - Sling Academy](https://www.slingacademy.com/article/nginx-error-the-plain-http-request-was-sent-to-https-port/)
* [Dealing with nginx 400 "The plain HTTP request was sent to HTTPS port" error - Stack Overflow](https://stackoverflow.com/questions/8768946/dealing-with-nginx-400-the-plain-http-request-was-sent-to-https-port-error)
* [ssl - Update certificate with certbot to add subdomain - Stack Overflow](https://stackoverflow.com/questions/55778765/update-certificate-with-certbot-to-add-subdomain)

