[{"data":1,"prerenderedAt":389},["ShallowReactive",2],{"blog-\u002Fblog\u002Fconfiguration-nginx-avec-vuejs-erreur-404":3,"blog-\u002Fblog\u002Fconfiguration-nginx-avec-vuejs-erreur-404-surround":256,"blog-\u002Fblog\u002Fconfiguration-nginx-avec-vuejs-erreur-404-certifications":316},{"id":4,"title":5,"body":6,"categories":241,"cover":243,"cover_contain":156,"credly_badge_id":244,"date":245,"description":246,"extension":247,"meta":248,"navigation":156,"path":249,"related_certifications":250,"seo":252,"slug":253,"stem":254,"__hash__":255},"blog\u002Fblog\u002Fconfiguration-nginx-avec-vuejs-erreur-404.md","Configuration Nginx avec VueJS (erreur 404)",{"type":7,"value":8,"toc":232},"minimark",[9,14,18,24,28,38,42,45,50,53,56,60,63,116,119,210,213,217,228],[10,11,13],"h2",{"id":12},"cas-dusage-concret","Cas d'usage concret",[15,16,17],"p",{},"Vos rafraîchissements de page renvoient une erreur 404 sur une SPA VueJS derrière Nginx : voici la configuration qui corrige ce comportement.",[15,19,20],{},[21,22,23],"strong",{},"Dans le cadre d’un projet web sous docker avec Nginx j’ai rencontré un problème avec un projet VueJS. Le chemin absolu n’est pas connu par le serveur nginx à cause d’un comportement normal de VueJS. Une erreur 404 apparaît lors des actualisations d’URI.",[10,25,27],{"id":26},"configuration-nginx-avec-vuejs","Configuration Nginx avec VueJS",[15,29,30,31,37],{},"Dans l’utilisation d’un serveur web Nginx avec VueJS vous avez peut-être rencontré l’erreur 404. Pour rappel, Nginx est un serveur web et VueJS est un framework javascript. Une fois notre application web terminée avec VueJS, il est nécessaire de la transpiler et de la minifier avec webpack. À l’issue, nous disposons d’un dossier « dist » prêt à l’emploi que le serveur Nginx va héberger et lire. Or nous nous apercevons rapidement qu’une erreur 404 apparaît pour accéder à nos différents URI. (ex : ",[32,33,34],"a",{"href":34,"rel":35},"https:\u002F\u002Fkassianoff.fr\u002F**blog\u002F",[36],"nofollow","**).",[10,39,41],{"id":40},"notre-environnement","Notre environnement",[15,43,44],{},"Dans mon cas j’utilise la dernière version de Nginx 1.21.6 datant du 25 janvier 2022. Le serveur est publié en tant de micro-service avec une configuration par défaut. Le dossier dist est positionné à l’emplacement par défaut du serveur web. J’accède à mon serveur de production mais dès que j’actualise la page sur une URI j’ai une erreur web 404.",[46,47,49],"h3",{"id":48},"vuejs","VueJS",[15,51,52],{},"Durant la phase de développement dans VueJS un routeur qui utilise le mode « hachage » par défaut est utilisé, ce qui ne pose aucun problème dans l’environnement local (et en ligne) car il utilise un caractère dièse (#) avant l’URL transmise en interne. Étant donné que cette section de l’URL n’est jamais envoyée au serveur, elle ne nécessite aucun traitement particulier.",[15,54,55],{},"En phase de production (derrière un reverse proxy) la page d’accueil est accessible normalement et il n’y a aucun problème. Cependant, lorsque vous actualisez la page, une erreur 404 apparaîtra et la ressource à laquelle accéder est introuvable sur le serveur, car l’adresse de routage définie par le routeur Vue est considérée comme l’adresse URL, or le chemin d’adresse n’existe pas, donc le phénomène 404 apparaît.",[46,57,59],{"id":58},"nginx","Nginx",[15,61,62],{},"Lorsque je regarde la configuration par défaut de mon serveur Nginx il n’y a pas de véritable ressource « menu\u002Findex » sous le répertoire racine \u002Fdist de la configuration Nginx. Ces ressources d’accès sont rendues en JS. La configuration initiale de Nginx sur le serveur est la suivante (en supposant que le nom de domaine est : kassianoff.fr) :",[64,65,69],"pre",{"className":66,"code":67,"language":58,"meta":68,"style":68},"language-nginx shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","server\n{\n    listen 80;\n    server_name kassianoff.fr;\n    index index.php index.html index.htm default.php default.htm default.html;\n    root \u002Fvar\u002Fwww\u002Fkassianoff\u002Fdist;\n}\n","",[70,71,72,80,86,92,98,104,110],"code",{"__ignoreMap":68},[73,74,77],"span",{"class":75,"line":76},"line",1,[73,78,79],{},"server\n",[73,81,83],{"class":75,"line":82},2,[73,84,85],{},"{\n",[73,87,89],{"class":75,"line":88},3,[73,90,91],{},"    listen 80;\n",[73,93,95],{"class":75,"line":94},4,[73,96,97],{},"    server_name kassianoff.fr;\n",[73,99,101],{"class":75,"line":100},5,[73,102,103],{},"    index index.php index.html index.htm default.php default.htm default.html;\n",[73,105,107],{"class":75,"line":106},6,[73,108,109],{},"    root \u002Fvar\u002Fwww\u002Fkassianoff\u002Fdist;\n",[73,111,113],{"class":75,"line":112},7,[73,114,115],{},"}\n",[15,117,118],{},"Il convient alors d'ajouter le paramètre jump de Vue route dans la configuration Nginx du serveur. La première page ici est index.html. La configuration correcte est la suivante :",[64,120,122],{"className":66,"code":121,"language":58,"meta":68,"style":68},"server\n{\n    listen 80;\n    server_name kassianoff.fr;\n    index index.php index.html index.htm default.php default.htm default.html;\n    root \u002Fvar\u002Fwww\u002Fkassianoff\u002Fdist;\n\n    #Vue router configuration\n    location \u002F {\n        try_files $uri $uri\u002F @router;\n        index index.html;\n    }\n    location @router {\n        rewrite ^.*$ \u002Findex.html last;\n    }\n}\n",[70,123,124,128,132,137,142,147,152,158,164,170,176,182,188,194,200,205],{"__ignoreMap":68},[73,125,126],{"class":75,"line":76},[73,127,79],{},[73,129,130],{"class":75,"line":82},[73,131,85],{},[73,133,134],{"class":75,"line":88},[73,135,136],{},"    listen 80;\n",[73,138,139],{"class":75,"line":94},[73,140,141],{},"    server_name kassianoff.fr;\n",[73,143,144],{"class":75,"line":100},[73,145,146],{},"    index index.php index.html index.htm default.php default.htm default.html;\n",[73,148,149],{"class":75,"line":106},[73,150,151],{},"    root \u002Fvar\u002Fwww\u002Fkassianoff\u002Fdist;\n",[73,153,154],{"class":75,"line":112},[73,155,157],{"emptyLinePlaceholder":156},true,"\n",[73,159,161],{"class":75,"line":160},8,[73,162,163],{},"    #Vue router configuration\n",[73,165,167],{"class":75,"line":166},9,[73,168,169],{},"    location \u002F {\n",[73,171,173],{"class":75,"line":172},10,[73,174,175],{},"        try_files $uri $uri\u002F @router;\n",[73,177,179],{"class":75,"line":178},11,[73,180,181],{},"        index index.html;\n",[73,183,185],{"class":75,"line":184},12,[73,186,187],{},"    }\n",[73,189,191],{"class":75,"line":190},13,[73,192,193],{},"    location @router {\n",[73,195,197],{"class":75,"line":196},14,[73,198,199],{},"        rewrite ^.*$ \u002Findex.html last;\n",[73,201,203],{"class":75,"line":202},15,[73,204,187],{},[73,206,208],{"class":75,"line":207},16,[73,209,115],{},[15,211,212],{},"Après un redémarrage du serveur Nginx le problème n'est plus présent. Vous remarquerez que la configuration est simple car je n'utilise pas directement Nginx frontalement sur le web mais derrière un reverse-proxy qui gère la partie TLS ainsi que le routage avec des middlwares spécifiques. Si vous rencontrez le moindre problème n'hésitez pas à partager votre retour d'expérience à ce sujet.",[10,214,216],{"id":215},"conclusion","Conclusion",[15,218,219,220,223,224,227],{},"Cette erreur 404 sur actualisation d'une application VueJS derrière Nginx provient simplement de l'absence de règle de réécriture vers ",[70,221,222],{},"index.html"," côté serveur web. L'ajout d'un bloc ",[70,225,226],{},"try_files"," avec redirection vers le routeur Vue résout le problème sans complexifier la configuration. Ce correctif reste valable que Nginx soit exposé directement ou, comme ici, derrière un reverse-proxy gérant le TLS.",[229,230,231],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":68,"searchDepth":82,"depth":82,"links":233},[234,235,236,240],{"id":12,"depth":82,"text":13},{"id":26,"depth":82,"text":27},{"id":40,"depth":82,"text":41,"children":237},[238,239],{"id":48,"depth":88,"text":49},{"id":58,"depth":88,"text":59},{"id":215,"depth":82,"text":216},[242],"Linux","\u002Fimages\u002Fblog\u002Fconfiguration-nginx-avec-vuejs-erreur-404\u002Fc5873a58c2.jpg",null,"2022-05-24","Dans le cadre d'un projet web sous docker avec Nginx j'ai rencontré un problème avec un projet VueJS.","md",{},"\u002Fblog\u002Fconfiguration-nginx-avec-vuejs-erreur-404",[251],"certificat-lpi-linux-essentials-exam-010-150",{"title":5,"description":246},"configuration-nginx-avec-vuejs-erreur-404","blog\u002Fconfiguration-nginx-avec-vuejs-erreur-404","Xv3SUXRdKxXsYK5_1svGWQYNFaWrF1vpHzXIVX2C5HE",[257,266,274,281,287,294,302,309],{"title":258,"path":259,"stem":260,"date":261,"cover":262,"categories":263,"children":-1},"Microsoft : Security, Compliance, and Identity Fundamentals","\u002Fblog\u002Fcertificat-microsoft-security-compliance-and-identity-fundamentals","blog\u002Fcertificat-microsoft-security-compliance-and-identity-fundamentals","2022-10-17","\u002Fimages\u002Fblog\u002Fcertificat-microsoft-security-compliance-and-identity-fundamentals\u002F70ef935f2a.png",[264,265],"Certifications","Microsoft",{"title":267,"path":268,"stem":269,"date":270,"cover":271,"categories":272,"children":-1},"Hack In Paris 2022 conférence cybersécurité de l’année","\u002Fblog\u002Fhack-in-paris-2022-conference-cybersecurite-de-lannee","blog\u002Fhack-in-paris-2022-conference-cybersecurite-de-lannee","2022-06-19","\u002Fimages\u002Fblog\u002Fhack-in-paris-2022-conference-cybersecurite-de-lannee\u002F8ad6403cd6.png",[273],"Évènement",{"title":275,"path":276,"stem":277,"date":278,"cover":279,"categories":280,"children":-1},"Déployer Microsoft Defender ATP avec Ansible","\u002Fblog\u002Fdeployer-microsoft-defender-atp-avec-ansible","blog\u002Fdeployer-microsoft-defender-atp-avec-ansible","2022-05-28","\u002Fimages\u002Fblog\u002Fdeployer-microsoft-defender-atp-avec-ansible\u002F20b08b6e35.jpg",[242],{"title":282,"path":283,"stem":284,"date":245,"cover":285,"categories":286,"children":-1},"Configuration de Terraform Scaleway\u002FOVHcloud","\u002Fblog\u002Fblog-configuration-terraform-scaleway-ovhcloud","blog\u002Fblog-configuration-terraform-scaleway-ovhcloud","\u002Fimages\u002Fblog\u002Fblog-configuration-terraform-scaleway-ovhcloud\u002Fce5716efc3.png",[242],{"title":288,"path":289,"stem":290,"date":291,"cover":292,"categories":293,"children":-1},"Gérez votre parc informatique avec GLPI","\u002Fblog\u002Fcertificat-gerez-votre-parc-informatique-avec-glpi","blog\u002Fcertificat-gerez-votre-parc-informatique-avec-glpi","2022-01-12","\u002Fimages\u002Fblog\u002Fcertificat-gerez-votre-parc-informatique-avec-glpi\u002Fb3a9f2486c.jpg",[264],{"title":295,"path":296,"stem":297,"date":298,"cover":299,"categories":300,"children":-1},"Sécurisez vos infrastructures","\u002Fblog\u002Fcertificat-securisez-vos-infrastructures","blog\u002Fcertificat-securisez-vos-infrastructures","2021-10-29","\u002Fimages\u002Fblog\u002Fcertificat-securisez-vos-infrastructures\u002Fdcf3ea9308.jpg",[264,301],"Sécurité",{"title":303,"path":304,"stem":305,"date":306,"cover":307,"categories":308,"children":-1},"En route vers l’électrique avec Tesla","\u002Fblog\u002Fen-route-vers-electrique-avec-tesla","blog\u002Fen-route-vers-electrique-avec-tesla","2021-07-07","\u002Fimages\u002Fblog\u002Fen-route-vers-electrique-avec-tesla\u002F7dec469e8d.jpg",[273],{"title":310,"path":311,"stem":312,"date":313,"cover":314,"categories":315,"children":-1},"Stormshield Network Administrator","\u002Fblog\u002Fcertificat-stormshield-network-administrator","blog\u002Fcertificat-stormshield-network-administrator","2021-04-12","\u002Fimages\u002Fblog\u002Fcertificat-stormshield-network-administrator\u002Fca545c454a.png",[264,301],[317],{"id":318,"title":319,"body":320,"categories":378,"cover":379,"cover_contain":380,"credly_badge_id":381,"date":382,"description":383,"extension":247,"meta":384,"navigation":156,"path":385,"related_certifications":244,"seo":386,"slug":251,"stem":387,"__hash__":388},"blog\u002Fblog\u002Fcertificat-lpi-linux-essentials-exam-010-150.md","LPI Linux Essentials – Exam 010-150",{"type":7,"value":321,"toc":374},[322,324,327,334,363,369,371],[10,323,13],{"id":12},[15,325,326],{},"Pour fiabiliser mes interventions sur des serveurs Linux en clientèle, j'ai passé cette certification LPI Linux Essentials.",[15,328,329,330,333],{},"Le parcours de formation \"LPI Linux Essentials\" est dédié aux professionnels des systèmes.",[331,332],"br",{},"\nLe catalogue de cours en ligne aborde les modules suivants :",[335,336,337,343,348,353,358],"ul",{},[338,339,340],"li",{},[21,341,342],{},"Communauté Linux et carrière dans le logiciel libre",[338,344,345],{},[21,346,347],{},"Trouver son chemin sur un système Linux",[338,349,350],{},[21,351,352],{},"Le pouvoir de la ligne de commande",[338,354,355],{},[21,356,357],{},"Le système d'exploitation Linux",[338,359,360],{},[21,361,362],{},"Sécurité et droits d'accès aux fichiers",[15,364,365,366,368],{},"le temps à accorder à la formation est d'environ 2 jours.",[331,367],{},"\nIl faut ensuite prévoir environ 1h pour le passage de la certification : LPI Linux Essentials.",[10,370,216],{"id":215},[15,372,373],{},"Cette formation via NDG prépare à la certification LPI Linux Essentials, en couvrant les bases de l'écosystème Linux : ligne de commande, système d'exploitation et sécurité des fichiers. Elle constitue une première certification solide pour toute personne débutant sur les systèmes Linux. Un socle indispensable avant d'aborder des certifications Linux plus avancées.",{"title":68,"searchDepth":82,"depth":82,"links":375},[376,377],{"id":12,"depth":82,"text":13},{"id":215,"depth":82,"text":216},[264,242],"\u002Fimages\u002Fblog\u002Fcertificat-lpi-linux-essentials-exam-010-150\u002F4497f02702.jpg",false,"dbc3a0e7-5909-47df-b9b1-c05ecb60ccb4","2017-11-24","Certification LPI Linux Essentials Exam 010-150 via un cours en ligne NDG.",{},"\u002Fblog\u002Fcertificat-lpi-linux-essentials-exam-010-150",{"title":319,"description":383},"blog\u002Fcertificat-lpi-linux-essentials-exam-010-150","dWE6IEkGgqM6lYMKZ-nr8Wu-9p_hkgSwca7ZOpKGQtQ",1786644871034]