Retour aux projets

Portfolio mprost.fr — Conception, Sécurisation et Auto-hébergement d'un site Next.js

2025-08-23
Next.js React TypeScript Tailwind CSS MDX Proxmox Debian Nginx Node.js Git GitHub Actions CI/CD Stalwart Nodemailer Sécurité web Turnstile RGPD SEO

Conception, sécurisation et auto-hébergement de mon portfolio professionnel avec Next.js, MDX, Proxmox, Nginx et Node.js. Le projet intègre un déploiement automatisé avec GitHub Actions ainsi qu'un formulaire sécurisé relié à une messagerie Stalwart auto-hébergée.


Portfolio mprost.fr

Introduction

mprost.fr est mon portfolio professionnel. Il centralise ma présentation, mon parcours, mon CV, mes projets ainsi que mes documentations techniques.

J'ai développé et fait évoluer ce projet afin de maîtriser l'ensemble de la chaîne technique d'un service Web : développement de l'application, gestion du contenu, sécurisation, versionnement, déploiement, hébergement, exposition sur Internet et messagerie associée.

Le site repose sur Next.js et utilise principalement des contenus générés statiquement. Certaines fonctionnalités nécessitent néanmoins une exécution côté serveur, notamment le formulaire de contact.

Le projet était auparavant hébergé sur Plesk. Il a ensuite été migré vers ma propre infrastructure Proxmox, avec un conteneur Debian dédié au Web, Nginx comme reverse proxy, un déploiement automatisé depuis GitHub et une messagerie Stalwart hébergée sur une VM séparée.


Objectifs

  • Présenter mon profil, mon CV, mes réalisations et mes documentations dans un site unique.
  • Publier facilement de nouveaux projets et documentations grâce à MDX.
  • Héberger l'application sur ma propre infrastructure.
  • Séparer les rôles Web et messagerie dans des environnements distincts.
  • Protéger le formulaire de contact contre les robots, le spam et les abus.
  • Acheminer les messages du formulaire directement vers ma messagerie auto-hébergée.
  • Conserver les secrets uniquement côté serveur.
  • Versionner le code avec Git et automatiser la mise en production.
  • Journaliser les événements utiles à la sécurité et au diagnostic.
  • Limiter la collecte de données personnelles et documenter leur traitement.
  • Suivre le référencement et la qualité du site.

Stack technique

DomaineTechnologiesRôle
FrameworkNext.js 16, React 19, TypeScriptPages, routage, rendu serveur et routes API
InterfaceTailwind CSS, Tailwind Typography, Framer Motion, LucideDesign, mise en page, animations et icônes
Thèmenext-themesMode clair et sombre
ContenuMDX, next-mdx-remote, gray-matterProjets et documentations avec métadonnées
Veillerss-parserExploitation de flux RSS
Anti-robotCloudflare TurnstileProtection du formulaire de contact
Envoi du formulaireNodemailer, SMTP TLSTransmission directe du message vers la messagerie
MessagerieStalwart Mail ServerBoîte contact@mprost.fr, SMTP et IMAP
HyperviseurProxmox VEHébergement des services
Serveur WebLXC Debian 13Isolation de l'application Web
Serveur MailVM Debian 13Isolation de la messagerie
Reverse proxyNginxEntrée HTTP/HTTPS et transmission vers Next.js / WebUI mail
RuntimeNode.jsExécution de Next.js en production
Gestion du servicesystemdDémarrage et maintien du processus Next.js
VersionnementGit / GitHubHistorique et dépôt du code source
DéploiementGitHub Actions, runner self-hostedDéploiement automatique du portfolio
DNSIONOSGestion du domaine et des enregistrements Web/Mail

Architecture générale

Le portfolio et la messagerie sont hébergés sur la même infrastructure Proxmox, mais dans deux environnements distincts.

                         Internet
                            |
                         mprost.fr
                            |
                        DNS IONOS
                            |
                      IP publique
                            |
                     Routeur / NAT
                            |
             +--------------+--------------+
             |                             |
         HTTP / HTTPS                  Ports mail
             |                             |
             v                             v
     CT Web Debian 13               VM Mail Debian 13
      192.168.1.210                   192.168.1.211
             |                             |
           Nginx                        Stalwart
             |                      SMTP / IMAP / Mail
         Next.js                          |
             |                     contact@mprost.fr
          Portfolio

Le serveur physique exécute Proxmox VE. Le site Web fonctionne dans un conteneur LXC Debian 13 tandis que la messagerie fonctionne dans une VM Debian 13 dédiée.

Cette séparation évite de mélanger le rôle applicatif du portfolio et le rôle critique de serveur de messagerie.


Serveur Web et reverse proxy

Le conteneur Web utilise l'adresse locale :

192.168.1.210

Nginx constitue le frontal HTTP/HTTPS. Il reçoit les requêtes publiques destinées à mprost.fr et les transmet au processus Next.js exécuté localement par Node.js.

Visiteur
   |
   v
Nginx : 80 / 443
   |
   v
Next.js : 3000
   |
   v
Portfolio / API

Nginx sert également de reverse proxy pour l'interface Web de la messagerie accessible via mail.mprost.fr, tandis que les protocoles SMTP et IMAP sont dirigés directement vers la VM Mail.


Messagerie auto-hébergée

La messagerie @mprost.fr repose sur Stalwart Mail Server installé sur une VM Debian 13 dédiée.

La VM Mail utilise :

192.168.1.211

Le serveur expose notamment les services nécessaires à la réception, à l'envoi et à la consultation des mails. La boîte utilisée par le portfolio est :

contact@mprost.fr

Le domaine utilise des enregistrements DNS dédiés à la messagerie :

  • MX pour désigner mail.mprost.fr comme serveur de réception ;
  • SPF pour déclarer les serveurs autorisés à envoyer ;
  • DKIM avec signatures RSA et Ed25519 ;
  • DMARC pour définir la politique d'authentification ;
  • enregistrements de découverte pour les clients mail.

Le serveur Web et le serveur Mail partagent le même domaine public mais conservent des rôles réseau séparés.


Organisation de l'application

L'application utilise l'App Router de Next.js.

app/
components/
content/
lib/
public/
.github/
  workflows/
  • app contient les pages et routes serveur ;
  • components contient les composants React réutilisables ;
  • content contient les contenus MDX ;
  • lib regroupe les fonctions utilitaires ;
  • public contient les ressources publiques ;
  • .github/workflows contient le workflow de déploiement.

Le portfolio propose notamment l'accueil, la présentation, le parcours, les compétences, les projets, les documentations techniques, la veille, le CV, le formulaire de contact, les mentions légales et la politique de confidentialité.


MDX et gestion du contenu

Une partie importante du portfolio repose sur MDX.

Chaque projet ou documentation peut être représenté par un fichier comportant ses propres métadonnées : titre, description, date, tags ou lien de démonstration.

Code Next.js
     +
Contenu MDX
     =
Portfolio

Cette organisation permet d'ajouter de nouvelles publications sans créer manuellement une page React complète pour chaque contenu.


Formulaire de contact

Le formulaire de contact est la principale fonctionnalité dynamique du portfolio.

L'ancienne architecture utilisait Formspree comme relais. Cette dépendance a été supprimée. La route serveur du portfolio envoie maintenant directement les messages vers Stalwart avec Nodemailer et une connexion SMTP chiffrée.

Le parcours est désormais :

Visiteur
   |
Formulaire mprost.fr
   |
/api/contact
   |
Contrôle Origin
   |
Rate limiting
   |
Validation des champs
   |
Honeypot
   |
Cloudflare Turnstile
   |
Nodemailer
   |
SMTP TLS :465
   |
Stalwart
   |
contact@mprost.fr

L'adresse saisie par le visiteur est utilisée comme Reply-To, tandis que l'expéditeur SMTP reste la boîte du domaine. Cela permet de répondre au visiteur depuis la messagerie sans faire passer son adresse pour l'expéditeur technique du message.


Sécurité applicative

Cloudflare Turnstile

Le widget Turnstile fournit un jeton côté navigateur. La route /api/contact vérifie ensuite ce jeton côté serveur avec la clé secrète Turnstile.

La clé de site reste publique dans le composant client. La clé secrète n'est jamais incluse dans le dépôt Git.

Limitation de débit

Deux niveaux sont appliqués :

  • limite par adresse IP ;
  • plafond global du formulaire.

Ces limites réduisent les envois répétés et l'utilisation abusive de la route serveur.

Honeypot

Un champ invisible pour un visiteur normal permet de détecter certains robots remplissant automatiquement tous les champs d'un formulaire.

Contrôle d'origine

La route vérifie l'en-tête Origin pour accepter uniquement les domaines prévus par l'application.

Validation côté serveur

Le nom, l'adresse email, le message et le jeton Turnstile disposent de contrôles de présence, de format et de taille.

Gestion des secrets

Les secrets de production ne sont pas stockés dans GitHub. Ils sont placés sur le serveur dans un fichier d'environnement dédié chargé par systemd.

Les variables comprennent notamment :

TURNSTILE_SECRET_KEY
SMTP_HOST
SMTP_PORT
SMTP_SECURE
SMTP_USER
SMTP_PASSWORD
CONTACT_TO

Le fichier de production reste séparé du dépôt. Un fichier .env.example peut documenter les variables nécessaires sans contenir leurs valeurs.


Journalisation et détection

La route /api/contact journalise les événements importants afin de faciliter la détection des abus et le diagnostic.

Les événements peuvent notamment représenter :

  • un message envoyé avec succès ;
  • une limitation de débit ;
  • un CAPTCHA absent ou refusé ;
  • le déclenchement du honeypot ;
  • une origine incorrecte ;
  • des données invalides ;
  • une erreur de configuration ;
  • une erreur SMTP.

Les journaux ne contiennent pas le nom, l'adresse email ou le contenu du message. Les journaux de sécurité sont conservés séparément des ressources publiques du site.


HTTPS et TLS

Les accès Web publics utilisent HTTPS.

Navigateur
    |
    | HTTPS
    v
  Nginx
    |
    | HTTP local
    v
 Next.js

mail.mprost.fr utilise également Nginx comme frontal HTTPS pour l'interface Web de Stalwart.

Les protocoles mail TLS, comme SMTP Submission et IMAP, aboutissent directement sur Stalwart. Le certificat Let's Encrypt utilisé par Nginx a donc également été importé dans Stalwart afin d'éviter l'utilisation du certificat auto-signé sur les connexions directes aux services mail.


Versionnement avec Git

Le code source du portfolio est versionné avec Git et hébergé dans un dépôt GitHub.

Poste de développement
        |
        | commit / push
        v
      GitHub
        |
        v
GitHub Actions
        |
        v
Serveur de production

Les secrets de production ne transitent pas dans ce dépôt.


Déploiement automatisé avec GitHub Actions

Le workflow de déploiement est stocké dans :

.github/workflows/deploy.yml

Il est déclenché lors d'un push sur la branche principale.

Le workflow est exécuté par un runner GitHub Actions auto-hébergé installé sur le conteneur Web.

Runner : mprost-production
Compte : github-runner

Le cycle est :

Modification locale
       |
     git add
       |
    git commit
       |
     git push
       |
      GitHub
       |
 GitHub Actions
       |
Runner mprost-production
       |
       +--> git pull
       +--> npm ci
       +--> npm run build
       +--> restart mprost.service
       |
       v
   Production

Sécurisation du runner

Le runner fonctionne avec le compte Linux dédié github-runner et non avec root.

Une Deploy Key SSH dédiée lui permet de récupérer le dépôt privé. Le serveur de production utilise uniquement l'accès nécessaire au déploiement.

La règle sudo du runner est limitée au redémarrage de mprost.service, conformément au principe du moindre privilège.


Exécution de Next.js avec systemd

L'application Next.js est exécutée comme un service systemd :

mprost.service

systemd permet au site de fonctionner indépendamment d'une session SSH et de redémarrer proprement après un déploiement.

Le service charge également le fichier d'environnement de production contenant les secrets nécessaires à la route de contact.


Séparation des responsabilités

IONOS
└── Domaine et DNS

Routeur
├── HTTP / HTTPS vers Nginx
└── SMTP / IMAP vers Stalwart

Proxmox VE
├── CT Web Debian 13
│   ├── Nginx
│   ├── Node.js / Next.js
│   ├── systemd
│   └── GitHub Actions Runner
│
└── VM Mail Debian 13
    └── Stalwart Mail Server

GitHub
└── Dépôt source

GitHub Actions
└── Orchestration du déploiement

MDX
└── Contenu du portfolio

Cette séparation simplifie le diagnostic et évite de concentrer les rôles Web, déploiement et messagerie dans un seul service.


Conformité et protection des données

Le formulaire collecte uniquement les informations nécessaires à la réponse : nom, adresse email et message.

Le traitement ne repose plus sur Formspree. Après validation des contrôles de sécurité, les messages sont envoyés directement vers la boîte contact@mprost.fr de l'infrastructure de messagerie auto-hébergée.

Cloudflare Turnstile reste utilisé comme service externe de protection anti-robot.

Le journal de sécurité reste séparé du contenu des messages et ne journalise pas le nom, l'adresse email ou le texte envoyé.

Le site dispose de pages dédiées aux mentions légales et à la politique de confidentialité.


Référencement et qualité

Le portfolio intègre notamment :

  • des métadonnées par page ;
  • un sitemap ;
  • un fichier robots.txt ;
  • la génération statique lorsque cela est pertinent ;
  • Google Search Console ;
  • Lighthouse.

Analyse Lighthouse du portfolio

Performances dans Google Search Console


Évolution du projet

Hébergement initial sous Plesk

Les premières versions en production étaient hébergées sous Plesk avec un environnement Node.js administré par la plateforme.

Passage à l'auto-hébergement

Le portfolio a ensuite été migré sur Proxmox :

Serveur physique
      |
  Proxmox VE
      |
CT Debian 13
      |
      +-- Nginx
      +-- Node.js / Next.js
      +-- systemd
      +-- GitHub Actions Runner

Passage au déploiement continu

Le déploiement manuel a été remplacé par un workflow GitHub Actions exécuté directement sur l'infrastructure grâce à un runner self-hosted.

Auto-hébergement de la messagerie

Une VM Debian 13 dédiée a ensuite été ajoutée pour héberger Stalwart Mail Server.

Le domaine mprost.fr utilise maintenant mail.mprost.fr pour sa messagerie, avec une boîte contact@mprost.fr et les mécanismes DNS d'authentification associés.

Suppression de Formspree

Le formulaire dépendait initialement de Formspree pour acheminer les messages. Cette dépendance a été supprimée.

La route serveur Next.js utilise désormais Nodemailer pour établir une connexion SMTP TLS authentifiée avec Stalwart et remettre directement les messages dans contact@mprost.fr.


Difficultés rencontrées

Application Next.js derrière Nginx

Le portfolio n'est pas un simple ensemble de fichiers HTML. Les routes API nécessitent un processus Node.js actif. Nginx agit donc comme reverse proxy vers Next.js.

Ressources du runner GitHub Actions

La configuration initiale du conteneur Web disposait de trop peu de mémoire pour certains npm ci et builds. Un job a été interrompu par le mécanisme OOM du système. Les ressources du conteneur ont ensuite été augmentées.

Permissions Git du runner

Le runner utilise un compte Linux différent du propriétaire historique du dépôt. Il a fallu gérer proprement les permissions et déclarer le dépôt utilisable par le compte de déploiement.

Authentification SSH GitHub

Le runner dispose de sa propre Deploy Key SSH en lecture seule afin de récupérer le dépôt privé sans réutiliser une identité personnelle.

Reverse proxy vers Stalwart

L'interface Web Stalwart est publiée via Nginx sous mail.mprost.fr, avec une URL publique cohérente pour OAuth et JMAP.

Certificat TLS des protocoles mail

Le certificat Let's Encrypt du frontal Web ne couvre pas automatiquement les connexions directes SMTP/IMAP vers Stalwart. Le certificat valide de mail.mprost.fr a donc été importé dans Stalwart pour remplacer le certificat auto-signé présenté initialement sur les services mail.

Migration du formulaire hors Formspree

Le remplacement de Formspree a nécessité :

  • l'installation de Nodemailer ;
  • l'ajout des variables SMTP côté serveur ;
  • la configuration du certificat TLS Stalwart ;
  • la configuration d'une authentification SMTP pour contact@mprost.fr ;
  • l'adaptation des mentions RGPD et de la politique de confidentialité.

Compétences mobilisées

Développement Web

  • Next.js ;
  • React ;
  • TypeScript ;
  • Tailwind CSS ;
  • MDX ;
  • routes serveur ;
  • Nodemailer ;
  • génération statique et dynamique.

Système et hébergement

  • Debian 13 ;
  • Node.js ;
  • systemd ;
  • Nginx ;
  • exploitation de services en production.

Virtualisation

  • Proxmox VE ;
  • conteneurs LXC ;
  • machines virtuelles ;
  • séparation des rôles applicatifs.

Réseau

  • adressage IPv4 ;
  • DNS ;
  • NAT/PAT ;
  • HTTP / HTTPS ;
  • SMTP / IMAP ;
  • reverse proxy ;
  • TLS.

Messagerie

  • Stalwart Mail Server ;
  • SMTP Submission ;
  • IMAP ;
  • MX ;
  • SPF ;
  • DKIM ;
  • DMARC ;
  • certificats TLS.

DevOps et versionnement

  • Git ;
  • GitHub ;
  • GitHub Actions ;
  • runner self-hosted ;
  • pipeline de build et de déploiement ;
  • Deploy Keys SSH.

Sécurité

  • principe du moindre privilège ;
  • séparation des comptes système ;
  • clés SSH ;
  • HTTPS et SMTP TLS ;
  • gestion de secrets hors Git ;
  • Cloudflare Turnstile ;
  • rate limiting ;
  • validation des entrées ;
  • honeypot ;
  • journalisation.

Protection des données

  • minimisation des données ;
  • politique de confidentialité ;
  • suppression d'un relais tiers du chemin des messages ;
  • séparation des journaux techniques et du contenu des messages ;
  • conservation limitée des journaux.

SEO et qualité Web

  • métadonnées ;
  • sitemap ;
  • robots.txt ;
  • Google Search Console ;
  • Lighthouse.

Pistes d'amélioration

Déploiement sans interruption

Construire les nouvelles versions dans un emplacement séparé, effectuer un contrôle de santé puis basculer vers la nouvelle release seulement si le build est valide.

Synchronisation des certificats

Automatiser la synchronisation du certificat Let's Encrypt de mail.mprost.fr vers Stalwart après chaque renouvellement afin que SMTP et IMAP présentent toujours un certificat valide.

Sécurité HTTP

Renforcer progressivement les en-têtes HTTP, notamment CSP, HSTS et X-Content-Type-Options, en conservant la compatibilité avec Cloudflare Turnstile.

Journalisation et supervision

Centraliser les événements Nginx, Next.js, systemd et Stalwart afin de faciliter la supervision et la création d'alertes.

Sauvegarde et restauration

Formaliser une stratégie couvrant :

  • le conteneur Web ;
  • la VM Mail ;
  • les données de messagerie ;
  • les configurations Nginx et Stalwart ;
  • les variables d'environnement ;
  • les certificats ;
  • les journaux utiles ;
  • la procédure de restauration.

Conclusion

Le portfolio mprost.fr a progressivement évolué d'un site personnel vers un projet complet associant développement Web, cybersécurité, Linux, réseau, virtualisation, DevOps et messagerie.

Next.js et MDX constituent la base applicative et éditoriale. Proxmox héberge les différents services. Nginx assure l'entrée Web, systemd maintient l'application, GitHub Actions automatise les déploiements et Stalwart fournit désormais la messagerie du domaine.

Le formulaire de contact ne dépend plus d'un relais Formspree : après ses contrôles de sécurité, la route serveur transmet directement les messages via SMTP TLS à la messagerie auto-hébergée.

Développement
    |
Git / GitHub
    |
GitHub Actions
    |
Runner de production
    |
Next.js / Nginx
    |
Formulaire sécurisé
    |
Nodemailer / SMTP TLS
    |
Stalwart
    |
contact@mprost.fr

Ce projet constitue désormais un environnement concret pour mettre en pratique le développement, l'exploitation système, la sécurité, le réseau, la messagerie et l'automatisation autour d'un service réellement accessible sur Internet.