Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
6d54cbef61
|
|||
|
3062cba541
|
|||
|
f0810eb8e5
|
@@ -1,9 +1,9 @@
|
|||||||
# Package versions
|
# Package versions
|
||||||
ARG HUGO_VERSION="latest"
|
ARG HUGO_VERSION="0.152.2"
|
||||||
ARG CADDY_VERSION="2.10.0"
|
ARG CADDY_VERSION="2.10.2"
|
||||||
|
|
||||||
# Stage 1: Build
|
# Stage 1: Build
|
||||||
FROM git.brds.ca/d-b.ca/hugo-builder:${HUGO_VERSION} AS builder
|
FROM core.harbor.brds.ca/d-b.ca/hugo-builder:${HUGO_VERSION} AS builder
|
||||||
WORKDIR /project
|
WORKDIR /project
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN hugo --minify build
|
RUN hugo --minify build
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
disabled = false
|
|
||||||
languageCode = "fr"
|
|
||||||
languageName = "Français"
|
|
||||||
weight = 2
|
|
||||||
title = "Drew Bowering"
|
|
||||||
|
|
||||||
[params]
|
|
||||||
displayName = "FR"
|
|
||||||
isoCode = "fr"
|
|
||||||
rtl = false
|
|
||||||
dateFormat = "2 January 2006"
|
|
||||||
logo = "img/d-bca_logo_light.png"
|
|
||||||
secondaryLogo = "img/d-bca_logo_dark.png"
|
|
||||||
description = "Drew Bowering's personal website"
|
|
||||||
# copyright = "Copy, _right?_ :thinking_face:"
|
|
||||||
|
|
||||||
[params.author]
|
|
||||||
name = "Drew Bowering"
|
|
||||||
# email = "drew@d-b.ca"
|
|
||||||
image = "img/DrewBowering.jpg"
|
|
||||||
# imageQuality = 96
|
|
||||||
headline = "Architecte informatique, Développeur, Canoeiste, Tubiste"
|
|
||||||
# bio = "A little bit about me"
|
|
||||||
links = [
|
|
||||||
{ email = "mailto:drew@d-b.ca" },
|
|
||||||
# { link = "https://link-to-some-website.com/" },
|
|
||||||
# { amazon = "https://www.amazon.com/hz/wishlist/ls/wishlist-id" },
|
|
||||||
# { apple = "https://www.apple.com" },
|
|
||||||
# { blogger = "https://username.blogspot.com/" },
|
|
||||||
# { bluesky = "https://bsky.app/profile/username" },
|
|
||||||
# { codepen = "https://codepen.io/username" },
|
|
||||||
# { dev = "https://dev.to/username" },
|
|
||||||
# { discord = "https://discord.gg/invitecode" },
|
|
||||||
# { dribbble = "https://dribbble.com/username" },
|
|
||||||
{ facebook = "https://www.facebook.com/drew.bowering" },
|
|
||||||
# { flickr = "https://www.flickr.com/photos/username/" },
|
|
||||||
# { foursquare = "https://foursquare.com/username" },
|
|
||||||
{ github = "https://github.com/drewbowering" },
|
|
||||||
# { gitlab = "https://gitlab.com/username" },
|
|
||||||
# { google = "https://www.google.com/" },
|
|
||||||
# { hashnode = "https://username.hashnode.dev" },
|
|
||||||
# { instagram = "https://instagram.com/username" },
|
|
||||||
# { itch-io = "https://username.itch.io" },
|
|
||||||
# { keybase = "https://keybase.io/username" },
|
|
||||||
# { kickstarter = "https://www.kickstarter.com/profile/username" },
|
|
||||||
# { lastfm = "https://lastfm.com/user/username" },
|
|
||||||
{ linkedin = "https://www.linkedin.com/in/drew-bowering/" },
|
|
||||||
# { mastodon = "https://mastodon.instance/@username" },
|
|
||||||
# { medium = "https://medium.com/username" },
|
|
||||||
# { microsoft = "https://www.microsoft.com/" },
|
|
||||||
# { orcid = "https://orcid.org/userid" },
|
|
||||||
# { patreon = "https://www.patreon.com/username" },
|
|
||||||
# { pinterest = "https://pinterest.com/username" },
|
|
||||||
# { reddit = "https://reddit.com/user/username" },
|
|
||||||
# { researchgate = "https://www.researchgate.net/profile/username" },
|
|
||||||
# { slack = "https://workspace.url/team/userid" },
|
|
||||||
# { snapchat = "https://snapchat.com/add/username" },
|
|
||||||
# { soundcloud = "https://soundcloud.com/username" },
|
|
||||||
# { spotify = "https://open.spotify.com/user/userid" },
|
|
||||||
# { stack-overflow = "https://stackoverflow.com/users/userid/username" },
|
|
||||||
# { steam = "https://steamcommunity.com/profiles/userid" },
|
|
||||||
# { telegram = "https://t.me/username" },
|
|
||||||
# { threads = "https://www.threads.net/@username" },
|
|
||||||
# { tiktok = "https://tiktok.com/@username" },
|
|
||||||
# { tumblr = "https://username.tumblr.com" },
|
|
||||||
# { twitch = "https://twitch.tv/username" },
|
|
||||||
# { twitter = "https://twitter.com/username" },
|
|
||||||
# { x-twitter = "https://twitter.com/username" },
|
|
||||||
# { whatsapp = "https://wa.me/phone-number" },
|
|
||||||
# { youtube = "https://youtube.com/username" },
|
|
||||||
# { ko-fi = "https://ko-fi.com/username" },
|
|
||||||
# { codeberg = "https://codeberg.org/username"},
|
|
||||||
]
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
# -- Main Menu --
|
|
||||||
# The main menu is displayed in the header at the top of the page.
|
|
||||||
# Acceptable parameters are name, pageRef, page, url, title, weight.
|
|
||||||
#
|
|
||||||
# The simplest menu configuration is to provide:
|
|
||||||
# name = The name to be displayed for this menu link
|
|
||||||
# pageRef = The identifier of the page or section to link to
|
|
||||||
#
|
|
||||||
# By default the menu is ordered alphabetically. This can be
|
|
||||||
# overridden by providing a weight value. The menu will then be
|
|
||||||
# ordered by weight from lowest to highest.
|
|
||||||
|
|
||||||
[[main]]
|
|
||||||
name = "Posts"
|
|
||||||
pageRef = "posts"
|
|
||||||
weight = 10
|
|
||||||
|
|
||||||
#[[main]]
|
|
||||||
# name = "Parent"
|
|
||||||
# weight = 20
|
|
||||||
|
|
||||||
#[[main]]
|
|
||||||
# name = "example sub-menu 1"
|
|
||||||
# parent = "Parent"
|
|
||||||
# pageRef = "posts"
|
|
||||||
# weight = 20
|
|
||||||
|
|
||||||
#[[main]]
|
|
||||||
# name = "example sub-menu 2"
|
|
||||||
# parent = "Parent"
|
|
||||||
# pageRef = "posts"
|
|
||||||
# weight = 20
|
|
||||||
|
|
||||||
#[[subnavigation]]
|
|
||||||
# name = "An interesting topic"
|
|
||||||
# pageRef = "tags/interesting-topic"
|
|
||||||
# weight = 10
|
|
||||||
|
|
||||||
#[[subnavigation]]
|
|
||||||
# name = "My Awesome Category"
|
|
||||||
# pre = "github"
|
|
||||||
# pageRef = "categories/awesome"
|
|
||||||
# weight = 20
|
|
||||||
|
|
||||||
#[[main]]
|
|
||||||
# name = "Categories"
|
|
||||||
# pageRef = "categories"
|
|
||||||
# weight = 20
|
|
||||||
|
|
||||||
#[[main]]
|
|
||||||
# name = "Tags"
|
|
||||||
# pageRef = "tags"
|
|
||||||
# weight = 30
|
|
||||||
|
|
||||||
|
|
||||||
# -- Footer Menu --
|
|
||||||
# The footer menu is displayed at the bottom of the page, just before
|
|
||||||
# the copyright notice. Configure as per the main menu above.
|
|
||||||
|
|
||||||
|
|
||||||
# [[footer]]
|
|
||||||
# name = "Tags"
|
|
||||||
# pageRef = "tags"
|
|
||||||
# weight = 10
|
|
||||||
|
|
||||||
# [[footer]]
|
|
||||||
# name = "Categories"
|
|
||||||
# pageRef = "categories"
|
|
||||||
# weight = 20
|
|
||||||
@@ -1,208 +0,0 @@
|
|||||||
---
|
|
||||||
title: "Nouveau site web"
|
|
||||||
slug: "nouveau-site-web"
|
|
||||||
date: "2025-06-12T08:00:00-06:00"
|
|
||||||
description: "Il y a enfin un nouveau site web sur d-b.ca."
|
|
||||||
summary: "J'ai publié mon site web personnel. Un aperçu de certaines réalisations passées et quelques détails sur la technologie utilisée pour le nouveau site."
|
|
||||||
---
|
|
||||||
|
|
||||||
J'ai enfin publié un site web correct à [https://d-b.ca/](https://d-b.ca/).
|
|
||||||
La dernière fois que j'avais quelque chose en ligne sur ce domaine remontait à
|
|
||||||
plus de 20 ans, selon le [Wayback Machine](https://web.archive.org/). Pourquoi
|
|
||||||
si longtemps? La vérité est que mes intérêts ont évolué au fil des années, et
|
|
||||||
j'ai beaucoup appris. Ce site, bien qu'utile en lui-même, est en réalité le
|
|
||||||
fruit d'une plateforme personnelle que j'ai développée au fil du temps.
|
|
||||||
|
|
||||||
## Histoire
|
|
||||||
|
|
||||||
Mon premier site web personnel a été développé alors que j'étais étudiant à
|
|
||||||
l'[Université de l'Alberta](https://ualberta.ca), à la fin du siècle dernier.
|
|
||||||
Le web était encore à ses débuts, mais l'université permettait aux étudiants
|
|
||||||
de publier du contenu web. À l'époque, c'était surtout une nouveauté qui n'a
|
|
||||||
pas duré au-delà de mon temps à l'école, mais cela a éveillé mon intérêt pour
|
|
||||||
les technologies internet et leurs applications.
|
|
||||||
|
|
||||||
Ce site initial comprenait une fonction intéressante. J'ai développé un
|
|
||||||
mécanisme pour mettre à jour automatiquement une page chaque fois que je me
|
|
||||||
connectais à l'un des ordinateurs de l'école, afin que mes amis puissent me
|
|
||||||
trouver si nécessaire. À l'époque, les mises à jour dynamiques des sites web
|
|
||||||
étaient difficiles. La méthode la plus courante était d'utiliser des
|
|
||||||
[CGI](https://fr.wikipedia.org/wiki/Common_Gateway_Interface), qui consistait
|
|
||||||
à exécuter un petit programme chaque fois qu'une page était demandée.
|
|
||||||
L'université n'autorisait pas les sites étudiants à utiliser cela. J'ai donc
|
|
||||||
rédigé des scripts shell qui étaient appelés lors de mes scripts de connexion
|
|
||||||
et de déconnexion, générant ainsi un fichier HTML statique et le stockant dans
|
|
||||||
mon répertoire de contenu web. Il fallait gérer des cas comme des connexions
|
|
||||||
multiples, et le script de déconnexion ne s'exécutait pas toujours, donc je
|
|
||||||
devais surveiller les entrées obsolètes.
|
|
||||||
|
|
||||||
### Hébergement autonome
|
|
||||||
|
|
||||||
J'ai toujours été un grand fan de l'hébergement autonome. Apprendre en mettant
|
|
||||||
un système en marche fonctionne bien pour moi. J'apprécie aussi la
|
|
||||||
confidentialité et le contrôle qu'il offre. De plus, c'est bien plus
|
|
||||||
économique à long terme!
|
|
||||||
|
|
||||||
Cela a vraiment commencé lorsque je travaillais chez un fournisseur local
|
|
||||||
d'accès à Internet. J'ai obtenu un bon accord sur une connexion large bande à
|
|
||||||
la maison, qui comprenait un petit bloc réseau (`/28`, comprenant 16 adresses
|
|
||||||
IP) que je pouvais utiliser. J'ai dédié mon ordinateur le plus puissant comme
|
|
||||||
serveur et développé plusieurs services, notamment un nouveau site web.
|
|
||||||
|
|
||||||
À l'époque, mon site web n'était pas très élaboré et était principalement
|
|
||||||
orienté vers l'expérimentation. J'ai développé un système de gestion de
|
|
||||||
contenu simple à partir de zéro en PHP, que j'ai utilisé pour publier un blog.
|
|
||||||
Il s'intégrait également aux listes de diffusion, un domaine que j'explorais
|
|
||||||
à l'époque.
|
|
||||||
|
|
||||||
### D-B.CA
|
|
||||||
|
|
||||||
À l'époque, je n'avais pas encore enregistré de nom de domaine personnel, donc
|
|
||||||
tout se trouvait sous un domaine d'un ami. En fin d'année 2002, j'ai décidé
|
|
||||||
d'enregistrer le mien, principalement pour avoir une adresse e-mail stable.
|
|
||||||
J'ai voulu intégrer les initiales de mon nom, donc j'ai choisi `d-b.ca`.
|
|
||||||
C'était un compromis, car quelqu'un squattait `db.ca` à l'époque, et, à ma
|
|
||||||
connaissance, c'est toujours le cas.
|
|
||||||
|
|
||||||
Au début, j'ai principalement focalisé mon attention sur l'exploitation de mes
|
|
||||||
services de messagerie et d'autres expérimentations, sans trop me soucier de
|
|
||||||
mon site web. Il y avait quelques pages de test de temps en temps, mais rien
|
|
||||||
de substantiel.
|
|
||||||
|
|
||||||
## Technologie moderne
|
|
||||||
|
|
||||||
L'un des projets que je suis depuis un certain temps est
|
|
||||||
[Hugo](https://gohugo.io/). J'ai eu l'occasion de travailler avec divers
|
|
||||||
systèmes de gestion de contenu web, et ils ont souvent semblé encombrants et
|
|
||||||
poser des problèmes de sécurité. Hugo est un exemple de «générateur de sites
|
|
||||||
statiques». Imaginez-le comme suit: au lieu de créer des pages web en temps
|
|
||||||
réel chaque fois qu'une personne les visite, Hugo prend tout le contenu brut
|
|
||||||
et le transforme en un ensemble de fichiers prêts à être servis, de manière
|
|
||||||
similaire à la manière dont un compilateur transforme du code en un programme
|
|
||||||
exécutable. Les ressources statiques résultantes peuvent être servies comme
|
|
||||||
des fichiers réguliers depuis n'importe quel service web, sans avoir besoin de
|
|
||||||
générer dynamiquement du contenu à partir d'une base de données, comme le font
|
|
||||||
les systèmes de gestion de contenu traditionnels.
|
|
||||||
|
|
||||||
Utiliser Hugo est beaucoup plus simple avec un modèle de base solide. Il
|
|
||||||
existe de nombreux modèles à choisir ([voir ici](https://themes.gohugo.io/)),
|
|
||||||
notamment celui que j'ai choisi ici appelé
|
|
||||||
[«Blowfish»](https://blowfish.page/). J'aime l'aspect qu'il a, et il prend
|
|
||||||
bien en charge le style de site que je souhaite.
|
|
||||||
|
|
||||||
Un autre avantage d'un générateur de sites statiques est que l'ensemble des
|
|
||||||
sources du site peut être traité comme du code logiciel, ce qui rend simple
|
|
||||||
l'utilisation d'outils de développement comme [Git](https://git-scm.com/) pour
|
|
||||||
le contrôle de version. Je garde les sources de ce site dans un dépôt public
|
|
||||||
sur mon propre serveur Git. N'hésitez pas à jeter un œil:
|
|
||||||
|
|
||||||
{{< gitea repo="d-b.ca/web" >}}
|
|
||||||
|
|
||||||
### CI/CD
|
|
||||||
|
|
||||||
J'ai également configuré un pipeline CI/CD pour construire et déployer le site
|
|
||||||
chaque fois que des modifications sont apportées au dépôt source. Qu'est-ce
|
|
||||||
que cela signifie ?
|
|
||||||
|
|
||||||
**CI** = *Intégration continue*
|
|
||||||
> C'est la pratique d'intégrer fréquemment les modifications dans un dépôt
|
|
||||||
> source. Les modifications sont vérifiées, assemblées et empaquetées via des
|
|
||||||
> processus automatisés. [Plus d'informations](https://martinfowler.com/articles/continuousIntegration.html)
|
|
||||||
|
|
||||||
**CD** = *Livraison continue*
|
|
||||||
> C'est la capacité à pouvoir prendre de nouvelles modifications (comme les
|
|
||||||
> sorties du processus CI) et les déployer et les exécuter automatiquement.
|
|
||||||
> [Plus d'informations](https://continuousdelivery.com/)
|
|
||||||
|
|
||||||
La partie CI est déclenchée par un push vers le dépôt
|
|
||||||
[web](https://git.brds.ca/d-b.ca/web) . Il exécute un workflow automatisé qui
|
|
||||||
construit le site et empaquette les artefacts résultants dans une image
|
|
||||||
conteneur basée sur le serveur web [Caddy](https://caddyserver.com/).
|
|
||||||
|
|
||||||
Une image conteneur est comme un environnement logiciel préemballé qui assure
|
|
||||||
que le site web fonctionne de manière cohérente, quel que soit
|
|
||||||
l'infrastructure sous-jacente. L'image résultante contient tout ce dont le
|
|
||||||
site a besoin pour fonctionner et peut s'exécuter sur n'importe quelle
|
|
||||||
infrastructure capable de l'héberger, comme mon propre ordinateur portable ou
|
|
||||||
mon cluster de serveurs.
|
|
||||||
|
|
||||||
L'image conteneur utilisée avec Hugo est une autre image, uniquement utilisée
|
|
||||||
pour créer l'image conteneur du site web. Je la maintiens dans ce dépôt:
|
|
||||||
|
|
||||||
{{< gitea repo="d-b.ca/hugo-builder" >}}
|
|
||||||
|
|
||||||
Une fois que le workflow a construit l'image conteneur pour exécuter le site
|
|
||||||
web, il met à jour le dépôt GitOps de livraison continue pour déployer
|
|
||||||
immédiatement cette nouvelle version sur un site de prévisualisation privé.
|
|
||||||
Une autre définition:
|
|
||||||
|
|
||||||
> **GitOps** désigne la pratique de gérer l'automatisation de l'infrastructure
|
|
||||||
> en conservant des descriptions lisibles par machine de l'infrastructure
|
|
||||||
> souhaitée dans un dépôt Git contrôlé en version. Un système de livraison
|
|
||||||
> continue surveille le dépôt pour des changements, ajoutant, modifiant ou
|
|
||||||
> supprimant immédiatement l'infrastructure pour aligner l'état du système
|
|
||||||
> opérationnel sur la description source.
|
|
||||||
|
|
||||||
Il y a de nombreux avantages à gérer l'infrastructure de cette manière. Les
|
|
||||||
changements sont automatiquement traqués, car tout est stocké dans un système
|
|
||||||
de dépôt de code existant conçu spécifiquement pour gérer et suivre les
|
|
||||||
changements. Les changements problématiques peuvent être facilement annulés en
|
|
||||||
annulant le changement dans le dépôt. L'automatisation maintient les choses
|
|
||||||
synchronisées en permanence - tout changement effectué manuellement en dehors
|
|
||||||
de ce système est immédiatement détecté et supprimé.
|
|
||||||
|
|
||||||
Quand je veux publier cette nouvelle version en tant que site web de
|
|
||||||
production, j'utilise mon dépôt GitOps privé régulier pour mettre à jour le
|
|
||||||
tag de version de l'image, et le reste se fait automatiquement. Le dépôt
|
|
||||||
GitOps de livraison continue pour le site de prévisualisation est public, vous
|
|
||||||
êtes les bienvenus pour le consulter ici:
|
|
||||||
|
|
||||||
{{< gitea repo="d-b.ca/db-cd" >}}
|
|
||||||
|
|
||||||
#### Diagramme du pipeline
|
|
||||||
|
|
||||||
{{< mermaid >}}
|
|
||||||
flowchart TB
|
|
||||||
subgraph GIT [Dépôt GIT]
|
|
||||||
WR[(Web)]
|
|
||||||
CDR[(CD)]
|
|
||||||
end
|
|
||||||
|
|
||||||
WP(Envoyer les mises à jour du site web)-->WR
|
|
||||||
WP ~~~ HBI
|
|
||||||
|
|
||||||
subgraph CI [Workflow CI]
|
|
||||||
CIP[Récupérer le dépôt source]-->BWI[Construire l'image web]
|
|
||||||
BWI-->PWI[Envoyer l'image web]
|
|
||||||
PWI-->UCD[Mettre à jour le dépôt CD]
|
|
||||||
end
|
|
||||||
|
|
||||||
PWI-->WI
|
|
||||||
WR-->CIP
|
|
||||||
|
|
||||||
subgraph DOCKER [Dépôt d'images]
|
|
||||||
HBI((Hugo
|
|
||||||
Build))
|
|
||||||
WI((Web))
|
|
||||||
end
|
|
||||||
|
|
||||||
HBI-->BWI
|
|
||||||
|
|
||||||
UCD-->CDP(Envoyer la mise à jour de l'image)
|
|
||||||
CDP-->CDR
|
|
||||||
CDR-->CDPull
|
|
||||||
|
|
||||||
subgraph CD [Processus CD]
|
|
||||||
CDPull[Récupérer le dépôt source]-->DWI[Déployer l'image web]
|
|
||||||
end
|
|
||||||
|
|
||||||
WI-->DWI
|
|
||||||
{{< /mermaid >}}
|
|
||||||
|
|
||||||
## Plateforme sous-jacente
|
|
||||||
|
|
||||||
Dans des articles futurs, je décrirai l'évolution du réseau physique et des
|
|
||||||
systèmes sur lesquels ce site s'exécute, et comment ils m'ont permis de
|
|
||||||
construire un cluster [Kubernetes](https://kubernetes.io/) pour mettre à
|
|
||||||
l'échelle ce site et exécuter d'autres services, tout cela sur du matériel que
|
|
||||||
j'ai assemblé moi-même!
|
|
||||||
4
go.mod
4
go.mod
@@ -1,5 +1,5 @@
|
|||||||
module git.brds.ca/drew/web
|
module git.brds.ca/drew/web
|
||||||
|
|
||||||
go 1.24.2
|
go 1.25.4
|
||||||
|
|
||||||
require github.com/nunocoracao/blowfish/v2 v2.86.0 // indirect
|
require github.com/nunocoracao/blowfish/v2 v2.92.0 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,2 +1,2 @@
|
|||||||
github.com/nunocoracao/blowfish/v2 v2.86.0 h1:wAnsjubJuoAWgvM0Xgh2H7+4bOBVFAgX3WUvYtXO2k8=
|
github.com/nunocoracao/blowfish/v2 v2.92.0 h1:1EgHMRaY6VI438TIAN/5luNx16lg1e0Lrbi+6kDxpdA=
|
||||||
github.com/nunocoracao/blowfish/v2 v2.86.0/go.mod h1:4SkMc+Ht8gpQCwArqiHMBDP3soxi2OWuAhVney+cuyk=
|
github.com/nunocoracao/blowfish/v2 v2.92.0/go.mod h1:4SkMc+Ht8gpQCwArqiHMBDP3soxi2OWuAhVney+cuyk=
|
||||||
|
|||||||
Reference in New Issue
Block a user