Deployer votre site Hugo sur AWS avec Terraform v2
Dans mon article précédent, nous avons vu comment mettre en place un site web statique avec Hugo sur AWS via Terraform notamment celui qui héberge ce site.
Cela fait maintenant un peu plus d’un an (voire deux) que ce site est déployé de cette façon et j’ai eu l’occasion d’améliorer/changer plusieurs choses.
Dans cet article nous verrons les nouveautés apportées sur ce site notamment:
- L’usage de OAC a la place de l’OAI
- L’upgrade du provider Terraform AWS en v5
- L’ajout de GitHub Action (pour déployer le site automatiquement) et de l’injection des credentials AWS de façon dynamique
- L’amélioration de la stack Terraform avec l’autoconfiguration d’ACM (AWS Certificate Manager) avec AWS Route53
TL;TR: Pour ceux qui souhaitent déployer leurs infrastructures sur AWS avec la nouvelle version, voici le repository GitHub
Prérequis
Pour comprendre ce post, vous devez:
- Avoir des notions sur AWS
- Connaître Terraform et notamment déployer sur AWS via Terraform
- Avoir vu l’article précédent pour comprendre le contexte
Pour reproduire l’exemple de ce blog, vous devez :
- Avoir un compte AWS et des credentials
- Avoir un nom de domaine
- Deployer l’infrastructure sur AWS via Terraform
Rappel de l’infrastructure
Dans l’article précédent nous avons déployé l’infrastructure suivante:
Nous avons:
- Amazon Route 53: Qui héberge notre Hosted Zone et notre domaine (
mehdilaruelle.com
) - Amazon CloudFront: Qui fait office de CDN (Content Delivry Network) et point d’entré pour nos end users
- AWS Certificate Manager: Qui va héberger notre certificat et être utilisé par Amazon CloudFront pour le
HTTPS
- Un bucket S3: Qui hébergera notre site web statique déployé par Hugo et uniquement accessible par Amazon CloudFront. Notre bucket est donc
privé
L’ensemble de l’infrastructure est déployé par Terraform.
Remplacement de l’OAI par l’OAC
Dans l’architecture que nous avons vue, le bucket S3 est privé et est uniquement accessible par Amazon CloudFront. Anciennement, la méthode utilisé était l’Origin Access Identity (OAI) qui est aujourd’hui déprécié. En guise de remplacement, AWS a mit en placce l’Origin Access Control (OAC).
Contrairement a l’OAI qui était vue comme un principal IAM CloudFront, ici l’OAC est vue comme une ressource AWS CloudFront. Les avantages de l’OAC par rapport à l’OAI sont le support de:
- Tous les bucket S3 dans toutes les régions.
- Chiffrement server-side encryption avec AWS KMS (SSE-KMS)
- Requêtes dynamiques (PUT et DELETE) vers Amazon S3
Cette migration est plutôt simple car il suffit de:
- Créer un OAC
- Mettre la bucket policy
- Mettre à jour Amazon CloudFront en remplaçant l’OAI par l’OAC
Vous retrouverez le commit GitHub concernant cette migration ou encore la docummentation officiel d’AWS sur le sujet.
Upgrade du Terraform provider AWS v5
Ce n’est pas tous les jours que le provider AWS
de Terraform reçoit une mise à jour majeur et c’est donc tout naturellement que l’upgrade s’imposait.
Pour les plus curieux qui souhaite en savoir plus sur les nouveautés du provider, je vous invite a regarder le Upgrade Guide d’HashiCorp
Aucun impact au niveau du code Terraform mais je préfère explicitement l’indiquer au niveau du code Terraform:
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~>5.0"
}
}
}
Pour ceux qui ne connaisse pas, vous avez tfupdate utilisable via le pre-commit-terraform pour rester à jour sur vos dépendances.
Github action et credentials dynamique AWS
Jusqu’à peu, les déploiements de mes blog posts ou mise à jour des thèmes se faisait localement depuis mon terminal car ma fréquence de déploiement de mes blog posts était assez faible. Cependant, je faisais face à 2 problématiques:
- A chaque déploiement, je pouvais avoir des problèmes de résidus de cache ou encore d’autres anomalies liées a mon environnement
- Des credentials AWS statique qui étaient utilisés une fois tous les 3 mois au mieux. Plutôt dommage pour des credentials statique
Pour répondre à ces problématiques, j’ai:
- Mis en place GitHub Action (gratuit jusqu’à 2000 minutes par mois) pour automatiser le déploiement de mon site a chaque
git push
- Mise en place de credential AWS temporaire a chaque déploiement dans GitHub action
Mise en place de GitHub Action
Mon objectif est: “A chaque push
sur ma branche master
, je veux que mon site Hugo
soit déployé sur S3
”.
Bonne nouvelle, sur GitHub Action c’est possible de le faire (et gratuitement) assez facilement car il existe des Actions.
Dans un premier temps, j’ai utilisé l’Action Hugo de peaceiris pour l’usage de Hugo dans Github Action.
Voilà le contenu de mon fichier .github/workflows/main.yml
de GitHub action:
name: Hugo deploy website on S3
on:
push:
branches: [ main ] # Only when a push is done on main branch
permissions:
contents: read # This is required for actions/checkout
jobs:
Build_and_Deploy:
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Git clone the repository
uses: actions/checkout@v4
with:
submodules: 'true' # Some Hugo theme are imported as a submodule, so you need it
# Sets up Hugo with latest version
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true
- name: Build
run: hugo --minify
- name: Deploy to S3
run: hugo deploy --force
Si nous résumons les étapes de notre job, nous avons:
- Checkout: Permet de cloner notre repository avec les submodules nécessaires pour les Hugo thèmes
- Setup Hugo: Installation de Hugo en édition extended. car certains de mes thèmes utilisent des fonctionnalités de cette éditio
- Build: On construit notre site web statique en version minify
- Deploy: Enfin, on déploie notre site web Hugo sur S3
Pour que Hugo sache comment déployer, au niveau de l’étape 4, il faudra ajouter la bonne configuration au niveau du config.toml
.
Dans mon cas, le bout de configuration ressemble à ça:
[deployment]
[[deployment.targets]]
name = "aws"
URL = "s3://hugo-website-mlaruelle?region=eu-west-3"
Remarque
L’URL doit contenir la region. La région dans mon cas est eu-west-3
(paris).
A ce stade, presque tout est fonctionnel. En effet, il nous manque les droits pour déployer sur le bucket S3.
Mise en place des credentials AWS temporaire
Jusqu’à présent, j’utilisais un IAM user avec des credentials statiques. Sachant que maintenant les déploiements se font via GitHub action, je me suis dit qu’il était temps de passer à des credentials temporaires afin d’avoir “des credentials à usage unique à chaque déploiement”.
Pour ce faire, j’ai utilisé un AWS Assume Role With Web Identity avec GitHub Action.
je vous invite à en apprendre plus sur l’ensemble du process et de la configuration via la documentation officielle de GitHub Action. Dans notre cas, nous allons résumer la migration vers cette méthode en 2 étapes:
- La mise en place de la Web Identity
- La mise en place du GitHub Action
configure-aws-credentials-for-github-actions
Etape 1: Mise en place de la Web Identity
Cette première étape consiste à mettre en place un Identity Provider
(de type OIDC) au niveau du service IAM
et établir un lien de trust de IAM Identity Provider vers GitHub Action sur lequel GitHub Action pourra assumer notre rôle.
En version simplifié, cela représente ça:
Pour ce faire, j’ai mis en place un Terraform pour mettre en place la Web Identity que j’invite les plus curieux a regarder.
Dans le repository Terraform, pour activer le déploiement de la Web Identity pour votre repository GibHub,
vous devez fournir les valeurs aux variables github_org
(le nom de l’organisation GitHub) et github_repositories
(Une liste de repositories GitHub autorisé à assusmer la Web Identity role).
Dans mon cas, cela donne ça:
github_org = "mehdilaruelle" # GitHub Organization name
github_repositories = ["blog_hugo"] # The list of GitHub repositories to allow to assume the Web Identity role
Puis faites un terraform apply
et récupérez l’output de aws_role_arn
via un terraform output aws_role_arn
.
Gardez l’output, nous en aurons besoin pour la configuration de notre GitHub Action.
Etape 2: Mise en place du GitHub Action configure-aws-credentials-for-github-actions
Enfin, l’étape 2 consiste à ce que GitHub Action puisse assumer notre rôle. Toujours en version simplifiée, cela représente ça:
Nous allons compléter notre GitHub Action Workflow avec l’action configure-aws-credentials-for-github-actions. Pour ce faire, il faudra:
- Ajouter la permission à notre workflow d’utiliser un JSON Web Token GitHub.
- Ajouter la step avec notre GitHub Action configure-aws-credentials-for-github-actions tout en mettant notre
aws_role_arn
en paramètre de la step.
Ce qui nous donne le rendu final et fonctionnel suivant:
name: Hugo deploy website on S3
on:
push:
branches: [ main ]
permissions:
id-token: write # This is required for requesting the JWT
contents: read # This is required for actions/checkout
jobs:
Build_and_Deploy:
runs-on: ubuntu-latest
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- name: Git clone the repository
uses: actions/checkout@v4
with:
submodules: 'true'
- name: configure aws credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::012345678912:role/GitHubOIDCRole # To replace with aws_role_arn
role-session-name: githubActionHugoDeploy
aws-region: eu-west-3
# Sets up Hugo with latest version
- name: Setup Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true
- name: Build
run: hugo --minify
- name: Deploy to S3
run: hugo deploy --force
Avec le résultat suivant, à la suite d’un git push
, via GitHub Action:
Auto setup d’ACM (AWS Certificate Manager)
Dans la construction du site web, nous partons du principe dans l’article précédent que le nom de domaine (ou sous domaine) est hébergé sur Amazon Route 53 et que la Hosted Zone doit être créée manuellement.
Jusqu’à récemment, la création du certificat dans AWS Certificate Manger (ACM) devait aussi être manuelle. Chose révolue à la suite de ce commit qui peut se résumer au travers du snippet suivant:
resource "aws_acm_certificate" "hugo" {
provider = aws.aws_cloudfront # CloudFront uses certificates from US-EAST-1 region only
domain_name = local.dns_name
validation_method = "DNS"
}
resource "aws_route53_record" "hugo" {
for_each = {
for dvo in aws_acm_certificate.hugo.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
allow_overwrite = true
name = each.value.name
records = [each.value.record]
ttl = 60
type = each.value.type
zone_id = data.aws_route53_zone.hugo.zone_id
}
resource "aws_acm_certificate_validation" "hugo" {
provider = aws.aws_cloudfront # CloudFront uses certificates from US-EAST-1 region only
certificate_arn = aws_acm_certificate.hugo.arn
validation_record_fqdns = [for record in aws_route53_record.hugo : record.fqdn]
}
Information
Vous pouvez retrouver ce snippet directement dans la documentation officielle d’HashiCorp.
Nouveau domain name
Enfin, dernière nouveauté concernant le site: le changement de nom de domaine de blog.mehdilaruelle.ninja
en mehdilaruelle.com
lié notamment a l’augmentation du prix des noms de domaine global et surtout celui du .ninja
.
Ce changement ma posé plusieurs défis, notamment:
- Le changement de configuration de Hugo dans le
config.toml
(plutôt facile) - Le certificat (plutôt facile avec l’automatisation via Terraform)
- La redirection de
blog.mehdilaruelle.ninja
versmehdilaruelle.com
sachant que l’hébergement du nom de domaine est situé côté OVH
Le dernier défi ma notamment poussé à mettre en place un mécanisme de redirection avec préservation du path (chose inexistante gratuitement côté OVH) en serverless via Amazon API Gateway mais cela fera l’objet d’un autre article.
Conclusion
Les différentes améliorations du site web m’ont apporté une expérience de release beaucoup plus fluide et transparente, notament via l’intégration de GitHub Action et des credentials dynamiques AWS. D’autre part, pour les mises à jour Terraform, vous pouvez passer par tfupdate au travers du pre-commit-terraform pour rester le plus à jour sur vos dépendances.
Information
Dans le repository Terraform pour déployer ce site, le pre-commit-terraform est utilisé.
Enfin, dans un prochain blog post, nous aurons l’occasion de parler plus en détail du mécanisme de redirection avec préservation du path en serverless via Amazon API Gateway. Si vous avez d’autres idées d’améliorations, n’hésitez pas à m’écrire.
HashiCorp Hugo Terraform AWS Serverless Static Github Actions Website Blog S3 Cloudfront HTTPS SSL TLS Certificate OIDC
1873 Mots
2023-10-31 16:30