Compare commits

..

4 Commits

5 changed files with 407 additions and 33 deletions

View File

@ -22,7 +22,7 @@ title = "Drew Bowering"
headline = "IT Architect, Developer, Canoeist, Tubist" headline = "IT Architect, Developer, Canoeist, Tubist"
# bio = "A little bit about me" # bio = "A little bit about me"
links = [ links = [
# { email = "mailto:hello@your_domain.com" }, { email = "mailto:drew@d-b.ca" },
# { link = "https://link-to-some-website.com/" }, # { link = "https://link-to-some-website.com/" },
# { amazon = "https://www.amazon.com/hz/wishlist/ls/wishlist-id" }, # { amazon = "https://www.amazon.com/hz/wishlist/ls/wishlist-id" },
# { apple = "https://www.apple.com" }, # { apple = "https://www.apple.com" },

View File

@ -0,0 +1,73 @@
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"},
]

View File

@ -0,0 +1,69 @@
# -- 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

View File

@ -1,6 +1,6 @@
--- ---
title: "New Website" title: "New Website"
date: "2025-06-10T08:00:00-06:00" date: "2025-06-12T08:00:00-06:00"
description: "There's finally a new website at d-b.ca." description: "There's finally a new website at d-b.ca."
summary: "I've published my personal website. A brief history of some past endeavours, and some details on the technology behind the new site." summary: "I've published my personal website. A brief history of some past endeavours, and some details on the technology behind the new site."
--- ---
@ -8,9 +8,9 @@ summary: "I've published my personal website. A brief history of some past endea
I've finally published a proper website at [https://d-b.ca/](https://d-b.ca/). I've finally published a proper website at [https://d-b.ca/](https://d-b.ca/).
The last time I had anything live on this domain was over 20 years ago, The last time I had anything live on this domain was over 20 years ago,
according to the [Wayback Machine](https://web.archive.org/). What took so according to the [Wayback Machine](https://web.archive.org/). What took so
long? Over the years I've learned a lot, and I'm constantly experimenting with long? The truth is, my interests have shifted over the years, and I've been
new ways of getting things done. This site, while useful in its own right, is learning a lot. This site, while useful in its own right, is really a
a culmination of the platform I've developed to host it. culmination of a personal platform I've developed over time.
## History ## History
@ -23,9 +23,10 @@ Internet technologies and their applications.
That early site included one interesting feature. I developed a mechanism to That early site included one interesting feature. I developed a mechanism to
automatically update a page every time I logged into one of the school's automatically update a page every time I logged into one of the school's
computers, so my friends could find me if they wanted to. The only way at the computers, so my friends could find me if they wanted to. At the time,
time that was available for generating dynamic content in a website was dynamically updating websites was a tricky thing. The most common way was
[CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface), and the using [CGI](https://en.wikipedia.org/wiki/Common_Gateway_Interface), which is
like having a tiny program run every time someone requested a page. The
university did not allow student sites to use it. So, I wrote some shell university did not allow student sites to use it. So, I wrote some shell
scripts that were called as part of my login and logout scripts that would scripts that were called as part of my login and logout scripts that would
generate the static HTML file and write it to my web content directory. It generate the static HTML file and write it to my web content directory. It
@ -34,25 +35,29 @@ always get triggered, so I'd have to keep an eye on it for stale entries.
### Self-Hosting ### Self-Hosting
I've always been an avid self-hoster. It began when I was working at a local I've always been an avid self-hoster. Learning by getting a system up and
Internet service provider. I was able to get a special deal on a running works well for me. I also value the privacy and control that it
business-class broadband connection at home, which included a small network provides. Plus, it's much cheaper for me in the long run!
block (a `/28`, consisting of 16 IP addresses) that I could use. I dedicated
my most powerful machine as my server and developed several services, It really began when I was working at a local Internet service provider. I was
including a new website. able to get a special deal on a good broadband connection at home, which
included a small network block (a `/28`, consisting of 16 IP addresses) that I
could use. I dedicated my largest machine as my server and developed several
services, including a new website.
My website at that time wasn't fancy, and was geared primarily towards My website at that time wasn't fancy, and was geared primarily towards
experimentation. I developed a simple content management system from scratch experimentation. I developed a simple content management system from scratch
in PHP3, which I used to publish a blog. It also integrated with mailing in PHP, which I used to publish a blog. It also integrated with mailing
lists, another area I was exploring at the time. lists, another area I was exploring at the time.
### D-B.CA ### D-B.CA
I hadn't registered a domain name of my own in those early days, so everything I hadn't registered a domain name of my own in those early days, so everything
resided under a friend's domain. In late 2002, I decided to finally register resided under a friend's domain. In late 2002, I decided to finally register
one of my own, primarily so I could have a stable email address. I came up one of my own, primarily so I could have a stable email address. I wanted to
with `d-b.ca` because someone was squatting on `db.ca` and still is, I might incorporate the initials in my name, so I came up with `d-b.ca`. This was a
add. compromise because someone was squatting on `db.ca` at the time, and, to my
knowledge, they still are.
Early on, I focused mostly on operating my email services and other Early on, I focused mostly on operating my email services and other
experiments, with little attention paid to a website. There were a few test experiments, with little attention paid to a website. There were a few test
@ -63,15 +68,18 @@ pages at times, but nothing substantial.
One of the projects I've been following is [Hugo](https://gohugo.io/). I've One of the projects I've been following is [Hugo](https://gohugo.io/). I've
seen and worked with various web content management systems in the past, and seen and worked with various web content management systems in the past, and
they often feel cumbersome and present security concerns. Hugo is an example they often feel cumbersome and present security concerns. Hugo is an example
of a "Static Site Generator," which transforms a source description of a site of a "Static Site Generator." Think of it like this: instead of creating web
into the static resources used to serve it much like a compiler. The pages on the fly every time someone visits, Hugo takes all the raw content and
resulting static resources can be served as regular files from any web turns it into a set of ready-to-serve files, much like a compiler turns code
service, without the need for dynamically generating content upon request from into an executable program. The resulting static resources can be served as
a database, as traditional CMS systems do. regular files from any web service, without the need for dynamically
generating content upon request from a database, as traditional CMS systems
do.
Using Hugo is much easier with a solid base template. There are Using Hugo is much easier with a solid base template. There are
[many to choose from](https://themes.gohugo.io/), including the one I've [many to choose from](https://themes.gohugo.io/), including the one I've
selected here called ["Blowfish"](https://blowfish.page/). selected here called ["Blowfish"](https://blowfish.page/). I like how it
looks, and it supports the style of site that this is very well.
Another benefit of a static site generator is that all the sources for the Another benefit of a static site generator is that all the sources for the
site can be treated like software code, making it simple to use development site can be treated like software code, making it simple to use development
@ -99,9 +107,16 @@ changes are made to the source repository. What does this mean?
The CI portion is triggered by a push to the The CI portion is triggered by a push to the
[`web`](https://git.brds.ca/d-b.ca/web) repository. It runs an automated [`web`](https://git.brds.ca/d-b.ca/web) repository. It runs an automated
workflow that builds the site and packages the resulting artifacts into a workflow that builds the site and packages the resulting artifacts into a
container image based on [Caddy](https://caddyserver.com/). This image container image based on the [Caddy](https://caddyserver.com/) web server.
contains everything needed to serve the website. The build container with Hugo
is another image I maintain in this repository: A container image is like a pre-packaged software environment that ensures the
website runs consistently regardless of the underlying infrastructure. The
resulting image contains everything the website needs to operate and can run
on any infrastructure that can support it, such as my own laptop or my server
cluster.
The build container with Hugo is another image that is only used to create the
website container. I maintain it in this repository:
{{< gitea repo="d-b.ca/hugo-builder" >}} {{< gitea repo="d-b.ca/hugo-builder" >}}
@ -116,10 +131,17 @@ private staging site. Another definition:
> bring the state of the operational system into alignment with the source > bring the state of the operational system into alignment with the source
> description. > description.
When I want to publish the new version as the production site, I use my There are many benefits to managing infrastructure this way. Changes are
regular private production GitOps repository to update the image tag, and the automatically tracked because everything is stored in an existing code
rest happens automatically. The CD repository for the staging site is public, repository system that's specifically designed for managing and tracking
you're welcome to check it out here: change. Problematic changes can be reverted easily by reverting the change in
the repository. Automation keeps things in sync at all times - any changes
made manually outside of this system are immediately spotted and removed.
When I want to publish the new version as the production website, I use my
regular private production GitOps repository to update the image version tag,
and the rest happens automatically. The CD repository for the staging site is
public, you're welcome to check it out here:
{{< gitea repo="d-b.ca/db-cd" >}} {{< gitea repo="d-b.ca/db-cd" >}}
@ -170,5 +192,7 @@ flowchart TB
## Underlying Platform ## Underlying Platform
In my next article, I'll describe the platform this site is running on, and In future articles, I'll describe the evolution of the physical network and
some of the history and decisions that drove its design. systems this site is running on, and how they enabled me to build a
[Kubernetes](https://kubernetes.io/) cluster to scale this site and run other
services, all on hardware I assembled myself!

View File

@ -0,0 +1,208 @@
---
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!