diff --git a/shoblog/nginx/cover.jpg b/shoblog/nginx/cover.jpg new file mode 100644 index 0000000..5ed36b3 Binary files /dev/null and b/shoblog/nginx/cover.jpg differ diff --git a/shoblog/nginx/nginx.md b/shoblog/nginx/nginx.md new file mode 100644 index 0000000..8939762 --- /dev/null +++ b/shoblog/nginx/nginx.md @@ -0,0 +1,167 @@ +--- +options: + command_prefix: "pr:" +theme: + name: tokyonight-storm + override: + default: + # colors: + # foreground: "4c4f69" + # background: "ffffff" + code: + alignment: center + palette: + colors: + base00: "24283B" + base01: "16161E" + base02: "343A52" + base03: "444B6A" + base04: "787C99" + base05: "A9B1D6" + base06: "CBCCD1" + base07: "D5D6DB" + base08: "C0CAF5" + base09: "A9B1D6" + base0A: "0DB9D7" + base0B: "9ECE6A" + base0C: "B4F9F8" + base0D: "2AC3DE" + base0E: "BB9AF7" + base0F: "F7768E" +--- + +static websites with nginx +=== +```file +line_numbers {1-20} +path: nginx.nix +language: nix +``` +On se retrouve pour la suite de notre introduction à **nix** et **nixos**, +j'essaye un nouveau format ainsi que de rajouter un glossaire à la fin, aujourd'hui +on parle de la partie serveur et déploiement avec nginx, alors comme ont dis au States: +buckle up bookaroo. +# album du jour +## once in a long long while - low roar +![](./cover.jpg) + +introduction +=== +```file +line_numbers {1-20} +path: nginx.nix +language: nix +``` +Sous **nixos**, il est possible de définir la configuration réseau du système +de façon déclarative, ainsi que des services, qui sont généralement des daemons +que l'on peut configurer via nix. +Sous le capot, cette configuration va être +interprétée par **nix** en des options de plus en plus bas niveau, jusqu'à générer +les commandes **bash** et les **fichiers de configurations** nécessaires à l'application +de la configuration demandée. +Ainsi, ultimement, cette configuration va nous générer un fichier de configuration +**nginx** correspondant à notre virtualhost, ainsi que les commandes nécessaires +pour lancer nginx (et l'installer évidemment) +![](./nix_nginx.png) + + +Paramètres généraux +=== +```file +line_numbers {1, 16-19} +path: nginx.nix +language: nix +``` +Sous nixos, la configuration du système est composée de modules, chaque module +est une fonction prenant un certain nombre de paramètres et retournant un set +d'options décrivant la configuration de notre système. +Au moment de builder cette dernière, tous les modules sont fusionnés afin de donner +la configuration finale à appliquer, puis cette dernière est interprétée par nix. +```nix +line_numbers +{inputs, ...}: { + # ... +} +``` +On commence notre module en définissant les arguments d'entrée de ce dernier, +les `...` agissent comme une wildcard, nous autorisant à fournir plus d'argument +d'entrée dans l'appel de la fonction que ce que cette dernière ne vas actuellement +utiliser. Ce pattern permet à nix de laisser au module la liberté de déclarer +uniquement les dépendances dont il a besoin. +Ici, on déclare un argument `inputs` +dont la déclaration est en dehors du scope de cet article, mais qui contient les +dépendances de notre configuration, incluant le site packager dans l'article +précédent. +```nix +line_numbers +security.acme = { + acceptTerms = true; + defaults.email = "lelu.awen@proton.me"; +}; +``` +l'option `services.nginx` de nixos permet d'automatiquement manager l'obtention +et le renouvellement des **certificats ssl**, par défaut, **let's encrypt** est utilisé, +mais n'importe quel CA peut être utiliser pourvu qu'il supporte le protocole +ACME. Afin d'utiliser ce service, il est nécessaire d'en accepter les conditions +d'utilisations ainsi que de fournir un email. + +Paramètres de Nginx +=== +```file +line_numbers {2-6, 15} +path: nginx.nix +language: nix +``` +Par défaut, nginx va écouter sur les ports 80 (pour les requètes http) et 443 +(pour SSL), on dit donc au firewall d'ouvrir les ports correspondants. +On active ensuite le service Nginx de nixos, qui vas se charger d'installer la +dernière version et de créer les units systemctl nécessaire à son fonctionnement. +Ce service propose un bon paquet d'options, mais on va ici voir uniquement la base. +Les options `recommendedTlsSettings` et `recommendedProxySettings` vont automatiquement +ajouter un set de paramètre à la conf générée de chaque virtualhost, à moins que +cette option ne soit set à la négative au niveau du dit host. + +Paramètres du virtualhost +=== +```file +line_numbers {7-14} +path: nginx.nix +language: nix +``` +Et voici l'option qui nous intéresse ici, cette option est un genre de dictionnaire, +chaque clé correspond à un nom de domaine sur lequel notre virtualhost sera mapper, +et la configuration propre à ce dernier. Voyons ça en détail: + +`enableACME` dit à nixos que l'on souhaite utiliser le module ACME pour ce virtualHost, +en utilisant ce dernier, il vas aller demander un certificat à let's encrypt qui +correspond au domaine de notre vhost, et renouveler ce dernier régulièrement avant +chaque expiration. De plus, il va aussi ajouter la configuration néscéssaire pour +que notre vhost prenne en charge les requêtes HTTPS. + +`forceSSL` force notre vhost à rediriger les requêtes http vers le https. + +`root` définis le dossier que notre serveur va servir, et si ce dernier contient +un fichier `index.html`, c'est ce fichier qui va être servis par défaut. L'astuce +ici est d'utiliser directement le paquet composé de notre site packager précédement, +après avoir pris soins d'ajouter celui-ci aux inputs de notre configuration, il se +retrouve accessible via l'argument `input..packages..default`. +Au moment de l'interprétation du fichier par nix, cette variable va interpoler +avec le chemin du paquet dans le nix store (un truc du genre /nix/store/zf9kgk4fkrpjl21i26bmpbsn7q01x6lm-shoblog-front), +qui contient tout nos assets statiques. +![](./terminal-ls.png) +Et voilà ! Un petit `nixos-rebuild switch` et le système lire notre config, télécharger +les paquets manquants, builder notre site, copier les assets dans le store, créer +notre virtualhost et demander les certificats. Et le plus beau c'est que si l'on +met à jour notre application, il nous suffit juste de pousser les modifications +sur notre repo et de dire à nix de checker si il y a eu des mises à jour dans ses +inputs et ce dernier vas checker le repo pour des nouveaux comits sur la branche +qu'il surveille et, le cas avenant, pull la nouvelle version, la build, et relancer +les services correspondant comme un grand. + +Glossaire +=== +nixos: distribution linux à la configuration déclarative basée sur le package mnager **nix** +nix: package manager servant à définir des environnements logiciels de manière +déclarative et reproductible +daemon: logiciel fonctionnement en arrière-plan, de façon transparente à l'utilisateur. +bash: interpréteur de commande pour les OS de type UNIX permettant d'interagir +directement avec ce dernier. +nginx: serveur web et reverse proxy assez commun et open source. +virtualhost: dans le contexte de nginx, ensemble de la configuration associée à un +domaine. +certificat ssl: fichier attestant de l'identité d'un domaine. +**C**ertificat **A**uthority: Organisation fournissant des certificats aux propriétaires +d'un domaine et servant de garantie à la validité de ces derniers. diff --git a/shoblog/nginx/nginx.nix b/shoblog/nginx/nginx.nix new file mode 100644 index 0000000..b97f5a2 --- /dev/null +++ b/shoblog/nginx/nginx.nix @@ -0,0 +1,20 @@ +{inputs, ...}: { + networking.firewall.allowedTCPPorts = [ 80 443 ]; + services.nginx = { + enable = true; + recommendedProxySettings = true; + recommendedTlsSettings = true; + virtualHosts = { + "shobu.fr" = { + enableACME = true; + forceSSL = true; + + root = "${inputs.shoblog-front.packages.x86_64-linux.default}/dist"; + }; + }; + }; + security.acme = { + acceptTerms = true; + defaults.email = "lelu.awen@proton.me"; + }; +} diff --git a/shoblog/nginx/nix_nginx.png b/shoblog/nginx/nix_nginx.png new file mode 100644 index 0000000..ab0488d Binary files /dev/null and b/shoblog/nginx/nix_nginx.png differ diff --git a/shoblog/nginx/terminal-ls.png b/shoblog/nginx/terminal-ls.png new file mode 100644 index 0000000..455e5a3 Binary files /dev/null and b/shoblog/nginx/terminal-ls.png differ diff --git a/shoblog/vuejs/shoblog_code.nix b/shoblog/vuejs/shoblog_code.nix new file mode 100644 index 0000000..994d0af --- /dev/null +++ b/shoblog/vuejs/shoblog_code.nix @@ -0,0 +1,47 @@ +{ + description = "developpement and deployment flake for shoblog"; + + inputs.nixpkgs.url = "github:nixos/nixpkgs/nixos-25.05"; + + outputs = { self, nixpkgs }: + let + supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" "aarch64-darwin" ]; + forEachSupportedSystem = f: nixpkgs.lib.genAttrs supportedSystems (system: f { + pkgs = import nixpkgs { inherit system; config.allowUnfree = true; }; + }); + in + { + devShells = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkShell { + packages = with pkgs; [ nodejs yarn jetbrains.webstorm yarn2nix ]; + }; + }); + + packages = forEachSupportedSystem ({ pkgs }: { + default = pkgs.mkYarnPackage { + name = "shoblog-front"; + src = ./.; + + packageJSON = ./package.json; + yarnLock = ./yarn.lock; + yarnNix = ./yarn.nix; + + buildPhase = '' + runHook preBuild; + mkdir $TEMPDIR/dist + yarn run build --outDir $TEMPDIR/dist; + runHook postBuild; + ''; + + installPhase = '' + runHook preInstall + mkdir -p $out/ + cp -r $TEMPDIR/dist/ $out/ + runHook postInstall + ''; + + distPhase = ''true''; + }; + }); + }; +} diff --git a/shoblog/vuejs/vue.md b/shoblog/vuejs/vue.md new file mode 100644 index 0000000..9252503 --- /dev/null +++ b/shoblog/vuejs/vue.md @@ -0,0 +1,172 @@ +--- +options: + command_prefix: "pr:" +theme: + name: tokyonight-storm + override: + default: + # colors: + # foreground: "4c4f69" + # background: "ffffff" + palette: + colors: + base00: "24283B" + base01: "16161E" + base02: "343A52" + base03: "444B6A" + base04: "787C99" + base05: "A9B1D6" + base06: "CBCCD1" + base07: "D5D6DB" + base08: "C0CAF5" + base09: "A9B1D6" + base0A: "0DB9D7" + base0B: "9ECE6A" + base0C: "B4F9F8" + base0D: "2AC3DE" + base0E: "BB9AF7" + base0F: "F7768E" +--- + + + +# Définition des environnements de développement du package +* on défini un seul +environnement (**default**) +* la fonction **forEachSupportedSystem** à pour +fonction de générer un élément pour chaque architecture supportée par le package + * ces architectures sont définie à la ligne 8 et correspondent aux architectures + supportée par nix. +* Dans cet environnement, on fournis les packages suivants + * **nodejs** + c'est un projet vue.js, donc faut bien un runtime + * **yarn** + ici on préfèrera yarn pour pouvoir utiliser yarn2nix afin de générer les + dépendances. + * webstorm + * je l'installe que pour ce projet, donc ça me permet de le garbage collecter + quand j'en ai pas besoin (merci nix) + * **yarn2nix** + * yarn2nix est un outil qui vas lire notre fichier package.json et générer + un fichier yarn.nix avec toutes nos dépendances packager pour nix, pour des + question de reproductibilité, lors du build avec nix, les outils n'ont pas accès + à internet, il n'est donc pas possible de juste faire un "yarn add". + +```file +line_numbers {13-18} +path: shoblog_code.nix +language: nix +``` + + + + +# Définition des packages + +* d'une manière similaire aux **devShells**, on vas ici générer un package par +architecture supportée. Lors du build (qui se fait généralement localement), +nix va néanmoins builder uniquement le package correspondant à l'architecture +de la machine. +* Pour ce faire, on utilise la fonction +**mkYarnPackage** qui fournit diverses options pour générer un package +manager par **Yarn** + * **name**: assez explicite, le nom du package générer + * **src**: les source sur lequel la fonction va se baser pour générer le package + * **PackageJSON**: package.json + * **yarnLock**: yarn.lock + * **yarnNix**: Ah ! C'est ici qu'on + retrouve notre fameux **yarn.nix**. + * En fait, lors du process de build et pour + pour des raisons de reproductibilité, les programmes n'ont pas accès à internet. Chez nix, + toutes les dépendances doivent être connue et regroupée à l'avance. Pour ce faire, + **yarn2nix** nous génère un fichier **yarn.nix** définissant sous forme de package + nix toutes les dépendances de notre projet, ainsi lors du build, nix vas toutes + les pull, donner le résultat à mkYarnPackage qui vas les installer dans son + environnement de build. + * Et pour finis, les phases de notre build. Par défaut, **mkYarnPackage** va + juste chercher à build un binaire basée sur la configuration de notre package.json, + dans notre cas + +```file +line_numbers {20-45} +path: shoblog_code.nix +language: nix +``` + + + + +## buildPhase +Le build d'un package sous nix est découpé en plusieurs phases, si la plupart +sont généralement transparente, celons le cas, certaines ont besoin d'être +override en fonction des besoins. Ici, l'on cherche à packager des assets statiques, donc: +* première étape, appeler `runhook preBuild`, rien à voir avec notre affaire, mais +cela permet à d'éventuel futur dev de venir surcharger notre package sans toucher +à notre buildphase, chaque phase à des pré et post hook de la même manière. +* `mkdir $TEMPDIR/dist`, on créer un dossier temporaire pour nos fichiers de build +* `yarn run build --outDir $TEMPDIR/dist`, on run notre script de build en précisant +notre dossier temporaire comme output +* et on run le hook de postBuild + + +```file +line_numbers {29-34} +path: shoblog_code.nix +language: nix +``` + + + + +## installPhase +Cette phase a pour rôle de placer les fichiers résultant du build dans le store +de nix, je passe sur les hook qu'on à déjà vu précédemment +* `mkdir -p $out/`, **$out** est une variable spécifique à cette phase de build +qui pointe vers le dossier final attribué par nix pour notre package. +* `cp -r $TEMPDIR/dist/ $out/`, on copie les fichiers de notre build dans le +dossier ainsi créer et zou ! :3 + + +```file +line_numbers {36-41} +path: shoblog_code.nix +language: nix +``` + + +## Résultat + Hop, un petit coup de `nix build` et sous vos yeux ébahis, nix nous pull toutes + nos dépendances, build notre projet et le place au chaud dans son store. \ + Bon c'est vachement bien tout ça, mais pourquoi faire ? + On verra les avantages en détails dans d'autres articles (peut-être même dès demain ? + mystère mystère...) mais voici déjà quelques bullet points + * Reproductibilité + * Nix nous assure que, pour des entrées données, le résultat sera toujours le + même, ainsi, il nous est possible de pin un commit spécifique de nixpkgs pour + figer la release de notre paquet dans le temps. Contrairement à un package + manager plus classique (apt par exemple), lors du build de votre paquet, vous + serez ainsi assurer de toujours pull la même version de node tant que l'on + update pas le flake.lock du projet. + * Isolation + * Nix installe chaque dépendance dans un dossier appellé le **store**, chaque + dépendance étant installer dans un dossier au hash unique basé sur le nom du + package et sa version. Ce qui fait qu'il est parfaitement possible d'avoir + deux projets utilisant deux versions de node différentes sans aucun problème, + et ce sans avoir besoin de docker, d'environnement virtuel ou de faire mumuse + avec des liens symboliques. Bonus, si un autre projet nécessite la même version + de node, nix va simplement utiliser celle déjà installer, ce qui évite les + duplicatas. + * Tracking + * étant donné que toutes les dépendances de chaque package sont déclarées dans + le `flake.nix`, il suffit de lire ce dernier pour savoir quels paquets sont + nécessaires à son déploiement. De plus, si l'on enlève un paquet de l'environnement, + nix vas pouvoir checker si ses dépendances sont utiliser par d'autres paquets, + et dans la négative, les supprimer pour économiser la place. + * Configuration + * Un peu hors du scope de cet exemple, mais il est possible de définir une + fonction d'override pour un paquet afin de permettre à l'utilisateur final + de ce dernier de spécifier des paramètres à ce dernier au moment du build. + Que ce sois l'utilisation d'une version spécifique de node, ou une clé d'API + par exemple. + * en utilisant NixOS, il est possible de définir des **modules** que + l'utilisateur peut importer dans la configuration de son système afin de + déclarer des services, installer et configurer d'autres packages, configurer + des interfaces réseaux, ect... Cela peut permettre d'automatiser grandement + le déploiement de certains projets et de grandement organiser ses configurations + (comme avec la déclaration de virtualhost nginx par exemple, teasing teasing...)