diff --git a/pr/119/.well-known/mta-sts.txt b/pr/119/.well-known/mta-sts.txt deleted file mode 100644 index 740174fd..00000000 --- a/pr/119/.well-known/mta-sts.txt +++ /dev/null @@ -1,6 +0,0 @@ - -version: STSv1 -mode: enforce -mx: mail.protonmail.ch -mx: mailsec.protonmail.ch -max_age: 1209600 \ No newline at end of file diff --git a/pr/119/.well-known/security.txt b/pr/119/.well-known/security.txt deleted file mode 100644 index 6a418ea6..00000000 --- a/pr/119/.well-known/security.txt +++ /dev/null @@ -1,3 +0,0 @@ -Contact: security@rix.fr -Expires: Wed, 1 Jan 2030 00:00 +0200 -Encryption: https://keys.openpgp.org/vks/v1/by-fingerprint/67B08D2BE9C8ACC2C40D28F1F69D39C94B03BD79 diff --git a/pr/119/404.html b/pr/119/404.html deleted file mode 100644 index af039a7c..00000000 --- a/pr/119/404.html +++ /dev/null @@ -1,270 +0,0 @@ - - - - - - - Page introuvable - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
-
-
-

- Erreur - 404 -

-

La page que vous recherchez n'existe pas ou a été supprimée.

-

Que voulez-vous faire ?

- -
-
-
- - - - - - diff --git a/pr/119/a-propos/index.html b/pr/119/a-propos/index.html deleted file mode 100644 index 399f4f1c..00000000 --- a/pr/119/a-propos/index.html +++ /dev/null @@ -1,413 +0,0 @@ - - - - - - - Rix 🐺 - À propos de nous. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
- -

- Histoire - Notre histoire -

-
-
-
-
    -
  • -

    Analyse

    -

    Parce que nous avons évolué au plus près des équipes de développement, nous savons qu'il est essentiel de bien comprendre le métier et d'assimiler ses contraintes.

    -
  • -
  • -

    Exploitation

    -

    Parce que nous sommes issus de l’exploitation nous avons la prétention d’avoir une bonne vision des problématiques de mise en oeuvre d’une application web moderne. Et bien évidemment de son maintien en conditions opérationnelles.

    -
  • -
  • -

    Hébergement

    -

    Spécialistes de l’hébergement des applications PHP/ Symfony métier sur-mesure nous avons au cours de notre expérience été confrontés à beaucoup des situations que vous rencontrez peut-être aujourd’hui.

    -
  • -
-
-
-

- Nos valeurs - «Profile, don't assume !» -

-
-
    -
  • -
    - -

    Anticiper

    -
    - Personne n’aime travailler en plein incident, nous mettons un point d’honneur à essayer d’anticiper les plus courants et quand nous n'y arrivons pas à effectuer un diagnostique précis et rapide. -
  • -
  • -
    - -

    Préserver et sécuriser

    -
    - Vos données sont le coeur de votre métier. Nous nous efforçons de toujours être irréprochables quant à leur conservation, à leur intégrité et à leur sécurité. -
  • -
  • -
    - -

    Accompagner

    -
    - Nous avons conscience que nos métiers se sont énormément complexifiés, nous proposons toujours la solution qui nous semble le mieux convenir au contexte actuel d'un client sans jamais oublier que ce projet va évoluer, se transformer et grandir. -
  • -
-
-
-
-
-
- -
-
-

- Notre équipe - Notre meute, c'est notre force -

-

Nous sommes soudés et fiers de l'être depuis de nombreuses années.

- -
-
-
- - - - - - diff --git a/pr/119/android-chrome-192x192.png b/pr/119/android-chrome-192x192.png deleted file mode 100644 index 751e5e92..00000000 Binary files a/pr/119/android-chrome-192x192.png and /dev/null differ diff --git a/pr/119/apple-touch-icon.png b/pr/119/apple-touch-icon.png deleted file mode 100644 index 229f5b3f..00000000 Binary files a/pr/119/apple-touch-icon.png and /dev/null differ diff --git a/pr/119/blog/cours/cle-ssh-principes-de-base/index.html b/pr/119/blog/cours/cle-ssh-principes-de-base/index.html deleted file mode 100644 index 1c9f8fc4..00000000 --- a/pr/119/blog/cours/cle-ssh-principes-de-base/index.html +++ /dev/null @@ -1,480 +0,0 @@ - - - - - - - Principes de base de l'utilisation de clés SSH. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Cours -
  • -
  • - #Ssh -
  • -
  • - #HowTo -
  • -
-

Principes de base de l'utilisation de clés SSH.

-

Génération, utilisation et cas pratiques d'utilisation de clés SSH.

-
-
    -
  1. - Pré-requis -
  2. -
  3. - TL;DR -
  4. -
  5. - Génération d'une paire de clés -
  6. -
  7. - Se connecter à un serveur distant -
  8. -
  9. - Compléments -
  10. -
  11. - Aller plus loin avec les sources -
  12. -
- -
-
-

Une clé SSH est un moyen d'authentification vers un serveur SSH reposant sur les principes de cryptographie asymétrique et d'authentification défi / réponse.

-

Elle a deux avantages fondamentaux comparativement avec une authentification par couple identifiant/mot de passe:

-
    -
  • Permettre une authentification facilité (plus de mot de passe à mémoriser) et plus rapide (possibilité de rebond de serveur à serveur par exemple).
  • -
  • Se prémunir des attaques de type force brute
  • -
-

La très grande majorité des accès serveurs sont aujourd'hui basés sur leur utilisation, au dela de l'aspect fluidité et sécurité, elle ouvre également la possibilité d'authorisation multiple (sur plusieurs serveurs), de révocation et de signature des accès facilités.

-
-

Secure Shell (SSH)

-

- Secure Shell (SSH) est à la fois un programme informatique et un protocole de communication sécurisé. - Le protocole de connexion impose un échange de clés de chiffrement en début de connexion. Par la suite, tous les segments TCP sont authentifiés et chiffrés. Il devient donc impossible d'utiliser un sniffer pour voir ce que fait l'utilisateur. - Le protocole SSH a été conçu avec l'objectif de remplacer les différents protocoles non chiffrés comme rlogin, telnet, rcp et rsh. -

-
-

Pré-requis

-
    -
  • Avoir un client SSH installé (OpenSSH pour Linux/OSX et Windows à présent ou encore Putty pour Windows)
  • -
  • Une ligne de commande ( le truc noir dans lequel on tape du texte ;) )
  • -
-

TL;DR

-

Génération d'une paire de clés:

-
ssh-keygen -t ed25519 -a 150
-

Se connecter à un serveur distant

-
ssh -i ~/.ssh/id25519 user@server_address
-

Génération d'une paire de clés

-

Le principe de l'authentification par clés repose, comme explicité sur les différents liens ci-dessus, par la création d'une paire de clés asymétriques. -L'une de ces clés sera votre clé publique à déployer sur les machines auxquelles vous avez le droit de vous connecter, l'autre, votre clé privée. Et comme son nom l'indique, celle-ci est à vous et rien qu'à vous ; elle ne se partage pas. JAMAIS.

-

Deux notions de base avant de se lancer pour bien comprendre ce que l'on fait:

-
    -
  • Il existe plusieurs types d'algorithmes de signature numérique, les plus répandus étant RSA et Ed25519;
  • -
  • Il est possible de spécifier la longueur de vos clés, ce paramètre est essentiel à leur robustesse.
  • -
-

Il est recommandé, à la date de rédaction de cet article, d'utiliser l'algorithme Ed25519 qui a plusieurs avantages comparativement à RSA:

-
    -
  • Robustesse accrue;
  • -
  • Plus petite taille de clés;
  • -
  • Génération des clés plus rapide.
  • -
-
ssh-keygen -t ed25519 -a 150 -C "courriel@example.com"
-
- -
- Génération d'une paire de clé SSH -
-
-

L'option -C permet d'ajouter un commentaire à votre clé, pratique notamment pour identifier le propriétaire d'une clé publique coté serveur.

-
-

Phrase de passe

-

- Bien que facultative, il est « extrêmement vachement recommandé » de disposer d'une phrase de passe sur vos clés SSH (dans le cadre des cours et pour gagner du temps il est possible de s'en passer si vous n'utilisez pas votre clé en dehors de ceux-ci). -

-
-

Cette commande vous aura généré deux fichiers dans le répertoire ~/.ssh/ (sauf si vous l'avez modifié bien évidemment):

-
    -
  • id_ed25519.pub (comme son extension l'indique c'est votre clé publique);
  • -
  • id_ed25519 votre clé privée (on remarquera les droits qui lui sont appliqués 0600, en effet seul votre utilisateur doit y avoir accès).
  • -
-
-

Générer une clé RSA

-

- Ed25519 n'étant de temps en temps pas supporté (surtout par les anciens systèmes) il est parfois nécessaire de générer une paire de clé RSA (on remarquera la longueur de clé de 4096 bits recommandée à date de rédaction de l'article): - ssh-keygen -t rsa -a 150 -b 4096 -

-
-

Se connecter à un serveur distant

-

C'est un peu la finalité. -Imaginons un serveur pour lequel votre clé est autorisée à se connecter (pour rappel fichier authorized_keys), nous pouvons initier une connexion à l'aide de la commande:

-

ssh user@server_address

-

Cette commande aura donc pour effet « d'ouvrir » une connexion sur un serveur distant via le protocol SSH vous permettant de saisir des lignes de commande directement sur ce serveur et donc de l'administrer.

-
- -
- Ouverture d'une session sur un serveur distant -
-
-

Cette exemple montre l'ouverture d'une session avec l'utilisateur debian sur le serveur ayant pour adresse IP 146.59.243.95.

-

Plusieurs choses à retenir à cette étape:

-
    -
  • Par défaut ssh parcourt les clés SSH privées disponibles dans le répertoire ~/.ssh afin de les proposer au serveur auquel vous essayez de vous connecter.
  • -
  • Vous optenez en retour la première fois que vous vous connectez un message vous demandant de confirmer la connexion vers le serveur distant (Host key checking).
  • -
-

Compléments

-

Si vous disposez de plusieurs clés SSH et que vous ne souhaitez pas que l'ensemble de vos clés privées soient soumises au serveur distant vous pouvez spécifier quelle clé utiliser en utilisant l'option -i.

-
ssh -i ~/.ssh/id25519 debian@146.59.243.95
-

Il est possible d'utiliser des syntaxes différentes en fonction de votre fichier de configuration SSH.

-

Vous pouvez ainsi agir sur les comportements par défaut de votre client SSH et notamment sur la clé à utiliser en fonction de tel ou tel serveur.

-

Aller plus loin avec les sources

- -
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/cours/docker-avec-windows-et-wsl/index.html b/pr/119/blog/cours/docker-avec-windows-et-wsl/index.html deleted file mode 100644 index 02d3d8bb..00000000 --- a/pr/119/blog/cours/docker-avec-windows-et-wsl/index.html +++ /dev/null @@ -1,460 +0,0 @@ - - - - - - - Faire fonctionner des conteneurs Docker dans WSL. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Cours -
  • -
  • - #Windows -
  • -
  • - #Docker -
  • -
  • - #Conteneur -
  • -
-

Faire fonctionner des conteneurs Docker dans WSL.

-

Avec l'intégration WSL2 de Windows et Docker Desktop, comment utiliser des conteneurs Docker dans une machine virtuelle WSL ?

-
-
    -
  1. - Pré-requis -
  2. -
  3. - Installer WSL 2 et lancer une machine virtuelle -
  4. -
  5. - Installer Docker Desktop -
      -
    1. - Configuration -
    2. -
    -
  6. -
  7. - Tester le fonctionnement de Docker dans une machine virtuelle WSL -
  8. -
  9. - Allez plus loin avec les sources -
  10. -
- -
-
-

Avec l'arrivée de Docker Desktop il est dorénavant aisé de faire « tourner » des conteneurs Docker sous Windows. -Il est par contre moins simple d'utiliser d'autres outils propres au monde UNIX que nous aurons besoin d'utiliser avec le Lazy Ansible de Manala (make par exemple).

-

Et comme nous préférons éviter d'installer trop de choses sur les machines hôtes nous opterons pour un fonctionnement qui reste relativement élégant à savoir lancer une machine WSL Debian et y faire tourner notre conteneur Docker. -De cette manière nous disposerons de l'ensemble de l'outillage Linux, sans avoir à l'installer sur notre poste.

-

Pré-requis

-
    -
  • Windows 10 au minimum
  • -
  • Installer terminal windows (pour le confort).
  • -
-

Installer WSL 2 et lancer une machine virtuelle

-
    -
  • S'assurer que l'on utilise bien la version 2 de WSL: wsl --set-default-version 2
  • -
  • Installer et lancer une machine virtuelle Debian: wsl --install -d Debian
  • -
-

Il faudra ensuite renseigner un nom d'utilisateur ainsi qu'un mot de passe (à ne pas perdre de préference). -Vous devriez au final obtenir un shell comme ci-dessous, félicitation vous êtes dans une machine virtuelle Debian WSL !

-
- Un shell WSL -
- Un shell WSL -
-
-

Installer Docker Desktop

-

La partie la plus simple, téléchargez et installez le ici: https://docs.docker.com/desktop/windows/wsl/#download

-

Configuration

-

Il y a quelques options à vérifier / activer pour un bon fonctionnement.

-
    -
  • Tout d'abord vérifier que le support de WSL 2 est activé dans les paramètres (Resources -> WSL integration);
  • -
-
- Les paramètres Docker Desktop -
- Les paramètres Docker Desktop -
-
-
    -
  • Ensuite vérifier que le support pour votre distribution est activé (Debian);
  • -
-

Tester le fonctionnement de Docker dans une machine virtuelle WSL

-

Il faudra pour cela quitter et relancer (Dans un PowerShell wsl -d Debian) votre machine virtuelle Debian. -Une fois à l'intérieur de celle-ci il sera nécessaire de donner les droits à votre utilisateur d'utiliser Docker en l'ajoutant au groupe du même nom.

-
usermod -a -G docker <username>
-

Pour terminer la commande docker ps devrait vous renvoyer l'écran ci-dessous:

-
- Ajouter un utilisateur au groupe docker -
- Ajouter un utilisateur au groupe docker -
-
-

Allez plus loin avec les sources

- -
- Crédits: photo de couverture par - - Jason Cooper - -
-
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/cours/utiliser-la-configuration-ssh-client/index.html b/pr/119/blog/cours/utiliser-la-configuration-ssh-client/index.html deleted file mode 100644 index 59e46de5..00000000 --- a/pr/119/blog/cours/utiliser-la-configuration-ssh-client/index.html +++ /dev/null @@ -1,561 +0,0 @@ - - - - - - - Utiliser le fichier de configuration SSH pour ses connexions distantes. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Cours -
  • -
  • - #Ssh -
  • -
  • - #HowTo -
  • -
-

Utiliser le fichier de configuration SSH pour ses connexions distantes.

-

Apprendre à utiliser le fichier de configuration SSH pour organiser ses options de connexion.

-
-
    -
  1. - Pré-requis -
  2. -
  3. - TL;DR -
  4. -
  5. - Pourquoi utiliser un fichier de configuration ? -
  6. -
  7. - Le fichier de configuration -
  8. -
  9. - Les instructions de configuration -
  10. -
  11. - Priorité des instructions -
  12. -
  13. - Séparer et inclure ses fichiers de configuration -
  14. -
  15. - Les instructions les plus courantes / utiles -
  16. -
  17. - Multiplexer ses connexions SSH -
      -
    1. - Exemple de fichiers de configuration avec multiplexage -
    2. -
    -
  18. -
  19. - Pour aller plus loin: -
  20. -
- -
-
-

Si vous vous connectez à plusieurs hôtes distants il y a fort à parier que vous ne mémorisez pas les subtilités de connexion propre à chacun d'entre eux (utilisateur spécifique, port non standard, options spécifiques…).

-

On a eu, il est vrai, l'occasion de croiser des façons originales de le faire, notamment à base d'alias Bash mais ça reste assez artisanal alors même que tout est prévu et qu'OpenSSH permet de définir un fichier de configuration propre à chaque utilisateur du système ;)

-

Cet article, principalement à destination des étudiant·e·s et des nouveaux arrivants dans le domaine saura sans doute également servir de pense bête aux confirmé·e·s !

-

Pré-requis

-

Ils sont plus que pauvre puisqu'un client OpenSSH et une machine distante à laquelle se connecter suffiront.

-

TL;DR

-

Contenu d'un fichier config d'un client SSH pour référence:

-
Host *
-    User rix
-    IdentityFile ~/.ssh/ed_25519.key
-    IdentityFile ~/.ssh/id_rsa.key
-    IdentitiesOnly yes
-    ForwardAgent yes
-

Pourquoi utiliser un fichier de configuration ?

-

Comme abordé dans l'introduction, il existe autant de manières de se connecter à un serveur avec SSH qu'il n'en existe (de serveurs), les principaux bénéfices que l'on peut retirer de cette utilsation:

-
    -
  • Ajouter de la cohérence dans votre façon de vous connecter à vos différentes machines ( et on aime ça la cohérence ! ) il est en effet possible de créer une configuration spécifique à un serveur ou alors propre à différentes machines partageant les mêmes spécifités de connexion.
  • -
  • Faciliter les connexions multiples, en créant des configurations aux contextes différents. Il est par exemple possible d'avoir une configuration utilisant une clé différente pour un groupe de machines données.
  • -
-

Le fichier de configuration

-

En « standard » vous trouverez un dossier appelé .ssh dans le répertoire utilisateur de votre système (/home/username/ sur un système de type UNIX ou C:\Users\username\sous Windows). C'est ici que nous allons créé un fichier appelé tout simplement config (sans extension).

-
-

Configuration globale

-

- Il est possible d'appliquer un comportement global au client SSH (C'est à dire pour tous les utilisateurs du système) en utilisant le fichier /etc/ssh/ssh_config. -

-
-

Si le répertoire .ssh n'existe pas (il est créé automatiquement lorsque vous créez une nouvelle clé par exemple) vous pouvez le créer comme suit:

-
mkdir -p ~/.ssh && chmod 0700 ~/.ssh
-

Pour ensuite créer le fichier config

-
touch ~/.ssh/config && chmod 0600 ~/.ssh/config
-
-

Les droits

-

- Attention SSH est très sensible (à juste titre) aux droits appliqués aux fichiers qu'il doit utiliser. - Le répertoire .ssh tout comme le fichier config ne doit être accessible, lisible et modifiable qu'à l'utilisateur propriétaire. -

-
-

Les instructions de configuration

-

Le fichier config est basé sur un système de paires clé/valeur organisées par section, une structure minimal d'un fichier de configuration pourrait être la suivante:

-
Host server-hostname-1
-    KEY value
-    KEY value
-

Allons plus loin avec une configuration:

-
Host server-hostname-1
-    HostName server.tld
-    User rix
-    IdentityFile ~/.ssh/ed_25519.key
-

La directive Host permet d'indiquer à la fois une nouvelle section mais également le « pattern » qui permettra au client de savoir quand appliquer la configuration. -Dans ce premier exemple c'est assez simple et spécifique puisque notre bloc s'appliquera à la chaine server-hostname-1

-

Ainsi lorsque nous taperons ssh server-hostname-1 notre client saura à quel hote se connecter, avec quel utilisateur et quelle clé. -L'équivalent sans fichier de configuration serait ssh -i ~/.ssh/ed_25519.key rix@server.tld

-

L'utilisation d'un fichier de configuration prend tout son sens lorsque l'on souhaite appliquer des comportements spécifiques à un ensemble de machines.

-

Il est ainsi possible d'utiliser des « pattern » (et de les enchaîner) en utilisant des opérateurs:

-
    -
  • Host * par exemple s'appliquera à tous les hôtes puisque le caractère * correspond à aucun ou plusieurs caractères.
  • -
  • 192.168.140.* il est possible de composer, dans ce cas vous appliquerez votre configuration à l'ensemble des hôtes dont l'adresse fait partie du sous réseau 192.168.140.0/24
  • -
  • ? permet de restreindre une expression à un seul caractère. Ainsi Host 172.16.1.? correspondra à tous les hôtes ayant en dernier octet un chiffre compris entre 0 et 9.
  • -
  • ! En début de chaîne permet d'exclure une correspondance. Ainsi 172.16.1.* !172.16.1.20 s'appliquera à tous les hôtes du sous réseau 172.16.1.0/24 à l'exception de 172.16.1.20.
  • -
-
-

Organisation et structure du fichier

-

- Le fichier de configuration SSH n'impose pas d'indentation, il est toutefois fortement recommandé de l'organiser afin de faciliter sa lecture et sa maintenance. - Il faut également noter que les instructions sont appliquées dans leur ordre d'apparition il est donc préférable de commencer par les sections très spécifiques et de terminer par les plus génériques. -

-
-

Priorité des instructions

-

Il est possible en fonction d'où elles sont indiquées de surcharger certaines options de connexion, ainsi votre client SSH considérera par ordre de priorité:

-
    -
  • Les options spécifiées dans la ligne de commande
  • -
  • Les options définies dans le fichier config du compte utilisateur (~/.ssh/config)
  • -
  • Les options définies dans le fichier générique /etc/ssh/ssh_config
  • -
-

Ainsi en reprendant notre section précédente:

-
Host server-hostname-1
-    HostName server.tld
-    User rix
-    IdentityFile ~/.ssh/ed_25519.key
-

Il est possible de vous connecter avec un autre utilisateur que celui défini dans votre fichier en surchargeant la clé User, soit avec ssh root@server-hostname-1 ou encore ssh -o "User=root" server-hostname-1.

-

Séparer et inclure ses fichiers de configuration

-

Il est également possible, notamment lorsque le contenu des fichiers devient conséquent ou tout simplement pour organiser ses configurations entre différents contextes (clients, perso, pro...), de séparer la configuration dans plusieurs fichiers.

-

Il est ainsi possible d'avoir autant de fichiers de configuration que de contextes pour ensuite les inclure dans notre fichier principal.

-

Exemple:

-
# Contenu de ~/.ssh/config
-Host server-hostname-1
-    HostName server.tld
-    User rix
-    IdentityFile ~/.ssh/ed_25519.key
-
-Include ~/.ssh/config_alternative
-
# Contenu de ~/.ssh/config_alternative
-Host 192.168.140.*
-    User debian
-    IdentityFile ~/.ssh/id_rsa.key
-    AddKeysToAgent yes
-    UseKeychain yes
-

Les instructions les plus courantes / utiles

-

Le fichier config supporte nombre d'options de configuration, celles-ci sont consultables ici. -Il va de soi que dans l'activité quotidienne, les mêmes instructions sont souvent utilisées, ci-dessous une liste des plus courantes:

-
    -
  • IdentityFile: Nous l'avons vu précédemment, elle permet d'indiquer la clé à utiliser pour la section définie;
  • -
  • ForwardAgent: Un grand classique, permet de « faire suivre » comme son nom l'indique au serveur distant, votre clé privée de manière à ce que celui-ci la stocke dans son propre agent SSH. Cette option permet ensuite de se connecter à d'autres serveurs « par rebond », c'est ce principe qui est notamment mis en oeuvre par les « bastions » SSH;
  • -
  • IdentitiesOnly: Important si vous utilisez l'option précédente, permet de ne transmettre que la ou les clé(s) spécifiée(s) avec l'option IdentityFile précédente, par défaut SSH envoie toutes les clés privées qu'il trouvera dans votre trousseau;
  • -
  • StrictHostKeyChecking: Permet de vérifier la signature du serveur auquel on se connecte, toujours à Yes sauf dans le cas de figure que l'on présente plus bas.
  • -
-
-

Désactiver StrictHostKeyChecking

-

- Précaution d'usage, à ne faire que si vous savez réellement ce que vous faites ;) - Le seul exemple qui me vient à l'esprit pouvant nécessiter de désactiver cette option est celui de séances de cours / TP durant lesquelles nous avons souvent besoin de créer / détruire des instances qui peuvent potentillement récupérer les mêmes adresses IPs. -

-
-

Pour éviter d'avoir régulièrement l'erreur, WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! il est possible de spécifier:

-
StrictHostKeyChecking no
-UserKnownHostsFile /dev/null
-

Multiplexer ses connexions SSH

-

Le principe du multiplexage réside dans le fait de « partager » la même connexion entre les différentes sessions ouvertes sur une même machine. -Cette stratégie permet, dans le cas d'SSH de réutiliser une connexion TCP déjà ouverte vers un serveur distant.

-

Le but ? S'épargner le délai d'ouverture d'une connexion TCP ainsi que celui de la réauthentification. -Cette fonctionnalité peut-être particulièrement utile lors du transfert de nombreux fichiers d'une machine à une autre, elle réside principalement en l'utilisation de 3 options de configuration:

-
    -
  • ControlMaster: Permet d'indiquer à SSH la stratégie à adopter lorsqu'il détecte une possibilité de réutilisation d'une connexion ouverte (Fixée à no par défaut);
  • -
  • ControlPersist: Permet d'indiquer comment SSH doit gérer la fermeture de la connexion initiale à la machine distante (celle qui a entrainée l'ouverture de la socket partagée);
  • -
  • ControlPath: Le chemin vers la socket utilisée pour le partage de connexion, cette option supporte les tokens %h %p et %r dont la combinaison est très fortement recommandée. Plus d'informations sur les tokens supportés par SSH (https://man.openbsd.org/ssh_config#TOKENS).
  • -
-

Exemple de fichiers de configuration avec multiplexage

-
Host server-hostname-1
-    HostName server.tld
-    User rix
-    IdentityFile ~/.ssh/ed_25519.key
-    ControlPath ~/.ssh/controlmasters/%C
-    ControlMaster auto
-    ControlPersist 10m
-
-

Le token %C

-

- On remarquera son utilisation dans l'exemple ci-dessus. Il s'agit du hash SHA1 des tokens %l%h%p%r (Respectivement le nom d'hôte local (%l), le nom d'hôte distant (%h), le port de connexion distant (%p) et pour finir le nom d'utilisateur distant utilisé (%r)). - L'utilisation du token %C assurant à la fois, l'unicité de la connexion et l'obfuscation de ses détails sur le système de fichiers. -

-
-

Pour aller plus loin:

- -
- Crédits: photo de couverture par - - Mohammad Rahmani - -
-
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/index.html b/pr/119/blog/index.html deleted file mode 100644 index c83c5265..00000000 --- a/pr/119/blog/index.html +++ /dev/null @@ -1,656 +0,0 @@ - - - - - - - Le blog de l'équipe Rix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - - -
-
-
-
- - -
-
-
-
- - - - - - diff --git a/pr/119/blog/linux/construire-image-debian-raspberry/index.html b/pr/119/blog/linux/construire-image-debian-raspberry/index.html deleted file mode 100644 index 533dcf21..00000000 --- a/pr/119/blog/linux/construire-image-debian-raspberry/index.html +++ /dev/null @@ -1,580 +0,0 @@ - - - - - - - Construire une image Debian pour Raspberry Pi - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Devops -
  • -
  • - #Linux -
  • -
  • - #Build -
  • -
  • - #Raspberry -
  • -
-

Construire une image Debian pour Raspberry Pi

-

Construire une image source Debian à déployer sur Raspberry Pi en remplacement de Raspberry Pi OS (anciennement Raspbian).

-
-
    -
  1. - TL;DR -
  2. -
  3. - Mise en contexte -
  4. -
  5. - Pourquoi reconstruire et pourquoi Debian ? -
  6. -
  7. - Pré-requis -
  8. -
  9. - Let's go ! -
      -
    1. - Configuration de l'image -
    2. -
    3. - Construction de l'image -
    4. -
    5. - Installation de l'image -
    6. -
    -
  10. -
  11. - Pour aller plus loin -
  12. -
- -
-
-

Je vous vois venir ! Quelle idée de vouloir construire sa propre image ? -Alors même que Raspberry fourni un OS ET un utilitaire permettant de créer des cartes SD « bootables » rapidement et quasi sans douleur !

-

TL;DR

-

Pour les opérations à suivre utilisez une Debian Bulleyes (de préférence VM)

-
    -
  1. Récupérer le dépôt avec les outils pour construire l'image; -
    git clone --recursive https://salsa.debian.org/raspi-team/image-specs.git
    -cd image-specs
  2. -
  3. Installer les différents paquets nécessaires à l'opération; -
    apt install -y vmdb2 dosfstools qemu-utils qemu-user-static debootstrap binfmt-support time kpartx bmap-tools python3
    -apt install -y fakemachine
  4. -
  5. Construire l'image (Pour l'exemple à destination d'un Raspberry Pi 4): make raspi_4_bullseye.img;
  6. -
  7. Écrire cette image sur une carte SD: dd if=raspi_4_bullseye.img of=/dev/XXX bs=64k oflag=dsync status=progress.
  8. -
-

Mise en contexte

-

Oui mais…

-

Avant d'aller plus loin il faut savoir que nous utilisons en interne plusieurs Raspberry Pi afin de faire tourner des services qui nous permettent de piloter la gestion du réseau local de nos bureaux et/ou d'y fournir des services basiques et non critiques (Serveurs DNS locaux, VPN, métriques, monitoring…).

-

Nous avons également une petite flotte de ces machines qui nous permettent d'aller enseigner « quelques trucs » à des étudiants (du réseau, du provisioning, linux…) en se reposant dessus.

-

Alors bien évidemment le besoin ne tombe pas du ciel, et même si l'exercice reste formateur et amusant (si, si) le but n'est bien évidemment pas « juste ludique ». -Raspberry Pi OS a en fait ses limites, particulièrement lorsqu'on va l'utiliser sur d'anciens Raspberry Pi (notamment des 2 ou précédents).

-

Pour terminer il faut savoir que Raspbian (dérivé de Debian) a été créé en premier lieu parce que jusqu'à 2018 il n'était pas possible de démarrer un kernel linux sur Raspberry Pi mais également parce que Raspbian arrivait avec des composants non libres contraires à la philosophie Debian.

-

Pourquoi reconstruire et pourquoi Debian ?

-
    -
  • En tout premier lieu parce que nous avons besoin d'avoir accès facilement à certains paquets non disponibles sur Raspberry Pi OS dans les versions dont nous avons besoin;
  • -
  • En second lieu parce que l'intégration de dépôts externes sur une base Raspberry Pi OS est parfois assez chaotique, notamment dû aux différentes architectures utilisées par les processeurs ARM des Raspberry Pi et de leur disponibilité (ou pas) dans ces mêmes dépôts.
  • -
-

On se retrouve notamment par défaut (il est possible d'aller chercher d'autres versions d'OS dans l'utilitaire de création d'images) avec une version de Raspberry Pi OS commune à toutes les versions et donc 32 bits

-

Pour rappel les premières architectures 64 bits des Raspberry Pi sont arrivées avec la version 3. -Debian fait le choix de coller exactement aux différentes archi, mais au prix d'une image pour chacune, celles-ci sont d'ailleurs disponibles ici.

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Version Raspberry PiDebianRaspberry Pi OS
0 / 1armel, 32 bitarmhf, 32 bit
2armhf, 32 bitarmhf, 32 bit
3arm64, 64 bitarmhf, 32 bit
4arm64, 64 bitarmhf, 32 bit
-

Il existe d'autres versions d'OS disponibles en version serveur ou desktop (Ubuntu, Manjaro…) mais comme nous utilisons les roles Ansible du projet Manala pour provisionner l'ensemble de nos machines et afin d'assurer au maximum la compatibilité (et nous éviter de la maintenance), nous préferons rester cohérents et utiliser Debian.

-

Pour terminer, les images pré-construites Debian peuvent carrément faire l'affaire mais certains choix de configuration ne nous vont pas et nous avons besoin que nos images soient prêtes à être « provisionnées » et donc disposer:

-
    -
  • de certains paquets;
  • -
  • de comptes utilisateurs spécifiques;
  • -
  • et bien évidemment de nos clés SSH pour l'authentification.
  • -
-

Pré-requis

-

Ils sont peu nombreux, tant la construction d'images est rendue très simple par les contributeurs à la version Raspberry Pi de Debian.

-

Vous aurez besoin:

- -

Let's go !

-

En tout premier lieu, une fois sur votre VM Debian Bullseye, on clone le répertoire d'outils:

-
git clone --recursive https://salsa.debian.org/raspi-team/image-specs.git
-cd image-specs
-

Nous aurons également besoin de quelques paquets pour la construction:

-
apt install -y vmdb2 dosfstools qemu-utils qemu-user-static debootstrap binfmt-support time kpartx bmap-tools python3
-apt install -y fakemachine
-

Le fichier makefile fournit vous permet ensuite, au choix:

-
    -
  • -

    De construire une image spécifique à votre Raspberry Pi en utilisant une configuration par défaut:

    -

    make raspi_<model>_<release>.img

    -
      -
    • <model> vaut pour la version de votre Raspberry (1,2,3 ou 4 avec 1 utilisé pour les versions Pi 0, 0w and 1);
    • -
    • <release> pour la version de Debian que vous souhaitez construire.
    • -
    -

    Dans notre cas une Bullseye pour un Raspberry Pi 2: make raspi_2_bullseye.img

    -
  • -
  • -

    De construire une image spécifique à partir de VOTRE configuration (et c'est ce choix qui nous intéresse)

    -
  • -
-

Configuration de l'image

-

Alors bien évidemment nous ne partirons pas d'une page blanche mais du fichier de configuration généré par l'outil grâce à la commande:

-

make raspi_2_bullseye.yaml

-

Nous obtenons un fichier de configuration par défaut (celui utilisé pour la construction de l'image avec la commande précédente). -Il est possible de l'éditer directement mais préférable de le nommer différemment histoire de ne pas malencontreusement écraser nos prochaines modifications en rejouant la commande précédente.

-

cp raspi_2_bullseye.yaml rix_raspi_2_bullseye.yaml

-

En ce qui nous concerne nous y opérerons plusieurs modifications:

-
    -
  • L'ajout d'un compte utilisateur non privilégié:
  • -
-
- chroot: tag-root
-    shell: |
-      useradd -g100 -Gsudo -m -s /bin/bash rix
-
    -
  • L'ajout des clés publiques SSH
  • -
-
- create-dir: /home/rix/.ssh
-    uid: 1000
-    gid: 100
-
- create-file: /home/rix/.ssh/authorized_keys
-    contents: |+
-      ssh-ed25519 AAAAC3XXXXXXXXXXXXXXXXXXXX
-
    -
  • L'ajout des droits sudo à notre utilisateur
  • -
-
- create-file: /etc/sudoers.d/rix-default
-    contents: |+
-      rix ALL=(ALL) NOPASSWD: ALL
-
    -
  • La suppression de la connexion root locale sans mot de passe.
  • -
-
- # Allow root logins locally with no password
-- sed -i 's,root:[^:]*:,root::,' "${ROOT?}/etc/shadow"
-
-

La directive chroot

-

- Elle est essentielle dès lors que vous souhaitez exécuter une commande dans le contexte du système en cours de construction. -

-
-

Construction de l'image

-

Une fois l'ensemble de nos instructions ajoutées à notre fichier nous pouvons démarrer la construction de notre image:

-
vmdb2 --rootfs-tarball=rix_raspi_2_bullseye.tar.gz --output \
-rix_raspi_2_bullseye.img rix_raspi_2_bullseye.yaml --log rix_raspi_bullseye.log
-

Cette commande devrait nous donner en sortie 3 fichiers:

-
    -
  • Un fichier de logs rix_raspi_bullseye.log
  • -
  • Un fichier image rix_raspi_2_bullseye.img
  • -
  • Un fichier image compressé rix_raspi_2_bullseye.tar.gz
  • -
-

Installation de l'image

-

L'installation de l'image est ensuite assez standard, une fois votre carte SD montée:

-
    -
  • Soit via bmaptool à partir de l'image compressée;
  • -
-

bmaptool copy rix_raspi_2_bullseye.tar.gz /dev/mmcblk0

-
    -
  • Soit via un bon vieux dd:
  • -
-

dd if=rix_raspi_2_bullseye.img of=/dev/XXX bs=64k oflag=dsync status=progress

-
-

- Attention à la « cible » de l'écriture, en cas de mauvais volume sélectionné vous écraserez son contenu. -

-
-

Vous voilà paré·e·s pour déployer du Raspberry Pi en série sur une base Debian !

-

Pour aller plus loin

-

Sources:

- -
- Crédits: photo de couverture par - - Jainath Ponnala - -
-
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/linux/integrer-icloud-gnome-calendar/index.html b/pr/119/blog/linux/integrer-icloud-gnome-calendar/index.html deleted file mode 100644 index e30f0b6f..00000000 --- a/pr/119/blog/linux/integrer-icloud-gnome-calendar/index.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - Intégrer des agendas iCloud à Gnome Calendar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Linux -
  • -
  • - #Icloud -
  • -
  • - #Calendar -
  • -
  • - #Gnome -
  • -
-

Intégrer des agendas iCloud à Gnome Calendar

-

Intégrer (relativement) facilement des agendas iCloud à Gnome Calendar

-
- -
-
-

Contrairement à ce que certains pensent on peut être utilisateur d'un iPhone (ou d'un iPad) sans avoir de mac.

-

Et oui c'est mon cas d'ailleurs ;) -Autant je ne changerais pas mon iPhone contre un Android (même si j'ai aussi un XPeria avec SailfishOS) autant je n'échangerais pas plus mon Linux contre un OSX.

-

Oui mais… bien qu'il devrait être très facile de synchroniser ses agendas iCloud avec Gnome (étant donné qu'iCloud propose un format CalDAV), la réalité n'est pas tout aussi simple !

-

Petit guide pour épargner les arrachages de cheveux pour y parvenir.

-

Les pré-requis

-
    -
  • Un compte iCloud, et oui…
  • -
  • Avoir créé un mot de passe d'application spécifique à votre client à partir de votre AppleID (C'est tout bien expliqué ici)
  • -
  • Installer Evolution sur votre machine (pas de panique c'est temporaire 😉).
  • -
-

Configurer vos agendas dans Evolution

-
-
-

En tout premier lieu, ouvrez l'onglet « Agenda » (vous serez pas défaut sur la vue « courriel ») une fois sur la partie agenda, créer en un nouveau comme ci-contre.

-
-
- Créer un nouvel agenda dans Evolution. -
-
-
- Informations de connexion à iCloud. -
-

Renseignez ensuite vos informations et suivez les étapes ci-contre.

-

-

    -
  • Sélectionnez le type d'agenda: CalDAV;
  • -
  • URL: https://caldav.icloud.com (Elle sera par la suite remplacée par l'adresse de l'agenda sélectionné);
  • -
  • Dans le champs utilisateur, votre Apple ID (En général votre adresse de courriel);
  • -
  • Appuyez enfin sur « Rechercher les agendas » vous devriez avoir la liste des agendas dont vous disposez sur iCloud, sélectionnez l'agenda que vous voulez synchroniser;
  • -
  • Vous pouvez ensuite sélectionner la couleur de votre agenda (ou conserver celle par défaut).
  • -
- -
-
-

Pour terminer, libre à vous d'activer les options afin de rendre vos agendas disponibles hors ligne et de sélectionner votre agenda par défaut.

-

ATTENTION les étapes ci-dessus devront être répétées pour CHACUN des agendas dont vous disposez, je n'ai pas trouvé mieux pour l'instant. -Une fois vos agendas synchronisés vous pouvez fermer Evolution, l'agenda de Gnome devrait automatiquement ajouter les agendas que vous venez de configurer.

-
- Crédits: photo de couverture par - - Estée Janssens - -
-
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/linux/osx-to-linux-part-1/index.html b/pr/119/blog/linux/osx-to-linux-part-1/index.html deleted file mode 100644 index 72e5b258..00000000 --- a/pr/119/blog/linux/osx-to-linux-part-1/index.html +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - - D'OSX à Linux (en milieu professionnel) - Partie 1 - Le quotidien - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Linux -
  • -
  • - #Osx -
  • -
-

D'OSX à Linux (en milieu professionnel) - Partie 1 - Le quotidien

-

Passer d'OSX à Linux en milieu professionnel, le quotidien, équivalence d'applications, fonctionnement, astuces.

-
-
    -
  1. - Introduction -
  2. -
  3. - Les clients de courriels -
  4. -
  5. - Les messageries (perso) -
  6. -
  7. - Les navigateurs -
  8. -
  9. - La bureautique -
      -
    1. - Documents et tableurs -
    2. -
    3. - PDF -
    4. -
    -
  10. -
  11. - Les agendas -
  12. -
- -
-
-

Parce que le choix (ou la nécessité) de changer de système d'exploitation remet en cause notre utilisation quotidienne et nos réflèxes applicatifs, il me parait louable de partager MA façon d'utiliser Linux après de nombreuses années avec OSX et quelles solutions j'ai « trouvé » pour reprendre mes marques notamment en terme d'équivalence d'applications et d'utilisation au quotidien.

-

Billet à destination de celles et ceux qui hésitent encore à franchir le pas de peur de se retrouver perdu·e.

-

Introduction

-

En préambule et pour mieux cerner certaines contraintes que j'ai pu avoir ou choix que j'ai pu faire:

-
    -
  • J'utilise Linux à titre pro et perso depuis plus de 20 ans (J'ai commencé avec Debian/Potato);
  • -
  • Je ne prêche pour aucune distribution en particulier, sauf côté serveur, mais ça n'est pas le sujet; -
    Il existe aujourd'hui suffisamment de distributions « matures » pour que chacun y trouve son bonheur, il n'y a pas de « meilleure » distro il y a celle qui vous convient. En ce qui me concerne j'ai eu de la Debian (beaucoup), de la Fedora et de l'Ubuntu (un peu pour les deux) et ça fait maintenant 3 ans que j'utilise Manjaro après un rapide passage sur Antergos;
  • -
  • J'ai passé pas loin de 10 ans avec OSX coté pro avec ses bons et ses mauvais côtés et même si je ne m'y retrouve plus aujourd'hui, c'est toujours à mon sens un bon OS;
  • -
  • J'utilise Gnome comme environnement graphique;
  • -
  • Je dispose de plusieurs adresses de messagerie dont pas mal sont gérées par ProtonMail;
  • -
  • Mon quotidien est celui d'un SysAdmin/Ops/SRE (Je ne sais plus où on en est dans les appellations) bref tout ce qui va toucher à l'administration système et à l'outillage autour.
  • -
-

Je séparerai cet article en plusieurs parties en fonction des différentes utilisations:

-
    -
  • Le quotidien (qui pourra intéresser tout un chacun);
  • -
  • Le spécifique (qui relève de mon utilisation);
  • -
  • Le pro (très focalisé sur le métier).
  • -
  • Le cosmétique
  • -
-

Sans plus attendre un premier chapitre qui va se concentrer sur l'utilisation que chacun d'entre nous peut avoir d'une machine.

-

Les clients de courriels

-

L'une des premières utilisation, les courriels !
-J'utilise uniquement les clients de courriel et quasiment jamais un navigateur pour consulter ma messagerie. Avec OSX j'utilisais l'excellent Postbox.

-

Du côté de linux j'ai retenu deux candidats:

-
    -
  • L'incontournable Thunderbird qui reste, fonctionnellement et de très loin le plus complet. Son ergonomie est toutefois très datée et on ne va pas se le cacher, l'organisation de ses menus est tout de même un sacré bordel ! À son crédit c'est un des rares à supporter GPG nativement.
  • -
  • Celui que j'utilise depuis quelques temps, Mailspring qui dispose d'une interface beaucoup plus simple et accessible et fonctionne très bien avec le bridge de chez ProtonMail.
  • -
-
- L'interface de Mailspring -
- L'interface de Mailspring -
-
-

À noter que j'attends la refonte annoncée de Thunderbird avec impatience tant le fonctionnel de Mailspring reste « relativement » limité.
-(Mise à jour du 18 Novembre 2022: Quelques écrans de la nouvelle interface ont fait leur apparition, ils semblent augurer d'un gros et bon travail d'UI.)

-

Les messageries (perso)

-

Au niveau des messageries j'utilise principalement Signal et Whatsapp (pour les proches), les deux disposent d'intégration des clients comme je l'avais sous OSX rien à signaler à ce niveau on est ISO !

-

Les navigateurs

-

Probablement la brique la plus standardisée à l'heure actuelle, on retrouve exactement la même chose côté Linux c'est donc plus l'affinité de chacun qui va jouer. -De mon côté j'en utilise deux principalement Brave (sur une base chromium donc) et Librewolf (sur une base Firefox).

-

À ces derniers vient se greffer TorBrowser.

-

La bureautique

-

Documents et tableurs

-

Ah ! La bureautique…

-

Point de friction lié principalement à la comptabilité avec les formats propriétaires, je n'ai plus rencontré de « vrai » problème depuis un moment. -J'utilise OnlyOffice Desktop pour l'édition de document de type Word et Excel et ça juste marche !

-

Point plus embêtant si vous avez des imprimantes réseau un peu anciennes il est probable qu'il vous soit compliqué d'imprimer sans faire un effort de configuration (je ne l'ai pas fait, je n'imprime quasiment jamais).

-

PDF

-

Du côté des PDFs, le visionneur de documents de Gnome fait très bien le boulot pour de la lecture.
-Au niveau de l'édition c'est un domaine ou il faut encore bricoler par rapport à OSX qui est très bon nativement pour manipuler les PDFs. -J'utilise donc Xournal++ dès lors que je dois y insérer des images ou autres éléments mais il s'agit d'un projet qui semble être à l'abandon et pour lequel je n'ai pas encore cherché/trouvé d'alternative viable.

-
- La visionneuse de Gnome -
- La visionneuse de Gnome -
-
-

Les agendas

-

Là encore l'offre est plétorique, après avoir pas mal utilisé Lightning (Thunderbird) je suis revenu sur Gnome Calendar qui fait le boulot.

-

ATTENTION toutefois il n'intègre pas la mécanique d'invitations, si vous planifiez beaucoup de réunions il vaut sans doute mieux rester sur Lightning.

-

Pour ceux qui disposent d'agendas iCloud (j'en fais partie) leur ajout à Lightning passe par l'utilisation de l'extension TBSync quant à Gnome Calendar il faut passer par une gymnastique assez lourde que je décris ici.

-
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/post-mortem/sre-interpretation-incident/index.html b/pr/119/blog/post-mortem/sre-interpretation-incident/index.html deleted file mode 100644 index 5c0648c4..00000000 --- a/pr/119/blog/post-mortem/sre-interpretation-incident/index.html +++ /dev/null @@ -1,545 +0,0 @@ - - - - - - - Interprétation et diagnostic d'un incident en production. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Sre -
  • -
  • - #Devops -
  • -
  • - #Incident -
  • -
  • - #PostMortem -
  • -
-

Interprétation et diagnostic d'un incident en production.

-

Interprétation pas à pas d'un incident sur infrastructures applicatives, cas pratique d'un incident vécu.

-
-
    -
  1. - Préambule -
  2. -
  3. - Contexte -
  4. -
  5. - Déroulé de l'incident -
      -
    1. - Diagnostic infra -
    2. -
    3. - Diagnostic applicatif -
    4. -
    5. - Analyse des métriques -
    6. -
    7. - Analyse des requêtes SQL -
    8. -
    9. - Le fin mot de l'histoire -
    10. -
    -
  6. -
  7. - Conclusion -
  8. -
  9. - Ce qu'il faut en retenir -
  10. -
- -
-
-

Préambule

-

Premier article concernant la résolution d'incidents, toujours à but de formation. -N'ayant jamais vu beaucoup d'articles traitant du sujet il nous parait intéressant d'expliquer et commenter les post-mortems qu'il nous arrive d'envoyer à nos clients. -C'est aussi, à notre avis, une bonne façon (si ce n'est la meilleure) d'expliquer pourquoi le DevOps est important dans les métiers SRE, à quoi il sert et comment nous utilisons les outils que l'on met en place.

-

Gardez à l'esprit que chaque applicatif est unique (même si l'on retrouve des comportements type) et que l'un des meilleurs indices d'anomalie et « l'écart par rapport à la moyenne normale », autrement dit un comportement qui diffère fortement de ce que vous avez l'habitude de voir.

-

Pour finir, c'est l'exercice le moins « confortable » du métier. -En fonction de sa gravité, l'incident infra peut passer inaperçu comme impacter de manière significative l'activité d'un client, l'expérience des équipes dans ce cas de figure est souvent un facteur clé pour la rapidité de la résolution.

-

Contexte

-

Le contexte est assez classique pour de l'application web.

-
    -
  • Un applicatif métier « relativement » pas mal utilisé en journée recevant environ 240 requêtes/s (Réparties à 80% sur l'API, les 20% restant étant dédié à du back-office);
  • -
  • 6 frontaux web (Nginx / PHP-FPM);
  • -
  • 1 répartiteur de charge managé;
  • -
  • 1 répartiteur de charge SQL MaxScale;
  • -
  • 2 instances MariaDB en configuration « Primary / Replica ».
  • -
-

En complément:

-
    -
  • L'API répond principalement à une application mobile;
  • -
  • Le back-office déclenche l'envoi de notifications (~ 800 000/jour) vers ces mêmes applications.
  • -
-

Déroulé de l'incident

-
    -
  • Durée totale de l'incident: 1h20
  • -
  • Impact: Significatif
  • -
  • Type: Indisponibilité complète
  • -
-

Comme tous les incidents, nous sommes alertés par nos sondes infra:

-
-
-

Il n'est pas rare d'avoir des alertes isolées dues à une défaillance d'un hyperviseur ou à une panne réseau, dans notre cas de figure l'effondrement de l'infrastructure est très rapide (inférieure à 3 minutes), aucun doute donc sur « un gros pépin ».

-

Les alertes infras se terminent par une alerte StatusCake sur le « endpoint » applicatif HTTP configuré.

-
-
- Déclenchement des alertes. -
-
-

Nous notifions à notre client le début de l'incident et le début d'analyse pour remédiation.

-

Diagnostic infra

-

Elles sont systématiques en cas d'incident et consistent en une checklist assez simple:

-
    -
  • Vérification de l'état des instances;
  • -
  • Vérification d'un incident déclaré chez le fournisseur de cloud (ici OVHCloud);
  • -
  • Vérification de la connectivité des réseaux privés.
  • -
-

En seconde étape nous procédons à une première analyse des « graphs » sur quelques unes des instances applicatives:

-
- -
- Effondrement des processus PHP -
-
-

Pour autant les instances n'apparaissent pas « chargées » outre mesure.

-
- -

Sur l'ensemble des instances nous ne constatons pas d'augmentation de la consommation des ressources, de même le traffic n'explose pas, nous ne sommes donc pas dans le cas d'un afflux massif de connexions (légitimes ou non d'ailleurs), ni d'une charge anormale du à un script mal conçu.

-
-
- -

Nous disposons toutefois d'un premier indice au niveau réseau, puisque nous constatons une augmentation des connexions « ouvertes » et une chute flagrante des connexions en attente de fermeture.

-
-

Nous avons également constaté que les médias applicatifs sont bien disponibles et que nous n'avons pas de coupure vers les espaces de stockage distants.

-

À ce stade nous avons donc une infra fonctionnelle mais une application « dans les choux ». -Nous tentons une première approche en redémarrant les services PHP-FPM sur l'ensemble des instances, ceux-ci se retrouvent rapidement à nouveau saturés et hors service, comportement qui semble confirmer un souci d'ordre applicatif.

-

Diagnostic applicatif

-

Il est temps d'aller jeter un oeil aux logs applicatifs qui donnent rapidement un résultat puisque nous avons l'erreur suivante:

-
SQLSTATE[HY000]: General error: 2006 MySQL server has gone away at XXXXXXX
-

Nous avons donc bien une perturbation au niveau de la connectivité entre les instances applicatives et les instances de base de données, reste à déterminer la raison !

-

À ce stade nous prenons contact avec l'équipe de développement applicatif afin de disposer de sa connaissance métier et fonctionnelle.

-

Analyse des métriques

-

Nous poursuivons nos investigations à l'aide de nos métriques infra / applicatif plus spécifiquement sur le réseau privé, zone d'échange entre les instances applives et données pour y trouver ceci:

-
- -
- 1.- Bande passante - Instance applicative -
-
-
- -
- 2.- Bande passante - Instance base de données -
-
-
- -
- 3.- Bande passante - Instance base de données (Saturation de la bande passante) -
-
-

Enfin du concret ! On constate à l'aide de ces deux graphs une volumétrie de données d'échange anormalement élevée entre les instances applicatives et les instances de base de données.

-

Constat:

-
    -
  • En entrée des instances applicatives (1) nous avons un débit x20 qui passe de 2~2,5MB/s en moyenne à 45MB/s pour ensuite se stabiliser à hauteur de 20~25MB/s;
  • -
  • En sortie des instances de base de données (2) un débit moyen qui explose (x7) pour s'installer à hauteur de 150 MB/s.
  • -
-

On constate surtout que cette volumétrie vient saturer la bande passante avec un bel « effet plafond » du graph concerné (3).

-

Nous avons donc la cause de l'incident à savoir, la saturation de la bande passante entre les instances applicatives et les instances de base de données, ce qui conduit à une grosse attente au niveau PHP-FPM qui se retrouve dans l'incapacité de prendre de nouvelles connexions entrantes.

-

Au passage, on voit ici l'importance de « caper » le nombre de connexions maximum que l'on autorise à PHP-FPM, dans le cas ou ce travail n'est pas et/ou mal fait ou si aucun seuil n'est fixé, nous pouvons avoir potentiellement une perte complète de la connectivité à l'instance applicative qui peut impacter de manière significative le temps de rétablissement.

-

Nous avons l'origine du blocage, il nous faut à présent comprendre d'où cela vient, nous passons donc du côté serveur de base de données.

-

Analyse des requêtes SQL

-

Afin d'identifier d'éventuelles requêtes problématiques nous jouons un SHOW PROCESSLIST sur notre serveur de base de données et isolons les requêtes en cours d'exécution depuis plusieurs secondes. -En rejouant l'une de ces requêtes nous constatons qu'elle est anormalement volumineuse (taille supérieure à 5Mo).

-

Plus spécifiquement elle « ramène » un champ d'une table bien précise et après échange avec les équipes applicatives il correspond à l'ajout d'un « relativement nouveau » fonctionnel, relativement parce qu'il a tout de même quelques semaines mais n'a, à priori pas été utilisé tout de suite par les utilisateurs finaux.

-

Le champ en question permet de stocker du contenu libre saisi par l'utilisateur à l'aide d'un éditeur de contenu (À ce moment là, certain(e)s d'entre vous doivent avoir une idée de ce qu'il se passe ;)).

-

Nous décidons de passer la publication concernée en « draft »... ce qui est sans influence directe sur la saturation de la bande passante.

-

Nous élargissons notre champ de recherche, cette fois-ci en recherchant les lignes disposant d'un champ de contenu dont la taille est supérieure au Mo (SELECT id ... WHERE CHAR_LENGTH(content) > 10000), pour finalement identifier une centaine de lignes présentant la même problématique.

-

Vu la gravité de la situation (indisponibilité complète de l'application) et en concertation avec les équipes applicatives nous « dépublions » l'ensemble des contenus problématiques ce qui a pour effet de faire revenir les échanges de données à un seuil normal et de facto rendre à nouveau disponible l'applicatif.

-

Dans le même temps les équipes applicatives auront préparé un « quick fix » désactivant la fonctionnalité, le temps de la retravailler.

-

Le fin mot de l'histoire

-

Il s'avère que l'application proposait un module de publication à ses utilisateurs embarquant un éditeur de contenus riches qui autorisait l'insertion d'images directement dans les contenus HTML (sans passer par un stockage sur le système de fichiers et donc directement en base de données). -Cerise sur le gateau, nous sommes en 2023 et les images « brutes » pèsent souvent plusieurs Mo.

-

Conclusion

-

Ce cas est une parfaite illustration de ce que l'on peut avoir comme incident avec une application web, bien que l'origine soit assez sournoise, en effet il n'est pas déclenché par une mise à jour récente mais par un fonctionnel développé il y a plusieurs semaines, mais mis en avant que récemment. -De plus, en première lecture, il n'y a pas d'incident apparent, ni charge anormale des instances, ni pépin réseau.

-

Les logs applicatifs permettent de s'orienter vers une cause probable de l'indisponibilité mais ne sont pas suffisants pour identifier de manière précise son origine, c'est leur corrélation avec la lecture des métriques qui permet de gagner énormément de temps sur le diagnostic et ainsi cerner le problème.

-

Les équipes applicatives sont un renfort précieux, pour dans un premier temps, fournir les informations de dernières mises à jour ou d'arrivée de nouveau fonctionnel (et surtout de mettre en relation un fonctionnel et un schéma de données) et dans un second temps pour corriger (même temporairement) le code, afin d'éviter une rechute inévitable.

-

Ce qu'il faut en retenir

-
    -
  • Éviter de stocker des médias en base de données qui plus est dans un champ « texte »
  • -
  • Méfiez-vous des éditeurs de contenus riches et prenez le temps de bien les intégrer / configurer. Entre les potentiels dépôts de fichiers sauvages qui peuvent mettre en cause la sécurité applicative, l'injection de scripts et l'ajout de médias non optimisés c'est une source d'ennuis sans fin
  • -
  • Monitorez vos infras !
  • -
  • Intégrer les équipes applicatives au diagnostic
  • -
  • Si vous en avez la possibilité, faites des tirs de charge !
  • -
  • « Profile ! Don't assume.»
  • -
-
- Crédits: photo de couverture par - - ThisisEngineering RAEng - -
-
- -
-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/blog/rss.xml b/pr/119/blog/rss.xml deleted file mode 100644 index 33035f9b..00000000 --- a/pr/119/blog/rss.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - Le blog de l'équipe Rix - Découvrez nos articles techniques (ou non), rédigés par les membres de l'équipe Rix ! - Rix - L’utilisation des flux RSS de rix.fr est réservée à un usage strictement personnel, non professionnel et non collectif. Toute autre exploitation doit faire l’objet d’une autorisation et donner lieu au versement d’une rémunération. Contact : contact@rix.fr - https://rix-fr.github.io/rix/pr/119/blog - Mon, 06 Nov 2023 15:15:35 +0000 - fr - - https://rix-fr.github.io/rix/pr/119/apple-touch-icon.png - Le blog de l'équipe Rix - https://rix-fr.github.io/rix/pr/119/blog - - - - Principes de base de l'utilisation de clés SSH. - Fri, 20 Oct 2023 00:00:00 +0000 - - - - https://rix-fr.github.io/rix/pr/119/blog/cours/cle-ssh-principes-de-base - https://rix-fr.github.io/rix/pr/119/blog/cours/cle-ssh-principes-de-base - - Principes de base de l'utilisation de clés SSH. - - cours - ssh - how-to - - - Interprétation et diagnostic d'un incident en production. - Mon, 16 Oct 2023 00:00:00 +0000 - - - - https://rix-fr.github.io/rix/pr/119/blog/post-mortem/sre-interpretation-incident - https://rix-fr.github.io/rix/pr/119/blog/post-mortem/sre-interpretation-incident - - Interprétation et diagnostic d'un incident en production. - ThisisEngineering RAEng, https://unsplash.com/@thisisengineering - - sre - devops - incident - post-mortem - - - diff --git a/pr/119/blog/styleguide/example/index.html b/pr/119/blog/styleguide/example/index.html deleted file mode 100644 index 58adee30..00000000 --- a/pr/119/blog/styleguide/example/index.html +++ /dev/null @@ -1,741 +0,0 @@ - - - - - - - Petit guide de style du blog - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- - - Retour à l'accueil - - - - - - - - -
-
-
- - -
-
-
-
-
    -
  • - #Tag1 -
  • -
  • - #Tag2 -
  • -
-

Petit guide de style du blog

-

Tour d'horizon de ce qu'on a pour faire de beaux articles. Et quelques bonnes pratiques de rédaction.

-
-
    -
  1. - Style -
      -
    1. - Les titres -
    2. -
    -
  2. -
  3. - h2 laceat quas odio atque molestiae -
      -
    1. - h3 laceat quas odio atque molestiae -
    2. -
    3. - Le sommaire -
    4. -
    5. - Les éléments typographiques -
    6. -
    7. - Les images -
    8. -
    9. - Images alignées à gauche / à droite -
    10. -
    11. - Le code -
    12. -
    13. - Bonus -
    14. -
    -
  4. -
  5. - Quelques règles typographiques -
      -
    1. - Ponctuation -
    2. -
    3. - Unités -
    4. -
    5. - Utiliser les bonnes abréviations -
    6. -
    7. - Faut-il un point à la fin d'une abréviation ? -
    8. -
    9. - Nombres -
    10. -
    11. - Listes -
    12. -
    13. - D'autres petites règles bien utiles -
    14. -
    15. - L'écriture inclusive -
    16. -
    17. - Pour aller plus loin -
    18. -
    -
  6. -
- -
-
-

Style

-

Les titres

-

1 page = 1 titre principal h1.

-

Dans le blog, le h1 est le titre de l'article. Dans le corps de l'article, on commence donc par des h2.

-

h2 laceat quas odio atque molestiae

-

h3 laceat quas odio atque molestiae

-

h4 laceat quas odio atque molestiae

-
h5 laceat quas odio atque molestiae
-
h6 laceat quas odio atque molestiae
-

Le sommaire

-

Le sommaire permet d'afficher les h2 et les h3 présents dans l'article. Selon le besoin, précisez le niveau de titre à faire figurer au sommaire.

-
tableOfContent: true
-# identique à:
-# tableOfContent: 2
-

ou

-
tableOfContent: 3
-

Les éléments typographiques

-

Nous avons des paragraphes, des liens, parfois du code inline.

-
    -
  • des listes de choses
  • -
  • des listes de choses
  • -
  • des listes de choses
  • -
-
-

Nous avons aussi des citations. -- Jane Doe

-
-

Un coup sur deux, on a un style différent de citation, sinon on s'ennuie.

-
-

Quoi ? Un deuxième style de citation ? Eos officia, vel corporis eaque architecto eveniet voluptatibus, ullam impedit excepturi quis quidem sint facere laboriosam harum error esse iusto. Asperiores, placeat. -John Doe

-
-

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod -tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo -consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse -cillum dolore eu fugiat nulla pariatur.

-
-

Titre

-

- Nous avons des admonition pour les informations à faire ressortir. -

-
-

Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

-
-

Titre

-

- Le même composant dans le style "success". -

-
-

Excepteur sint occaecat cupidatat non -proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

-
-

Titre

-

- Le même composant dans le style "danger". -

-
-

Les images

-

Une image (qui a du sens, ça n'inclut pas les gifs rigolos) a toujours une légende, et si possible on crédite son auteur·ice.

-
- -
- Légende de l'image - Crédit photo : Auteur -
-
-
<figure>
-    <img src="./../../images/blog/styleguide/photo.png" alt="photo de ...">
-    <figcaption>
-      <span class="figure__legend">Photo de ...</span>
-      <span class="figure__credits">Crédit photo : <a href="">Nom de l'auteur</a></span>
-    </figcaption>
-</figure>
-

Images alignées à gauche / à droite

-
-
-

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo mollitia eaque iste accusantium similique fugit voluptatem nisi asperiores facilis consectetur.

-

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo mollitia eaque iste accusantium similique fugit voluptatem nisi asperiores facilis consectetur.

-
-
- -
- Légende - Crédit photo : Auteur -
-
-
-
- -
-

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo mollitia eaque iste accusantium similique fugit voluptatem nisi asperiores facilis consectetur.

-

Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo.

-
-
-
<div class="side-image">
-  <div class="side-image__content">
-    <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo mollitia eaque iste accusantium similique fugit voluptatem nisi asperiores facilis consectetur.</p>
-  </div>
-  <figure>
-      <img src="https://upload.wikimedia.org/wikipedia/commons/b/bc/Juvenile_Ragdoll.jpg">
-      <figcaption>
-        <span class="figure__legend">Légende</span>
-        <span class="figure__credits">Crédit photo</span>
-      </figcaption>
-  </figure>
-</div>
-

ou si l'image n'a pas besoin de légende / crédit :

-
<div class="side-image">
-  <img src="content/images/blog/styleguide/exemple-image.jpg">
-  <div class="side-image__content">
-    <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo mollitia eaque iste accusantium similique fugit voluptatem nisi asperiores facilis consectetur.</p>
-    <p>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Non natus laborum optio provident, ad dolore molestiae ea, labore quo.</p>
-  </div>
-</div>
-

Pour les autres images, utilisez simplement la syntaxe Markdown classique (cf sections suivantes).

-

Images retina

-

Les images inclues dans un contenu sont automatiquement adaptée et fournies en version rétina et non-rétina lorsque cela le permet.

-
Depuis la racine du projet
-Image d'exemple depuis la racine du projet -
![Image d'exemple depuis la racine du projet](content/images/blog/styleguide/exemple-image.jpg)
-
Avec un chemin relatif au contenu (recommandé)
-Image d'exemple en relatif -
![Image d'exemple en relatif](./../../images/blog/styleguide/exemple-image-relative.jpg)
-
-

- Les GIFs ne peuvent être redimensionnés mais peuvent tout de même être référencés -

-
-Test gif -
![Test gif](./../../images/blog/styleguide/exemple-gif.gif)
-

Le code

-

Pensez à préciser dans le markdown le langage dans lequel est votre code, si vous voulez des couleurs ! 🌈

-
<html>
-  <head></head>
-  <body>
-    Oups
-  </body>
-</html>
-
<html>
-  <head></head>
-  <body>
-    C'est mieux
-  </body>
-</html>
-

Bonus

-

Comme toujours, on essaie tant que possible de choisir des photos libres de droit et d'en créditer les auteurs. Quelques sites de photos libres de droit : Unsplash (chouchou ❤️), Pexels, etc.

-

Pour créditer l'auteur de la photo de couverture, renseignez la clé credits dans le header de l'article :

-
credits: { name: 'Jane Doe', url: 'https://unsplash.com/@janedoe' }
-

Quelques règles typographiques

-

Ponctuation

-
    -
  • Les signes simples comme , et . ne sont précédés d'aucune espace ;
    -Exemple : Je suis contente, aujourd'hui il fait grand soleil, ça faisait longtemps que ça n'était pas arrivé.
  • -
  • Les signes doubles comme ! , ? , ; , :, «, » sont toujours entourés de deux espaces ;
    -Exemple : Bonjour, comment vas-tu ? Je suis contente de te revoir !
  • -
  • Cette règle ne fonctionne pas en anglais où le signe double n'a pas d'espace avant (Hello!).
  • -
  • Attention à bien utiliser les vrais points de suspension et non 3 points à la suite ... . Sur Mac, ⌥ alt + .
  • -
  • Les points de suspension sont suivis d'une espace ;
  • -
  • Préférez les guillemets français pour vos citations : « ». Sur Mac, ⌥ alt + è et ⌥ alt + ⇧ maj + è.
  • -
-

Unités

-
    -
  • Toutes les unités suivant une valeur doivent avoir une espace insécable qui les précède ;
    -Exemple : 10 % et non 10%, 10 h et non 10h, 10 € et non 10€, 10 km et non 10km.
  • -
  • En français, cela marche avec absolument toutes les unités. On écrira donc plutôt "10 km / h" et non "10km/h" ;
  • -
  • Cette règle ne fonctionne pas en anglais où l'on accole l'unité à la valeur (10$ ou $10) ;
  • -
  • Les abréviations d'unités ne sont jamais mises au pluriels : 10 kms, 10 cms.
  • -
-

Utiliser les bonnes abréviations

-

Souvent, les abréviations officielles sont assez méconnues. En voici quelques-unes :

-
    -
  • M. et non Mr;
  • -
  • Mme ;
  • -
  • Mlle et non Melle ;
  • -
  • 10 min et non 10 mn;
  • -
  • 10 h et non 10 hr;
  • -
  • 1er, 1re, 2e, 3e, 4e et non 1ère, 2eme ou 2ème ;
  • -
  • 15 Mo, 15 Go, 15 To et non 15mb, 15gb, 15tb.
  • -
-

Faut-il un point à la fin d'une abréviation ?

-

Une abréviation est suivie d’un point, sauf :

-
    -
  • les abréviations des unités de mesure, pour lesquelles le point n’est jamais utilisé ;
  • -
  • les abréviations construites en conservant la dernière lettre du mot : « bd » pour boulevard. -Autre cas particulier : il faut inclure un espace dans l'abréviation de Nota Bene, N. B.
  • -
-

Nombres

-

Le séparateur de millier est l’espace insécable, le séparateur de décimale est la virgule.
-Exemple : « Le solde est de 3 586,12 euros ».

-

Listes

-

Listes à puces

-

Les items d'une liste à puces commencent toujours avec une majuscule et finissent par un point-virgule, sauf le dernier qui se termine par un point.

-

Exemple :
-Pour se sentir mieux :

-
    -
  • Pensez à faire des pauses plusieurs fois dans la journée ;
  • -
  • Levez les yeux de votre écran plusieurs fois par heure ;
  • -
  • Évitez de consommer trop d'excitants (café, thé, etc.).
  • -
-

N. B. : la règle étant à la base pour l'édition de documents imprimés, il est admis pour les présentations et interfaces web de ne pas surcharger et de ne pas suivre la règle des ponctuations de liste. Mais si vous souhaitez en mettre, c'est cette règle qu'il faut suivre.

-

Listes numérotées

-

Les items d'une liste numérotée commencent toujours avec une majuscule et finissent par un point.

-

Exemple :
-Les valeurs d'Elao sont :

-
    -
  1. L'humain avant tout.
  2. -
  3. Rester humbles et apprendre de nos erreurs.
  4. -
  5. S’ouvrir, partager, ne rien garder pour soi.
  6. -
-

L'emploi du "etc"

-

Quand on fait une liste qui se termine par "etc", celui-ci est précédé d'une virgule et suivi d'un point. Il n'est JAMAIS suivi de points de suspension "etc...".
-Exemple : « Pensez à acheter des fruits : pommes, bananes, clémentines, etc. »

-

D'autres petites règles bien utiles

-
    -
  • Dans le web, l'usage du souligné est utilisé strictement pour signifier un lien. Pour mettre l'emphase sur un mot, préférez le gras.
  • -
  • Il est inutile de mettre un point final . à un titre ;
  • -
  • Il est inutile de mettre deux points : après un titre ou un label de formulaire, puisqu'ils introduisent toujours leur sujet, c'est redondant ;
  • -
  • Les et ne doivent jamais être précédés d'une virgule, sauf dans des cas exceptionnels comme l'énumération ;
  • -
  • L’usage du mot « Éditer » pour « Modifier » est incorrect. Éditer, c’est « publier, diffuser », non « corriger » ;
  • -
  • L'usage du mot « Adresser » pour « Traiter » est incorrect. En français, « adresser » signifie « envoyer », « émettre des paroles », ou « diriger quelqu’un vers la personne qui convient », par exemple adresser un malade à un spécialiste. On ne dira donc pas « Adresser un problème/sujet » mais plutôt « Traiter », « Aborder », « S'attaquer à » ;
  • -
  • L'adjectif « Transverse » est un anglicisme. On lui préfère sa traduction française « Transversal » ;
  • -
  • Les guillemets servent à citer quelqu’un et c’est tout, jamais à insister sur un mot ni à couvrir une approximation ; -Exemple : gérer un projet en mode “agile” ou “classique” => gérer un projet en mode agile ou classique ;
  • -
  • Accentuez les majuscules ! Cela rend la lecture plus facile. Sur Mac, il suffit d'activer le capslock avant d'appuyer sur la touche à accentuer.
  • -
-

L'écriture inclusive

-

Si vous souhaitez être inclusif·ve dans votre rédaction, voici quelques solutions possibles pour que cela reste lisible en fonction du contexte :

-

Doubler au féminin la formule masculine

-

Exemple 1 : « Chaque employé et employée doit faire sa demande de congés sur Lucca. »
-Exemple 2 : « Bonjour à toutes et à tous ! »

-

Utiliser le point médian

-

Exemple 1 : « Chaque employé·e doit faire sa demande de congés sur Lucca. »
-Exemple 2 : « Bonjour à tou·te·s ! »

-

Pour faire un point médian :
-Sur Mac : ⌥ alt + ⇧ maj + F ;
-Sur PC : Alt+0183 ou Alt+00B7.

-

Utiliser des formules non genrées (épicène)

-

Exemple 1 : « L'ensemble de l'équipe doit faire sa demande de congés sur Lucca. »
-Exemple 2 : « Bonjour tout le monde ! »

-

Il est à votre discrétion d'utiliser la formule la plus adaptée en fonction du contexte.

-

Pour aller plus loin

-

Quelques ressources intéressantes :

- -
- Crédits: photo de couverture par - - Jon Tyson - -
-
- -
-
-

Commenter

-

- Des commentaires ? - - Poursuivons la discussion sur twitter ! - -

-
-

- Une typo ? - Modifier cet article sur Github -

-
-
-
-
-
- - - - - - diff --git a/pr/119/browserconfig.xml b/pr/119/browserconfig.xml deleted file mode 100644 index 73cb7330..00000000 --- a/pr/119/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #ff4344 - - - diff --git a/pr/119/build/305.d7ed609b.css b/pr/119/build/305.d7ed609b.css deleted file mode 100644 index 8e5f73f9..00000000 --- a/pr/119/build/305.d7ed609b.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";*{box-sizing:border-box}html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-family:sans-serif}body{margin:0;padding:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}a{background-color:transparent}small{font-size:80%}img{border:none}svg:not(:root){overflow:hidden}hr{box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace}button,input,optgroup,select,textarea{margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}legend{border:0;padding:0}textarea{overflow:auto}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}p{margin:unset}@font-face{font-family:Montserrat Regular;font-style:normal;font-weight:400;src:url(/rix/pr/119/build/fonts/montserrat-regular.4ada7f2f.woff2) format("woff2"),url(/rix/pr/119/build/fonts/montserrat-regular.4a3d6361.woff) format("woff")}@font-face{font-family:Montserrat Medium;font-style:normal;font-weight:400;src:url(/rix/pr/119/build/fonts/montserrat-medium.cf734a37.woff2) format("woff2"),url(/rix/pr/119/build/fonts/montserrat-medium.2451e96b.woff) format("woff")}@font-face{font-family:Outfit Semi Bold;font-style:normal;font-weight:400;src:url(/rix/pr/119/build/fonts/outfit-semi-bold.007337b1.woff2) format("woff2"),url(/rix/pr/119/build/fonts/outfit-semi-bold.58a47c5f.woff) format("woff")}@font-face{font-family:"DM Serif Display";font-style:normal;font-weight:400;src:url(/rix/pr/119/build/fonts/dm-serif-display-regular.f7535417.woff2) format("woff2"),url(/rix/pr/119/build/fonts/dm-serif-display-regular.7265fe7d.woff) format("woff")}@font-face{font-display:block;font-family:icomoon;font-style:normal;font-weight:400;src:url(/rix/pr/119/build/fonts/icomoon.81a5b7b9.eot);src:url(/rix/pr/119/build/fonts/icomoon.81a5b7b9.eot) format("embedded-opentype"),url(/rix/pr/119/build/fonts/icomoon.450cbdb1.ttf) format("truetype"),url(/rix/pr/119/build/fonts/icomoon.32b7badb.woff) format("woff"),url(/rix/pr/119/build/images/icomoon.00ceb532.svg) format("svg")}.icon,address{font-style:normal}.icon{speak:never;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:icomoon!important;font-variant:normal;font-weight:400;line-height:1;text-transform:none}.icon--arrow-right:before{content:"\e905"}.icon--arrow-left:before{content:"\e90b"}.icon--chevron:before{content:"\e902"}.icon--close:before{content:"\e900"}.icon--hamburger:before{content:"\e901"}.icon--location:before{content:"\e903"}.icon--message:before{content:"\e904"}.icon--github:before{content:"\e906"}.icon--linkedin:before{content:"\e907"}.icon--twitter:before{content:"\e908"}.icon--quotations-left:before{content:"\e909"}.icon--quotations-right:before{content:"\e90a"}.icon--website:before{content:"\e90c"}.icon--info:before{content:"\e926"}.icon--danger:before{content:"\e927"}.icon--success:before{content:"न"}.header{background:#fff;border-top:30px solid #07162f;height:155px}.header img{margin:0}.header .container{align-items:center;display:flex;padding:0 20px 20px}.header .logo{position:relative;top:-1px;width:170px}@media (max-width:1220px){.header{height:125px}.header .logo{width:115px}}html{scroll-behavior:smooth}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#07162f;display:flex;flex-direction:column;font-family:Montserrat Regular;font-size:16px;height:100vh;line-height:1.9}main{background:url(/rix/pr/119/build/images/background.fe096fd5.jpg) no-repeat;background-position:bottom;background-size:contain;flex:1;padding-bottom:350px}b,strong{font-family:Montserrat Medium;font-weight:unset}.container{margin:0 auto;max-width:1440px;padding:0 125px;width:100%}.twitter-tweet{margin:10px auto}@media (max-width:760px){main{background:url(/rix/pr/119/build/images/background-mobile.90615db1.jpg) no-repeat}.container{padding:0 20px}}.nav{margin-left:auto}.nav ul{display:flex;list-style:none;margin:0;padding:0}.nav__item{align-items:center;display:flex;margin:0 20px}.nav__item:after,.nav__item:before{content:none}.nav__item a{color:#07162f;font-family:Outfit Semi Bold;font-size:1.125rem;text-decoration:none}.nav__item a span{padding:7px 2px;position:relative}.nav__item a span:after{background:#eb5050;bottom:-5px;content:"";height:2px;left:0;opacity:0;position:absolute;transition:.15s ease-out;width:100%}.nav__item a:hover span:after{bottom:0;opacity:1}.nav__item--icon a{align-items:center;display:flex}.nav__item--icon a svg{margin-right:9px;width:25px}.nav__item--icon a svg circle,.nav__item--icon a svg path{transition:stroke .3s ease,fill .3s ease}.nav__item--icon a:active span:after,.nav__item--icon a:focus span:after,.nav__item--icon a:hover span:after{display:none}.nav__item--icon a:active svg path,.nav__item--icon a:focus svg path,.nav__item--icon a:hover svg path{stroke:#eb5050}.nav__item--icon a:active svg circle,.nav__item--icon a:focus svg circle,.nav__item--icon a:hover svg circle{fill:#eb5050}.nav__item--active a span:after{background:#99b7d1;bottom:0;opacity:1}@media (max-width:1220px){.nav__item{margin:0 15px}.nav__item--icon svg{display:none}}@media (max-width:995px){.nav{display:none}}.nav-mobile{display:none}@media (max-width:995px){.nav-mobile ul{display:flex;flex:1;flex-direction:column;margin:0;padding:50px 0 0}.nav-mobile__header{align-items:center;border-top:30px solid #fff;display:flex;padding:0 20px}.nav-mobile__item{display:flex;font-size:1.9375rem;margin:0 0 10px;padding:0 0 0 45px}.nav-mobile__item:after,.nav-mobile__item:before{content:none}.nav-mobile__item a{color:#fff;font-family:Outfit Semi Bold;padding:10px 0;text-decoration:none}.nav-mobile__item a:hover{color:#fff}.nav-mobile__item--active a{border-bottom:2px solid #eb5050;position:relative}.nav-mobile__item--icon{border-top:1px solid #99b7d1;height:100px;margin:auto 0 0;padding:0}.nav-mobile__item--icon a{align-items:center;display:flex;justify-content:center;width:100%}.nav-mobile__item--icon svg{margin-right:15px;width:40px}.nav-mobile--open{background:#07162f;bottom:0;display:flex;flex-direction:column;left:0;position:fixed;right:0;top:0;z-index:9999999}}.nav-toggle{display:none}@media (max-width:995px){.nav-toggle{align-items:center;background:transparent;border:1px solid #99b7d1;border-radius:0;display:flex;font-size:1.25rem;height:52px;justify-content:center;margin-left:auto;width:52px}.nav-toggle--open{color:#07162f}.nav-toggle--close{color:#99b7d1}}.footer{background:#07162f;color:#fff;line-height:1.6;padding:100px 0 160px;z-index:1}.footer .container{padding:0 20px}.footer img{margin:0}.footer a{color:hsla(0,0%,100%,.8);font-family:Montserrat Regular;text-decoration:none}.footer a:active,.footer a:focus,.footer a:hover{color:#fff}.footer__contact{display:flex;justify-content:space-between;margin-bottom:100px}.footer__contact .catchphrase{flex:1;font-size:3rem;line-height:1.2;max-width:660px}.footer__contact .catchphrase .h1{color:#fff;font-family:"DM Serif Display";font-size:4rem;line-height:1.2;margin:0 0 24px}.footer__contact .catchphrase strong{color:#45d5d0}.footer__brand{border-top:2px solid #fff;color:#fff;position:relative}.footer__brand img{width:170px}.footer__brand span{left:105px;position:absolute;top:65px}.footer__links{align-items:flex-end;display:flex;margin-bottom:75px;margin-top:-30px;padding-left:105px;position:relative;z-index:1}.footer__links ul{flex:1;list-style:none;margin:0;padding:0}.footer__links li{margin:0 0 20px;padding-left:30px;position:relative}.footer__links li:after,.footer__links li:before{height:16px;position:absolute;top:4px;width:16px}.footer__links li:before{background:#203860;border-radius:50%;content:"";left:0}.footer__links li:after{align-items:center;color:#fff;content:"\e902";display:flex;font-family:icomoon;font-size:.4375rem;justify-content:center;left:0}.footer__links li a{font-family:Montserrat Regular;text-decoration:none}.footer__links li a:active,.footer__links li a:focus,.footer__links li a:hover{color:#fff}.footer__links a{font-family:Outfit Semi Bold;margin-bottom:45px}.footer__links a:active,.footer__links a:focus,.footer__links a:hover{color:#eb5050}.footer__links .pages{display:flex;width:300px}.footer__links .services{align-items:flex-start;display:flex;flex:1;flex-direction:column}.footer__links .services>div{display:flex;width:100%}.footer__links .services ul{margin:0 10px}.footer__links .services ul:first-of-type{margin-left:0}.footer__links .services ul:last-of-type{margin-right:0}.footer__legals{text-align:center}@media (max-width:1280px){.footer__contact{flex-direction:column}.footer__contact .catchphrase{font-size:1.875rem;margin-bottom:60px;max-width:unset}}@media (max-width:1220px){.footer__links{align-items:flex-start}.footer__links .pages{margin-top:65px;width:400px}.footer__links .services>div{flex-direction:column}.footer__links .services ul{margin:0}}@media (max-width:995px){.footer__contact .catchphrase{font-size:2.25rem}.footer__contact .catchphrase .h1{font-size:3rem}.footer__brand img{width:115px}.footer__brand span{left:71px;top:50px}.footer__links{flex-direction:column;margin-top:0;padding-left:0}.footer__links a{font-size:1.25rem}.footer__links ul a{font-size:1rem}.footer__links .pages{margin-top:45px;width:unset}.footer__links .services{margin-top:35px}.footer__links .services a{margin-bottom:25px}.footer__legals a{white-space:nowrap}}:root{--area-b-height:76px;--area-b-width:1000px;--area-d-width:30px}.beveled-wrapper{margin-bottom:-1300px;overflow:hidden;padding-top:var(--area-b-height);position:relative;top:-1300px}.beveled-wrapper__gradient{background:linear-gradient(90deg,transparent calc(50% + 719px),#fff calc(50% + 719px) 100%)}.beveled-wrapper__gradient .shape{background:url(/rix/pr/119/build/images/bevel.4a9689a3.svg) no-repeat;background-position:100% 0!important;background-size:cover!important;padding-top:200px;position:relative}.beveled-wrapper__gradient .shape:before{background:url(/rix/pr/119/build/images/bevel-right.29104ed1.svg) no-repeat;background-size:cover;content:"";height:var(--area-b-height);position:absolute;right:calc(var(--area-b-width)*-1 + var(--area-d-width));top:calc(var(--area-b-height)*-1 + 1px);width:var(--area-b-width)}.beveled-wrapper__gradient .shape .h2--large{margin:0}.beveled-wrapper__gradient .content{background:#fff;display:flex;flex-direction:column}.beveled-wrapper--wolf .beveled-wrapper__gradient .shape{background:url(/rix/pr/119/build/images/bevel-wolf.23f6cdd6.svg) no-repeat}@media (max-width:1440px){.beveled-wrapper .beveled-wrapper__gradient .shape,.beveled-wrapper--wolf .beveled-wrapper__gradient .shape{background:url(/rix/pr/119/build/images/bevel.4a9689a3.svg) no-repeat}.beveled-wrapper__gradient{background:transparent}.beveled-wrapper__gradient .shape:before{display:none}}@media (max-width:1220px){.beveled-wrapper{margin-bottom:-1200px;top:-1200px}.beveled-wrapper__gradient .shape{padding-top:130px}}@media (max-width:995px){.beveled-wrapper{margin-bottom:-1400px;margin-left:15px;top:-1400px}}@media (max-width:760px){.beveled-wrapper{margin-bottom:-1300px;top:-1300px}.beveled-wrapper .shape{padding-top:100px}}@media (max-width:380px){.beveled-wrapper .shape{padding-top:100px}}.author{align-items:center;color:#07162f;display:flex;flex-wrap:wrap;font-size:1.125rem}.author img{border-radius:50%;margin:0 15px 0 0;max-width:unset;width:50px}.author__image{position:relative}.author__image img{border:3px solid #fff;border-radius:50%;height:60px;margin:0 15px 0 0;max-width:unset;width:60px}.author__info{display:flex;flex-direction:column;line-height:1.3}.author__info strong{font-family:Outfit Semi Bold}.author__social{display:flex;flex-wrap:wrap;margin-top:10px;min-width:100%}.author__social a{align-items:center;border:1px solid #07162f;border-radius:50%;color:#07162f;display:flex;height:40px;justify-content:center;margin:0 6px 5px;text-decoration:none;transition:color .15s ease-in,background .15s ease-in;width:40px}.author--multi{align-items:flex-start;flex-direction:column}.author--multi .author__image{height:60px;left:-45px;margin-bottom:10px;position:relative}.author--multi .author__image img:first-child{left:45px;position:absolute}.author--multi .author__image img:nth-child(2){left:90px;position:absolute}.author--multi .author__image img:nth-child(3){left:135px;position:absolute}.author--multi .author__image img:nth-child(4){left:180px;position:absolute}.author--multi .author__image img:nth-child(5){left:225px;position:absolute}.author--multi .author__info+.author__info{margin-left:0;margin-top:20px}.alert{display:flex;font-family:Montserrat Medium;padding:20px 30px}.alert .icon{font-size:1.5625rem;margin-right:15px}.alert p:last-of-type{margin-bottom:0}.alert--error{background:#eb5050;color:hsla(0,0%,100%,.9)}.alert--info{background:#99b7d1;color:hsla(0,0%,100%,.9)}.admonition{background:#45d5d0;color:#07162f;font-family:monospace;font-size:1.125rem;line-height:1.6;margin:60px 0;padding:45px 60px 30px;position:relative}.admonition:after,.admonition:before{position:absolute}.admonition:before{background:#45d5d0;border-radius:50px;content:"";height:58px;left:31px;top:-29px;width:58px}.admonition:after{color:#fff;content:"\e926";font-family:icomoon;font-size:3.75rem;left:30px;line-height:1;position:absolute;top:-30px}.admonition p{margin:0 0 10px!important}.admonition p:last-of-type{margin:0}.admonition a{border-bottom-color:#07162f;font-family:monospace}.admonition a:active,.admonition a:focus,.admonition a:hover{color:#07162f}.admonition-title{font-family:monospace;font-size:1.25rem;font-weight:700}.admonition.success,.admonition.success:before{background:#3ec789}.admonition.success:after{content:"\e928"}.admonition.success a{border-bottom-color:#0d2c1e;color:#0d2c1e}.admonition.success a:active,.admonition.success a:focus,.admonition.success a:hover{color:#0d2c1e}.admonition.danger,.admonition.danger:before{background:#eb5050}.admonition.danger:after{content:"\e927"}.admonition.danger a{border-bottom-color:#07162f;color:#07162f}.admonition.danger a:active,.admonition.danger a:focus,.admonition.danger a:hover{color:#07162f}.article-overview{display:flex;margin-bottom:80px}@media (max-width:1220px){.article-overview{flex-direction:column}}.article-info{border:1px solid #99b7d1;flex:1;height:100%;margin:0 0 0 -1px}.article-info .author{border-bottom:1px solid #99b7d1;padding:30px 35px}.article-info__date{display:flex;flex-wrap:wrap;padding:30px 35px}.article-info__date span{display:flex;flex-direction:column;margin-bottom:20px;margin-right:35px}.article-info__date strong{font-family:Outfit Semi Bold;margin-top:2px}@media (max-width:1220px){.article-info{border:1px solid #99b7d1;margin:-1px 0 0}.article-info__date{padding-top:25px}}.article-footer{background:#fff;border:1px solid #99b7d1;display:flex;flex-wrap:wrap;margin:0 0 20px;padding:45px 75px}.article-footer .author{margin-bottom:20px;min-width:180px;padding:0;width:33.3333333333%}.article-footer .author:nth-last-of-type(-n+3){margin-bottom:0}.article-footer .author__details{display:flex}@media (max-width:760px){.article-footer{flex-direction:column;padding:25px 30px}.article-footer .author:nth-last-of-type(-n+3){margin-bottom:20px}.article-footer .author:last-of-type{margin-bottom:0}}.miniature-list{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.banner{background-image:url(/rix/pr/119/build/images/banner-home.e928350e.webp);background-position:top;background-repeat:no-repeat;background-size:cover;display:flex;height:1850px;position:relative}.banner:before{background:linear-gradient(180deg,transparent,#fff);bottom:0;content:"";height:200px;left:0;position:absolute;right:0}.banner h1{max-width:950px}.banner p{max-width:700px}.banner .button{margin-top:35px}.page-article .banner,.page-blog .banner,.page-case-study .banner,.page-casebook .banner{height:1550px}.banner--about{background-image:url(/rix/pr/119/build/images/banner-about.cf7414b4.webp)}.banner--blog{background-image:url(/rix/pr/119/build/images/banner-blog.777e5df6.webp)}.banner--case-study{background-image:url(/rix/pr/119/build/images/banner-case-study.c6780f13.webp)}.banner--home{background-image:url(/rix/pr/119/build/images/banner-home.e928350e.webp)}.banner--services{background-image:url(/rix/pr/119/build/images/banner-services.6d7424af.webp)}@media (max-width:995px){.page-home .banner{height:1950px}.banner--about{background-image:url(/rix/pr/119/build/images/banner-about-mobile.ac090375.webp)}.banner--blog{background-image:url(/rix/pr/119/build/images/banner-blog-mobile.dd80f874.webp)}.banner--case-study{background-image:url(/rix/pr/119/build/images/banner-case-study-mobile.9a484e1a.webp)}.banner--home{background-image:url(/rix/pr/119/build/images/banner-home-mobile.2fa58f16.webp)}.banner--services{background-image:url(/rix/pr/119/build/images/banner-services-mobile.cde6025f.webp)}}@media (max-width:760px){.page-article .banner,.page-blog .banner,.page-case-study .banner{height:1350px}.page-casebook .banner{height:1400px}}.button{align-items:center;background:#eb5050;color:#fff;display:inline-flex;font-family:Outfit Semi Bold;justify-content:center;line-height:1.4;min-height:48px;overflow:hidden;padding:15px 35px;position:relative;text-decoration:none;z-index:1}.button:before{background:#07162f;content:"";height:200px;position:absolute;transform:translateY(70%);transition:transform .6s;width:300px;z-index:-1}.button:hover{color:#fff}.button:hover:before{transform:translateY(0) rotate(10deg)}.button-ghost{background:transparent;border:1px solid #99b7d1;padding:15px 35px 15px 60px}.button-ghost:before{background:#eb5050}.button-ghost:after{content:"\e905";font-family:icomoon;left:25px;position:absolute;top:50%;transform:translateY(-50%);transition:transform .4s linear}.button-ghost span{transition:transform .3s linear}.button-ghost:active,.button-ghost:focus,.button-ghost:hover{border:1px solid #eb5050}.button-ghost:active:after,.button-ghost:focus:after,.button-ghost:hover:after{transform:translate(10px,-50%)}.button-ghost:active span,.button-ghost:focus span,.button-ghost:hover span{transform:translateX(5px)}.button-ghost--light{color:#fff}.button-ghost--light:after{color:#eb5050}.button-ghost--light:active,.button-ghost--light:focus,.button-ghost--light:hover{color:#fff}.button-ghost--dark,.button-ghost--light:active:after,.button-ghost--light:focus:after,.button-ghost--light:hover:after{color:#07162f}.button-ghost--dark:after{color:#eb5050}.button-ghost--dark:active,.button-ghost--dark:focus,.button-ghost--dark:hover{color:#07162f}.button-ghost--dark:active:after,.button-ghost--dark:focus:after,.button-ghost--dark:hover:after{color:#fff}@media (max-width:380px){.button{padding:15px 20px}.button-ghost:after{display:none}}.comment{border:1px solid #99b7d1;margin:20px 0;min-width:100%;padding:35px 75px;width:100%}.comment p{margin-bottom:0}.comment .title{font-family:Outfit Semi Bold;font-size:2rem;margin:20px 0 10px}.comment .tweet-container{margin-top:40px}@media (max-width:760px){.comment{padding:25px 30px}}@media (max-width:380px){.comment .tweet-container{display:none}}blockquote{border:1px solid #99b7d1;font-size:2.25rem;line-height:1.4;margin:80px 0;padding:46px 80px;position:relative}blockquote:after,blockquote:before{background-color:#fff;color:#45d5d0;font-family:icomoon;padding:0 8px;position:absolute}blockquote:before{content:"\e909";top:-34px}blockquote:after{bottom:-32px;content:"\e90a";right:90px}blockquote p{margin:0}blockquote cite{display:block;margin-top:15px}@media (max-width:995px){blockquote{font-size:1.5rem;padding:35px 30px}blockquote:before{top:-23px}blockquote:after{bottom:-23px}}.miniature{background:#fff;border:1px solid #99b7d1;display:flex;flex-direction:column;margin:0 20px 40px;min-width:calc(33.33333% - 30px);padding:0;width:calc(33.33333% - 30px)}.miniature:after,.miniature:before{content:none!important}.miniature:nth-child(3n+1){margin-left:0}.miniature:nth-child(3n+3){margin-right:0}.miniature:last-of-type{margin-bottom:40px}.miniature a{display:flex;flex-direction:column;height:100%;text-decoration:none}.miniature a:focus .miniature__image:before,.miniature a:hover .miniature__image:before{background-color:rgba(0,0,0,.2)}.miniature a:focus .miniature__image .image,.miniature a:hover .miniature__image .image{transform:scale(1.02);transform-origin:center}.miniature a .sliding-button{border-top:1px solid #99b7d1;margin-top:auto}.miniature a .sliding-button:before,.miniature a .sliding-button__content{transform:translateY(0) rotate(0deg)}.miniature__content{display:flex;flex:1;flex-direction:column;padding:30px 30px 80px;position:relative;text-decoration:none}.miniature__content .h3{color:#07162f;line-height:1.5;margin:0 0 15px}.miniature__image{height:350px;overflow:hidden;position:relative}.miniature__image:before{background-color:transparent;bottom:0;content:"";left:0;position:absolute;right:0;top:0;transition:background-color .2s ease-in-out;z-index:1}.miniature__image .image{background-position:50%;background-repeat:no-repeat;background-size:cover;display:block;height:100%;position:relative;transition:transform .2s ease-in-out}.miniature__name{color:#eb5050;font-family:Outfit Semi Bold;font-size:1.25rem}@media (max-width:1440px){.miniature{min-width:calc(50% - 20px);width:calc(50% - 20px)}.miniature:nth-child(3n+1),.miniature:nth-child(3n+3){margin-left:20px;margin-right:20px}.miniature:nth-child(odd){margin-left:0}.miniature:nth-child(2n+2){margin-right:0}}@media (max-width:995px){.miniature{margin:0 0 40px!important;min-width:100%;width:100%}.miniature__image{height:260px}}.miniature-inline{background:#fff;margin:0 0 40px;padding:0;width:100%}.miniature-inline:after,.miniature-inline:before{display:none!important}.miniature-inline a{border:1px solid #99b7d1;display:flex;text-decoration:none;width:100%}.miniature-inline a:active .miniature-inline__image:before,.miniature-inline a:focus .miniature-inline__image:before,.miniature-inline a:hover .miniature-inline__image:before{background-color:rgba(0,0,0,.2)}.miniature-inline a:active .miniature-inline__image .image,.miniature-inline a:focus .miniature-inline__image .image,.miniature-inline a:hover .miniature-inline__image .image{transform:scale(1.02);transform-origin:center}.miniature-inline a:active .sliding-button,.miniature-inline a:focus .sliding-button,.miniature-inline a:hover .sliding-button{border-top:1px solid #99b7d1}.miniature-inline a:active .sliding-button:before,.miniature-inline a:active .sliding-button__content,.miniature-inline a:focus .sliding-button:before,.miniature-inline a:focus .sliding-button__content,.miniature-inline a:hover .sliding-button:before,.miniature-inline a:hover .sliding-button__content{transform:translateY(0) rotate(0deg)}.miniature-inline__title{color:#07162f;font-size:2.25rem;line-height:1.5;margin:0 0 15px}.miniature-inline__name{color:#eb5050;font-family:Outfit Semi Bold;font-size:1.75rem;font-weight:400;line-height:1.7}.miniature-inline__image{overflow:hidden;position:relative}.miniature-inline__image:before{background-color:transparent;bottom:0;content:"";left:0;position:absolute;right:0;top:0;transition:background-color .2s ease-in-out;z-index:1}.miniature-inline__image .image{background-position:50%;background-repeat:no-repeat;background-size:cover;display:block;height:100%;margin:0;min-height:350px;min-width:575px;transition:transform .2s ease-in-out;width:575px}.miniature-inline__content{display:flex;flex:1;flex-direction:column;padding:30px 30px 80px;position:relative}@media (max-width:1220px){.miniature-inline a{flex-direction:column}.miniature-inline__image .image{min-width:100%!important;width:100%!important}}@media (max-width:995px){.miniature-inline__image .image{min-height:260px}}@media (max-width:760px){.miniature-inline__title{font-size:1.75rem}.miniature-inline__name{font-size:1.25rem}}.client-list{display:flex;flex-wrap:wrap;list-style:none;margin:65px 0 0}.client-list__item{margin:0;padding:0 20px;width:50%}.client-list__item:after,.client-list__item:before{content:none}.client-list__item:nth-of-type(odd){padding-left:0}.client-list__item:nth-of-type(2n){padding-right:0}.client-list__item .image{background-position:0;background-repeat:no-repeat;background-size:contain;height:35px;margin-bottom:16px;width:100%}@media (max-width:995px){.client-list{flex-direction:column;margin:0}.client-list__item{padding:0;width:100%}}.contact-infos{background:#fff;border:1px solid #99b7d1;max-width:575px}.contact-infos__item{border-bottom:1px solid #99b7d1;display:flex;font-size:1.125rem;padding:35px 60px;position:relative}.contact-infos__item:last-of-type{border:none}.contact-infos__item .dl,.contact-infos__item dl{margin:0 0 0 70px}.contact-infos__item .dt,.contact-infos__item dt{font-family:Outfit Semi Bold;font-size:1.5rem;line-height:1.4}.contact-infos__item .dd,.contact-infos__item dd{display:block;margin:0;padding:0}.contact-infos__item svg{left:35px;position:absolute;top:50%;transform:translateY(-50%);width:35px}.contact-infos__item a{color:#07162f}.contact-infos__item a .mail-icon__letter{transition:transform .15s ease-out}.contact-infos__item a:active .contact-icon circle:first-of-type,.contact-infos__item a:focus .contact-icon circle:first-of-type,.contact-infos__item a:hover .contact-icon circle:first-of-type{animation:fade 2s infinite both}.contact-infos__item a:active .contact-icon circle:nth-of-type(2),.contact-infos__item a:focus .contact-icon circle:nth-of-type(2),.contact-infos__item a:hover .contact-icon circle:nth-of-type(2){animation:fade 2s infinite both;animation-delay:.4s}.contact-infos__item a:active .contact-icon circle:nth-of-type(3),.contact-infos__item a:focus .contact-icon circle:nth-of-type(3),.contact-infos__item a:hover .contact-icon circle:nth-of-type(3){animation:fade 2s infinite both;animation-delay:.8s}.contact-infos__item a:active .mail-icon__letter,.contact-infos__item a:focus .mail-icon__letter,.contact-infos__item a:hover .mail-icon__letter{transform:translateY(-4px)}@keyframes fade{0%,40%,to{opacity:0;transform:translateZ(80px)}20%{opacity:1;transform:translateZ(0)}}.contact-tiles__item{background:#eb5050;color:#fff;display:flex;margin-bottom:20px;max-width:480px;padding:30px 35px 35px 0;width:100%}.contact-tiles__item:last-of-type{margin-bottom:0}.contact-tiles__item>span{align-items:flex-start;display:flex;flex-direction:column;padding-left:35px}.contact-tiles__item a{font-family:Montserrat Medium;position:relative}.contact-tiles__item .icon{align-items:center;border-right:2px solid #fff;display:flex;font-size:2.5rem;justify-content:center;min-width:120px;width:120px}.contact-tiles__item .title{font-family:Outfit Semi Bold;font-size:1.5rem;line-height:1.2;margin-bottom:12px}@media (max-width:1280px){.contact-tiles{align-items:flex-start;display:flex;justify-content:space-around}.contact-tiles__item{margin:0 10px}.contact-tiles__item:first-of-type{margin-left:0}.contact-tiles__item:last-of-type{margin-right:0}}@media (max-width:995px){.contact-tiles{flex-direction:column}.contact-tiles__item{margin:0 0 20px}.contact-tiles__item>span{padding-left:30px}.contact-tiles__item .icon{min-width:80px;width:80px}}@media (max-width:380px){.contact-tiles__item .icon{display:none}}.values{display:flex;list-style:none;margin:50px 0;padding:0}.values__item{margin:0 15px;min-width:calc(33.33333% - 15px);width:calc(33.33333% - 15px)}.values__item:after,.values__item:before{content:none}@media (max-width:1220px){.values{flex-direction:column;margin-left:20px}.values__item{margin:0 0 40px;min-width:100%;width:100%}}.about-values{background:#07162f url(/rix/pr/119/build/images/glow.10e86a4f.png) no-repeat;background-position:0 100%;background-size:550px;color:#fff;margin:100px 0 200px;position:relative}.about-values:after,.about-values:before{background-size:cover!important;content:"";position:absolute;width:100%}.about-values:before{background:url(/rix/pr/119/build/images/top.0eb15c3f.svg) no-repeat;background-position:100% 100%;height:100px;top:-100px}.about-values:after{background:url(/rix/pr/119/build/images/bottom.69774221.svg) no-repeat;background-position:bottom;bottom:-200px;height:200px}.about-values h2{color:#fff;margin-left:124px}.about-values .grid{background-image:url(/rix/pr/119/build/images/grid.6e242290.svg);background-position:bottom;background-repeat:no-repeat;background-size:contain;height:900px}.about-values ul{display:flex;flex-wrap:wrap;justify-content:flex-end;list-style:none;margin:0;padding:85px 195px 0}.about-values ul li{height:350px;padding:30px 35px;width:400px}.about-values ul li:after,.about-values ul li:before{content:none}@media (max-width:1440px){.about-values{background-size:350px;padding-bottom:135px}.about-values:after{bottom:-100px;height:100px}.about-values .grid{background:none;height:unset}.about-values ul{flex-direction:column;padding:0 125px}.about-values ul li{height:unset;margin:0 0 80px;padding:0;width:unset}}@media (max-width:995px){.about-values h2{margin:0 40px 80px}.about-values ul{padding:0 40px}}.open-source{align-items:center;background:#07162f url(/rix/pr/119/build/images/grid.cd7dfaaa.svg) no-repeat;background-position:bottom;background-size:contain;color:#fff;display:flex;margin:0 0 50px;padding:130px 100px 100px 150px;position:relative}.open-source:after,.open-source:before{content:"";position:absolute}.open-source:before{background:url(/rix/pr/119/build/images/triangle.db3b1be9.svg) no-repeat;background-position:0 100%;background-size:cover;height:100px;left:0;margin-left:-1px;margin-right:-1px;margin-top:-1px;top:0;width:calc(100% + 2px)}.open-source:after{background:url(/rix/pr/119/build/images/github.ae472559.svg) no-repeat;background-position:bottom;background-size:contain;height:100px;left:150px;top:60px;width:95px}.open-source__title{margin-right:120px!important;margin-top:20px!important;padding:0;white-space:nowrap}.open-source__content .button{margin-top:20px}@media (max-width:1220px){.open-source{align-items:flex-start;flex-direction:column;padding-bottom:40px;padding-left:40px;padding-right:40px}.open-source:before{top:-40px}.open-source:after{left:40px;top:30px}.open-source__title{margin-bottom:40px;margin-right:0}}@media (max-width:760px){.open-source{left:20px;position:relative}}@media (max-width:380px){.open-source{left:0;width:calc(100% + 20px)}}.services-list{border:1px solid #99b7d1;margin:0 0 60px;position:relative}.services-list:first-of-type{left:-125px}.services-list:last-of-type{right:-125px}.services-list ul{display:flex;list-style:none;margin:0;padding:0}.services-list__title{border-bottom:1px solid #99b7d1;padding:20px 50px 25px}.services-list__title h3{color:#07162f;font-family:Outfit Semi Bold;font-size:2.25rem;font-weight:400;line-height:1.25;margin:0}.services-list__title h3>span{color:#eb5050;display:block;font-family:Outfit Semi Bold;font-size:1.75rem}.services-list__item{border-right:1px solid #99b7d1;margin-bottom:0;min-width:33.3333333333%;padding-left:0;position:relative;width:33.3333333333%}.services-list__item:after,.services-list__item:before{content:none}.services-list__item:last-of-type{border-right:none}.services-list__item img{margin:0;width:95px}.services-list__item a{color:#07162f;display:block;height:100%;padding:0 50px 160px;text-decoration:none}.services-list__item a:active .sliding-button,.services-list__item a:focus .sliding-button,.services-list__item a:hover .sliding-button{border-top:1px solid #99b7d1}.services-list__item a:active .sliding-button:before,.services-list__item a:active .sliding-button__content,.services-list__item a:focus .sliding-button:before,.services-list__item a:focus .sliding-button__content,.services-list__item a:hover .sliding-button:before,.services-list__item a:hover .sliding-button__content{transform:translateY(0) rotate(0deg)}.services-list__item h4{color:#07162f;font-family:Outfit Semi Bold;font-size:1.5rem;line-height:1.3;margin:40px 0 15px}@media (max-width:1440px){.services-list:first-of-type,.services-list:last-of-type{left:unset;right:unset}}@media (max-width:1280px){.services-list{border:none}.services-list ul{flex-direction:column}.services-list__title{border:1px solid #99b7d1;border-bottom:none}.services-list__item{border:1px solid #99b7d1!important;margin:0 0 10px;min-width:100%;width:100%}.services-list__item a{padding:0 50px 80px}}@media (max-width:995px){.services-list__item img{width:60px}.services-list__item a{padding:0 25px 80px}}.sliding-button{background:#fff;bottom:0;display:flex;flex-wrap:wrap;height:80px;left:0;overflow:hidden;position:absolute;right:0}.sliding-button:before{background-color:#fff;content:"";height:80px;position:absolute;transform:translateY(160%) rotate(10deg);transition:transform .6s;width:500px}.sliding-button img{border-bottom:1px solid #99b7d1;border-right:1px solid #99b7d1;margin:0;padding:0 20px;width:50%}.sliding-button img:nth-of-type(2n){border-right:none}.sliding-button img:last-of-type,.sliding-button img:nth-last-of-type(2){border-bottom:none}.sliding-button__content{align-items:center;background:#fff;display:flex;font-family:Outfit Semi Bold;height:80px;justify-content:flex-end;left:0;padding:0 40px;position:absolute;top:0;transform:translateY(160%) rotate(10deg);transition:transform .35s;width:100%}.sliding-button__content .icon{color:#eb5050;margin-right:15px}.sliding-button--replaced{border-top:1px solid #99b7d1}.sliding-button--replaced .sliding-button__content{border-top:1px solid transparent}.sliding-button--large,.sliding-button--large .sliding-button__content,.sliding-button--large:before{height:160px}@media (max-width:1280px){.sliding-button{display:none}.sliding-button--mobile{border-top:none!important;display:flex}.sliding-button--mobile .sliding-button__content{transform:none;transition:none}}.signature{display:flex;justify-content:space-between}.signature textarea{height:200px;padding:10px;width:100%}.signature__preview{margin-top:25px;padding-right:95px}.signature__code{flex:1}.signature__code p{margin:0 0 15px}@media (max-width:1220px){.signature{flex-direction:column-reverse}}.ecosystem{position:relative}.ecosystem>img{left:400px;position:absolute;top:275px;width:330px}.ecosystem__list{display:flex;flex-wrap:wrap;list-style:none;margin:0;padding:0;position:relative;z-index:1}.ecosystem__list li{background:#fff;border:1px solid #d7e4ef;margin-bottom:20px;min-height:300px;padding:30px 35px;width:370px}.ecosystem__list li:after,.ecosystem__list li:before{content:none}.ecosystem__list li img{width:50px}.ecosystem__list li strong{font-size:1.5rem}.ecosystem__list li h4{color:#07162f;font-family:Outfit Semi Bold;font-size:1.5rem;line-height:1.3;margin:40px 0 15px}.ecosystem__list .analysis{margin-left:200px}.ecosystem__list .detection{margin-left:40px}.ecosystem__list .automation{margin-left:45px}.ecosystem__list .supervision{margin-left:300px}.ecosystem__list .backup{margin-left:225px}@media (max-width:1440px){.ecosystem>img{margin-bottom:-20px;margin-left:auto;position:static;width:270px}.ecosystem__list li{min-height:unset;width:100%}.ecosystem__list .analysis,.ecosystem__list .automation,.ecosystem__list .backup,.ecosystem__list .detection,.ecosystem__list .supervision{margin-left:0}}@media (max-width:1220px){.ecosystem>img{width:200px}}.tags-list{display:flex;flex-wrap:wrap;margin:0;padding:0}.miniature .tags-list,.miniature-inline .tags-list{margin-bottom:35px}.tags-list__item{background-color:#d7e4ef;border:none!important;color:#07162f;display:flex;font-family:Outfit Semi Bold;font-size:.875rem;margin:5px!important;padding:7px 10px!important}.tags-list__item:after,.tags-list__item:before{display:none}.tags-list__item a{text-decoration:none}.timeline{display:flex;list-style:none;margin:50px 0;padding:0}.timeline__item{margin:0 80px;max-width:330px;padding-top:68px;position:relative}.timeline__item:after,.timeline__item:before{content:"";position:absolute}.timeline__item:before{background-image:url(/rix/pr/119/build/images/dot.ec074665.svg);background-repeat:repeat-x;height:2px;left:100px;top:32px;width:100%}.timeline__item:after{background-image:url(/rix/pr/119/build/images/circle.aa70b6bc.svg);height:65px;top:0;width:65px}.timeline__item:last-of-type:before{display:none}.timeline__item .title{font-size:1.5rem}@media (max-width:995px){.timeline{flex-direction:column}.timeline__item{margin:0 0 50px}.timeline__item:before{display:none}.timeline__item:last-of-type{margin:0}}.technologies-list{margin:0 0 60px;position:relative}.technologies-list ul{display:flex;flex-wrap:wrap;margin:0;padding:0}.technologies-list ul>li:after,.technologies-list ul>li:before{content:none}.technologies-list__title{padding-bottom:20px}.technologies-list__item{border:1px solid #99b7d1;border-left:none;margin-bottom:15px;min-width:33.3333333333%;padding-left:0;position:relative;text-align:center;width:33.3333333333%}.technologies-list__item:nth-of-type(3n+1){border-left:1px solid #99b7d1}.technologies-list__item:last-of-type{margin-bottom:15px}.technologies-list__item a{color:#99b7d1;display:block;font-family:Outfit Semi Bold;height:100%;text-decoration:none}.technologies-list__item a>span{display:block;padding:20px 0}.technologies-list__item img{border-bottom:1px solid #99b7d1;padding:0 50px;width:100%}@media (max-width:995px){.technologies-list__item{border-left:1px solid #99b7d1;width:100%}.technologies-list__item img{padding:0 100px}}.table-of-contents{border:1px solid #99b7d1;color:#eb5050;display:flex;flex-direction:column;font-family:Montserrat Medium;margin:0;padding:30px 45px;width:calc(100% - 330px)}.table-of-contents__item{padding:0 15px}.table-of-contents__item a{text-decoration:none}.table-of-contents__sub-level{list-style-type:lower-alpha}@media (max-width:1220px){.table-of-contents{padding:20px 25px;width:100%}}.profile{background:#fff;border:1px solid #99b7d1;display:flex;flex-direction:column;padding-left:0}.profile__image{background:#d7e4ef 0/contain no-repeat url(/rix/pr/119/build/images/default.c762a445.png);height:195px;margin-bottom:20px}.profile__name{font-family:Outfit Semi Bold;font-size:1.5rem}.profile__job,.profile__name{line-height:1.4;padding:0 40px}.profile__job{color:#eb5050;font-size:1.25rem}.profile__socials{display:flex;margin-top:20px}.profile__socials a{border-right:1px solid #99b7d1;border-top:1px solid #99b7d1;color:#eb5050;flex:1;font-size:1.0625rem;padding:7px 0;text-align:center;text-decoration:none}.profile__socials a:last-of-type{border-right:none}.profile__socials a:active,.profile__socials a:focus,.profile__socials a:hover{background-color:#d7e4ef}.profile-list{align-items:flex-start;display:flex;flex-wrap:wrap;list-style:none;margin:70px -125px;padding:0}.profile-list>li{margin:0 20px 30px;min-width:calc(25% - 40px);width:calc(25% - 40px)}.profile-list>li:after,.profile-list>li:before{content:none}@media (max-width:1280px){.profile-list>li{display:none;min-width:calc(33.33% - 40px);width:calc(33.33% - 40px)}.profile-list .experience,.profile-list .profile{display:flex}}@media (max-width:995px){.profile-list>li{min-width:calc(50% - 40px);width:calc(50% - 40px)}}@media (max-width:760px){.profile-list{margin:70px 0 0}.profile-list>li{margin:0 0 30px;min-width:100%;width:100%}}.pagination{align-items:center;background:#fff;display:flex;justify-content:center;margin:0;padding:20px 0}.pagination__item{border-bottom:1px solid #99b7d1;border-top:1px solid #99b7d1;margin:0;padding-left:0}.pagination__item:after,.pagination__item:before{display:none}.pagination__item:nth-of-type(2){padding-left:20px}.pagination__item:nth-last-of-type(2){padding-right:20px}.pagination__item a{align-items:center;color:#07162f;display:flex;font-family:Outfit Semi Bold;font-size:1.125rem;height:48px;justify-content:center;margin:0;position:relative;text-decoration:none;width:48px;z-index:1}.pagination__item a:after{background:transparent;border-radius:50%;content:"";height:25px;pointer-events:none;position:absolute;transition:background .1s ease-in;width:25px;z-index:-1}.pagination__item a:active,.pagination__item a:focus,.pagination__item a:hover{color:#fff}.pagination__item a:active:after,.pagination__item a:focus:after,.pagination__item a:hover:after{background:#07162f;border-radius:50%}.pagination__item--active a{pointer-events:none}.pagination__item--active a:after{background:#d7e4ef;border-radius:unset}.pagination__item--nav{border-left:1px solid #99b7d1;border-right:1px solid #99b7d1}.pagination__item--nav a{color:#eb5050;font-size:1.25rem;transition:background .1s ease-in}.pagination__item--nav a:after{display:none}.pagination__item--nav a:active,.pagination__item--nav a:focus,.pagination__item--nav a:hover{background:#eb5050;color:#fff}@media (max-width:760px){.pagination__item:nth-of-type(2){padding-left:10px}.pagination__item:nth-last-of-type(2){padding-right:10px}.pagination__item a{height:50px;width:35px}.pagination__item--nav a{width:40px}}.experience{background:#fff;border:1px solid #99b7d1;border-top:13px solid #07162f;color:#07162f;display:flex;flex-direction:column;min-height:370px;padding:70px 0;position:relative;text-align:center;white-space:nowrap}.experience strong{font-family:"DM Serif Display";font-size:2.5rem;line-height:1.1}.experience strong span{font-size:7.5rem}.experience--dark{background:#07162f;border:none;border-top:13px solid #d7e4ef;color:#fff}.experience--dark:before{background:url(/rix/pr/119/build/images/expertise.9d4f8cd1.svg) no-repeat;background-position:top;background-size:contain;border-radius:0;content:""!important;height:55px;left:unset;position:absolute;right:35px;top:-1px;width:45px}.preview{background:url(/rix/pr/119/build/images/preview.1e8ad7d0.svg) no-repeat;background-position:top;background-size:cover;color:#fff;padding:128px 55px 55px;position:absolute;right:125px;top:-275px;width:575px}.preview .preview__content{text-align:center}.preview .button{margin:0 auto;max-width:400px;width:100%}.preview .button:before{width:750px}.preview__image{background:no-repeat;background-position:50%;background-size:cover;height:350px;margin-bottom:74px}@media (max-width:1220px){.preview{max-width:100%;position:unset;width:100%}}.miniature-highlight{display:flex;flex-direction:column;margin:0 0 40px;padding:0;width:100%}.miniature-highlight a:focus .miniature-highlight__image:before,.miniature-highlight a:hover .miniature-highlight__image:before{background-color:rgba(0,0,0,.2)}.miniature-highlight a:focus .miniature-highlight__image .image,.miniature-highlight a:hover .miniature-highlight__image .image{transform:scale(1.02);transform-origin:center}.miniature-highlight__image{min-height:350px;min-width:575px;overflow:hidden;position:relative;width:575px}.miniature-highlight__image:before{background-color:transparent;bottom:0;content:"";left:0;position:absolute;right:0;top:0;transition:background-color .2s ease-in-out;z-index:1}.miniature-highlight__image .image{background-position:50%;background-repeat:no-repeat;background-size:cover;display:block;height:100%;transition:transform .2s ease-in-out}.miniature-highlight__content{display:flex;text-decoration:none}.miniature-highlight__content h2{margin:10px 0 15px}.miniature-highlight__content .details{padding:60px 80px 20px}.miniature-highlight__content .date{color:#eb5050;font-family:Outfit Semi Bold;font-size:1rem}.miniature-highlight__tags{border-top:1px solid #99b7d1;padding:25px 450px 25px 80px}.miniature-highlight__author{background:#fff;border-left:1px solid #99b7d1;border-top:1px solid #99b7d1;bottom:0;min-width:370px;padding:30px;position:absolute;right:0;z-index:2}@media (max-width:1220px){.miniature-highlight__content{flex-direction:column-reverse}.miniature-highlight__content .details{padding:30px 30px 0}.miniature-highlight__image{min-height:260px;min-width:100%;width:100%}.miniature-highlight__image .image{height:100%;width:100%}.miniature-highlight__tags{padding:15px 30px}.miniature-highlight__author{border-left:none;min-width:100%;position:static}}.side-image{align-items:center;display:flex;margin:0 0 35px}.side-image figure,.side-image>img{margin:0 50px!important;max-width:calc(50% - 100px);width:unset!important}.side-image__content{flex:1}@media (max-width:1280px){.side-image{flex-direction:column}.side-image figure,.side-image>img{margin:50px 0!important;max-width:100%}}a{text-decoration:underline}a,a:active,a:focus,a:hover{color:#07162f}code,code [class*=language-],code[class*=language-],pre,pre [class*=language-],pre[class*=language-]{word-wrap:normal;background:#d7e4ef;color:#07162f;font-family:monospace;font-size:1.125rem;-webkit-hyphens:none;hyphens:none;line-height:1.5;overflow:auto;padding:0;-moz-tab-size:4;-o-tab-size:4;tab-size:4;text-align:left;white-space:pre;word-break:normal;word-spacing:normal}.code-multiline{font-size:1.125rem;margin:30px 0!important;padding:20px 30px!important}.code-inline{background:#d7e4ef;border-radius:5px;font-family:monospace;padding:2px 4px;white-space:pre-wrap}.code-inline,.token.cdata,.token.class-name,.token.delimiter,.token.doctype,.token.function,.token.function-name,.token.inserted,.token.operator,.token.prolog,.token.property,.token.punctuation,.token.selector{color:#07162f}.token.atrule,.token.attr-name,.token.builtin,.token.constant,.token.deleted,.token.important,.token.keyword,.token.namespace,.token.symbol,.token.tag,.token.variable{color:#eb5050}.token.attr-value,.token.boolean,.token.char,.token.entity,.token.number,.token.regex,.token.string,.token.url{color:#294262}.token.block-comment,.token.block-comment *,.token.comment,.token.comment *{border:none;color:#616161!important}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.content{background:#d7e4ef;display:initial}img,video{display:block;margin:35px auto;max-width:100%}figure{margin-bottom:50px}figure img{display:block;margin:0 auto 20px;max-width:100%}figcaption{display:flex;flex-wrap:wrap;justify-content:center;margin:0 auto;max-width:600px}figcaption a{border:none}figcaption a,figcaption a:active,figcaption a:focus,figcaption a:hover{color:#07162f}.figure__credits{padding-left:30px;position:relative}.figure__credits:before{background-color:#07162f;content:"";height:1px;left:8px;position:absolute;top:50%;transform:translateY(-50%);width:12px}p{margin:0 0 35px}.h1,.h2,.h3,.h4,.h5,.h6{display:block}.h1,h1{font-size:4.5rem;font-weight:400;line-height:1.25;margin:75px 0 35px}.h1,.h1 *,h1,h1 *{font-family:"DM Serif Display"}.h1 span,h1 span{color:#eb5050;display:block;font-family:Outfit Semi Bold;font-size:3.3125rem}.h1 strong,h1 strong{color:#eb5050}.h2,h2{font-family:Outfit Semi Bold;font-size:2.25rem;font-weight:400;line-height:1.3;margin:30px 0}.h3,h3{font-size:1.75rem;line-height:1.7;margin:30px 0 23px}.h3,.h4,.h5,.h6,h3,h4,h5,h6{color:#eb5050;font-family:Outfit Semi Bold;font-weight:400}.h4,.h5,.h6,h4,h5,h6{font-size:1.25rem;line-height:2.4;margin:23px 0}.h2--large{font-family:"DM Serif Display";font-size:4.5rem;font-weight:400;line-height:1.2}.h2--large>span{display:block;font-size:1.75rem;line-height:1.8}.h2--large>span,.h3--small{color:#eb5050;font-family:Outfit Semi Bold}.h3--small{font-size:1rem;font-weight:400;line-height:1.7;margin-bottom:0}.h3--dark{color:#07162f;font-family:Outfit Semi Bold;font-size:1.75rem;margin-top:0}.image-title{margin:0 0 25px}.image-title img{height:55px;margin:0 0 15px}.image-title__content{color:#07162f;font-family:Outfit Semi Bold;font-size:1.5rem;line-height:1.3;margin:0}.image-title--light .image-title__content{color:#fff}.case-study__title{margin-bottom:40px!important}.anchor-title{scroll-margin-top:130px}.anchor-title a{text-decoration:none}.anchor-title a:after{bottom:-10px;color:#294262;content:"#";left:10px;opacity:0;position:relative;transform:translateY(-10px);transition:opacity .15s ease-in,bottom .15s ease-in}.anchor-title a:active:after,.anchor-title a:focus:after,.anchor-title a:hover:after{bottom:0;opacity:1}@media (max-width:995px){.h1,h1{font-size:3rem;margin:15px 0 30px}.h2,.h3,h2,h3{font-size:1.5rem}.h2--large{font-size:2.25rem}.h3--dark{font-size:1.5rem}.h2--large>span,.h2>span{font-size:1.25rem}.case-study__title{font-size:2.25rem}.anchor-title{scroll-margin-top:50px}}@media (max-width:380px){.h1,h1{font-size:2.1875rem}}ul{list-style:none;margin:35px 0;padding:0}ul li{margin-bottom:3px;padding-left:30px;position:relative}ul li:last-of-type{margin-bottom:0}ul li:after,ul li:before{height:16px;position:absolute;top:4px;width:16px}ul li:before{background:#d7e4ef;border-radius:50%;content:"";left:0}ul li:after{align-items:center;color:#07162f;content:"\e902";display:flex;font-family:icomoon;font-size:.4375rem;justify-content:center;left:1px}.screen-reader{height:1px;left:-10000px;overflow:hidden;position:absolute;top:auto;width:1px}.page-home main{padding-bottom:0}.home-services>p{margin-bottom:100px;max-width:690px}.home-ecosystem{background:url(/rix/pr/119/build/images/waves.be5ec2dc.svg) no-repeat;background-position:50%;background-size:1650px;position:relative}.home-ecosystem:before{background:linear-gradient(180deg,#fff 40%,hsla(0,0%,100%,.5) 70%,hsla(0,0%,100%,0));content:"";height:200px;left:0;position:absolute;top:0;width:100%;z-index:0}.home-ecosystem h2{position:relative;z-index:1}.home-clients{background:#fff;margin-left:0;padding-top:117px}@media (max-width:760px){.home-ecosystem{background-position:top;background-size:105%}.home-ecosystem:after,.home-ecosystem:before{display:none}}.page-article main{background-image:none;padding-bottom:75px}.page-article h2:first-of-type{margin-top:0;padding-top:0}.page-article .alert{margin:0 0 40px}.page-blog main{background-image:none}.page-blog .content{padding-bottom:50px}.page-blog .content ul>li:first-of-type{border:1px solid #99b7d1}.page-blog .content ul>li:after,.page-blog .content ul>li:before{content:none!important}.page-blog .miniature:nth-child(3n+1),.page-blog .miniature:nth-child(3n+3){margin-left:20px;margin-right:20px}.page-blog .miniature:nth-child(3n+5),.page-blog .miniature:nth-child(5){margin-left:0}.page-blog .miniature:nth-child(3n+7),.page-blog .miniature:nth-child(7){margin-right:0}@media (max-width:1440px){.page-blog .miniature:nth-child(2n+2),.page-blog .miniature:nth-child(3n+5),.page-blog .miniature:nth-child(3n+7),.page-blog .miniature:nth-child(5),.page-blog .miniature:nth-child(7),.page-blog .miniature:nth-child(odd){margin-left:20px;margin-right:20px}.page-blog .miniature:nth-child(2n+5),.page-blog .miniature:nth-child(5){margin-left:0}.page-blog .miniature:nth-child(2n+6),.page-blog .miniature:nth-child(6){margin-right:0}}@media (max-width:1280px){.sliding-button--mobile{border-top:1px solid #99b7d1!important}}.page-casebook main{background-image:none}.page-casebook .h3{margin-bottom:20px}@media (max-width:995px){.page-casebook .content{padding-bottom:50px}}.page-case-study main{background-image:none}.page-case-study .beveled-wrapper__gradient .content{padding-bottom:55px;position:relative}.page-case-study .beveled-wrapper__gradient .content ul{margin-top:0}.page-case-study .beveled-wrapper__gradient .content figure{margin-left:-125px}.page-case-study .beveled-wrapper__gradient .content figure img{margin:0 auto 20px}.page-case-study .beveled-wrapper__gradient .content figure figcaption{text-align:center}.page-case-study .beveled-wrapper__gradient .case-study__header{width:50%}.page-case-study .beveled-wrapper__gradient .case-study__header ul>li{padding-left:0}.page-case-study .beveled-wrapper__gradient .case-study__header ul>li h3{margin-bottom:0}.page-case-study .beveled-wrapper__gradient .case-study__header ul>li:after,.page-case-study .beveled-wrapper__gradient .case-study__header ul>li:before{content:none}.page-case-study .beveled-wrapper__gradient .case-study__image{height:743px}.page-case-study iframe{margin:0 auto}@media (max-width:1220px){.page-case-study .beveled-wrapper__gradient .case-study__header{width:100%}}@media (max-width:995px){.page-case-study .beveled-wrapper__gradient .content figure{margin:0}}.page-services .miniature__content h3{color:#07162f;margin:0 0 29px}.page-services__images{border:1px solid #99b7d1;border-top:none;display:flex;height:125px}.page-services__images>span{align-items:center;background-color:#fff;border-right:1px solid #99b7d1;display:flex;flex:1;justify-content:center;padding:20px}.page-services__images>span:last-of-type{border-right:none}.page-services__images>span img{max-height:100%}.page-services__content{background:#fff;border:1px solid #99b7d1;margin:60px 0 0;padding:0 80px 70px}.page-services__content h3{color:#07162f}.page-services__content img{margin:0}@media (max-width:760px){.page-services .h3,.page-services h3{font-size:1.5rem}.page-services__content{padding:0 25px}.page-services__content img{width:60px}}.page-contact main{background-position:top;background-size:cover}.page-contact h1 span{display:block}.page-legals h2:first-of-type{margin:0}.page-error main{background-position:top;background-size:cover}.error__title span{color:#eb5050;display:block;font-family:Outfit Semi Bold;font-size:3.3125rem}.error__action{margin:35px 0 0}.error__action .button{margin-right:35px}.error__action .button:last-of-type{margin:0}@media (max-width:1280px){.page-error main{background-image:none}.page-error .error{align-items:center;display:flex;flex-direction:column;text-align:center}}@media (max-width:995px){.page-error .error__action{display:flex;flex-direction:column}.page-error .error__action .button{margin:0 0 35px}}.page-signature main{background-image:none} \ No newline at end of file diff --git a/pr/119/build/70.671fda9c.js b/pr/119/build/70.671fda9c.js deleted file mode 100644 index 246d8a7b..00000000 --- a/pr/119/build/70.671fda9c.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunkrix_website=self.webpackChunkrix_website||[]).push([[70],{8360:(t,e,r)=>{"use strict";r.d(e,{x:()=>tt});class n{constructor(t,e,r){this.eventTarget=t,this.eventName=e,this.eventOptions=r,this.unorderedBindings=new Set}connect(){this.eventTarget.addEventListener(this.eventName,this,this.eventOptions)}disconnect(){this.eventTarget.removeEventListener(this.eventName,this,this.eventOptions)}bindingConnected(t){this.unorderedBindings.add(t)}bindingDisconnected(t){this.unorderedBindings.delete(t)}handleEvent(t){const e=function(t){if("immediatePropagationStopped"in t)return t;{const{stopImmediatePropagation:e}=t;return Object.assign(t,{immediatePropagationStopped:!1,stopImmediatePropagation(){this.immediatePropagationStopped=!0,e.call(this)}})}}(t);for(const t of this.bindings){if(e.immediatePropagationStopped)break;t.handleEvent(e)}}get bindings(){return Array.from(this.unorderedBindings).sort(((t,e)=>{const r=t.index,n=e.index;return rn?1:0}))}}class i{constructor(t){this.application=t,this.eventListenerMaps=new Map,this.started=!1}start(){this.started||(this.started=!0,this.eventListeners.forEach((t=>t.connect())))}stop(){this.started&&(this.started=!1,this.eventListeners.forEach((t=>t.disconnect())))}get eventListeners(){return Array.from(this.eventListenerMaps.values()).reduce(((t,e)=>t.concat(Array.from(e.values()))),[])}bindingConnected(t){this.fetchEventListenerForBinding(t).bindingConnected(t)}bindingDisconnected(t){this.fetchEventListenerForBinding(t).bindingDisconnected(t)}handleError(t,e,r={}){this.application.handleError(t,`Error ${e}`,r)}fetchEventListenerForBinding(t){const{eventTarget:e,eventName:r,eventOptions:n}=t;return this.fetchEventListener(e,r,n)}fetchEventListener(t,e,r){const n=this.fetchEventListenerMapForEventTarget(t),i=this.cacheKey(e,r);let o=n.get(i);return o||(o=this.createEventListener(t,e,r),n.set(i,o)),o}createEventListener(t,e,r){const i=new n(t,e,r);return this.started&&i.connect(),i}fetchEventListenerMapForEventTarget(t){let e=this.eventListenerMaps.get(t);return e||(e=new Map,this.eventListenerMaps.set(t,e)),e}cacheKey(t,e){const r=[t];return Object.keys(e).sort().forEach((t=>{r.push(`${e[t]?"":"!"}${t}`)})),r.join(":")}}const o=/^((.+?)(@(window|document))?->)?(.+?)(#([^:]+?))(:(.+))?$/;function s(t){return"window"==t?window:"document"==t?document:void 0}function a(t){return t.replace(/(?:[_-])([a-z0-9])/g,((t,e)=>e.toUpperCase()))}function c(t){return t.charAt(0).toUpperCase()+t.slice(1)}function u(t){return t.replace(/([A-Z])/g,((t,e)=>`-${e.toLowerCase()}`))}const l={a:t=>"click",button:t=>"click",form:t=>"submit",details:t=>"toggle",input:t=>"submit"==t.getAttribute("type")?"click":"input",select:t=>"change",textarea:t=>"input"};function h(t){throw new Error(t)}function d(t){try{return JSON.parse(t)}catch(e){return t}}class f{constructor(t,e){this.context=t,this.action=e}get index(){return this.action.index}get eventTarget(){return this.action.eventTarget}get eventOptions(){return this.action.eventOptions}get identifier(){return this.context.identifier}handleEvent(t){this.willBeInvokedByEvent(t)&&this.invokeWithEvent(t)}get eventName(){return this.action.eventName}get method(){const t=this.controller[this.methodName];if("function"==typeof t)return t;throw new Error(`Action "${this.action}" references undefined method "${this.methodName}"`)}invokeWithEvent(t){const{target:e,currentTarget:r}=t;try{const{params:n}=this.action,i=Object.assign(t,{params:n});this.method.call(this.controller,i),this.context.logDebugActivity(this.methodName,{event:t,target:e,currentTarget:r,action:this.methodName})}catch(e){const{identifier:r,controller:n,element:i,index:o}=this,s={identifier:r,controller:n,element:i,index:o,event:t};this.context.handleError(e,`invoking action "${this.action}"`,s)}}willBeInvokedByEvent(t){const e=t.target;return this.element===e||(e instanceof Element&&this.element.contains(e)?this.scope.containsElement(e):this.scope.containsElement(this.action.element))}get controller(){return this.context.controller}get methodName(){return this.action.methodName}get element(){return this.scope.element}get scope(){return this.context.scope}}class p{constructor(t,e){this.mutationObserverInit={attributes:!0,childList:!0,subtree:!0},this.element=t,this.started=!1,this.delegate=e,this.elements=new Set,this.mutationObserver=new MutationObserver((t=>this.processMutations(t)))}start(){this.started||(this.started=!0,this.mutationObserver.observe(this.element,this.mutationObserverInit),this.refresh())}pause(t){this.started&&(this.mutationObserver.disconnect(),this.started=!1),t(),this.started||(this.mutationObserver.observe(this.element,this.mutationObserverInit),this.started=!0)}stop(){this.started&&(this.mutationObserver.takeRecords(),this.mutationObserver.disconnect(),this.started=!1)}refresh(){if(this.started){const t=new Set(this.matchElementsInTree());for(const e of Array.from(this.elements))t.has(e)||this.removeElement(e);for(const e of Array.from(t))this.addElement(e)}}processMutations(t){if(this.started)for(const e of t)this.processMutation(e)}processMutation(t){"attributes"==t.type?this.processAttributeChange(t.target,t.attributeName):"childList"==t.type&&(this.processRemovedNodes(t.removedNodes),this.processAddedNodes(t.addedNodes))}processAttributeChange(t,e){const r=t;this.elements.has(r)?this.delegate.elementAttributeChanged&&this.matchElement(r)?this.delegate.elementAttributeChanged(r,e):this.removeElement(r):this.matchElement(r)&&this.addElement(r)}processRemovedNodes(t){for(const e of Array.from(t)){const t=this.elementFromNode(e);t&&this.processTree(t,this.removeElement)}}processAddedNodes(t){for(const e of Array.from(t)){const t=this.elementFromNode(e);t&&this.elementIsActive(t)&&this.processTree(t,this.addElement)}}matchElement(t){return this.delegate.matchElement(t)}matchElementsInTree(t=this.element){return this.delegate.matchElementsInTree(t)}processTree(t,e){for(const r of this.matchElementsInTree(t))e.call(this,r)}elementFromNode(t){if(t.nodeType==Node.ELEMENT_NODE)return t}elementIsActive(t){return t.isConnected==this.element.isConnected&&this.element.contains(t)}addElement(t){this.elements.has(t)||this.elementIsActive(t)&&(this.elements.add(t),this.delegate.elementMatched&&this.delegate.elementMatched(t))}removeElement(t){this.elements.has(t)&&(this.elements.delete(t),this.delegate.elementUnmatched&&this.delegate.elementUnmatched(t))}}class m{constructor(t,e,r){this.attributeName=e,this.delegate=r,this.elementObserver=new p(t,this)}get element(){return this.elementObserver.element}get selector(){return`[${this.attributeName}]`}start(){this.elementObserver.start()}pause(t){this.elementObserver.pause(t)}stop(){this.elementObserver.stop()}refresh(){this.elementObserver.refresh()}get started(){return this.elementObserver.started}matchElement(t){return t.hasAttribute(this.attributeName)}matchElementsInTree(t){const e=this.matchElement(t)?[t]:[],r=Array.from(t.querySelectorAll(this.selector));return e.concat(r)}elementMatched(t){this.delegate.elementMatchedAttribute&&this.delegate.elementMatchedAttribute(t,this.attributeName)}elementUnmatched(t){this.delegate.elementUnmatchedAttribute&&this.delegate.elementUnmatchedAttribute(t,this.attributeName)}elementAttributeChanged(t,e){this.delegate.elementAttributeValueChanged&&this.attributeName==e&&this.delegate.elementAttributeValueChanged(t,e)}}class g{constructor(t,e){this.element=t,this.delegate=e,this.started=!1,this.stringMap=new Map,this.mutationObserver=new MutationObserver((t=>this.processMutations(t)))}start(){this.started||(this.started=!0,this.mutationObserver.observe(this.element,{attributes:!0,attributeOldValue:!0}),this.refresh())}stop(){this.started&&(this.mutationObserver.takeRecords(),this.mutationObserver.disconnect(),this.started=!1)}refresh(){if(this.started)for(const t of this.knownAttributeNames)this.refreshAttribute(t,null)}processMutations(t){if(this.started)for(const e of t)this.processMutation(e)}processMutation(t){const e=t.attributeName;e&&this.refreshAttribute(e,t.oldValue)}refreshAttribute(t,e){const r=this.delegate.getStringMapKeyForAttribute(t);if(null!=r){this.stringMap.has(t)||this.stringMapKeyAdded(r,t);const n=this.element.getAttribute(t);if(this.stringMap.get(t)!=n&&this.stringMapValueChanged(n,r,e),null==n){const e=this.stringMap.get(t);this.stringMap.delete(t),e&&this.stringMapKeyRemoved(r,t,e)}else this.stringMap.set(t,n)}}stringMapKeyAdded(t,e){this.delegate.stringMapKeyAdded&&this.delegate.stringMapKeyAdded(t,e)}stringMapValueChanged(t,e,r){this.delegate.stringMapValueChanged&&this.delegate.stringMapValueChanged(t,e,r)}stringMapKeyRemoved(t,e,r){this.delegate.stringMapKeyRemoved&&this.delegate.stringMapKeyRemoved(t,e,r)}get knownAttributeNames(){return Array.from(new Set(this.currentAttributeNames.concat(this.recordedAttributeNames)))}get currentAttributeNames(){return Array.from(this.element.attributes).map((t=>t.name))}get recordedAttributeNames(){return Array.from(this.stringMap.keys())}}function v(t,e,r){y(t,e).add(r)}function b(t,e,r){y(t,e).delete(r),function(t,e){const r=t.get(e);null!=r&&0==r.size&&t.delete(e)}(t,e)}function y(t,e){let r=t.get(e);return r||(r=new Set,t.set(e,r)),r}class w{constructor(){this.valuesByKey=new Map}get keys(){return Array.from(this.valuesByKey.keys())}get values(){return Array.from(this.valuesByKey.values()).reduce(((t,e)=>t.concat(Array.from(e))),[])}get size(){return Array.from(this.valuesByKey.values()).reduce(((t,e)=>t+e.size),0)}add(t,e){v(this.valuesByKey,t,e)}delete(t,e){b(this.valuesByKey,t,e)}has(t,e){const r=this.valuesByKey.get(t);return null!=r&&r.has(e)}hasKey(t){return this.valuesByKey.has(t)}hasValue(t){return Array.from(this.valuesByKey.values()).some((e=>e.has(t)))}getValuesForKey(t){const e=this.valuesByKey.get(t);return e?Array.from(e):[]}getKeysForValue(t){return Array.from(this.valuesByKey).filter((([e,r])=>r.has(t))).map((([t,e])=>t))}}class O{constructor(t,e,r){this.attributeObserver=new m(t,e,this),this.delegate=r,this.tokensByElement=new w}get started(){return this.attributeObserver.started}start(){this.attributeObserver.start()}pause(t){this.attributeObserver.pause(t)}stop(){this.attributeObserver.stop()}refresh(){this.attributeObserver.refresh()}get element(){return this.attributeObserver.element}get attributeName(){return this.attributeObserver.attributeName}elementMatchedAttribute(t){this.tokensMatched(this.readTokensForElement(t))}elementAttributeValueChanged(t){const[e,r]=this.refreshTokensForElement(t);this.tokensUnmatched(e),this.tokensMatched(r)}elementUnmatchedAttribute(t){this.tokensUnmatched(this.tokensByElement.getValuesForKey(t))}tokensMatched(t){t.forEach((t=>this.tokenMatched(t)))}tokensUnmatched(t){t.forEach((t=>this.tokenUnmatched(t)))}tokenMatched(t){this.delegate.tokenMatched(t),this.tokensByElement.add(t.element,t)}tokenUnmatched(t){this.delegate.tokenUnmatched(t),this.tokensByElement.delete(t.element,t)}refreshTokensForElement(t){const e=this.tokensByElement.getValuesForKey(t),r=this.readTokensForElement(t),n=function(t,e){const r=Math.max(t.length,e.length);return Array.from({length:r},((r,n)=>[t[n],e[n]]))}(e,r).findIndex((([t,e])=>{return n=e,!((r=t)&&n&&r.index==n.index&&r.content==n.content);var r,n}));return-1==n?[[],[]]:[e.slice(n),r.slice(n)]}readTokensForElement(t){const e=this.attributeName;return function(t,e,r){return t.trim().split(/\s+/).filter((t=>t.length)).map(((t,n)=>({element:e,attributeName:r,content:t,index:n})))}(t.getAttribute(e)||"",t,e)}}class E{constructor(t,e,r){this.tokenListObserver=new O(t,e,this),this.delegate=r,this.parseResultsByToken=new WeakMap,this.valuesByTokenByElement=new WeakMap}get started(){return this.tokenListObserver.started}start(){this.tokenListObserver.start()}stop(){this.tokenListObserver.stop()}refresh(){this.tokenListObserver.refresh()}get element(){return this.tokenListObserver.element}get attributeName(){return this.tokenListObserver.attributeName}tokenMatched(t){const{element:e}=t,{value:r}=this.fetchParseResultForToken(t);r&&(this.fetchValuesByTokenForElement(e).set(t,r),this.delegate.elementMatchedValue(e,r))}tokenUnmatched(t){const{element:e}=t,{value:r}=this.fetchParseResultForToken(t);r&&(this.fetchValuesByTokenForElement(e).delete(t),this.delegate.elementUnmatchedValue(e,r))}fetchParseResultForToken(t){let e=this.parseResultsByToken.get(t);return e||(e=this.parseToken(t),this.parseResultsByToken.set(t,e)),e}fetchValuesByTokenForElement(t){let e=this.valuesByTokenByElement.get(t);return e||(e=new Map,this.valuesByTokenByElement.set(t,e)),e}parseToken(t){try{return{value:this.delegate.parseValueForToken(t)}}catch(t){return{error:t}}}}class x{constructor(t,e){this.context=t,this.delegate=e,this.bindingsByAction=new Map}start(){this.valueListObserver||(this.valueListObserver=new E(this.element,this.actionAttribute,this),this.valueListObserver.start())}stop(){this.valueListObserver&&(this.valueListObserver.stop(),delete this.valueListObserver,this.disconnectAllActions())}get element(){return this.context.element}get identifier(){return this.context.identifier}get actionAttribute(){return this.schema.actionAttribute}get schema(){return this.context.schema}get bindings(){return Array.from(this.bindingsByAction.values())}connectAction(t){const e=new f(this.context,t);this.bindingsByAction.set(t,e),this.delegate.bindingConnected(e)}disconnectAction(t){const e=this.bindingsByAction.get(t);e&&(this.bindingsByAction.delete(t),this.delegate.bindingDisconnected(e))}disconnectAllActions(){this.bindings.forEach((t=>this.delegate.bindingDisconnected(t))),this.bindingsByAction.clear()}parseValueForToken(t){const e=class{constructor(t,e,r){this.element=t,this.index=e,this.eventTarget=r.eventTarget||t,this.eventName=r.eventName||function(t){const e=t.tagName.toLowerCase();if(e in l)return l[e](t)}(t)||h("missing event name"),this.eventOptions=r.eventOptions||{},this.identifier=r.identifier||h("missing identifier"),this.methodName=r.methodName||h("missing method name")}static forToken(t){return new this(t.element,t.index,function(t){const e=t.trim().match(o)||[];return{eventTarget:s(e[4]),eventName:e[2],eventOptions:e[9]?(r=e[9],r.split(":").reduce(((t,e)=>Object.assign(t,{[e.replace(/^!/,"")]:!/^!/.test(e)})),{})):{},identifier:e[5],methodName:e[7]};var r}(t.content))}toString(){const t=this.eventTargetName?`@${this.eventTargetName}`:"";return`${this.eventName}${t}->${this.identifier}#${this.methodName}`}get params(){return this.eventTarget instanceof Element?this.getParamsFromEventTargetAttributes(this.eventTarget):{}}getParamsFromEventTargetAttributes(t){const e={},r=new RegExp(`^data-${this.identifier}-(.+)-param$`);return Array.from(t.attributes).forEach((({name:t,value:n})=>{const i=t.match(r),o=i&&i[1];o&&Object.assign(e,{[a(o)]:d(n)})})),e}get eventTargetName(){return(t=this.eventTarget)==window?"window":t==document?"document":void 0;var t}}.forToken(t);if(e.identifier==this.identifier)return e}elementMatchedValue(t,e){this.connectAction(e)}elementUnmatchedValue(t,e){this.disconnectAction(e)}}class k{constructor(t,e){this.context=t,this.receiver=e,this.stringMapObserver=new g(this.element,this),this.valueDescriptorMap=this.controller.valueDescriptorMap,this.invokeChangedCallbacksForDefaultValues()}start(){this.stringMapObserver.start()}stop(){this.stringMapObserver.stop()}get element(){return this.context.element}get controller(){return this.context.controller}getStringMapKeyForAttribute(t){if(t in this.valueDescriptorMap)return this.valueDescriptorMap[t].name}stringMapKeyAdded(t,e){const r=this.valueDescriptorMap[e];this.hasValue(t)||this.invokeChangedCallback(t,r.writer(this.receiver[t]),r.writer(r.defaultValue))}stringMapValueChanged(t,e,r){const n=this.valueDescriptorNameMap[e];null!==t&&(null===r&&(r=n.writer(n.defaultValue)),this.invokeChangedCallback(e,t,r))}stringMapKeyRemoved(t,e,r){const n=this.valueDescriptorNameMap[t];this.hasValue(t)?this.invokeChangedCallback(t,n.writer(this.receiver[t]),r):this.invokeChangedCallback(t,n.writer(n.defaultValue),r)}invokeChangedCallbacksForDefaultValues(){for(const{key:t,name:e,defaultValue:r,writer:n}of this.valueDescriptors)null==r||this.controller.data.has(t)||this.invokeChangedCallback(e,n(r),void 0)}invokeChangedCallback(t,e,r){const n=`${t}Changed`,i=this.receiver[n];if("function"==typeof i){const n=this.valueDescriptorNameMap[t],o=n.reader(e);let s=r;r&&(s=n.reader(r)),i.call(this.receiver,o,s)}}get valueDescriptors(){const{valueDescriptorMap:t}=this;return Object.keys(t).map((e=>t[e]))}get valueDescriptorNameMap(){const t={};return Object.keys(this.valueDescriptorMap).forEach((e=>{const r=this.valueDescriptorMap[e];t[r.name]=r})),t}hasValue(t){const e=`has${c(this.valueDescriptorNameMap[t].name)}`;return this.receiver[e]}}class A{constructor(t,e){this.context=t,this.delegate=e,this.targetsByName=new w}start(){this.tokenListObserver||(this.tokenListObserver=new O(this.element,this.attributeName,this),this.tokenListObserver.start())}stop(){this.tokenListObserver&&(this.disconnectAllTargets(),this.tokenListObserver.stop(),delete this.tokenListObserver)}tokenMatched({element:t,content:e}){this.scope.containsElement(t)&&this.connectTarget(t,e)}tokenUnmatched({element:t,content:e}){this.disconnectTarget(t,e)}connectTarget(t,e){var r;this.targetsByName.has(e,t)||(this.targetsByName.add(e,t),null===(r=this.tokenListObserver)||void 0===r||r.pause((()=>this.delegate.targetConnected(t,e))))}disconnectTarget(t,e){var r;this.targetsByName.has(e,t)&&(this.targetsByName.delete(e,t),null===(r=this.tokenListObserver)||void 0===r||r.pause((()=>this.delegate.targetDisconnected(t,e))))}disconnectAllTargets(){for(const t of this.targetsByName.keys)for(const e of this.targetsByName.getValuesForKey(t))this.disconnectTarget(e,t)}get attributeName(){return`data-${this.context.identifier}-target`}get element(){return this.context.element}get scope(){return this.context.scope}}class S{constructor(t,e){this.logDebugActivity=(t,e={})=>{const{identifier:r,controller:n,element:i}=this;e=Object.assign({identifier:r,controller:n,element:i},e),this.application.logDebugActivity(this.identifier,t,e)},this.module=t,this.scope=e,this.controller=new t.controllerConstructor(this),this.bindingObserver=new x(this,this.dispatcher),this.valueObserver=new k(this,this.controller),this.targetObserver=new A(this,this);try{this.controller.initialize(),this.logDebugActivity("initialize")}catch(t){this.handleError(t,"initializing controller")}}connect(){this.bindingObserver.start(),this.valueObserver.start(),this.targetObserver.start();try{this.controller.connect(),this.logDebugActivity("connect")}catch(t){this.handleError(t,"connecting controller")}}disconnect(){try{this.controller.disconnect(),this.logDebugActivity("disconnect")}catch(t){this.handleError(t,"disconnecting controller")}this.targetObserver.stop(),this.valueObserver.stop(),this.bindingObserver.stop()}get application(){return this.module.application}get identifier(){return this.module.identifier}get schema(){return this.application.schema}get dispatcher(){return this.application.dispatcher}get element(){return this.scope.element}get parentElement(){return this.element.parentElement}handleError(t,e,r={}){const{identifier:n,controller:i,element:o}=this;r=Object.assign({identifier:n,controller:i,element:o},r),this.application.handleError(t,`Error ${e}`,r)}targetConnected(t,e){this.invokeControllerMethod(`${e}TargetConnected`,t)}targetDisconnected(t,e){this.invokeControllerMethod(`${e}TargetDisconnected`,t)}invokeControllerMethod(t,...e){const r=this.controller;"function"==typeof r[t]&&r[t](...e)}}function M(t,e){const r=j(t);return Array.from(r.reduce(((t,r)=>(function(t,e){const r=t[e];return Array.isArray(r)?r:[]}(r,e).forEach((e=>t.add(e))),t)),new Set))}function T(t,e){return j(t).reduce(((t,r)=>(t.push(...function(t,e){const r=t[e];return r?Object.keys(r).map((t=>[t,r[t]])):[]}(r,e)),t)),[])}function j(t){const e=[];for(;t;)e.push(t),t=Object.getPrototypeOf(t);return e.reverse()}function N(t){return function(t,e){const r=L(t),n=function(t,e){return C(e).reduce(((r,n)=>{const i=function(t,e,r){const n=Object.getOwnPropertyDescriptor(t,r);if(!n||!("value"in n)){const t=Object.getOwnPropertyDescriptor(e,r).value;return n&&(t.get=n.get||t.get,t.set=n.set||t.set),t}}(t,e,n);return i&&Object.assign(r,{[n]:i}),r}),{})}(t.prototype,e);return Object.defineProperties(r.prototype,n),r}(t,function(t){return M(t,"blessings").reduce(((e,r)=>{const n=r(t);for(const t in n){const r=e[t]||{};e[t]=Object.assign(r,n[t])}return e}),{})}(t))}const C="function"==typeof Object.getOwnPropertySymbols?t=>[...Object.getOwnPropertyNames(t),...Object.getOwnPropertySymbols(t)]:Object.getOwnPropertyNames,L=(()=>{function t(t){function e(){return Reflect.construct(t,arguments,new.target)}return e.prototype=Object.create(t.prototype,{constructor:{value:e}}),Reflect.setPrototypeOf(e,t),e}try{return function(){const e=t((function(){this.a.call(this)}));e.prototype.a=function(){},new e}(),t}catch(t){return t=>class extends t{}}})();class F{constructor(t,e){this.application=t,this.definition=function(t){return{identifier:t.identifier,controllerConstructor:N(t.controllerConstructor)}}(e),this.contextsByScope=new WeakMap,this.connectedContexts=new Set}get identifier(){return this.definition.identifier}get controllerConstructor(){return this.definition.controllerConstructor}get contexts(){return Array.from(this.connectedContexts)}connectContextForScope(t){const e=this.fetchContextForScope(t);this.connectedContexts.add(e),e.connect()}disconnectContextForScope(t){const e=this.contextsByScope.get(t);e&&(this.connectedContexts.delete(e),e.disconnect())}fetchContextForScope(t){let e=this.contextsByScope.get(t);return e||(e=new S(this,t),this.contextsByScope.set(t,e)),e}}class B{constructor(t){this.scope=t}has(t){return this.data.has(this.getDataKey(t))}get(t){return this.getAll(t)[0]}getAll(t){const e=this.data.get(this.getDataKey(t))||"";return e.match(/[^\s]+/g)||[]}getAttributeName(t){return this.data.getAttributeNameForKey(this.getDataKey(t))}getDataKey(t){return`${t}-class`}get data(){return this.scope.data}}class D{constructor(t){this.scope=t}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get(t){const e=this.getAttributeNameForKey(t);return this.element.getAttribute(e)}set(t,e){const r=this.getAttributeNameForKey(t);return this.element.setAttribute(r,e),this.get(t)}has(t){const e=this.getAttributeNameForKey(t);return this.element.hasAttribute(e)}delete(t){if(this.has(t)){const e=this.getAttributeNameForKey(t);return this.element.removeAttribute(e),!0}return!1}getAttributeNameForKey(t){return`data-${this.identifier}-${u(t)}`}}class ${constructor(t){this.warnedKeysByObject=new WeakMap,this.logger=t}warn(t,e,r){let n=this.warnedKeysByObject.get(t);n||(n=new Set,this.warnedKeysByObject.set(t,n)),n.has(e)||(n.add(e),this.logger.warn(r,t))}}function P(t,e){return`[${t}~="${e}"]`}class I{constructor(t){this.scope=t}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get schema(){return this.scope.schema}has(t){return null!=this.find(t)}find(...t){return t.reduce(((t,e)=>t||this.findTarget(e)||this.findLegacyTarget(e)),void 0)}findAll(...t){return t.reduce(((t,e)=>[...t,...this.findAllTargets(e),...this.findAllLegacyTargets(e)]),[])}findTarget(t){const e=this.getSelectorForTargetName(t);return this.scope.findElement(e)}findAllTargets(t){const e=this.getSelectorForTargetName(t);return this.scope.findAllElements(e)}getSelectorForTargetName(t){return P(this.schema.targetAttributeForScope(this.identifier),t)}findLegacyTarget(t){const e=this.getLegacySelectorForTargetName(t);return this.deprecate(this.scope.findElement(e),t)}findAllLegacyTargets(t){const e=this.getLegacySelectorForTargetName(t);return this.scope.findAllElements(e).map((e=>this.deprecate(e,t)))}getLegacySelectorForTargetName(t){const e=`${this.identifier}.${t}`;return P(this.schema.targetAttribute,e)}deprecate(t,e){if(t){const{identifier:r}=this,n=this.schema.targetAttribute,i=this.schema.targetAttributeForScope(r);this.guide.warn(t,`target:${e}`,`Please replace ${n}="${r}.${e}" with ${i}="${e}". The ${n} attribute is deprecated and will be removed in a future version of Stimulus.`)}return t}get guide(){return this.scope.guide}}class V{constructor(t,e,r,n){this.targets=new I(this),this.classes=new B(this),this.data=new D(this),this.containsElement=t=>t.closest(this.controllerSelector)===this.element,this.schema=t,this.element=e,this.identifier=r,this.guide=new $(n)}findElement(t){return this.element.matches(t)?this.element:this.queryElements(t).find(this.containsElement)}findAllElements(t){return[...this.element.matches(t)?[this.element]:[],...this.queryElements(t).filter(this.containsElement)]}queryElements(t){return Array.from(this.element.querySelectorAll(t))}get controllerSelector(){return P(this.schema.controllerAttribute,this.identifier)}}class K{constructor(t,e,r){this.element=t,this.schema=e,this.delegate=r,this.valueListObserver=new E(this.element,this.controllerAttribute,this),this.scopesByIdentifierByElement=new WeakMap,this.scopeReferenceCounts=new WeakMap}start(){this.valueListObserver.start()}stop(){this.valueListObserver.stop()}get controllerAttribute(){return this.schema.controllerAttribute}parseValueForToken(t){const{element:e,content:r}=t,n=this.fetchScopesByIdentifierForElement(e);let i=n.get(r);return i||(i=this.delegate.createScopeForElementAndIdentifier(e,r),n.set(r,i)),i}elementMatchedValue(t,e){const r=(this.scopeReferenceCounts.get(e)||0)+1;this.scopeReferenceCounts.set(e,r),1==r&&this.delegate.scopeConnected(e)}elementUnmatchedValue(t,e){const r=this.scopeReferenceCounts.get(e);r&&(this.scopeReferenceCounts.set(e,r-1),1==r&&this.delegate.scopeDisconnected(e))}fetchScopesByIdentifierForElement(t){let e=this.scopesByIdentifierByElement.get(t);return e||(e=new Map,this.scopesByIdentifierByElement.set(t,e)),e}}class R{constructor(t){this.application=t,this.scopeObserver=new K(this.element,this.schema,this),this.scopesByIdentifier=new w,this.modulesByIdentifier=new Map}get element(){return this.application.element}get schema(){return this.application.schema}get logger(){return this.application.logger}get controllerAttribute(){return this.schema.controllerAttribute}get modules(){return Array.from(this.modulesByIdentifier.values())}get contexts(){return this.modules.reduce(((t,e)=>t.concat(e.contexts)),[])}start(){this.scopeObserver.start()}stop(){this.scopeObserver.stop()}loadDefinition(t){this.unloadIdentifier(t.identifier);const e=new F(this.application,t);this.connectModule(e)}unloadIdentifier(t){const e=this.modulesByIdentifier.get(t);e&&this.disconnectModule(e)}getContextForElementAndIdentifier(t,e){const r=this.modulesByIdentifier.get(e);if(r)return r.contexts.find((e=>e.element==t))}handleError(t,e,r){this.application.handleError(t,e,r)}createScopeForElementAndIdentifier(t,e){return new V(this.schema,t,e,this.logger)}scopeConnected(t){this.scopesByIdentifier.add(t.identifier,t);const e=this.modulesByIdentifier.get(t.identifier);e&&e.connectContextForScope(t)}scopeDisconnected(t){this.scopesByIdentifier.delete(t.identifier,t);const e=this.modulesByIdentifier.get(t.identifier);e&&e.disconnectContextForScope(t)}connectModule(t){this.modulesByIdentifier.set(t.identifier,t);this.scopesByIdentifier.getValuesForKey(t.identifier).forEach((e=>t.connectContextForScope(e)))}disconnectModule(t){this.modulesByIdentifier.delete(t.identifier);this.scopesByIdentifier.getValuesForKey(t.identifier).forEach((e=>t.disconnectContextForScope(e)))}}const z={controllerAttribute:"data-controller",actionAttribute:"data-action",targetAttribute:"data-target",targetAttributeForScope:t=>`data-${t}-target`};class _{constructor(t=document.documentElement,e=z){this.logger=console,this.debug=!1,this.logDebugActivity=(t,e,r={})=>{this.debug&&this.logFormattedMessage(t,e,r)},this.element=t,this.schema=e,this.dispatcher=new i(this),this.router=new R(this)}static start(t,e){const r=new _(t,e);return r.start(),r}async start(){await new Promise((t=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",(()=>t())):t()})),this.logDebugActivity("application","starting"),this.dispatcher.start(),this.router.start(),this.logDebugActivity("application","start")}stop(){this.logDebugActivity("application","stopping"),this.dispatcher.stop(),this.router.stop(),this.logDebugActivity("application","stop")}register(t,e){e.shouldLoad&&this.load({identifier:t,controllerConstructor:e})}load(t,...e){(Array.isArray(t)?t:[t,...e]).forEach((t=>this.router.loadDefinition(t)))}unload(t,...e){(Array.isArray(t)?t:[t,...e]).forEach((t=>this.router.unloadIdentifier(t)))}get controllers(){return this.router.contexts.map((t=>t.controller))}getControllerForElementAndIdentifier(t,e){const r=this.router.getContextForElementAndIdentifier(t,e);return r?r.controller:null}handleError(t,e,r){var n;this.logger.error("%s\n\n%o\n\n%o",e,t,r),null===(n=window.onerror)||void 0===n||n.call(window,e,"",0,0,t)}logFormattedMessage(t,e,r={}){r=Object.assign({application:this},r),this.logger.groupCollapsed(`${t} #${e}`),this.logger.log("details:",Object.assign({},r)),this.logger.groupEnd()}}function q([t,e]){return function(t,e){const r=`${u(t)}-value`,n=function(t){const e=function(t){const e=U(t.type);if(e){const r=W(t.default);if(e!==r)throw new Error(`Type "${e}" must match the type of the default value. Given default value: "${t.default}" as "${r}"`);return e}}(t),r=W(t),n=U(t),i=e||r||n;if(i)return i;throw new Error(`Unknown value type "${t}"`)}(e);return{type:n,key:r,name:a(r),get defaultValue(){return function(t){const e=U(t);if(e)return H[e];const r=t.default;return void 0!==r?r:t}(e)},get hasCustomDefaultValue(){return void 0!==W(e)},reader:G[n],writer:Y[n]||Y.default}}(t,e)}function U(t){switch(t){case Array:return"array";case Boolean:return"boolean";case Number:return"number";case Object:return"object";case String:return"string"}}function W(t){switch(typeof t){case"boolean":return"boolean";case"number":return"number";case"string":return"string"}return Array.isArray(t)?"array":"[object Object]"===Object.prototype.toString.call(t)?"object":void 0}const H={get array(){return[]},boolean:!1,number:0,get object(){return{}},string:""},G={array(t){const e=JSON.parse(t);if(!Array.isArray(e))throw new TypeError("Expected array");return e},boolean:t=>!("0"==t||"false"==t),number:t=>Number(t),object(t){const e=JSON.parse(t);if(null===e||"object"!=typeof e||Array.isArray(e))throw new TypeError("Expected object");return e},string:t=>t},Y={default:function(t){return`${t}`},array:J,object:J};function J(t){return JSON.stringify(t)}class Z{constructor(t){this.context=t}static get shouldLoad(){return!0}get application(){return this.context.application}get scope(){return this.context.scope}get element(){return this.scope.element}get identifier(){return this.scope.identifier}get targets(){return this.scope.targets}get classes(){return this.scope.classes}get data(){return this.scope.data}initialize(){}connect(){}disconnect(){}dispatch(t,{target:e=this.element,detail:r={},prefix:n=this.identifier,bubbles:i=!0,cancelable:o=!0}={}){const s=new CustomEvent(n?`${n}:${t}`:t,{detail:r,bubbles:i,cancelable:o});return e.dispatchEvent(s),s}}Z.blessings=[function(t){return M(t,"classes").reduce(((t,e)=>{return Object.assign(t,{[`${r=e}Class`]:{get(){const{classes:t}=this;if(t.has(r))return t.get(r);{const e=t.getAttributeName(r);throw new Error(`Missing attribute "${e}"`)}}},[`${r}Classes`]:{get(){return this.classes.getAll(r)}},[`has${c(r)}Class`]:{get(){return this.classes.has(r)}}});var r}),{})},function(t){return M(t,"targets").reduce(((t,e)=>{return Object.assign(t,{[`${r=e}Target`]:{get(){const t=this.targets.find(r);if(t)return t;throw new Error(`Missing target element "${r}" for "${this.identifier}" controller`)}},[`${r}Targets`]:{get(){return this.targets.findAll(r)}},[`has${c(r)}Target`]:{get(){return this.targets.has(r)}}});var r}),{})},function(t){const e=T(t,"values"),r={valueDescriptorMap:{get(){return e.reduce(((t,e)=>{const r=q(e),n=this.data.getAttributeNameForKey(r.key);return Object.assign(t,{[n]:r})}),{})}}};return e.reduce(((t,e)=>Object.assign(t,function(t){const e=q(t),{key:r,name:n,reader:i,writer:o}=e;return{[n]:{get(){const t=this.data.get(r);return null!==t?i(t):e.defaultValue},set(t){void 0===t?this.data.delete(r):this.data.set(r,o(t))}},[`has${c(n)}`]:{get(){return this.data.has(r)||e.hasCustomDefaultValue}}}}(e))),r)}],Z.targets=[],Z.values={};var X=r(8205);function Q(t){return t.keys().map((e=>function(t,e){const r=function(t){const e=(t.match(/^(?:\.\/)?(.+)(?:[_-]controller\..+?)$/)||[])[1];if(e)return e.replace(/_/g,"-").replace(/\//g,"--")}(e);if(r)return function(t,e){const r=t.default;if("function"==typeof r)return{identifier:e,controllerConstructor:r}}(t(e),r)}(t,e))).filter((t=>t))}function tt(t){const e=_.start();t&&e.load(Q(t));for(const t in X.Z)X.Z.hasOwnProperty(t)&&X.Z[t].then((r=>{e.register(t,r.default)}));return e}},2711:function(t,e,r){t.exports=function(){"use strict";var t="undefined"!=typeof window?window:void 0!==r.g?r.g:"undefined"!=typeof self?self:{},e="Expected a function",n=NaN,i="[object Symbol]",o=/^\s+|\s+$/g,s=/^[-+]0x[0-9a-f]+$/i,a=/^0b[01]+$/i,c=/^0o[0-7]+$/i,u=parseInt,l="object"==typeof t&&t&&t.Object===Object&&t,h="object"==typeof self&&self&&self.Object===Object&&self,d=l||h||Function("return this")(),f=Object.prototype.toString,p=Math.max,m=Math.min,g=function(){return d.Date.now()};function v(t,r,n){var i,o,s,a,c,u,l=0,h=!1,d=!1,f=!0;if("function"!=typeof t)throw new TypeError(e);function v(e){var r=i,n=o;return i=o=void 0,l=e,a=t.apply(n,r)}function w(t){var e=t-u;return void 0===u||e>=r||e<0||d&&t-l>=s}function O(){var t=g();if(w(t))return E(t);c=setTimeout(O,function(t){var e=r-(t-u);return d?m(e,s-(t-l)):e}(t))}function E(t){return c=void 0,f&&i?v(t):(i=o=void 0,a)}function x(){var t=g(),e=w(t);if(i=arguments,o=this,u=t,e){if(void 0===c)return function(t){return l=t,c=setTimeout(O,r),h?v(t):a}(u);if(d)return c=setTimeout(O,r),v(u)}return void 0===c&&(c=setTimeout(O,r)),a}return r=y(r)||0,b(n)&&(h=!!n.leading,s=(d="maxWait"in n)?p(y(n.maxWait)||0,r):s,f="trailing"in n?!!n.trailing:f),x.cancel=function(){void 0!==c&&clearTimeout(c),l=0,i=u=o=c=void 0},x.flush=function(){return void 0===c?a:E(g())},x}function b(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function y(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&f.call(t)==i}(t))return n;if(b(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=b(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(o,"");var r=a.test(t);return r||c.test(t)?u(t.slice(2),r?2:8):s.test(t)?n:+t}var w=function(t,r,n){var i=!0,o=!0;if("function"!=typeof t)throw new TypeError(e);return b(n)&&(i="leading"in n?!!n.leading:i,o="trailing"in n?!!n.trailing:o),v(t,r,{leading:i,maxWait:r,trailing:o})},O="Expected a function",E=NaN,x="[object Symbol]",k=/^\s+|\s+$/g,A=/^[-+]0x[0-9a-f]+$/i,S=/^0b[01]+$/i,M=/^0o[0-7]+$/i,T=parseInt,j="object"==typeof t&&t&&t.Object===Object&&t,N="object"==typeof self&&self&&self.Object===Object&&self,C=j||N||Function("return this")(),L=Object.prototype.toString,F=Math.max,B=Math.min,D=function(){return C.Date.now()};function $(t){var e=typeof t;return!!t&&("object"==e||"function"==e)}function P(t){if("number"==typeof t)return t;if(function(t){return"symbol"==typeof t||function(t){return!!t&&"object"==typeof t}(t)&&L.call(t)==x}(t))return E;if($(t)){var e="function"==typeof t.valueOf?t.valueOf():t;t=$(e)?e+"":e}if("string"!=typeof t)return 0===t?t:+t;t=t.replace(k,"");var r=S.test(t);return r||M.test(t)?T(t.slice(2),r?2:8):A.test(t)?E:+t}var I=function(t,e,r){var n,i,o,s,a,c,u=0,l=!1,h=!1,d=!0;if("function"!=typeof t)throw new TypeError(O);function f(e){var r=n,o=i;return n=i=void 0,u=e,s=t.apply(o,r)}function p(t){var r=t-c;return void 0===c||r>=e||r<0||h&&t-u>=o}function m(){var t=D();if(p(t))return g(t);a=setTimeout(m,function(t){var r=e-(t-c);return h?B(r,o-(t-u)):r}(t))}function g(t){return a=void 0,d&&n?f(t):(n=i=void 0,s)}function v(){var t=D(),r=p(t);if(n=arguments,i=this,c=t,r){if(void 0===a)return function(t){return u=t,a=setTimeout(m,e),l?f(t):s}(c);if(h)return a=setTimeout(m,e),f(c)}return void 0===a&&(a=setTimeout(m,e)),s}return e=P(e)||0,$(r)&&(l=!!r.leading,o=(h="maxWait"in r)?F(P(r.maxWait)||0,e):o,d="trailing"in r?!!r.trailing:d),v.cancel=function(){void 0!==a&&clearTimeout(a),u=0,n=c=i=a=void 0},v.flush=function(){return void 0===a?s:g(D())},v},V=function(){};function K(t){t&&t.forEach((function(t){var e=Array.prototype.slice.call(t.addedNodes),r=Array.prototype.slice.call(t.removedNodes);if(function t(e){var r=void 0,n=void 0;for(r=0;r=n.out&&!r.once?o():e>=n.in?t.animated||(function(t,e){e&&e.forEach((function(e){return t.classList.add(e)}))}(i,r.animatedClassNames),X("aos:in",i),t.options.id&&X("aos:in:"+t.options.id,i),t.animated=!0):t.animated&&!r.once&&o()}(t,window.pageYOffset)}))},tt=function(t){for(var e=0,r=0;t&&!isNaN(t.offsetLeft)&&!isNaN(t.offsetTop);)e+=t.offsetLeft-("BODY"!=t.tagName?t.scrollLeft:0),r+=t.offsetTop-("BODY"!=t.tagName?t.scrollTop:0),t=t.offsetParent;return{top:r,left:e}},et=function(t,e,r){var n=t.getAttribute("data-aos-"+e);if(void 0!==n){if("true"===n)return!0;if("false"===n)return!1}return n||r},rt=function(t,e){return t.forEach((function(t,r){var n=et(t.node,"mirror",e.mirror),i=et(t.node,"once",e.once),o=et(t.node,"id"),s=e.useClassNames&&t.node.getAttribute("data-aos"),a=[e.animatedClassName].concat(s?s.split(" "):[]).filter((function(t){return"string"==typeof t}));e.initClassName&&t.node.classList.add(e.initClassName),t.position={in:function(t,e,r){var n=window.innerHeight,i=et(t,"anchor"),o=et(t,"anchor-placement"),s=Number(et(t,"offset",o?0:e)),a=o||r,c=t;i&&document.querySelectorAll(i)&&(c=document.querySelectorAll(i)[0]);var u=tt(c).top-n;switch(a){case"top-bottom":break;case"center-bottom":u+=c.offsetHeight/2;break;case"bottom-bottom":u+=c.offsetHeight;break;case"top-center":u+=n/2;break;case"center-center":u+=n/2+c.offsetHeight/2;break;case"bottom-center":u+=n/2+c.offsetHeight;break;case"top-top":u+=n;break;case"bottom-top":u+=n+c.offsetHeight;break;case"center-top":u+=n+c.offsetHeight/2}return u+s}(t.node,e.offset,e.anchorPlacement),out:n&&function(t,e){window.innerHeight;var r=et(t,"anchor"),n=et(t,"offset",e),i=t;return r&&document.querySelectorAll(r)&&(i=document.querySelectorAll(r)[0]),tt(i).top+i.offsetHeight-n}(t.node,e.offset)},t.options={once:i,mirror:n,animatedClassNames:a,id:o}})),t},nt=function(){var t=document.querySelectorAll("[data-aos]");return Array.prototype.map.call(t,(function(t){return{node:t}}))},it=[],ot=!1,st={offset:120,delay:0,easing:"ease",duration:400,disable:!1,once:!1,mirror:!1,anchorPlacement:"top-bottom",startEvent:"DOMContentLoaded",animatedClassName:"aos-animate",initClassName:"aos-init",useClassNames:!1,disableMutationObserver:!1,throttleDelay:99,debounceDelay:50},at=function(){return document.all&&!window.atob},ct=function(){arguments.length>0&&void 0!==arguments[0]&&arguments[0]&&(ot=!0),ot&&(it=rt(it,st),Q(it),window.addEventListener("scroll",w((function(){Q(it,st.once)}),st.throttleDelay)))},ut=function(){if(it=nt(),ht(st.disable)||at())return lt();ct()},lt=function(){it.forEach((function(t,e){t.node.removeAttribute("data-aos"),t.node.removeAttribute("data-aos-easing"),t.node.removeAttribute("data-aos-duration"),t.node.removeAttribute("data-aos-delay"),st.initClassName&&t.node.classList.remove(st.initClassName),st.animatedClassName&&t.node.classList.remove(st.animatedClassName)}))},ht=function(t){return!0===t||"mobile"===t&&Z.mobile()||"phone"===t&&Z.phone()||"tablet"===t&&Z.tablet()||"function"==typeof t&&!0===t()};return{init:function(t){return st=U(st,t),it=nt(),st.disableMutationObserver||z.isSupported()||(console.info('\n aos: MutationObserver is not supported on this browser,\n code mutations observing has been disabled.\n You may have to call "refreshHard()" by yourself.\n '),st.disableMutationObserver=!0),st.disableMutationObserver||z.ready("[data-aos]",ut),ht(st.disable)||at()?lt():(document.querySelector("body").setAttribute("data-aos-easing",st.easing),document.querySelector("body").setAttribute("data-aos-duration",st.duration),document.querySelector("body").setAttribute("data-aos-delay",st.delay),-1===["DOMContentLoaded","load"].indexOf(st.startEvent)?document.addEventListener(st.startEvent,(function(){ct(!0)})):window.addEventListener("load",(function(){ct(!0)})),"DOMContentLoaded"===st.startEvent&&["complete","interactive"].indexOf(document.readyState)>-1&&ct(!0),window.addEventListener("resize",I(ct,st.debounceDelay,!0)),window.addEventListener("orientationchange",I(ct,st.debounceDelay,!0)),it)},refresh:ct,refreshHard:ut}}()},9662:(t,e,r)=>{var n=r(614),i=r(6330),o=TypeError;t.exports=function(t){if(n(t))return t;throw o(i(t)+" is not a function")}},6077:(t,e,r)=>{var n=r(614),i=String,o=TypeError;t.exports=function(t){if("object"==typeof t||n(t))return t;throw o("Can't set "+i(t)+" as a prototype")}},9670:(t,e,r)=>{var n=r(111),i=String,o=TypeError;t.exports=function(t){if(n(t))return t;throw o(i(t)+" is not an object")}},8533:(t,e,r)=>{"use strict";var n=r(2092).forEach,i=r(9341)("forEach");t.exports=i?[].forEach:function(t){return n(this,t,arguments.length>1?arguments[1]:void 0)}},1318:(t,e,r)=>{var n=r(5656),i=r(1400),o=r(6244),s=function(t){return function(e,r,s){var a,c=n(e),u=o(c),l=i(s,u);if(t&&r!=r){for(;u>l;)if((a=c[l++])!=a)return!0}else for(;u>l;l++)if((t||l in c)&&c[l]===r)return t||l||0;return!t&&-1}};t.exports={includes:s(!0),indexOf:s(!1)}},2092:(t,e,r)=>{var n=r(9974),i=r(1702),o=r(8361),s=r(7908),a=r(6244),c=r(5417),u=i([].push),l=function(t){var e=1==t,r=2==t,i=3==t,l=4==t,h=6==t,d=7==t,f=5==t||h;return function(p,m,g,v){for(var b,y,w=s(p),O=o(w),E=n(m,g),x=a(O),k=0,A=v||c,S=e?A(p,x):r||d?A(p,0):void 0;x>k;k++)if((f||k in O)&&(y=E(b=O[k],k,w),t))if(e)S[k]=y;else if(y)switch(t){case 3:return!0;case 5:return b;case 6:return k;case 2:u(S,b)}else switch(t){case 4:return!1;case 7:u(S,b)}return h?-1:i||l?l:S}};t.exports={forEach:l(0),map:l(1),filter:l(2),some:l(3),every:l(4),find:l(5),findIndex:l(6),filterReject:l(7)}},9341:(t,e,r)=>{"use strict";var n=r(7293);t.exports=function(t,e){var r=[][t];return!!r&&n((function(){r.call(null,e||function(){return 1},1)}))}},206:(t,e,r)=>{var n=r(1702);t.exports=n([].slice)},7475:(t,e,r)=>{var n=r(3157),i=r(4411),o=r(111),s=r(5112)("species"),a=Array;t.exports=function(t){var e;return n(t)&&(e=t.constructor,(i(e)&&(e===a||n(e.prototype))||o(e)&&null===(e=e[s]))&&(e=void 0)),void 0===e?a:e}},5417:(t,e,r)=>{var n=r(7475);t.exports=function(t,e){return new(n(t))(0===e?0:e)}},4326:(t,e,r)=>{var n=r(1702),i=n({}.toString),o=n("".slice);t.exports=function(t){return o(i(t),8,-1)}},648:(t,e,r)=>{var n=r(1694),i=r(614),o=r(4326),s=r(5112)("toStringTag"),a=Object,c="Arguments"==o(function(){return arguments}());t.exports=n?o:function(t){var e,r,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=function(t,e){try{return t[e]}catch(t){}}(e=a(t),s))?r:c?o(e):"Object"==(n=o(e))&&i(e.callee)?"Arguments":n}},9920:(t,e,r)=>{var n=r(2597),i=r(3887),o=r(1236),s=r(3070);t.exports=function(t,e,r){for(var a=i(e),c=s.f,u=o.f,l=0;l{var n=r(9781),i=r(3070),o=r(9114);t.exports=n?function(t,e,r){return i.f(t,e,o(1,r))}:function(t,e,r){return t[e]=r,t}},9114:t=>{t.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},8052:(t,e,r)=>{var n=r(614),i=r(3070),o=r(6339),s=r(3072);t.exports=function(t,e,r,a){a||(a={});var c=a.enumerable,u=void 0!==a.name?a.name:e;if(n(r)&&o(r,u,a),a.global)c?t[e]=r:s(e,r);else{try{a.unsafe?t[e]&&(c=!0):delete t[e]}catch(t){}c?t[e]=r:i.f(t,e,{value:r,enumerable:!1,configurable:!a.nonConfigurable,writable:!a.nonWritable})}return t}},3072:(t,e,r)=>{var n=r(7854),i=Object.defineProperty;t.exports=function(t,e){try{i(n,t,{value:e,configurable:!0,writable:!0})}catch(r){n[t]=e}return e}},9781:(t,e,r)=>{var n=r(7293);t.exports=!n((function(){return 7!=Object.defineProperty({},1,{get:function(){return 7}})[1]}))},4154:t=>{var e="object"==typeof document&&document.all,r=void 0===e&&void 0!==e;t.exports={all:e,IS_HTMLDDA:r}},317:(t,e,r)=>{var n=r(7854),i=r(111),o=n.document,s=i(o)&&i(o.createElement);t.exports=function(t){return s?o.createElement(t):{}}},8324:t=>{t.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},8509:(t,e,r)=>{var n=r(317)("span").classList,i=n&&n.constructor&&n.constructor.prototype;t.exports=i===Object.prototype?void 0:i},8113:(t,e,r)=>{var n=r(5005);t.exports=n("navigator","userAgent")||""},7392:(t,e,r)=>{var n,i,o=r(7854),s=r(8113),a=o.process,c=o.Deno,u=a&&a.versions||c&&c.version,l=u&&u.v8;l&&(i=(n=l.split("."))[0]>0&&n[0]<4?1:+(n[0]+n[1])),!i&&s&&(!(n=s.match(/Edge\/(\d+)/))||n[1]>=74)&&(n=s.match(/Chrome\/(\d+)/))&&(i=+n[1]),t.exports=i},748:t=>{t.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},1060:(t,e,r)=>{var n=r(1702),i=Error,o=n("".replace),s=String(i("zxcasd").stack),a=/\n\s*at [^:]*:[^\n]*/,c=a.test(s);t.exports=function(t,e){if(c&&"string"==typeof t&&!i.prepareStackTrace)for(;e--;)t=o(t,a,"");return t}},2914:(t,e,r)=>{var n=r(7293),i=r(9114);t.exports=!n((function(){var t=Error("a");return!("stack"in t)||(Object.defineProperty(t,"stack",i(1,7)),7!==t.stack)}))},7762:(t,e,r)=>{"use strict";var n=r(9781),i=r(7293),o=r(9670),s=r(30),a=r(6277),c=Error.prototype.toString,u=i((function(){if(n){var t=s(Object.defineProperty({},"name",{get:function(){return this===t}}));if("true"!==c.call(t))return!0}return"2: 1"!==c.call({message:1,name:2})||"Error"!==c.call({})}));t.exports=u?function(){var t=o(this),e=a(t.name,"Error"),r=a(t.message);return e?r?e+": "+r:e:r}:c},2109:(t,e,r)=>{var n=r(7854),i=r(1236).f,o=r(8880),s=r(8052),a=r(3072),c=r(9920),u=r(4705);t.exports=function(t,e){var r,l,h,d,f,p=t.target,m=t.global,g=t.stat;if(r=m?n:g?n[p]||a(p,{}):(n[p]||{}).prototype)for(l in e){if(d=e[l],h=t.dontCallGetSet?(f=i(r,l))&&f.value:r[l],!u(m?l:p+(g?".":"#")+l,t.forced)&&void 0!==h){if(typeof d==typeof h)continue;c(d,h)}(t.sham||h&&h.sham)&&o(d,"sham",!0),s(r,l,d,t)}}},7293:t=>{t.exports=function(t){try{return!!t()}catch(t){return!0}}},2104:(t,e,r)=>{var n=r(4374),i=Function.prototype,o=i.apply,s=i.call;t.exports="object"==typeof Reflect&&Reflect.apply||(n?s.bind(o):function(){return s.apply(o,arguments)})},9974:(t,e,r)=>{var n=r(1470),i=r(9662),o=r(4374),s=n(n.bind);t.exports=function(t,e){return i(t),void 0===e?t:o?s(t,e):function(){return t.apply(e,arguments)}}},4374:(t,e,r)=>{var n=r(7293);t.exports=!n((function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}))},7065:(t,e,r)=>{"use strict";var n=r(1702),i=r(9662),o=r(111),s=r(2597),a=r(206),c=r(4374),u=Function,l=n([].concat),h=n([].join),d={},f=function(t,e,r){if(!s(d,e)){for(var n=[],i=0;i{var n=r(4374),i=Function.prototype.call;t.exports=n?i.bind(i):function(){return i.apply(i,arguments)}},6530:(t,e,r)=>{var n=r(9781),i=r(2597),o=Function.prototype,s=n&&Object.getOwnPropertyDescriptor,a=i(o,"name"),c=a&&"something"===function(){}.name,u=a&&(!n||n&&s(o,"name").configurable);t.exports={EXISTS:a,PROPER:c,CONFIGURABLE:u}},1470:(t,e,r)=>{var n=r(4326),i=r(1702);t.exports=function(t){if("Function"===n(t))return i(t)}},1702:(t,e,r)=>{var n=r(4374),i=Function.prototype,o=i.call,s=n&&i.bind.bind(o,o);t.exports=n?s:function(t){return function(){return o.apply(t,arguments)}}},5005:(t,e,r)=>{var n=r(7854),i=r(614),o=function(t){return i(t)?t:void 0};t.exports=function(t,e){return arguments.length<2?o(n[t]):n[t]&&n[t][e]}},8173:(t,e,r)=>{var n=r(9662),i=r(8554);t.exports=function(t,e){var r=t[e];return i(r)?void 0:n(r)}},7854:(t,e,r)=>{var n=function(t){return t&&t.Math==Math&&t};t.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof r.g&&r.g)||function(){return this}()||Function("return this")()},2597:(t,e,r)=>{var n=r(1702),i=r(7908),o=n({}.hasOwnProperty);t.exports=Object.hasOwn||function(t,e){return o(i(t),e)}},3501:t=>{t.exports={}},490:(t,e,r)=>{var n=r(5005);t.exports=n("document","documentElement")},4664:(t,e,r)=>{var n=r(9781),i=r(7293),o=r(317);t.exports=!n&&!i((function(){return 7!=Object.defineProperty(o("div"),"a",{get:function(){return 7}}).a}))},8361:(t,e,r)=>{var n=r(1702),i=r(7293),o=r(4326),s=Object,a=n("".split);t.exports=i((function(){return!s("z").propertyIsEnumerable(0)}))?function(t){return"String"==o(t)?a(t,""):s(t)}:s},9587:(t,e,r)=>{var n=r(614),i=r(111),o=r(7674);t.exports=function(t,e,r){var s,a;return o&&n(s=e.constructor)&&s!==r&&i(a=s.prototype)&&a!==r.prototype&&o(t,a),t}},2788:(t,e,r)=>{var n=r(1702),i=r(614),o=r(5465),s=n(Function.toString);i(o.inspectSource)||(o.inspectSource=function(t){return s(t)}),t.exports=o.inspectSource},8340:(t,e,r)=>{var n=r(111),i=r(8880);t.exports=function(t,e){n(e)&&"cause"in e&&i(t,"cause",e.cause)}},9909:(t,e,r)=>{var n,i,o,s=r(4811),a=r(7854),c=r(111),u=r(8880),l=r(2597),h=r(5465),d=r(6200),f=r(3501),p="Object already initialized",m=a.TypeError,g=a.WeakMap;if(s||h.state){var v=h.state||(h.state=new g);v.get=v.get,v.has=v.has,v.set=v.set,n=function(t,e){if(v.has(t))throw m(p);return e.facade=t,v.set(t,e),e},i=function(t){return v.get(t)||{}},o=function(t){return v.has(t)}}else{var b=d("state");f[b]=!0,n=function(t,e){if(l(t,b))throw m(p);return e.facade=t,u(t,b,e),e},i=function(t){return l(t,b)?t[b]:{}},o=function(t){return l(t,b)}}t.exports={set:n,get:i,has:o,enforce:function(t){return o(t)?i(t):n(t,{})},getterFor:function(t){return function(e){var r;if(!c(e)||(r=i(e)).type!==t)throw m("Incompatible receiver, "+t+" required");return r}}}},3157:(t,e,r)=>{var n=r(4326);t.exports=Array.isArray||function(t){return"Array"==n(t)}},614:(t,e,r)=>{var n=r(4154),i=n.all;t.exports=n.IS_HTMLDDA?function(t){return"function"==typeof t||t===i}:function(t){return"function"==typeof t}},4411:(t,e,r)=>{var n=r(1702),i=r(7293),o=r(614),s=r(648),a=r(5005),c=r(2788),u=function(){},l=[],h=a("Reflect","construct"),d=/^\s*(?:class|function)\b/,f=n(d.exec),p=!d.exec(u),m=function(t){if(!o(t))return!1;try{return h(u,l,t),!0}catch(t){return!1}},g=function(t){if(!o(t))return!1;switch(s(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return p||!!f(d,c(t))}catch(t){return!0}};g.sham=!0,t.exports=!h||i((function(){var t;return m(m.call)||!m(Object)||!m((function(){t=!0}))||t}))?g:m},4705:(t,e,r)=>{var n=r(7293),i=r(614),o=/#|\.prototype\./,s=function(t,e){var r=c[a(t)];return r==l||r!=u&&(i(e)?n(e):!!e)},a=s.normalize=function(t){return String(t).replace(o,".").toLowerCase()},c=s.data={},u=s.NATIVE="N",l=s.POLYFILL="P";t.exports=s},8554:t=>{t.exports=function(t){return null==t}},111:(t,e,r)=>{var n=r(614),i=r(4154),o=i.all;t.exports=i.IS_HTMLDDA?function(t){return"object"==typeof t?null!==t:n(t)||t===o}:function(t){return"object"==typeof t?null!==t:n(t)}},1913:t=>{t.exports=!1},2190:(t,e,r)=>{var n=r(5005),i=r(614),o=r(7976),s=r(3307),a=Object;t.exports=s?function(t){return"symbol"==typeof t}:function(t){var e=n("Symbol");return i(e)&&o(e.prototype,a(t))}},6244:(t,e,r)=>{var n=r(7466);t.exports=function(t){return n(t.length)}},6339:(t,e,r)=>{var n=r(7293),i=r(614),o=r(2597),s=r(9781),a=r(6530).CONFIGURABLE,c=r(2788),u=r(9909),l=u.enforce,h=u.get,d=Object.defineProperty,f=s&&!n((function(){return 8!==d((function(){}),"length",{value:8}).length})),p=String(String).split("String"),m=t.exports=function(t,e,r){"Symbol("===String(e).slice(0,7)&&(e="["+String(e).replace(/^Symbol\(([^)]*)\)/,"$1")+"]"),r&&r.getter&&(e="get "+e),r&&r.setter&&(e="set "+e),(!o(t,"name")||a&&t.name!==e)&&(s?d(t,"name",{value:e,configurable:!0}):t.name=e),f&&r&&o(r,"arity")&&t.length!==r.arity&&d(t,"length",{value:r.arity});try{r&&o(r,"constructor")&&r.constructor?s&&d(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var n=l(t);return o(n,"source")||(n.source=p.join("string"==typeof e?e:"")),t};Function.prototype.toString=m((function(){return i(this)&&h(this).source||c(this)}),"toString")},4758:t=>{var e=Math.ceil,r=Math.floor;t.exports=Math.trunc||function(t){var n=+t;return(n>0?r:e)(n)}},6277:(t,e,r)=>{var n=r(1340);t.exports=function(t,e){return void 0===t?arguments.length<2?"":e:n(t)}},30:(t,e,r)=>{var n,i=r(9670),o=r(6048),s=r(748),a=r(3501),c=r(490),u=r(317),l=r(6200),h=l("IE_PROTO"),d=function(){},f=function(t){return" - - - - - - - - - -
- -
-
- - -
-
-
- -

Quels sont les outils que nous utilisons ?

-
-
-
    -
  • Matomo (anciennement Piwik). Il est recommandé par la CNIL, permet de ne pas envoyer vos données à des tiers, il est hébergé chez nous et nous permet la collecte et l'analyse de quelques données du trafic que nous recevons. Celles-ci nous permettent par la suite d'avoir une idée des interactions avec le contenu proposé et de travailler à son amélioration.
  • -
  • Et ... c'est tout.
  • -
-

Quelles sont les données que nous collectons ?

-

Avec Matomo

-

Matomo dépose un cookie à l'aide de votre navigateur sur le disque de votre machine, et vous attribue plusieurs identifiants aléatoires et anonymes.

-

La première fois que vous nous rendez visite

-
    -
  • Les deux premiers chiffres de votre adresse IP, qui nous permettent de déterminer votre réseau de provenance et par la même votre origine géographique
  • -
  • La date et l'heure de votre visite et sa durée
  • -
  • Les pages que vous avez consultées
  • -
  • L'appareil utilisé, son système d'exploitation (version, modèle) ainsi que le type de navigateur (nom, langue, version) que vous utilisez
  • -
  • Éventuellement le site qui vous a amené jusqu'à nous
  • -
-

À chaque fois que vous consultez une page

-
    -
  • L'URL de la page (titre, temps de chargement)
  • -
  • L'enchaînement des pages au cours de votre lecture
  • -
-

Correspondance électronique

-

L'ensemble des documents transmis par nos correspondants sont conservés sur un stockage privé, hébergé par en France.

-

Il est possible de chiffrer les correspondances envoyées à contact@rix.fr à l'aide de notre clé publique.

-

Où mes données sont-elles stockées ?

-

Elles sont stockées sur nos serveurs, en France, qu'il sagisse de données collectées lors de votre passage sur nos sites, ou de données collectées lors de l'une de nos correspondances.

-

Qui a accès à ces données ?

-

Ces données ne sont accessibles que par les employé·e·s Rix.

-

Candidatures

-

Lorsque vous nous envoyez votre candidature, vos coordonnées et les documents que vous nous avez transmis sont conservés le temps du traitement.

-

Données de navigation

-

Les données collectées par Matomo sont conservées 24 mois, à l'issue desquels elles sont supprimées.

-

Qui contacter en cas de questions ou de requête de suppression ?

-

Vous disposez bien évidemment du droit de demander la modification et la suppression de l'ensemble des données dont nous pourrions disposer en nous contactant : contact@rix.fr

-
-
-
-
- - - - - - diff --git a/pr/119/contact/index.html b/pr/119/contact/index.html deleted file mode 100644 index a9e28f4a..00000000 --- a/pr/119/contact/index.html +++ /dev/null @@ -1,345 +0,0 @@ - - - - - - - Rix 🐺 - Nous contacter - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
-
-

- Besoin d'informations ? - Contactez-nous - Promis, on ne mord pas -

- -
-
-
-
Téléphone
- Une question à nous poser ? -
- - - - - - - - - - - 04 82 53 76 09 - -
-
-
- -
-
-
Mail
- Un challenge à nous proposer ? -
- - - - - - - - contact@rix.fr - -
-
-
- -
-
- Passez nous voir - - - - - - - Expliquez-nous votre problématique autour d'un ☕ ! - - 34 rue Jean Broquin - 69006 Lyon, France -
-
-
-
- -
- - - - - - diff --git a/pr/119/etudes-de-cas/index.html b/pr/119/etudes-de-cas/index.html deleted file mode 100644 index 962c348b..00000000 --- a/pr/119/etudes-de-cas/index.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - - - Réalisations web : revue de nos projets depuis 17 ans | Rix - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - - -
-
- - - - - - diff --git a/pr/119/etudes-de-cas/musique-music/index.html b/pr/119/etudes-de-cas/musique-music/index.html deleted file mode 100644 index 897ac251..00000000 --- a/pr/119/etudes-de-cas/musique-music/index.html +++ /dev/null @@ -1,406 +0,0 @@ - - - - - - - Stockage résilient à haute disponibilité. | Rix 🐺 - Expertise & solutions devops sur-mesure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
-
-
-
-
-

Stockage résilient à haute disponibilité.

-

Musique & Music permet aux professionnels de la vidéo d'enrichir leurs productions avec de l'illustration sonore.

- Services -
    -
  • Conception
  • -
  • Infrastructure
  • -
  • Stockage haute dispo.
  • -
  • Stratégie de déploiement
  • -
-
-
-
- -
-
-
-
-
- Les technos utilisées -
- -
-

Le contexte du projet

-

Musique & Music est un éditeur spécialisé dans la musique de production dédiée aux professionnels. L'application web permet aux monteurs vidéos de chercher facilement des sons afin d'illustrer leurs productions. Parmi les atouts de l'application, il y a notamment la richesse du catalogue, la fluidité de la recherche et la pertinence des résultats proposés. Une recherche par similarité permet aux clients de Musique & Music de rechercher finement un style de musique en important des fichiers audio.

-

Musique & Music a confié à Rix la conception de son infrastructure et son infogérance, permettant de s'appuyer sur une équipe rodée à l'exploitation.

-

L'expertise Rix déployée pour l'application Musique Music

-

Analyse de l'existant

-

Musique & Music n'en était pas à sa première version, l'application existait déjà depuis plusieurs années mais la dette technique, l'obsolescence du code existant et la contrainte d'exploiter des briques logicielles propriétaires ne donnant plus satisfaction, ont décidé les fondateurs à repartir d'une feuille blanche. -Nous avons dès lors été solicités pour étudier et concevoir une infrastructure destinée à acceuillir la nouvelle application. -En collaboration avec les équipes de concepteurs d'Elao nous avons commencé à imaginer ce que pourrait être cette nouvelle infrastructure en fonction des contraintes métiers du projet (disponibilité, performance et résilience).

-

La première étape étant de récupérer, sécuriser et rendre hautement disponible les données musicales.

-

Le stockage

-

C'est la pierre angulaire du métier de Musique & Music, si l'application peut s'autoriser d'exceptionnelles interruptions de service la donnée doit elle, rester disponible. -Avec la volonté de rester souverain sur l'ensemble de son infrastructure, nous avons opté pour une solution reposant sur CEPH avec le Cloud Disk Array de chez OVH.

-

Les points important qui ont permis de retenir cette solution:

-
    -
  • La distribution du stockage
  • -
  • La triple réplication des données
  • -
  • La disponibilité
  • -
  • Le redimensionnement à chaud
  • -
-

La sureté des données

-

Au dela de l'aspect disponibilité des données, nous devions également veiller à disposer des pistes musicales hors infrastructure, en cas d'incident grave sur la brique de stockage entrainant son indisponibilité. -Nous avons opté pour une solution de synchronisation incrémentale des données sur un NAS Synology à travers un flux chiffré sur une instance dédiée à cette tâche.

-

La brique applicative

-

Elle repose sur une « stack » web assez standard basée sur du public cloud et mettant en oeuvre sur réseau privé:

-
    -
  • Un répartiteur de charge de type HAProxy
  • -
  • Un serveur Nginx
  • -
  • Un serveur de base de données de type MariaDB
  • -
-

Le tout fonctionnant sur un environnement applicatif PHP/Symfony.

-
- Étude de cas - Schema d'infrastructure -
- Musique & Music - Schema d'infrastructure -
-
-

Conception de l'infrastructure

-

Comme pour l'ensemble de nos infras, nous appuyons fortement sur l'automatisation, à la fois des déploiements applicatifs via CI/CD mais également de l'infrastructure avec différents outils:

-
    -
  • Terraform pour l'IaC (Infrastructure as Code) afin de déployer nos différentes briques;
  • -
  • Ansible pour la construction des environnements d'exécution applicatif;
  • -
  • Helm pour le déploiement des infrastructures de type Kubernetes.
  • -
-

Environnement d'exploitation

-

L'environnement d'exploitation réponds aux standards Rix à savoir:

-
    -
  • Un alerting de l'ensemble des services via messagerie, mail et SMS;
  • -
  • Une remontée des métriques dans différents dashboard Grafana (Système et applicatif) hébergé et infogéré sur nos infrastructures 🇫🇷;
  • -
  • Une exploitation des logs applicatifs et système via le composant Loki (Grafana) hébergé et infogéré sur nos infrastructures 🇫🇷;
  • -
  • Remontée des erreurs aux équipes applicatives via une plateforme Sentry (SaaS);
  • -
  • Les secrets applicatifs sont stockés dans un coffre de type Hashicorp Vault hébergé et infogéré sur nos infrastructures 🇫🇷.
  • -
-
-
- -
-
- - - - - - diff --git a/pr/119/etudes-de-cas/panneau-pocket/index.html b/pr/119/etudes-de-cas/panneau-pocket/index.html deleted file mode 100644 index 67e62044..00000000 --- a/pr/119/etudes-de-cas/panneau-pocket/index.html +++ /dev/null @@ -1,404 +0,0 @@ - - - - - - - Tenue de charge, disponibilité, scalabilité. | Rix 🐺 - Expertise & solutions devops sur-mesure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- -
-
-
-
-
-

Tenue de charge, disponibilité, scalabilité.

-

Panneau Pocket, acteur majeur auprès des collectivités pour l'information de leurs usagés.

- Services -
    -
  • Conception
  • -
  • Accompagnement
  • -
  • Pilotage
  • -
-
-
-
- -
-
-
-
-
- Les technos utilisées -
- -
-

Le contexte du projet

-

Panneau Pocket a pour objectif de permettre aux collectivités de mieux communiquer avec leurs administrés et propose à ce titre une application mobile capable d'alerter en temps réel ses utilisateurs d'une nouvelle publication.

-

Les objectifs

-
    -
  • Être capables de tenir une solicitation des infrastructures soutenue;
  • -
  • Répondre à des pics de trafic importants lors de communications d'envergure;
  • -
  • Avoir l'obligation de disponibilité;
  • -
  • Assurer la sécurité, la sureté et la confidentialités des données.
  • -
-

Architecture

-

Panneau pocket répose essentiellement sur de l'API qui permet d'exposer de manière structurée et sécurisée ses données à l'application mobile. -Nous intervenons en collaboration avec les équipes de développement applicatif afin de trouver les meilleures solutions pour répondre au besoin exposé par les équipes de PanneauPocket.

-

Métier et contraintes

-

Le travail de Rix est de faire en sorte que 3 points essentiels soient au rendez-vous:

-
    -
  • les temps de réponses doivent être bons (Ne pas oublier que nos utilisateurs sont souvent sur de l'itinérance et loin des infrastructures des grandes métropoles);
  • -
  • l'application doit mettre en oeuvre une tolérance à la panne resposant sur de la redondance et assurer, même en cas d'incident, une qualité de service minimum;
  • -
  • les incidents dans la mesure du possible, doivent être anticipés.
  • -
-

À cela vient s'ajouter les contraintes de sureté des données personnelles et bien évidemment les données des utilisateurs ne doivent pas quitter l'union européenne.

-

Auquel nous ajoutons bien évidemment nos propres contraintes de qualité/supervision:

-
    -
  • l'ensemble de l'infrastructure doit être décrite sour forme d'IAC (Infrastructure As Code);
  • -
  • les environnements applicatifs doivent être « versionnés » et doivent pouvoir être redéployés de manière automatique et idempotente;
  • -
  • l'ensemble des secrets applicatifs sont stockés dans un espace chiffré, sécurisé;
  • -
  • les sauvegardes bénéficient d'une triple réplique sur deux fournisseurs différents et sont chiffrées;
  • -
  • les accès sont controlés et audités.
  • -
-

Mise en oeuvre

-

Afin de remplir ce contrat et répondre aux contraintes métier nous nous sommes appuyés sur du matériel OVH et Scaleway en proposant une infrastructure redondée classique orchestrée sur un réseau privé intégrant:

-
    -
  • Un répartiteur de charge en frontal (redondé);
  • -
  • Plusieurs instances applicatives;
  • -
  • Un répartiteur de charge SQL Maxscale (redondé);
  • -
  • Plusieurs instances de base de données.
  • -
-

À cela vient s'ajouter les briques logiques standard (WAF, SG...) que nous ne détaillerons pas ici ainsi que les espaces de stockage reposants sur différentes stratégies mixant NFS, stockage de type bloc et stockage objet (S3).

-

Environnement d'exploitation

-

L'environnement d'exploitation réponds aux standards Rix à savoir:

-
    -
  • Une remontée des métriques dans différents dashboard Grafana (Système et applicatif);
  • -
  • Un alerting de l'ensemble des services via messagerie, mail et SMS;
  • -
  • Une exploitation des logs applicatifs et système via le composant Loki (Grafana);
  • -
  • Remontée des erreurs aux équipes applicatives via une plateforme Sentry;
  • -
  • Les secrets applicatifs sont stockés dans un coffre de type Hashicorp Vault déployé sur nos infrastructures.
  • -
-
-
- -
-
- - - - - - diff --git a/pr/119/favicon-16x16.png b/pr/119/favicon-16x16.png deleted file mode 100644 index 2243c906..00000000 Binary files a/pr/119/favicon-16x16.png and /dev/null differ diff --git a/pr/119/favicon-32x32.png b/pr/119/favicon-32x32.png deleted file mode 100644 index 92da1ced..00000000 Binary files a/pr/119/favicon-32x32.png and /dev/null differ diff --git a/pr/119/favicon-96x96.png b/pr/119/favicon-96x96.png deleted file mode 100644 index 09b5d0a3..00000000 Binary files a/pr/119/favicon-96x96.png and /dev/null differ diff --git a/pr/119/favicon.ico b/pr/119/favicon.ico deleted file mode 100644 index 2243c906..00000000 Binary files a/pr/119/favicon.ico and /dev/null differ diff --git a/pr/119/google98e08ccbf4b44d9b.html b/pr/119/google98e08ccbf4b44d9b.html deleted file mode 100644 index e195c9cc..00000000 --- a/pr/119/google98e08ccbf4b44d9b.html +++ /dev/null @@ -1 +0,0 @@ -google-site-verification: google98e08ccbf4b44d9b.html \ No newline at end of file diff --git a/pr/119/images/logo-signature.png b/pr/119/images/logo-signature.png deleted file mode 100644 index 992665ed..00000000 Binary files a/pr/119/images/logo-signature.png and /dev/null differ diff --git a/pr/119/index.html b/pr/119/index.html deleted file mode 100644 index 5cbd5f55..00000000 --- a/pr/119/index.html +++ /dev/null @@ -1,525 +0,0 @@ - - - - - - - Rix 🐺 - Expertise Kubernetes & SRE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - -
-
-
- -

- Nos valeurs - Nos engagements -

-
-
-
    -
  • -
    - -

    Indépendance et gouvernance

    -
    -

    Après plusieurs années à utiliser de grand fournisseurs de solution « cloud », nous avons pris le parti d'essayer au maximum, de travailler avec des acteurs nationaux afin de trouver des solutions matérielles permettant de construire des infrastructures robustes et évolutives.

    -

    Parce que nous croyons fermement en la nécessité d'indépendance des entreprises Françaises et Européennes vis à vis des grands acteurs étrangers.

    -
  • -
  • -
    - -

    Proximité et réactivité

    -
    -

    Nous aimons rencontrer les personnes avec lesquelles nous travaillons, notre objectif est de bien comprendre les enjeux du métier afin d'apporter un maximum de valeur à travers nos solutions.

    -

    Chaque projet étant différent nous avons besoin de comprendre vos contraintes et vos objectifs afin de faire correspondre nos infrastructures à vos besoins réels.

    -
  • -
  • -
    - -

    Sécurité

    -
    -

    Très sensibles aux problématiques de sécurité, nous sommes partie prenante de la mise en conformité de vos infrastructures.

    -

    Nous vous accompagnons pour la mise en place de vos PRA et leur mise en application. Si vous souhaitez aller plus loin, notre réseau de professionnels reconnus vous permettra de mettre en œuvre Pentest, Audit et/ou Bug Bounty.

    -
  • -
- -
-

Notre culture,
l'Open source

-
-

Adeptes depuis bien des années de la culture OpenSource, nous nous reposons sur des outils libres et contribuons lorsque nous le pouvons, notamment à travers notre projet Manala

- Aller sur notre Github -
-
- -
-

- Nos services - Apporter un maximum de valeur aux équipes techniques. -

-

Nous accompagnons vos équipes dans la mise en place de la culture et des outils orientés Ops en nous appuyant sur notre expérience de plus de 15 ans d'exploitation d'applications web.

- - - -
-
-
-
-
-
-

- Notre territoire - Un écosystème éprouvé -

-
- -
    -
  • - -

    Analyse

    -

    Collecte des données et analyse des comportements applicatifs et système pour le pilotage et la compréhension des incidents.

    -
  • -
  • - -

    Détection

    -

    Système de supervision permettant d'anticiper au maximum de potentiels incidents.

    -
  • -
  • - -

    Automation

    -

    Construction des environnements applicatifs à l'aide d'outils d'IAC et de stratégies « d'automation »

    -
  • -
  • - -

    Supervision

    -

    Supervision des systèmes et des applications en temps réel.

    -
  • -
  • - -

    Sauvegarde

    -

    Mise en sûreté de vos données, avec réplication et chiffrement.

    -
  • -
-
-
-
-
-

- Nos clients - Ils nous font confiance -

-
    -
  • -
    -

    M6

    -

    Fondé par le groupe M6 et co entreprit avec le groupe RTL, Bedrock conçoit et exploite des plateformes de streaming à la pointe de l'état de l'art à destination de différents groupe de médias et diffuseurs à travers l'Europe.

    -
  • -
  • -
    -

    Centre de Recherche en Nutrition Humaine Rhône-Alpes

    -

    Le Centre de Recherche en Nutrition Humaine Rhône-Alpes travaille à l’amélioration de l’alimentation pour la santé et le bien-être de l’Homme. Il développe des programmes de recherche en nutrition dans le cadre des appels d’offres nationaux, européens et internationaux et collabore avec les industriels et les chercheurs de grands groupes mondiaux.

    -
  • -
  • -
    -

    Elao

    -

    Elao est un atelier de co-conception d'applications web et mobile sur mesure mais avant tout une équipe de concepteurs / développeurs seniors. Spécialistes des applications métiers à forte valeur stratégique Elao aime être au contact des utilisateurs finaux afin d'être au cœur du métier de ses clients.

    -
  • -
  • -
    -

    GRIEPS

    -

    Le GRIEPS, organisme de formation-conseil, est une SCOP qui accompagne les établissements sanitaires et médicosociaux ainsi que les professionnels de santé salariés et libéraux à répondre aux besoins de santé de la population et à s'adapter aux mutations de l'environnement sur les plans cliniques, organisationnels et managériaux.

    -
  • -
  • -
    -

    Maison de la danse

    -

    Numeridanse est la plateforme multimédia de la danse. Elle donne accès à un fonds vidéo unique : spectacles filmés, documentaires, interviews, fictions, vidéo danse. Tous les genres, styles et formes sont représentés : butô, danse classique, néoclassique, baroque, danses indiennes, africaines, flamenco, contemporain, danses traditionnelles, hip hop, tango, jazz, arts du cirque, performance... Porté et coordonné par la Maison de la Danse de Lyon, Numeridanse a été imaginé par le réalisateur Charles Picq.

    -
  • -
  • -
    -

    Musique & Music

    -

    Première librairie musicale indépendante française. Musique & Music accompagne depuis 30 ans les professionnels dans l'illustration sonore de leurs projets audiovisuels. En associant des services et des outils innovant à une librairie musicale riche de près de 720 000 titres, Musique & Music permets à ses clients de gagner un temps précieux dans leurs recherches musicales.

    -
  • -
  • -
    -

    Panneau pocket

    -

    Panneau pocket est l’application mobile d’informations et d’alertes n°1 en France avec plus de 9000 collectivités équipées. Mairies, Gendarmeries, Intercommunalités, Ecoles, RPI des enfants, Syndicats des eaux … les citoyens retrouvent leur vie locale dans une seule et unique application sur leur smartphone. La population reçoit en temps réel les notifications des actualités de leur territoire : c’est l’information qui va vers l’habitant !

    -
  • -
  • -
    -

    Wotol

    -

    Wotol est une des plus anciennes place de marché B2B entièrement dédiée à l'industrie et à l'achat de revente de machines outils.

    -
  • -
- -
-
- - - - - - diff --git a/pr/119/legal/index.html b/pr/119/legal/index.html deleted file mode 100644 index b92d267a..00000000 --- a/pr/119/legal/index.html +++ /dev/null @@ -1,328 +0,0 @@ - - - - - - - Rix 🐺 - Expertise & solutions devops sur-mesure - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - -
-
-
- -

Conditions générales d'utilisation

-
-
-
- -

L'accès et l'utilisation de ce support sont régis par les présentes conditions d’utilisation. Par votre accès, votre navigation et votre utilisation de notre site, vous reconnaissez que vous avez lu, compris et accepté sans réserve ces présentes conditions. Nous nous réservons le droit de les modifier.

- -

Liens

-

Bien que nous vérifiions le contenu des liens hypertextes pointant sur des pages extérieures au moment de leur création, le contenu des sites visés peut changer postérieurement à cette vérification. Nous invitons donc les visiteurs à la plus grande prudence.

-

De même, nous vous prions de bien vouloir nous signaler tout lien hypertexte brisé ou erroné.

- -

Contenus

-

Bien que nous nous efforçions d'être le plus rigoureux possible, nous ne pouvons garantir l'exactitude et l'exhaustivité des données publiées sur ce support.

-

Le site est maintenu et mis à jour, nous ne pouvons néanmoins pas garantir l'actualisation des informations et méthodes qu'il contient.

-

Nous nous réservons le droits de corriger à tous moment ces données si d'aventure nous constations qu'elles sont érronées ou inexactes. En conséquence, l'utilisateur est seul responsable de leur utilisation.

- -

Responsabilité

-

Nous ne pourrions être tenu pour responsable des dommages directs ou indirects qui pourraient résulter de l'accès ou de l'utilisation des ressources proposées par ce site.

-

Concernant les articles du blog notamment, ils sont rédigés à des fins pédagogiques et éducatives et doivent être mis en application en ayant bien compris leur finalité.

-

Nous nous réservons le droit de modifier ou d'interrompre, temporairement ou de façon permanente, tout ou partie de l'accès au site afin d'effectuer les opérations de maintenance nécessaires à son bon fonctionnement.

- -

Protection des données personnelles

-

La confidentialité et la sécurité de vos données est une priorité absolue pour nous.

-

Les adresses électroniques recueillies dans le cadre du formulaire de contact ne sont utilisées que pour l'envoi d'informations ayant motivé l'inscription.

-

Pour plus d’informations sur nos pratiques de confidentialité et les mesures prises pour protéger votre vie privée, consultez en détails notre page protection des données.

- -

Droits d'auteur

-

Reproduction sur support papier

-

À l'exception de l'iconographie, la reproduction des pages de ce site sur un support papier est autorisée, sous réserve du respect des trois conditions suivantes :

-
    -
  • Gratuité de la diffusion
  • -
  • Respect de l'intégrité des documents reproduits (aucune modification, ni altération d'aucune sorte)
  • -
  • Citation explicite du site (https://rix-fr.github.io/rix/pr/119/) comme source et mention que les droits de reproduction sont réservés et strictement limités
  • -
-

Reproduction sur support électronique

-

La reproduction de tout ou partie de ce site sur un support électronique est autorisée sous réserve de l'ajout de façon claire et lisible de la source (https://rix-fr.github.io/rix/pr/119/) et de la mention "Droits réservés". Les informations utilisées ne doivent l'être à des fins personnelles, associatives ou professionnelles ; toute utilisation à des fins commerciales ou publicitaires est exclue.

-
-
-
-
- - - - - - diff --git a/pr/119/mstile-152x152.png b/pr/119/mstile-152x152.png deleted file mode 100644 index 498a4898..00000000 Binary files a/pr/119/mstile-152x152.png and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-connexion-icloud.jpg/0f7f8f434b8b8c19862771a6a260297b.jpg b/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-connexion-icloud.jpg/0f7f8f434b8b8c19862771a6a260297b.jpg deleted file mode 100644 index ecb9ddc7..00000000 Binary files a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-connexion-icloud.jpg/0f7f8f434b8b8c19862771a6a260297b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-connexion-icloud.jpg/e5d189ab24fcbd3857dbf579a7cdc917.jpg b/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-connexion-icloud.jpg/e5d189ab24fcbd3857dbf579a7cdc917.jpg deleted file mode 100644 index 1d42697a..00000000 Binary files a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-connexion-icloud.jpg/e5d189ab24fcbd3857dbf579a7cdc917.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-new-calendar.jpg/93cbb4c889c42310fd05bf1db5499e38.jpg b/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-new-calendar.jpg/93cbb4c889c42310fd05bf1db5499e38.jpg deleted file mode 100644 index fd12a6d9..00000000 Binary files a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-new-calendar.jpg/93cbb4c889c42310fd05bf1db5499e38.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-new-calendar.jpg/cea2561c4f29f52ce74d81d1292d2ddd.jpg b/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-new-calendar.jpg/cea2561c4f29f52ce74d81d1292d2ddd.jpg deleted file mode 100644 index 0614a550..00000000 Binary files a/pr/119/resized/content/images/blog/2022/icloud-sync-with-gnome-calendar/evolution-new-calendar.jpg/cea2561c4f29f52ce74d81d1292d2ddd.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/osx-to-linux/mailspring-screenshot-01.jpg/43afa9f7916f18f63bf34bc3e03aa0e5.jpg b/pr/119/resized/content/images/blog/2022/osx-to-linux/mailspring-screenshot-01.jpg/43afa9f7916f18f63bf34bc3e03aa0e5.jpg deleted file mode 100644 index 7dae32d1..00000000 Binary files a/pr/119/resized/content/images/blog/2022/osx-to-linux/mailspring-screenshot-01.jpg/43afa9f7916f18f63bf34bc3e03aa0e5.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/osx-to-linux/mailspring-screenshot-01.jpg/9b445763b027f4a80d28d4f7af9b4555.jpg b/pr/119/resized/content/images/blog/2022/osx-to-linux/mailspring-screenshot-01.jpg/9b445763b027f4a80d28d4f7af9b4555.jpg deleted file mode 100644 index b7709581..00000000 Binary files a/pr/119/resized/content/images/blog/2022/osx-to-linux/mailspring-screenshot-01.jpg/9b445763b027f4a80d28d4f7af9b4555.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/osx-to-linux/visionneuse-pdf.jpg/4f20a6fea1b9fa1bbf2335ee8ddbbf8e.jpg b/pr/119/resized/content/images/blog/2022/osx-to-linux/visionneuse-pdf.jpg/4f20a6fea1b9fa1bbf2335ee8ddbbf8e.jpg deleted file mode 100644 index b606fa55..00000000 Binary files a/pr/119/resized/content/images/blog/2022/osx-to-linux/visionneuse-pdf.jpg/4f20a6fea1b9fa1bbf2335ee8ddbbf8e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2022/osx-to-linux/visionneuse-pdf.jpg/8f62ab41cbb5677cff762e39b0aac290.jpg b/pr/119/resized/content/images/blog/2022/osx-to-linux/visionneuse-pdf.jpg/8f62ab41cbb5677cff762e39b0aac290.jpg deleted file mode 100644 index 628035a6..00000000 Binary files a/pr/119/resized/content/images/blog/2022/osx-to-linux/visionneuse-pdf.jpg/8f62ab41cbb5677cff762e39b0aac290.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/add-user-to-docker-group.jpg/9c284bf54b95c30385f2bb78ea00815b.jpg b/pr/119/resized/content/images/blog/2023/cours-docker-wsl/add-user-to-docker-group.jpg/9c284bf54b95c30385f2bb78ea00815b.jpg deleted file mode 100644 index b19bcd1d..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/add-user-to-docker-group.jpg/9c284bf54b95c30385f2bb78ea00815b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/add-user-to-docker-group.jpg/e2748db59362efca3ba6f018df84383b.jpg b/pr/119/resized/content/images/blog/2023/cours-docker-wsl/add-user-to-docker-group.jpg/e2748db59362efca3ba6f018df84383b.jpg deleted file mode 100644 index a1126546..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/add-user-to-docker-group.jpg/e2748db59362efca3ba6f018df84383b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/docker-desktop-settings.jpg/715304e02b5695843f019c99941dd8d3.jpg b/pr/119/resized/content/images/blog/2023/cours-docker-wsl/docker-desktop-settings.jpg/715304e02b5695843f019c99941dd8d3.jpg deleted file mode 100644 index d07f6786..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/docker-desktop-settings.jpg/715304e02b5695843f019c99941dd8d3.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/docker-desktop-settings.jpg/c3b93f12d11ccf947af7185c695bacec.jpg b/pr/119/resized/content/images/blog/2023/cours-docker-wsl/docker-desktop-settings.jpg/c3b93f12d11ccf947af7185c695bacec.jpg deleted file mode 100644 index 2eb2885c..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/docker-desktop-settings.jpg/c3b93f12d11ccf947af7185c695bacec.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/wsl_debian_shell.jpg/6fbef3ca7b35e4a4ba2503ac4d9f074b.jpg b/pr/119/resized/content/images/blog/2023/cours-docker-wsl/wsl_debian_shell.jpg/6fbef3ca7b35e4a4ba2503ac4d9f074b.jpg deleted file mode 100644 index fe1c0a4f..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/wsl_debian_shell.jpg/6fbef3ca7b35e4a4ba2503ac4d9f074b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/wsl_debian_shell.jpg/f988070bcb4009128e0af18075906181.jpg b/pr/119/resized/content/images/blog/2023/cours-docker-wsl/wsl_debian_shell.jpg/f988070bcb4009128e0af18075906181.jpg deleted file mode 100644 index 81530f59..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours-docker-wsl/wsl_debian_shell.jpg/f988070bcb4009128e0af18075906181.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours/ssh-keygen.gif/4c624a8987673a6deb25cf1395b926ce.gif b/pr/119/resized/content/images/blog/2023/cours/ssh-keygen.gif/4c624a8987673a6deb25cf1395b926ce.gif deleted file mode 100644 index 08d51c36..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours/ssh-keygen.gif/4c624a8987673a6deb25cf1395b926ce.gif and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/cours/ssh.gif/02e06122a9eba89d4faed7b89ae519d6.gif b/pr/119/resized/content/images/blog/2023/cours/ssh.gif/02e06122a9eba89d4faed7b89ae519d6.gif deleted file mode 100644 index 087af9d3..00000000 Binary files a/pr/119/resized/content/images/blog/2023/cours/ssh.gif/02e06122a9eba89d4faed7b89ae519d6.gif and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/alerts.jpg/8bcbbffcadbef7f75fde9d5075fff6c7.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/alerts.jpg/8bcbbffcadbef7f75fde9d5075fff6c7.jpg deleted file mode 100644 index 60d25ae7..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/alerts.jpg/8bcbbffcadbef7f75fde9d5075fff6c7.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/alerts.jpg/d8e4282a1f0b7b26dd76e70ffc584939.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/alerts.jpg/d8e4282a1f0b7b26dd76e70ffc584939.jpg deleted file mode 100644 index c4ba520a..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/alerts.jpg/d8e4282a1f0b7b26dd76e70ffc584939.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/global_charge.jpg/436e0eacf0a0486949f8f44a7b32572f.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/global_charge.jpg/436e0eacf0a0486949f8f44a7b32572f.jpg deleted file mode 100644 index ccc8504f..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/global_charge.jpg/436e0eacf0a0486949f8f44a7b32572f.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/global_charge.jpg/a53cd6721cba36d54e19dc82b424f187.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/global_charge.jpg/a53cd6721cba36d54e19dc82b424f187.jpg deleted file mode 100644 index 2037d9d4..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/global_charge.jpg/a53cd6721cba36d54e19dc82b424f187.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/graphs_php_down.jpg/87da498e177900e1315617b6158da966.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/graphs_php_down.jpg/87da498e177900e1315617b6158da966.jpg deleted file mode 100644 index 15e94e62..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/graphs_php_down.jpg/87da498e177900e1315617b6158da966.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/graphs_php_down.jpg/9adc412824436ea11dc0efeb47ffa049.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/graphs_php_down.jpg/9adc412824436ea11dc0efeb47ffa049.jpg deleted file mode 100644 index d5d50d81..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/graphs_php_down.jpg/9adc412824436ea11dc0efeb47ffa049.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/netstat.jpg/0047ca9060a60a16a5c470387107e90f.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/netstat.jpg/0047ca9060a60a16a5c470387107e90f.jpg deleted file mode 100644 index 34ec775e..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/netstat.jpg/0047ca9060a60a16a5c470387107e90f.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/netstat.jpg/2be0fdc956da99803fe72b8d43ba31ef.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/netstat.jpg/2be0fdc956da99803fe72b8d43ba31ef.jpg deleted file mode 100644 index 20af8ab1..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/netstat.jpg/2be0fdc956da99803fe72b8d43ba31ef.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/network_db.jpg/412cb9cf6da17be08defe32ae888d3f5.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/network_db.jpg/412cb9cf6da17be08defe32ae888d3f5.jpg deleted file mode 100644 index 387d7c42..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/network_db.jpg/412cb9cf6da17be08defe32ae888d3f5.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/network_db.jpg/c9853f03496f05e254f1e692784ff9c5.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/network_db.jpg/c9853f03496f05e254f1e692784ff9c5.jpg deleted file mode 100644 index bd2ffc62..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/network_db.jpg/c9853f03496f05e254f1e692784ff9c5.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/network_db_2.jpg/3155bb88a4cac88509c3b717e9475e8d.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/network_db_2.jpg/3155bb88a4cac88509c3b717e9475e8d.jpg deleted file mode 100644 index 73024abb..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/network_db_2.jpg/3155bb88a4cac88509c3b717e9475e8d.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/network_db_2.jpg/bd89ffdb7e4f9955ac21af37b9e23b3e.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/network_db_2.jpg/bd89ffdb7e4f9955ac21af37b9e23b3e.jpg deleted file mode 100644 index 3e8fd7f6..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/network_db_2.jpg/bd89ffdb7e4f9955ac21af37b9e23b3e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/network_web.jpg/8cce76c7e7bf1df3c864a3a66bd2271e.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/network_web.jpg/8cce76c7e7bf1df3c864a3a66bd2271e.jpg deleted file mode 100644 index 8213c1da..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/network_web.jpg/8cce76c7e7bf1df3c864a3a66bd2271e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/2023/post-mortem/network_web.jpg/bdb0e53c8e7700cd7fb63eb069c1b9d8.jpg b/pr/119/resized/content/images/blog/2023/post-mortem/network_web.jpg/bdb0e53c8e7700cd7fb63eb069c1b9d8.jpg deleted file mode 100644 index eccff16e..00000000 Binary files a/pr/119/resized/content/images/blog/2023/post-mortem/network_web.jpg/bdb0e53c8e7700cd7fb63eb069c1b9d8.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/styleguide/exemple-gif.gif/26720a805a265753b6f13e5a03fba4b5.gif b/pr/119/resized/content/images/blog/styleguide/exemple-gif.gif/26720a805a265753b6f13e5a03fba4b5.gif deleted file mode 100644 index 95fba5c6..00000000 Binary files a/pr/119/resized/content/images/blog/styleguide/exemple-gif.gif/26720a805a265753b6f13e5a03fba4b5.gif and /dev/null differ diff --git a/pr/119/resized/content/images/blog/styleguide/exemple-image-relative.jpg/470cd3cf457415c4960a560c201fc694.jpg b/pr/119/resized/content/images/blog/styleguide/exemple-image-relative.jpg/470cd3cf457415c4960a560c201fc694.jpg deleted file mode 100644 index 82c8f105..00000000 Binary files a/pr/119/resized/content/images/blog/styleguide/exemple-image-relative.jpg/470cd3cf457415c4960a560c201fc694.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/styleguide/exemple-image-relative.jpg/7b2c4debf6c584f73e5afaaa462ddb16.jpg b/pr/119/resized/content/images/blog/styleguide/exemple-image-relative.jpg/7b2c4debf6c584f73e5afaaa462ddb16.jpg deleted file mode 100644 index 34e6b367..00000000 Binary files a/pr/119/resized/content/images/blog/styleguide/exemple-image-relative.jpg/7b2c4debf6c584f73e5afaaa462ddb16.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/styleguide/exemple-image.jpg/460bc80c1807a1298f6305e117c1f5b0.jpg b/pr/119/resized/content/images/blog/styleguide/exemple-image.jpg/460bc80c1807a1298f6305e117c1f5b0.jpg deleted file mode 100644 index 429ac5d4..00000000 Binary files a/pr/119/resized/content/images/blog/styleguide/exemple-image.jpg/460bc80c1807a1298f6305e117c1f5b0.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/styleguide/exemple-image.jpg/6bda512686956a3df0bc5aef03d8e1c0.jpg b/pr/119/resized/content/images/blog/styleguide/exemple-image.jpg/6bda512686956a3df0bc5aef03d8e1c0.jpg deleted file mode 100644 index f3b36740..00000000 Binary files a/pr/119/resized/content/images/blog/styleguide/exemple-image.jpg/6bda512686956a3df0bc5aef03d8e1c0.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/1759af6b89e8a6cf93e2919540947b13.jpg b/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/1759af6b89e8a6cf93e2919540947b13.jpg deleted file mode 100644 index 702664fa..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/1759af6b89e8a6cf93e2919540947b13.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/4045862451ebd1f21a69fbfe1f05408b.jpg b/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/4045862451ebd1f21a69fbfe1f05408b.jpg deleted file mode 100644 index 62978076..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/4045862451ebd1f21a69fbfe1f05408b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/73773f96882739f398c4db9552656943.jpg b/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/73773f96882739f398c4db9552656943.jpg deleted file mode 100644 index 3415b037..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/73773f96882739f398c4db9552656943.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/855f4f842396350759226c8041b96f7b.jpg b/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/855f4f842396350759226c8041b96f7b.jpg deleted file mode 100644 index 68bf39a5..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/calendar.jpg/855f4f842396350759226c8041b96f7b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/20e08dbd8a74450ab6b73fea6ce37bb3.jpg b/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/20e08dbd8a74450ab6b73fea6ce37bb3.jpg deleted file mode 100644 index e3c2db6b..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/20e08dbd8a74450ab6b73fea6ce37bb3.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/54e9b51481250743bf2b4dc8403b4442.jpg b/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/54e9b51481250743bf2b4dc8403b4442.jpg deleted file mode 100644 index ad081861..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/54e9b51481250743bf2b4dc8403b4442.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/cfd86d11514e7101c38ec348b99539c0.jpg b/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/cfd86d11514e7101c38ec348b99539c0.jpg deleted file mode 100644 index b126862a..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/cfd86d11514e7101c38ec348b99539c0.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/f1c0389148b3a3a33cbfff09d577338f.jpg b/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/f1c0389148b3a3a33cbfff09d577338f.jpg deleted file mode 100644 index aed6ddb1..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/inside-linux.jpg/f1c0389148b3a3a33cbfff09d577338f.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/49a1600a5d20e55868ab81b9b0f988aa.jpg b/pr/119/resized/content/images/blog/thumbnails/nature.jpg/49a1600a5d20e55868ab81b9b0f988aa.jpg deleted file mode 100644 index c271fbd7..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/49a1600a5d20e55868ab81b9b0f988aa.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/51f1c24cccc96753857fb175bb93da75.jpg b/pr/119/resized/content/images/blog/thumbnails/nature.jpg/51f1c24cccc96753857fb175bb93da75.jpg deleted file mode 100644 index dea1483a..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/51f1c24cccc96753857fb175bb93da75.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/b00075bce16dedf5840531d2bf5f364e.jpg b/pr/119/resized/content/images/blog/thumbnails/nature.jpg/b00075bce16dedf5840531d2bf5f364e.jpg deleted file mode 100644 index 953cbcef..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/b00075bce16dedf5840531d2bf5f364e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/faa7915e423a40eb8f7e5b91040ab9ec.jpg b/pr/119/resized/content/images/blog/thumbnails/nature.jpg/faa7915e423a40eb8f7e5b91040ab9ec.jpg deleted file mode 100644 index 42725849..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/nature.jpg/faa7915e423a40eb8f7e5b91040ab9ec.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/15f5c1199fe3b6a241ceba169fd4176e.jpg b/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/15f5c1199fe3b6a241ceba169fd4176e.jpg deleted file mode 100644 index 3aa71ca1..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/15f5c1199fe3b6a241ceba169fd4176e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/37ef8477429497834f7e7ed106344ef8.jpg b/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/37ef8477429497834f7e7ed106344ef8.jpg deleted file mode 100644 index 34dae64b..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/37ef8477429497834f7e7ed106344ef8.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/56039b5e8a9d941732502f0ddd518ab4.jpg b/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/56039b5e8a9d941732502f0ddd518ab4.jpg deleted file mode 100644 index aefcb766..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/56039b5e8a9d941732502f0ddd518ab4.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/b9bc17312aafebf07471a69f6a56381e.jpg b/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/b9bc17312aafebf07471a69f6a56381e.jpg deleted file mode 100644 index 720b0c7b..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/network_ssh.jpg/b9bc17312aafebf07471a69f6a56381e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/40540f49ef3f539794bd75fd51f6acfd.jpg b/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/40540f49ef3f539794bd75fd51f6acfd.jpg deleted file mode 100644 index 7dd152dd..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/40540f49ef3f539794bd75fd51f6acfd.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/80aae598a50641b22d1bab9f3f560087.jpg b/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/80aae598a50641b22d1bab9f3f560087.jpg deleted file mode 100644 index 6b6178bc..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/80aae598a50641b22d1bab9f3f560087.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/c38eae8d1b9f4b8b5e845b0cef7ff224.jpg b/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/c38eae8d1b9f4b8b5e845b0cef7ff224.jpg deleted file mode 100644 index 46fe6523..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/c38eae8d1b9f4b8b5e845b0cef7ff224.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/c94b2bd8ba163dd5c3a809d26180e46c.jpg b/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/c94b2bd8ba163dd5c3a809d26180e46c.jpg deleted file mode 100644 index c6c8fe36..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/raspberrypi.jpg/c94b2bd8ba163dd5c3a809d26180e46c.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/01fb9421473fc2004327195b8776f337.jpg b/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/01fb9421473fc2004327195b8776f337.jpg deleted file mode 100644 index 869ccacc..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/01fb9421473fc2004327195b8776f337.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/021e6b5c9ea7fab2a10ea9a26a10a65c.jpg b/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/021e6b5c9ea7fab2a10ea9a26a10a65c.jpg deleted file mode 100644 index fb954e18..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/021e6b5c9ea7fab2a10ea9a26a10a65c.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/1f6775b2e4ad9cc3ccc3b4011557d29e.jpg b/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/1f6775b2e4ad9cc3ccc3b4011557d29e.jpg deleted file mode 100644 index 1382bce5..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/1f6775b2e4ad9cc3ccc3b4011557d29e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/ed9effd75cf35b088fcedcd589759c7b.jpg b/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/ed9effd75cf35b088fcedcd589759c7b.jpg deleted file mode 100644 index 9c2a2592..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/thisisengineering.jpg/ed9effd75cf35b088fcedcd589759c7b.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/00fc284e365bbe49d303c8f64ebb321d.jpg b/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/00fc284e365bbe49d303c8f64ebb321d.jpg deleted file mode 100644 index ad021cf1..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/00fc284e365bbe49d303c8f64ebb321d.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/3e17127815b0b2d86da6377f5a93f0e3.jpg b/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/3e17127815b0b2d86da6377f5a93f0e3.jpg deleted file mode 100644 index fe3891df..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/3e17127815b0b2d86da6377f5a93f0e3.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/4b1f480c3cf794ed4261fc8ffac6599e.jpg b/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/4b1f480c3cf794ed4261fc8ffac6599e.jpg deleted file mode 100644 index 3a9f7e9e..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/4b1f480c3cf794ed4261fc8ffac6599e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/985de3f6cb7e319c4763d6fd2c992f0d.jpg b/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/985de3f6cb7e319c4763d6fd2c992f0d.jpg deleted file mode 100644 index 48a4759c..00000000 Binary files a/pr/119/resized/content/images/blog/thumbnails/zsh.jpg/985de3f6cb7e319c4763d6fd2c992f0d.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/1f1cae10550c57cf5f9cd9930a1f0a65.jpg b/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/1f1cae10550c57cf5f9cd9930a1f0a65.jpg deleted file mode 100644 index 6742a6a5..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/1f1cae10550c57cf5f9cd9930a1f0a65.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/2dff0bc8922f329a819dd585cbef5754.jpg b/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/2dff0bc8922f329a819dd585cbef5754.jpg deleted file mode 100644 index abbb9f19..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/2dff0bc8922f329a819dd585cbef5754.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/59aafcc02a4fc671d3cad25c77e637bb.jpg b/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/59aafcc02a4fc671d3cad25c77e637bb.jpg deleted file mode 100644 index 015b6c39..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/59aafcc02a4fc671d3cad25c77e637bb.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/a9958791fa4a222c5d5b17ca3b5b636e.jpg b/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/a9958791fa4a222c5d5b17ca3b5b636e.jpg deleted file mode 100644 index 90ea8b2f..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/a9958791fa4a222c5d5b17ca3b5b636e.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/b78cfc3e4ee6df7bf507c4fc8f08b9a0.jpg b/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/b78cfc3e4ee6df7bf507c4fc8f08b9a0.jpg deleted file mode 100644 index 9f8dd247..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/b78cfc3e4ee6df7bf507c4fc8f08b9a0.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/ecfed8b4460fb69dc0850d025538a3fb.jpg b/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/ecfed8b4460fb69dc0850d025538a3fb.jpg deleted file mode 100644 index 3ae29c3b..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/musique-music-banner.jpg/ecfed8b4460fb69dc0850d025538a3fb.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/343e1c894fa80ff82473b99a053bb17a.jpg b/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/343e1c894fa80ff82473b99a053bb17a.jpg deleted file mode 100644 index 4450defb..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/343e1c894fa80ff82473b99a053bb17a.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/63f5c579c10945d2e2e72eb37d412037.jpg b/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/63f5c579c10945d2e2e72eb37d412037.jpg deleted file mode 100644 index a6a2500e..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/63f5c579c10945d2e2e72eb37d412037.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/91c96f92850b2a42a784cbcdd5eb03e3.jpg b/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/91c96f92850b2a42a784cbcdd5eb03e3.jpg deleted file mode 100644 index bab83123..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/91c96f92850b2a42a784cbcdd5eb03e3.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/ba8f61c3337904cafd02eff92fbddc20.jpg b/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/ba8f61c3337904cafd02eff92fbddc20.jpg deleted file mode 100644 index 6aebe46c..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/ba8f61c3337904cafd02eff92fbddc20.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/baaeaf9426a098c63b345f39f1b1cd04.jpg b/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/baaeaf9426a098c63b345f39f1b1cd04.jpg deleted file mode 100644 index 50fa4b33..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/baaeaf9426a098c63b345f39f1b1cd04.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/e9c7f838eea7a161a48541a001176cff.jpg b/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/e9c7f838eea7a161a48541a001176cff.jpg deleted file mode 100644 index bd2b18f8..00000000 Binary files a/pr/119/resized/content/images/case-study/headers/panneaupocket-banner.jpg/e9c7f838eea7a161a48541a001176cff.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/musique-music-homepage.jpg/cdb54e86578cb96c05bf5e2e351d866f.jpg b/pr/119/resized/content/images/case-study/musique-music-homepage.jpg/cdb54e86578cb96c05bf5e2e351d866f.jpg deleted file mode 100644 index c156e61c..00000000 Binary files a/pr/119/resized/content/images/case-study/musique-music-homepage.jpg/cdb54e86578cb96c05bf5e2e351d866f.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/musique-music-homepage.jpg/dd98aaa11f2cf8adfb04421cbaed50bd.jpg b/pr/119/resized/content/images/case-study/musique-music-homepage.jpg/dd98aaa11f2cf8adfb04421cbaed50bd.jpg deleted file mode 100644 index 5c2a3e0c..00000000 Binary files a/pr/119/resized/content/images/case-study/musique-music-homepage.jpg/dd98aaa11f2cf8adfb04421cbaed50bd.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/musique-music-playlists.jpg/beebf9c70e30fcecd35153abb57a12d8.jpg b/pr/119/resized/content/images/case-study/musique-music-playlists.jpg/beebf9c70e30fcecd35153abb57a12d8.jpg deleted file mode 100644 index f6b09422..00000000 Binary files a/pr/119/resized/content/images/case-study/musique-music-playlists.jpg/beebf9c70e30fcecd35153abb57a12d8.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/musique-music-playlists.jpg/e547a5dd2aef3b4c076d715edf38a0e5.jpg b/pr/119/resized/content/images/case-study/musique-music-playlists.jpg/e547a5dd2aef3b4c076d715edf38a0e5.jpg deleted file mode 100644 index 9edeea97..00000000 Binary files a/pr/119/resized/content/images/case-study/musique-music-playlists.jpg/e547a5dd2aef3b4c076d715edf38a0e5.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/musique-music-results.jpg/4b23263a6df515c071c55b67785b57ff.jpg b/pr/119/resized/content/images/case-study/musique-music-results.jpg/4b23263a6df515c071c55b67785b57ff.jpg deleted file mode 100644 index 64fcf5c0..00000000 Binary files a/pr/119/resized/content/images/case-study/musique-music-results.jpg/4b23263a6df515c071c55b67785b57ff.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/musique-music-results.jpg/73b50bff4d6508ab6cb55e3212504347.jpg b/pr/119/resized/content/images/case-study/musique-music-results.jpg/73b50bff4d6508ab6cb55e3212504347.jpg deleted file mode 100644 index 38b87a38..00000000 Binary files a/pr/119/resized/content/images/case-study/musique-music-results.jpg/73b50bff4d6508ab6cb55e3212504347.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/schemas/m_and_m/case_studies_m_and_m.png/00a5c051980fc70656aa8fcbdb772f4b.png b/pr/119/resized/content/images/case-study/schemas/m_and_m/case_studies_m_and_m.png/00a5c051980fc70656aa8fcbdb772f4b.png deleted file mode 100644 index 27511ffc..00000000 Binary files a/pr/119/resized/content/images/case-study/schemas/m_and_m/case_studies_m_and_m.png/00a5c051980fc70656aa8fcbdb772f4b.png and /dev/null differ diff --git a/pr/119/resized/content/images/case-study/schemas/m_and_m/case_studies_m_and_m.png/297b7509f9acc565f5a7edfa13f25857.png b/pr/119/resized/content/images/case-study/schemas/m_and_m/case_studies_m_and_m.png/297b7509f9acc565f5a7edfa13f25857.png deleted file mode 100644 index 9d8cd4b7..00000000 Binary files a/pr/119/resized/content/images/case-study/schemas/m_and_m/case_studies_m_and_m.png/297b7509f9acc565f5a7edfa13f25857.png and /dev/null differ diff --git a/pr/119/resized/content/images/member/avatars/gfaivre.jpg/b9e2ad5ccb2390253e2c23ccbfb41dc7.jpg b/pr/119/resized/content/images/member/avatars/gfaivre.jpg/b9e2ad5ccb2390253e2c23ccbfb41dc7.jpg deleted file mode 100644 index e4a14222..00000000 Binary files a/pr/119/resized/content/images/member/avatars/gfaivre.jpg/b9e2ad5ccb2390253e2c23ccbfb41dc7.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/member/avatars/gfaivre.jpg/d2d8af0b210c37c677635983f1c02d6d.jpg b/pr/119/resized/content/images/member/avatars/gfaivre.jpg/d2d8af0b210c37c677635983f1c02d6d.jpg deleted file mode 100644 index d0c46bcc..00000000 Binary files a/pr/119/resized/content/images/member/avatars/gfaivre.jpg/d2d8af0b210c37c677635983f1c02d6d.jpg and /dev/null differ diff --git a/pr/119/resized/content/images/member/avatars/rix.png/4f7bb694753bd129601b986c5bdaabdb.png b/pr/119/resized/content/images/member/avatars/rix.png/4f7bb694753bd129601b986c5bdaabdb.png deleted file mode 100644 index f168c791..00000000 Binary files a/pr/119/resized/content/images/member/avatars/rix.png/4f7bb694753bd129601b986c5bdaabdb.png and /dev/null differ diff --git a/pr/119/resized/content/images/member/avatars/rix.png/7bdb9f34d8b53f82d37c01fd92196263.png b/pr/119/resized/content/images/member/avatars/rix.png/7bdb9f34d8b53f82d37c01fd92196263.png deleted file mode 100644 index e44c1db8..00000000 Binary files a/pr/119/resized/content/images/member/avatars/rix.png/7bdb9f34d8b53f82d37c01fd92196263.png and /dev/null differ diff --git a/pr/119/robots.txt b/pr/119/robots.txt deleted file mode 100644 index 9cfced28..00000000 --- a/pr/119/robots.txt +++ /dev/null @@ -1,4 +0,0 @@ -User-agent: * -Allow: / - -Sitemap: https://www.rix.fr/sitemap.xml \ No newline at end of file diff --git a/pr/119/services/index.html b/pr/119/services/index.html deleted file mode 100644 index 8c3e4f6a..00000000 --- a/pr/119/services/index.html +++ /dev/null @@ -1,396 +0,0 @@ - - - - - - - Rix 🐺 - Nos services - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- -
-
- - - -
-
-
- -

- Services - Conseils DevOps -

-
-
-
- -

Accompagnement et outillage DevOps

-

DevLab qui regroupe des outils devops éprouvés tout au long de nos 15 ans d'expérience dans l'écosystème web : stratégie et automatisation des processus de déploiement d'applications (intégration continue, réduction des cycles de livraison), traitement des logs applicatifs et système, supervision des systèmes et applicatifs en temps réel, service de secrets applicatifs (vault), stratégie d'anonymisation des données, etc.

-

Nous prenons en charge leur hébergement et leur maintenance mais nous pouvons également intervenir directement chez vous pour vous conseiller et/ou les mettre en place ou accompagner vos équipes devops.

-
    -
  • Hébergé en France;
  • -
  • 15 ans d'expérience de stratégie de déploiement et d'outillages;
  • -
  • Expertise d'outils devops opensource;
  • -
  • Mise en place, conseil et accompagnement des équipes.
  • -
-
-
- -

Performance et diagnostique

-

Parce que la vie d'une application est loin d'être un long fleuve tranquille, nous pouvons vous accompagner à diagnostiquer certaines problématiques applicatives mais également vous aider à mettre en place PRA et PCA afin qu'en cas d'incident, sa résolution soit la plus efficace/rapide possible.

-

- -

-
    -
  • Tirs de charge afin d'estimer le point de dégradation et/ou de rupture de votre service;
  • -
  • Diagnostique et piste de résolution en cas de comportement anormal;
  • -
  • Accompagnement et rédaction des PRA/PCA.
  • -
-
-
- -

Environnement de développement

-

L'un des avantages d'évoluer dans l'écosystème des concepteurs d'applications c'est d'avoir une vision globale de sa mise en œuvre. De sa conception jusqu'à sa mise en production en passant par sa réalisation.

-

Nous avons très vite pris la mesure de l'importance d'avoir un environnement de développement (une usine logiciel) qui permet aux équipes de développeurs de ne pas (ou peu) avoir à se soucier de la création de l'environnement applicatif.

-

L'idéal ? Utiliser le même socle IAC (Infrastructure As Code) pour automatiser la création de ses environnements de développement que pour créer ses environnements de production.

-
    -
  • Même socle applicatif chez tous les développeurs;
  • -
  • Gain de temps, les équipes sont efficaces;
  • -
  • Porte d'entrée pour une montée en compétences vers la philosophie DevOps;
  • -
  • Mise en place, conseil et accompagnement des équipes.
  • -
-
-
-
-
-
-

- Services - Infrastructure -

-
- -

Conception d'infrastructures sur-mesure

-

De la conception à la mise en production, nous étudions le projet que vous souhaitez faire héberger, nous assimilons votre métier, ses contraintes et ses spécificités.

-

L’objectif étant de concevoir une infrastructure en adéquation avec le besoin de vos applicatifs et de vos équipes tout en respectant leur équilibre budgétaire.

-
    -
  • Étude de votre projet, recommandation d'un fournisseur en fonction de vos objectifs;
  • -
  • Conception et déploiement vers le fournisseur de matériel choisi.
  • -
-
-
- - OVH Cloud - - - Scaleway - -
-
- - AWS - - - Google Cloud - -
-
- -

Expertise Kubernetes

-

Technologie de plus en plus demandée, Kubernetes tient beaucoup de promesses mais amène énormément de contraintes. - Nous exploitons et concevons des solutions sur ce socle depuis la disponibilité du produit et avons accompagné des équipes importantes lors de la migration de leur existant vers cette solution.

-

Nous sommes en capacité de vous apporter une étude de faisabilité, d'accompagner et former vos équipes et de concevoir l'ensemble des composants nécessaires au bon fonctionnement d'une infrastructure Kubernetes.

-
    -
  • Conseils d'experts pour la conception (ou la migration) de votre application;
  • -
  • Grosse expérience auprès de « pure player » d'envergure;
  • -
  • Mise en place, conseil et accompagnement des équipes
  • -
-
-
- - AWS - - - Google Cloud - -
-
- - AWS - - - Google Cloud - -
-
- -

Pilotage d'infrastructures

-

Le coeur de notre métier ! Assurer la maintenance en conditions opérationnelles de vos infrastructures, être proactif quant aux possibles incidents et intervenir rapidement lorsqu'ils surviennent. -

-
    -
  • Hébergé au choix en France ou ailleurs;
  • -
  • Supervision active des serveurs et des applicatifs;
  • -
  • Une équipe support disponible en cas d'incidents;
  • -
  • La garantie d'un suivi régulier (Comportement, mise à jour, sécurité).
  • -
-
-
- - AWS - - - Google Cloud - -
-
-
- - - - - - diff --git a/pr/119/site.webmanifest b/pr/119/site.webmanifest deleted file mode 100644 index ea79e55f..00000000 --- a/pr/119/site.webmanifest +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "Rix website", - "short_name": "Rix", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" -} diff --git a/pr/119/sitemap.xml b/pr/119/sitemap.xml deleted file mode 100644 index 1933ee08..00000000 --- a/pr/119/sitemap.xml +++ /dev/null @@ -1,75 +0,0 @@ - - - - https://rix-fr.github.io/rix/pr/119/blog - 2023-10-20T00:00:00+00:00 0 monthly - - - https://rix-fr.github.io/rix/pr/119/etudes-de-cas - 2022-09-12T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/ - 2023-11-06T15:15:35+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/a-propos - 2023-11-06T15:15:35+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/services - 2023-11-06T15:15:35+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/contact - 2023-11-06T15:15:35+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/legal - 2023-11-06T15:15:35+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/confidentialite - 2023-11-06T15:15:35+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/cours/cle-ssh-principes-de-base - 2023-10-20T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/post-mortem/sre-interpretation-incident - 2023-10-16T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/cours/docker-avec-windows-et-wsl - 2023-04-11T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/cours/utiliser-la-configuration-ssh-client - 2023-01-02T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/linux/construire-image-debian-raspberry - 2022-12-22T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/linux/integrer-icloud-gnome-calendar - 2022-10-25T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/linux/osx-to-linux-part-1 - 2022-11-18T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/blog/styleguide/example - 2021-03-17T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/etudes-de-cas/musique-music - 2022-09-12T00:00:00+00:00 monthly - - - https://rix-fr.github.io/rix/pr/119/etudes-de-cas/panneau-pocket - 2021-04-21T00:00:00+00:00 monthly - - diff --git a/pr/119/social/og-default.jpg b/pr/119/social/og-default.jpg deleted file mode 100644 index 00ed6690..00000000 Binary files a/pr/119/social/og-default.jpg and /dev/null differ diff --git a/pr/119/social/twitter-default.jpg b/pr/119/social/twitter-default.jpg deleted file mode 100644 index 1fbacbb7..00000000 Binary files a/pr/119/social/twitter-default.jpg and /dev/null differ