Merge pull request #159 from ineszang/fix/prod-sous-domaine
fix(deploy): la prod passe sur prod.enervision-g3.dynv6.net
This commit is contained in:
@@ -28,7 +28,7 @@ jobs:
|
|||||||
timeout-minutes: 30
|
timeout-minutes: 30
|
||||||
environment:
|
environment:
|
||||||
name: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'dev' && 'rec' || 'dev' }}
|
name: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'dev' && 'rec' || 'dev' }}
|
||||||
url: ${{ github.ref_name == 'main' && 'https://enervision-g3.dynv6.net' || github.ref_name == 'dev' && 'https://rec.enervision-g3.dynv6.net' || 'https://dev.enervision-g3.dynv6.net' }}
|
url: ${{ github.ref_name == 'main' && 'https://prod.enervision-g3.dynv6.net' || github.ref_name == 'dev' && 'https://rec.enervision-g3.dynv6.net' || 'https://dev.enervision-g3.dynv6.net' }}
|
||||||
env:
|
env:
|
||||||
ENVIRONNEMENT: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'dev' && 'rec' || 'dev' }}
|
ENVIRONNEMENT: ${{ github.ref_name == 'main' && 'prod' || github.ref_name == 'dev' && 'rec' || 'dev' }}
|
||||||
PORT_HTTPS: ${{ github.ref_name == 'main' && '10443' || github.ref_name == 'dev' && '8443' || '9443' }}
|
PORT_HTTPS: ${{ github.ref_name == 'main' && '10443' || github.ref_name == 'dev' && '8443' || '9443' }}
|
||||||
|
|||||||
@@ -244,14 +244,14 @@ DNS01_JETON_FICHIER ?= $(abspath $(CURDIR)/../dns.token)
|
|||||||
acme-sh = docker run --rm --user "$$(id -u):$$(id -g)" -e $(DNS01_JETON_VAR) -e AUTO_UPGRADE=0 \
|
acme-sh = docker run --rm --user "$$(id -u):$$(id -g)" -e $(DNS01_JETON_VAR) -e AUTO_UPGRADE=0 \
|
||||||
-v "$(CURDIR)/infra/proxy/acme:/acme.sh" -v "$(CURDIR)/infra/proxy/tls:/tls" $(ACME_SH)
|
-v "$(CURDIR)/infra/proxy/acme:/acme.sh" -v "$(CURDIR)/infra/proxy/tls:/tls" $(ACME_SH)
|
||||||
|
|
||||||
# acme.sh sort en 2 quand le certificat n'est pas encore à renouveler, et recopie le jeton dans
|
# acme.sh sort en 2 quand le certificat n'est pas à renouveler, et recopie le jeton dans
|
||||||
# acme/account.conf : d'où le chmod, qui le soustrait aux autres comptes de la machine.
|
# acme/account.conf, d'où le chmod. `--dnssleep` : Let's Encrypt valide depuis plusieurs réseaux.
|
||||||
tls-dns01: ## Certificat Let's Encrypt par DNS-01, renouvelé seulement à échéance. Jeton : ../dns.token
|
tls-dns01: ## Certificat Let's Encrypt par DNS-01, renouvelé seulement à échéance. Jeton : ../dns.token
|
||||||
@case "$(PUBLIC_HOST)" in *.local | localhost) echo "PUBLIC_HOST=$(PUBLIC_HOST) n'est pas un nom public"; exit 1 ;; esac
|
@case "$(PUBLIC_HOST)" in *.local | localhost) echo "PUBLIC_HOST=$(PUBLIC_HOST) n'est pas un nom public"; exit 1 ;; esac
|
||||||
@test -r "$(DNS01_JETON_FICHIER)" || { echo "Jeton DNS illisible : $(DNS01_JETON_FICHIER)"; exit 1; }
|
@test -r "$(DNS01_JETON_FICHIER)" || { echo "Jeton DNS illisible : $(DNS01_JETON_FICHIER)"; exit 1; }
|
||||||
@mkdir -p infra/proxy/acme && chmod 700 infra/proxy/acme
|
@mkdir -p infra/proxy/acme && chmod 700 infra/proxy/acme
|
||||||
@$(DNS01_JETON_VAR)="$$(tr -d '[:space:]' < "$(DNS01_JETON_FICHIER)")"; export $(DNS01_JETON_VAR); \
|
@$(DNS01_JETON_VAR)="$$(tr -d '[:space:]' < "$(DNS01_JETON_FICHIER)")"; export $(DNS01_JETON_VAR); \
|
||||||
$(acme-sh) --issue --server letsencrypt --dns $(DNS01_API) -d "$(PUBLIC_HOST)"; \
|
$(acme-sh) --issue --server letsencrypt --dns $(DNS01_API) --dnssleep 90 -d "$(PUBLIC_HOST)"; \
|
||||||
code=$$?; chmod -R go-rwx infra/proxy/acme; [ $$code -eq 0 ] || [ $$code -eq 2 ] || exit $$code
|
code=$$?; chmod -R go-rwx infra/proxy/acme; [ $$code -eq 0 ] || [ $$code -eq 2 ] || exit $$code
|
||||||
@$(acme-sh) --install-cert --ecc -d "$(PUBLIC_HOST)" \
|
@$(acme-sh) --install-cert --ecc -d "$(PUBLIC_HOST)" \
|
||||||
--fullchain-file /tls/fullchain.pem --key-file /tls/privkey.pem
|
--fullchain-file /tls/fullchain.pem --key-file /tls/privkey.pem
|
||||||
|
|||||||
@@ -20,16 +20,19 @@ et API, depuis les postes comme depuis la VM.
|
|||||||
|
|
||||||
## Décision
|
## Décision
|
||||||
|
|
||||||
**Des noms publics qui visent l'IP privée.** `enervision-g3.dynv6.net`, zone gratuite de dynv6,
|
**Des noms publics qui visent l'IP privée.** Dans `enervision-g3.dynv6.net`, zone gratuite de
|
||||||
porte la prod, et deux enregistrements A portent `rec.` et `dev.`. `provision-host.sh` les publie
|
dynv6, trois enregistrements A portent `prod.`, `rec.` et `dev.`. `provision-host.sh` les publie
|
||||||
par l'API dynv6 : le DNS est décrit par le code comme le reste. Tout
|
par l'API dynv6 : le DNS est décrit par le code comme le reste. La prod n'est pas à la racine de
|
||||||
|
la zone : dynv6 y sert mal un TXT `_acme-challenge`, que l'API ne liste ni ne supprime et qu'un
|
||||||
|
seul de ses trois serveurs renvoie (constaté le 23/09), si bien que son défi DNS-01 échoue. Tout
|
||||||
poste du réseau de l'école les résout sans configuration ; hors de ce réseau, l'IP ne mène
|
poste du réseau de l'école les résout sans configuration ; hors de ce réseau, l'IP ne mène
|
||||||
nulle part.
|
nulle part.
|
||||||
|
|
||||||
**Des certificats Let's Encrypt par défi DNS-01.** Le défi passe par l'API dynv6, qui pose
|
**Des certificats Let's Encrypt par défi DNS-01.** Le défi passe par l'API dynv6, qui pose
|
||||||
l'enregistrement TXT : Let's Encrypt n'a jamais à joindre la VM. `make tls-dns01` (acme.sh
|
l'enregistrement TXT : Let's Encrypt n'a jamais à joindre la VM. `make tls-dns01` (acme.sh
|
||||||
épinglé) le joue dans chaque stack ; il ne renouvelle qu'à échéance, d'où son rejeu à chaque
|
épinglé) le joue dans chaque stack ; il ne renouvelle qu'à échéance, d'où son rejeu à chaque
|
||||||
déploiement et chaque nuit par cron. Un certificat par environnement plutôt qu'un joker : chaque
|
déploiement et chaque nuit par cron. `--dnssleep 90` laisse aux trois serveurs de dynv6 le temps
|
||||||
|
de servir le TXT avant que Let's Encrypt ne le cherche depuis plusieurs réseaux. Un certificat par environnement plutôt qu'un joker : chaque
|
||||||
stack garde le sien, et la clé de la prod n'est pas lisible depuis le clone de dev.
|
stack garde le sien, et la clé de la prod n'est pas lisible depuis le clone de dev.
|
||||||
|
|
||||||
**Un frontal SNI sur 443, le seul composant exposé.** `infra/front`, un nginx sur le réseau de
|
**Un frontal SNI sur 443, le seul composant exposé.** `infra/front`, un nginx sur le réseau de
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ les secrets et les certificats, et ne démarre rien.
|
|||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Branche, environnement GitHub | toute branche lancée à la main, `dev` | `dev`, `rec` | `main`, `prod` |
|
| Branche, environnement GitHub | toute branche lancée à la main, `dev` | `dev`, `rec` | `main`, `prod` |
|
||||||
| Dossier, projet Compose | `/srv/enervision/dev`, `enervision-dev` | `/srv/enervision/rec`, `enervision-rec` | `/srv/enervision/prod`, `enervision-prod` |
|
| Dossier, projet Compose | `/srv/enervision/dev`, `enervision-dev` | `/srv/enervision/rec`, `enervision-rec` | `/srv/enervision/prod`, `enervision-prod` |
|
||||||
| URL | `https://dev.enervision-g3.dynv6.net` | `https://rec.enervision-g3.dynv6.net` | `https://enervision-g3.dynv6.net` |
|
| URL | `https://dev.enervision-g3.dynv6.net` | `https://rec.enervision-g3.dynv6.net` | `https://prod.enervision-g3.dynv6.net` |
|
||||||
| Proxy HTTP, HTTPS, PROXY protocol, sur `127.0.0.1` | `8083`, `9443`, `9444` | `8081`, `8443`, `8444` | `10080`, `10443`, `10444` |
|
| Proxy HTTP, HTTPS, PROXY protocol, sur `127.0.0.1` | `8083`, `9443`, `9444` | `8081`, `8443`, `8444` | `10080`, `10443`, `10444` |
|
||||||
| PostgreSQL, Mailpit, Airflow, sur `127.0.0.1` | `5435`, `8027`, `8084` | `5434`, `8026`, `8082` | `5433`, `8025`, `8080` |
|
| PostgreSQL, Mailpit, Airflow, sur `127.0.0.1` | `5435`, `8027`, `8084` | `5434`, `8026`, `8082` | `5433`, `8025`, `8080` |
|
||||||
| Supervision (profil `monitoring`) | à la demande, `make monitoring-up` | à la demande, `make monitoring-up` | active, `COMPOSE_PROFILES=monitoring` |
|
| Supervision (profil `monitoring`) | à la demande, `make monitoring-up` | à la demande, `make monitoring-up` | active, `COMPOSE_PROFILES=monitoring` |
|
||||||
|
|||||||
+1
-1
@@ -40,7 +40,7 @@ sur `dev` et sur `main`, et a chaque lancement manuel d'une autre branche pour `
|
|||||||
|
|
||||||
Noms et certificats (ADR 0018) : avant l'apply, la zone `domaine` doit exister chez dynv6 et son
|
Noms et certificats (ADR 0018) : avant l'apply, la zone `domaine` doit exister chez dynv6 et son
|
||||||
jeton se trouver dans `<racine>/dns.token` (600, proprietaire). L'apply fait alors pointer la
|
jeton se trouver dans `<racine>/dns.token` (600, proprietaire). L'apply fait alors pointer la
|
||||||
zone, `rec` et `dev` vers la machine, obtient un certificat Let's Encrypt par environnement et planifie leur
|
zone, `prod`, `rec` et `dev` vers la machine, obtient un certificat Let's Encrypt par environnement et planifie leur
|
||||||
renouvellement ; sans jeton, chaque environnement garde un certificat auto-signe. Le frontal SNI (`infra/front`)
|
renouvellement ; sans jeton, chaque environnement garde un certificat auto-signe. Le frontal SNI (`infra/front`)
|
||||||
se demarre une fois depuis le dossier de la prod, `make front-up`.
|
se demarre une fois depuis le dossier de la prod, `make front-up`.
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ variable "depot_url" {
|
|||||||
|
|
||||||
variable "domaine" {
|
variable "domaine" {
|
||||||
type = string
|
type = string
|
||||||
description = "Zone dynv6 de la prod, rec. et dev. en sous-domaines (ADR 0018). Son jeton doit se trouver dans <racine>/dns.token sur la machine : provision-host.sh y fait pointer la zone et ses deux sous-domaines vers la machine."
|
description = "Zone dynv6 des trois environnements, prod., rec. et dev. en sous-domaines (ADR 0018). Son jeton doit se trouver dans <racine>/dns.token sur la machine : provision-host.sh y fait pointer la zone et ses trois sous-domaines vers la machine."
|
||||||
default = "enervision-g3.dynv6.net"
|
default = "enervision-g3.dynv6.net"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,7 +141,7 @@ preparer() {
|
|||||||
# jeton passe par l'environnement du seul processus Python, jamais par `argv`.
|
# jeton passe par l'environnement du seul processus Python, jamais par `argv`.
|
||||||
publier_dns() {
|
publier_dns() {
|
||||||
[[ -r "$JETON_DNS" ]] || { echo "pas de jeton $JETON_DNS : ni DNS ni Let's Encrypt"; return 0; }
|
[[ -r "$JETON_DNS" ]] || { echo "pas de jeton $JETON_DNS : ni DNS ni Let's Encrypt"; return 0; }
|
||||||
DNS_TOKEN="$(tr -d '[:space:]' < "$JETON_DNS")" python3 - "$DOMAINE" "$ADRESSE" rec dev <<'PY' \
|
DNS_TOKEN="$(tr -d '[:space:]' < "$JETON_DNS")" python3 - "$DOMAINE" "$ADRESSE" prod rec dev <<'PY' \
|
||||||
|| echo "DNS : dynv6 refuse la mise à jour de $DOMAINE, enregistrements inchangés" >&2
|
|| echo "DNS : dynv6 refuse la mise à jour de $DOMAINE, enregistrements inchangés" >&2
|
||||||
import json, os, sys, time, urllib.request
|
import json, os, sys, time, urllib.request
|
||||||
|
|
||||||
@@ -198,10 +198,10 @@ verifier_outils
|
|||||||
mkdir -p "$RACINE"
|
mkdir -p "$RACINE"
|
||||||
publier_dns
|
publier_dns
|
||||||
|
|
||||||
# Supervision active en prod seulement (ADR 0016). Le frontal (infra/front) publie 80 et 443 et
|
# Supervision active en prod seulement (ADR 0016). La prod vit sur `prod.` et non à la racine :
|
||||||
# relaie vers les ports `front` ; les stacks ne publient plus rien hors de la boucle locale.
|
# dynv6 ne sert pas de façon fiable un TXT `_acme-challenge` à la racine de la zone (ADR 0018).
|
||||||
# env branche hôte https http front pg mailpit airflow profils grafana prometheus alertmanager
|
# env branche hôte https http front pg mailpit airflow profils grafana prometheus alertmanager
|
||||||
preparer prod main "$DOMAINE" 127.0.0.1:10443 127.0.0.1:10080 127.0.0.1:10444 5433 8025 8080 monitoring 3001 9090 9093
|
preparer prod main "prod.$DOMAINE" 127.0.0.1:10443 127.0.0.1:10080 127.0.0.1:10444 5433 8025 8080 monitoring 3001 9090 9093
|
||||||
preparer rec dev "rec.$DOMAINE" 127.0.0.1:8443 127.0.0.1:8081 127.0.0.1:8444 5434 8026 8082 "" 3002 9091 9094
|
preparer rec dev "rec.$DOMAINE" 127.0.0.1:8443 127.0.0.1:8081 127.0.0.1:8444 5434 8026 8082 "" 3002 9091 9094
|
||||||
preparer dev dev "dev.$DOMAINE" 127.0.0.1:9443 127.0.0.1:8083 127.0.0.1:9444 5435 8027 8084 "" 3003 9092 9095
|
preparer dev dev "dev.$DOMAINE" 127.0.0.1:9443 127.0.0.1:8083 127.0.0.1:9444 5435 8027 8084 "" 3003 9092 9095
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user