<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>FRtags/SysAdmin on Blog | Émilien F. </title>
    <link>https://emilien-foissotte.github.io/fr/frtags/sysadmin/</link>
    <description>Recent content in FRtags/SysAdmin on Blog | Émilien F. </description>
    <generator>Hugo -- 0.140.2</generator>
    <language>fr</language>
    <lastBuildDate>Sun, 06 Aug 2023 22:15:11 +0200</lastBuildDate>
    <atom:link href="https://emilien-foissotte.github.io/fr/frtags/sysadmin/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Cloud personnel</title>
      <link>https://emilien-foissotte.github.io/fr/posts/2023/07/personal-drive/</link>
      <pubDate>Sun, 06 Aug 2023 22:15:11 +0200</pubDate>
      <guid>https://emilien-foissotte.github.io/fr/posts/2023/07/personal-drive/</guid>
      <description>&lt;h2 id=&#34;tldr&#34;&gt;TL;DR&lt;/h2&gt;
&lt;p&gt;Dans ce billet de blog post nous allons voir comment mettre en place un
système monitoré 📊 &amp;amp; sécurisé de stockage cloud personel ⏏️,
hébergé derrière un proxy ⚙️, afin que vous puissez exposer plein d&amp;rsquo;autres services
sur votre serveur personnel 🏠&lt;/p&gt;
&lt;p&gt;Délaissez Google Drive et Google Photos 📷, hébergez vos beaux pixels chéris directement
chez vous 🚀 !&lt;/p&gt;
&lt;h2 id=&#34;intro&#34;&gt;Intro&lt;/h2&gt;
&lt;p&gt;Ma copine a fait récemment face à une situation très stressante, laissez moi vous expliquer
brièvement la cause du problème 🫣&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="tldr">TL;DR</h2>
<p>Dans ce billet de blog post nous allons voir comment mettre en place un
système monitoré 📊 &amp; sécurisé de stockage cloud personel ⏏️,
hébergé derrière un proxy ⚙️, afin que vous puissez exposer plein d&rsquo;autres services
sur votre serveur personnel 🏠</p>
<p>Délaissez Google Drive et Google Photos 📷, hébergez vos beaux pixels chéris directement
chez vous 🚀 !</p>
<h2 id="intro">Intro</h2>
<p>Ma copine a fait récemment face à une situation très stressante, laissez moi vous expliquer
brièvement la cause du problème 🫣</p>
<p><img alt="StressGif" loading="lazy" src="https://media.giphy.com/media/17bvpzBFFQ5Xi/giphy.gif#center"></p>
<p>Elle adore, tout comme moi, prendre un tas de photos durant ses voyages et immortaliser
les moments de tous les jours. Par chance, Google a rendu possible avec son application Google Photo
la sauvegarde et le partage massif de photos à des proches &amp; amis, depuis son smartphone en un
claquement de doigt ! 🤳</p>
<p>Et bonus, à la clé, on peut même partager un album commun.
Il faut le dire, c&rsquo;est incroyable !</p>
<figure>
    <img loading="lazy" src="loulousinge.jpg"
         alt="Jolie photo d&rsquo;un de nos dernier festival 🎶"/> <figcaption>
            <p>Jolie photo d&rsquo;un de nos dernier festival 🎶</p>
        </figcaption>
</figure>

<p>Néanmoins, plus le temps avançait, et plus la quantité de photo approchait dangeureusement la limite
maximale.. 💽</p>
<p>Jusqu&rsquo;au jour où la limite gratuite a été atteinte, mais
face à cela nous n&rsquo;avons pas trouvé acceptable de débourser quelques euros tous les mois pour ce
service de stockage.. Que faire.. 📈</p>
<p>(Encore plus quand on sait, venant du ML, qu&rsquo;en donnant ces photos &ldquo;gratuitement&rdquo;, on laisse à Google un très joli
dataset de photos qui peut être ré-utilisé pour faire ô combien d&rsquo;applications ML) 😠</p>
<p>Et le drame a continué.. 😬</p>
<p>Et le pire dans tout cela, c&rsquo;est qu&rsquo;il n&rsquo;y a pas d&rsquo;isolation entre
Drive, Photos et GMail !! 😵</p>
<p>Alors évidemment Google envoyait constamment des notifications sur
le téléphone de ma conjointe, pour dire qu&rsquo;il n&rsquo;arrivait plus à recevoir les mails, faute d&rsquo;espace.
Imaginez la situation assez critique, quand on utilise cet email comme contact principal
(pour réserver les billets de train et d&rsquo;avion, pour son application bancaire, pour les factures&hellip;) 📮</p>
<p><em>Dans la tête d&rsquo;un nouvel email 📧 arrivant sur une boîte Gmail quasi-pleine</em> 🤣 :
<img alt="DangerGif" loading="lazy" src="https://media.giphy.com/media/55itGuoAJiZEEen9gg/giphy.gif#center"></p>
<p>L&rsquo;esprit &ldquo;craftsmanship&rdquo; qui sommeille en moi m&rsquo;a susuré l&rsquo;idée d&rsquo;utiliser l&rsquo;excellente
Raspberry Pi (Ubuntu, 64 bits, 8 GB) que je possède déjà à la maison pour streamer Films&amp;Séries( <a href="https://www.plex.tv/">Abonnement Plex</a>
solution incroyable, là aucun scrupule pour chaque € déboursé). 👨‍💻</p>
<p>La Raspberry Pi servira de serveur de stockage encore une fois, mais cette fois
pour héberger photos et fichiers perso ! 🦾</p>
<p>Voici un petit schéma du système :
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <title></title>
</head>

<body>
  

  <div class="mermaid" align="center">
    

graph TB
linkStyle default fill:#ffffff

subgraph diagram [System Landscape]
style diagram fill:#ffffff,stroke:#ffffff

    1["<div style='font-weight: bold'>Managed Users</div><div style='font-size: 70%; margin-top: 0px'>[Person]</div>"]
    style 1 fill:#dddddd,stroke:#9a9a9a,color:#000000
    16["<div style='font-weight: bold'>Smartphone</div><div style='font-size: 70%; margin-top: 0px'>[Software System]</div>"]
    style 16 fill:#dddddd,stroke:#9a9a9a,color:#000000
    2["<div style='font-weight: bold'>Grafana</div><div style='font-size: 70%; margin-top: 0px'>[Software System]</div>"]
    style 2 fill:#dddddd,stroke:#9a9a9a,color:#000000
    3["<div style='font-weight: bold'>Cloud Storage external Provider (Uptobox)</div><div style='font-size: 70%; margin-top: 0px'>[Software System]</div>"]
    style 3 fill:#dddddd,stroke:#9a9a9a,color:#000000
    4["<div style='font-weight: bold'>RaspberryPI</div><div style='font-size: 70%; margin-top: 0px'>[Software System]</div>"]
    style 4 fill:#dddddd,stroke:#9a9a9a,color:#000000

    1-. "<div>Manage personal data throught<br />computer</div><div style='font-size: 70%'></div>" .->4
    4-. "<div>is replicated (CRON)</div><div style='font-size: 70%'></div>" .->3
    2-. "<div>Display and monitor system<br />info</div><div style='font-size: 70%'></div>" .->4
    4-. "<div>Display and share data</div><div style='font-size: 70%'></div>" .->16
    16-. "<div>Upload to backup data</div><div style='font-size: 70%'></div>" .->4
    1-. "<div>Manage personal data throught<br />smartphone</div><div style='font-size: 70%'></div>" .->16

end

  </div>
</body>
</html>
</p>
<p>Et la vue détaillée du conteneur &ldquo;RaspberryPI&rdquo; ( exprimé dans le
<a href="https://c4model.com/">modèle C4</a> )
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>
<head>
  <title></title>
</head>

<body>
  

  <div class="mermaid" align="center">
    
graph TB
linkStyle default fill:#ffffff

subgraph diagram [RaspberryPI - Containers]
style diagram fill:#ffffff,stroke:#ffffff

    1["<div style='font-weight: bold'>Managed Users</div><div style='font-size: 70%; margin-top: 0px'>[Person]</div>"]
    style 1 fill:#dddddd,stroke:#9a9a9a,color:#000000
    3["<div style='font-weight: bold'>Cloud Storage external Provider (Uptobox)</div><div style='font-size: 70%; margin-top: 0px'>[Software System]</div>"]
    style 3 fill:#dddddd,stroke:#9a9a9a,color:#000000

    subgraph 4 [RaspberryPI]
      style 4 fill:#ffffff,stroke:#9a9a9a,color:#9a9a9a

      5["<div style='font-weight: bold'>NextCloudPi Web Application</div><div style='font-size: 70%; margin-top: 0px'>[Container]</div>"]
      style 5 fill:#dddddd,stroke:#9a9a9a,color:#000000
      6["<div style='font-weight: bold'>Database</div><div style='font-size: 70%; margin-top: 0px'>[Container]</div>"]
      style 6 fill:#dddddd,stroke:#9a9a9a,color:#000000
      7["<div style='font-weight: bold'>HDD1</div><div style='font-size: 70%; margin-top: 0px'>[Container]</div>"]
      style 7 fill:#dddddd,stroke:#9a9a9a,color:#000000
      8["<div style='font-weight: bold'>HDD2</div><div style='font-size: 70%; margin-top: 0px'>[Container]</div>"]
      style 8 fill:#dddddd,stroke:#9a9a9a,color:#000000
    end

    5-. "<div>Store elements</div><div style='font-size: 70%'></div>" .->6
    6-. "<div>is mounted on</div><div style='font-size: 70%'></div>" .->7
    7-. "<div>is replicated (CRON)</div><div style='font-size: 70%'></div>" .->8
    7-. "<div>is replicated (CRON)</div><div style='font-size: 70%'></div>" .->3
    1-. "<div>Manage personal data throught<br />computer</div><div style='font-size: 70%'></div>" .->5

end

  </div>
</body>
</html>
</p>
<p>Évidemment la pression est un peu plus grande sur le système, il faut avoir des sauvegardes plus régulières
et ne plus déléguer cette tâche à Google (<em>grands pouvoirs, grandes responsabilités..</em>), mais je me sentais confiant et avais la soif d&rsquo;apprendre
à mettre ça en place.</p>
<p>De plus, mon stockage froid distant (<a href="https://uptobox.com/">Uptobox</a> peut me sauver la mise au cas où mes
HDD de la maison brûlaient ou venaient à être disfonctionnels.</p>
<p>Voici l&rsquo;architecture à laquelle je suis parvenu, le système doit être bien isolé de l&rsquo;OS avec
des conteneurs dockers pour la simplicité de déploiement/re-déploiement, des connections chiffrées avec
le SSL et HTTPS et enfin le système devait être 100% gratuit (chaleureux remerciements à l&rsquo;équipe de
Nextcloud pour le travail incroyable). 💡</p>
<p>La sauvegarde sera effectuée par synchronisation de disques durs locaux et stockée également sur mon
stockage Uptobox (le seul potentiel poste de dépense, en + du nom DNS, mais c&rsquo;est à peine quelques euros
par mois et dans tous les cas j&rsquo;aurais continué à payer pour ces services
que j&rsquo;utilise déjà). ⚙️</p>
<p>Pour monitorer toute l&rsquo;architecture, un dashboard Grafana viendrait lire les métriques systèmes
régulièrement (CPU, RAM , espace disque restant, trafic réseau, docker uptimes)..</p>
<p>Voici une liste des composants utilisés :</p>
<ul>
<li><a href="https://github.com/nextcloud/nextcloudpi">NextCloudPi</a></li>
<li><a href="https://grafana.com/">Grafana</a></li>
<li><a href="https://www.docker.com/">Docker</a></li>
<li><a href="https://letsencrypt.org/">Let&rsquo;s encrypt</a></li>
<li><a href="https://traefik.io/">Traefik</a></li>
</ul>
<p>Tous ces graphes ont été générés en utilisant <a href="https://structurizr.com">Structurizr</a>,
dont voici l&rsquo;architecture, exprimée dans le langage DSL de la modélisation C4 :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>workspace &#34;NextCloudPi&#34; &#34;Home Personnal Storage System&#34; {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    model {
</span></span><span style="display:flex;"><span>        u = person &#34;Managed Users&#34;
</span></span><span style="display:flex;"><span>        monitoring = softwareSystem &#34;Grafana&#34;
</span></span><span style="display:flex;"><span>        webcloudprovider = softwareSystem &#34;Cloud Storage external Provider (Uptobox)&#34;
</span></span><span style="display:flex;"><span>        personnalcloudstorage = softwareSystem &#34;RaspberryPI&#34; {
</span></span><span style="display:flex;"><span>            webapp = container &#34;NextCloudPi Web Application&#34;
</span></span><span style="display:flex;"><span>            database = container &#34;Database&#34;
</span></span><span style="display:flex;"><span>            physicalstorage = container &#34;HDD1&#34;
</span></span><span style="display:flex;"><span>            physicalbackupstorage = container &#34;HDD2&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>            u -&gt; webapp &#34;Manage personal data throught computer&#34;
</span></span><span style="display:flex;"><span>            webapp -&gt; database &#34;Store elements&#34;
</span></span><span style="display:flex;"><span>            database -&gt; physicalstorage &#34;is mounted on&#34;
</span></span><span style="display:flex;"><span>            physicalstorage -&gt; physicalbackupstorage &#34;is replicated (CRON)&#34;
</span></span><span style="display:flex;"><span>            physicalstorage -&gt; webcloudprovider &#34;is replicated (CRON)&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>        }
</span></span><span style="display:flex;"><span>        client = softwareSystem &#34;Smartphone&#34;
</span></span><span style="display:flex;"><span>        monitoring -&gt; personnalcloudstorage &#34;Display and monitor system info&#34;
</span></span><span style="display:flex;"><span>        personnalcloudstorage -&gt; client &#34;Display and share data&#34;
</span></span><span style="display:flex;"><span>        client -&gt; personnalcloudstorage &#34;Upload to backup data&#34;
</span></span><span style="display:flex;"><span>        u -&gt; client &#34;Manage personal data throught smartphone&#34;
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    views {
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>    }
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>}
</span></span></code></pre></div><p>Maintenant que les bases de l&rsquo;architecture ont été posées, on peut réfléchir au
déploiement et développement de la solution !</p>
<h2 id="déploiement-de-la-solution">Déploiement de la solution</h2>
<h3 id="pare-feu">Pare-feu</h3>
<p>La première chose très importante à faire, c&rsquo;est de sécuriser notre Raspberry Pi
exposée sur internet, avec <a href="https://doc.ubuntu-fr.org/ufw">ufw</a> et
<a href="https://doc.ubuntu-fr.org/fail2ban">fail2ban</a>.
Comme notre pi sera directement accessible depuis internet (pour le confort d&rsquo;un accès en SSH depuis l'
extérieur en cas de besoin), il est important de mettre en place un bon pare-feu.</p>
<p>En effet, il faut à tout prix éviter les attaques par bruteforce, les attaques de type &ldquo;Fuzzers&rdquo; et
toutes les choses effrayantes qui peuvent atteindre votre Pi.
(Ne craignez rien, avec un bon mot de passe et un banissement efficace des IPs incriminées
, vous êtes à l&rsquo;abri de la plupart des attaques de bots)</p>
<p>Commencons par installer le paquet fail2ban</p>
<p><code>sudo apt-get update &amp;&amp; apt-get install fail2ban</code></p>
<p>Lancez et vérifiez le status de fail2ban</p>
<p><code>sudo systemctl start fail2ban &amp;&amp; sudo systemctl enable fail2ban &amp;&amp; sudo systemctl status fail2ban</code></p>
<p>Créer le fichier de configuration par défaut pour la prison d&rsquo;IPs en modifiant
ce fichier <code>/etc/fail2ban/jail.d/custom.conf</code>.</p>
<p>Attention, ajoutez ici quelques IPs que vous n&rsquo;inclurez pas dans la prison,
pour éviter de vous auto-bloquer en cas d&rsquo;erreurs successives de mot de passe.</p>
<pre tabindex="0"><code>[DEFAULT]
ignoreip = 127.0.0.1 124.32.5.48
findtime = 10m
bantime = 24h
maxretry = 3
</code></pre><p>Rapide explication du fichier : Si une IP échoue à 3 reprise à se
connecter en SSH suite à un mauvais mot de passe durant les 10
dernières minutes, elle va en prison pour 24h ☠️</p>
<p>La prison va surveiller l&rsquo;activité du démon ssh, sshd, grâce à votre
modification de ce fichier <code>/etc/fail2ban/jail.d/custom.conf</code></p>
<pre tabindex="0"><code>[sshd]
enabled = true
</code></pre><p>Relancez la configuration de fail2ban pour appliquer les modifications :</p>
<p><code>sudo systemctl restart fail2ban</code></p>
<p>Désormais il est beaucoup plus difficile de s&rsquo;introduire sur le système,
beau boulot 😈</p>
<p>Voici un petit aperçu de ma propre prison en place
au moment où j&rsquo;écris ces lignes (attendez quelques minutes sur votre
serveur pour voir l&rsquo;énorme quantité de bots être bloqués dans votre cas, c&rsquo;est dingue)</p>
<p><code>sudo fail2ban-client get sshd banip --with-time</code></p>
<p>Regardez toutes ces misérables IPs malveillantes bloquées !!</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>45.136.153.217  2023-07-28 19:27:25 + 86400 = 2023-07-29 19:27:25
</span></span><span style="display:flex;"><span>134.122.88.190  2023-07-29 02:07:52 + 86400 = 2023-07-30 02:07:52
</span></span><span style="display:flex;"><span>193.35.18.169   2023-07-29 02:26:39 + 86400 = 2023-07-30 02:26:39
</span></span><span style="display:flex;"><span>170.64.187.84   2023-07-29 04:06:54 + 86400 = 2023-07-30 04:06:54
</span></span><span style="display:flex;"><span>159.203.46.152  2023-07-29 04:20:42 + 86400 = 2023-07-30 04:20:42
</span></span><span style="display:flex;"><span>45.129.14.64    2023-07-29 04:27:53 + 86400 = 2023-07-30 04:27:53
</span></span><span style="display:flex;"><span>5.187.112.81    2023-07-29 07:05:13 + 86400 = 2023-07-30 07:05:13
</span></span><span style="display:flex;"><span>116.110.84.51   2023-07-29 14:19:34 + 86400 = 2023-07-30 14:19:34
</span></span><span style="display:flex;"><span>45.128.232.71   2023-07-29 15:03:22 + 86400 = 2023-07-30 15:03:22
</span></span></code></pre></div><p><img alt="jokerjail" loading="lazy" src="https://media.giphy.com/media/LUaRXbQZZ6pWg/giphy.gif#center"></p>
<p>Ajoutez aussi une règle NAT avec le port 22 sur votre routeur,
si vous ne l&rsquo;avez pas déjà fait, afin de rendre votre serveur accessible depuis Internet.</p>
<p>En guise de sécurité supplémentaire, j&rsquo;active ufw sur ma RaspberryPI pour éviter
un traffic inattendu en cas de problème de configuration sur des ports non maîtrisés, même s&rsquo;ils
sont fermés sur le routeur et non reliés, c&rsquo;est une sécurité supplémentaire.</p>
<p>Installez ufw avec :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt install ufw
</span></span></code></pre></div><p>Activer le protocole ssh sur la route 22 avant d&rsquo;appliquer le pare-feu,
sinon vous rendrez votre Pi complètement injoignable à distance par Ethernet/Wifi 😂:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo ufw allow ssh
</span></span></code></pre></div><p><img alt="sawtree" loading="lazy" src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExajF1bjU3N3pkd3d0bWNidmtxZTRpYnYzcjRsYjM0NGRqbHdtZm1mbiZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/79fGuiZ2MeyYxwLINP/giphy.gif#center"></p>
<p>Activez le pare-feu :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo ufw enable
</span></span></code></pre></div><h3 id="reverse-proxy-avec-docker">Reverse Proxy avec Docker</h3>
<p>L&rsquo;utilisation du reverse proxy, Traefik, est très simple. Tout ce qu&rsquo;il faut faire c&rsquo;est
appliquer les bons tags depuis les services docker-compose et traefik va surveiller ce qui se passe
sur le socket du démon docker et prendre tout en charge. Vous n&rsquo;avez rien besoin de faire en plus,
c&rsquo;est très puissant et évolutif !</p>
<p>Créons d&rsquo;abord le réseau docker qui servira d&rsquo;intermédiaire pour communiquer entre les services.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>docker network create pi
</span></span></code></pre></div><p>Pour activer Traefik, nous activerons d&rsquo;abord le service Docker de traefik. Pour cela, instancions un
le fichier docker-compose suivant :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#39;3.4&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">traefik</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;traefik:2.3&#39;</span>
</span></span><span style="display:flex;"><span>          <span style="color:#f92672">container_name</span>: <span style="color:#e6db74">&#39;traefik&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#e6db74">&#39;unless-stopped&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;80:80&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;443:443&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;8080:8080&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;/var/run/docker.sock:/var/run/docker.sock:ro&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;./traefik/traefik.toml:/etc/traefik/traefik.toml:ro&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;./traefik/traefik_dynamic.toml:/traefik_dynamic.toml:ro&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;./ssl:/etc/ssl:ro&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">whoami</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#e6db74">&#39;traefik/whoami&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#e6db74">&#39;unless-stopped&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">labels</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;traefik.enable=true&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;traefik.http.routers.whoami.rule=PathPrefix(`/whoami{regex:$$|/.*}`)&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;traefik.http.services.whoami.loadbalancer.server.port=80&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;traefik.http.routers.whoami.tls&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pi</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">pi</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">external</span>: <span style="color:#66d9ef">true</span>
</span></span></code></pre></div><p>Nous allons ensuite configurer traefik avec 2 fichiers (pour activer la journalisation, le
dashboard de supervision et l&rsquo;écoute sur le socket du démon docker).</p>
<p>Voici le contenu de notre fichier à placer sous <code>traefik/traefik.toml</code> :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>[<span style="color:#ae81ff">entryPoints]</span>
</span></span><span style="display:flex;"><span>  [<span style="color:#ae81ff">entryPoints.web]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">address = &#34;:80&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [<span style="color:#ae81ff">entryPoints.websecure]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">address = &#34;:443&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">api]</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">dashboard = true</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">providers.docker]</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">watch = true</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">network = &#34;web&#34;</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">exposedByDefault = false</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">providers.file]</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">filename = &#34;traefik_dynamic.toml&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">accessLog]</span>
</span></span></code></pre></div><p>Nous définissons ici :</p>
<ul>
<li>2 entrypoints, sur le port 80 pour le protocole HTTP, et un accès en HTTPS sur le port 443</li>
<li>L&rsquo;activation du dashboard super cool de traefik, accessible à <a href="">http://yoururl.com/dashboard/</a>,
(<em>NB: Prenez garde à inclure le dernier slash final, c&rsquo;est important sinon vous ne verez pas votre
dashboard.</em>)</li>
<li>L&rsquo;activation de l&rsquo;écoute du socket docker, pour ajouter facilement de nouveau services
tout en désactivant l&rsquo;exposition des services si on ne l&rsquo;a pas précisé par un label, (<em>meilleur d&rsquo;un point de vue sécurité</em>)</li>
<li>Un fichier de configuration <code>traefik_dynamic.toml</code></li>
<li>L&rsquo;affichage des logs d&rsquo;accès sur l&rsquo;instance docker du reverse proxy</li>
</ul>
<p>Super, désormais notre service traefik permet de faire le proxy depuis les points d&rsquo;accès <code>websecure</code> et
<code>web</code>. Sécurisons le dashbaord de visualisation Traefik en générant et en demandant un mot de passe par
l&rsquo;intermédiaire d&rsquo;un <code>middleware</code> devant notre service.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt-get install apache2-utils
</span></span></code></pre></div><p>Générez un hash de votre mot de passe d&rsquo;administration, en affichant le résultat sur la
sortie standard:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>htpasswd -Bnb admin superpassword123
</span></span></code></pre></div><p>Voici la configuration dynamique configuration, référençant le middleware avec une basic auth :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span>[<span style="color:#ae81ff">http.middlewares.simpleAuth.basicAuth]</span>
</span></span><span style="display:flex;"><span>  <span style="color:#ae81ff">users = [</span>
</span></span><span style="display:flex;"><span>    <span style="color:#e6db74">&#34;admin:$2y$05$fJ.OOvXhMrXSC4s6uDgtp.q320RmTyHQ7iuya90TKS./LXa5QoJue&#34;</span>
</span></span><span style="display:flex;"><span>  ]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#ae81ff">http.routers]</span>
</span></span><span style="display:flex;"><span>  [<span style="color:#ae81ff">http.routers.unsecurerouter-api]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">rule = &#34;Host(`192.168.X.X`) || Host(`yoururl.fr`) &amp;&amp; (PathPrefix(`/api`) || PathPrefix(`/dashboard`))&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">entrypoints = [&#34;web&#34;]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">middlewares = [&#34;simpleAuth&#34;]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">service = &#34;api@internal&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  [<span style="color:#ae81ff">http.routers.securerouter-api]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">rule = &#34;Host(`192.168.X.X`) || Host(`yoururl.fr`) &amp;&amp; (PathPrefix(`/api`) || PathPrefix(`/dashboard`))&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">entrypoints = [&#34;websecure&#34;]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">middlewares = [&#34;simpleAuth&#34;]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">service = &#34;api@internal&#34;</span>
</span></span><span style="display:flex;"><span>    [<span style="color:#ae81ff">http.routers.securerouter-api.tls]</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[[<span style="color:#ae81ff">tls.certificates]]</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">certFile = &#34;/etc/ssl/ssl-cert-snakeoil.pem&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#ae81ff">keyFile = &#34;/etc/ssl/ssl-cert-snakeoil.key&#34;</span>
</span></span></code></pre></div><p>Nous y définissons :</p>
<ul>
<li>Un <code>middleware</code> en utilisant le hash précédemment généré avec le mot de passe de l&rsquo;utilisateur admin</li>
<li>Quelques <code>routers</code> pour rediriger les chemins d&rsquo;URL commençant par <code>/dashboard</code> vers le dashboard</li>
<li>Un <code>router</code> sécurisé et non sécurisé , le sécurisé utilisant les certificats stockés sous <code>/etc/ssl</code>
(Nous y reviendrons au moment où nous allons générer ensemble le certificat avec Let&rsquo;s Encrypt)</li>
</ul>
<p>Démarrons le service traefik , allez dans votre système de ficher jusqu&rsquo;à votre <code>docker-compose.yml</code>,
à côté duquel vous avez enregistré les fichiers toml de configuration dynamique et statique.
Ajoutez aussi un dossier SSL vide.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>docker-compose up -di
</span></span></code></pre></div><p>Ouvrez un navigateur web à <a href="">http://yoururl/dashboard/</a> et vous devriez voir un
dashboard semblable à cela :</p>
<p><img alt="traefikdashboard" loading="lazy" src="/posts/2023/07/personal-drive/traefik.png"></p>
<p>Bravo, bien joué, votre proxy fonctionne, et il est prêt à servir tous vos services!!</p>
<p><img alt="spongebobserver" loading="lazy" src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExd2phdm01cDB6ZHpvazIwZWxnajlvZTZwYXYzazE3bmRnbWVlbzYweSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/3oKHW5ygEPHUNrb1SM/giphy.gif#center"></p>
<h3 id="mise-en-place-du-monitoring-avec-grafana">Mise en place du monitoring avec Grafana</h3>
<p>Maintenant nous allons déployer un dashboard Grafana également avec docker compose, tout en y ajoutant
quelques labels pour configurer le routage et le proxy avec traefik.
Vous pourrez ainsi monitorer votre serveur 24h/24h 7j/7j sans effort !</p>
<p>Pour cela, instanciez un fichier <code>docker-compose.yml</code> avec quelques services
dans un dossier <code>monitoring</code>.</p>
<p>Preparez en créant quelques sous-dossiers data (pour persister vos données si votre
serveur a besoin de redémarrer de temps à autre)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>mkdir ~/monitoring <span style="color:#f92672">&amp;&amp;</span> cd ~/monitoring <span style="color:#f92672">&amp;&amp;</span> mkdir -p prometheus/data grafana/data <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>sudo chown -R 472:472 grafana/ <span style="color:#f92672">&amp;&amp;</span> <span style="color:#ae81ff">\
</span></span></span><span style="display:flex;"><span><span style="color:#ae81ff"></span>sudo chown -R 65534:65534 prometheus/
</span></span></code></pre></div><p>Voici le fichier docker-compose :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#34;3&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">grafana</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">monitoring-grafana</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">grafana/grafana:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostname</span>: <span style="color:#ae81ff">rpi-grafana</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">user</span>: <span style="color:#e6db74">&#34;472&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">expose</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">3000</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">env_file</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./grafana/.env</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#75715e"># /!\ To be modified depending on your needs /!\</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./grafana/data:/var/lib/grafana</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./grafana/provisioning:/etc/grafana/provisioning</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">depends_on</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">prometheus</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">labels</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;traefik.enable=true&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;traefik.http.routers.grafana.rule=PathPrefix(`/grafana{regex:$$|/.*}`)&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;traefik.http.routers.grafana.tls&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;traefik.http.services.grafana.loadbalancer.server.port=3000&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;traefik.frontend.headers.customRequestHeaders=Authorization:-&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;traefik.http.routers.grafana.middlewares=simpleAuth@file&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">cadvisor</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">monitoring-cadvisor</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">zcube/cadvisor:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostname</span>: <span style="color:#ae81ff">rpi-cadvisor</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">privileged</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">expose</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">8080</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">devices</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/dev/kmsg</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/:/rootfs:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/var/run:/var/run:rw</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/sys:/sys:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/var/lib/docker/:/var/lib/docker:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/dev/disk/:/dev/disk:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/etc/machine-id:/etc/machine-id:ro</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">node-exporter</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">monitoring-node-exporter</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">prom/node-exporter:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostname</span>: <span style="color:#ae81ff">rpi-exporter</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">expose</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">9100</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">command</span>:
</span></span><span style="display:flex;"><span>      - --<span style="color:#ae81ff">path.procfs=/host/proc</span>
</span></span><span style="display:flex;"><span>      - --<span style="color:#ae81ff">path.sysfs=/host/sys</span>
</span></span><span style="display:flex;"><span>      - --<span style="color:#ae81ff">path.rootfs=/host</span>
</span></span><span style="display:flex;"><span>      - --<span style="color:#ae81ff">collector.filesystem.ignored-mount-points</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">^/(sys|proc|dev|host|etc|rootfs/var/lib/docker/containers|rootfs/var/lib/docker/overlay2|rootfs/run/docker/netns|rootfs/var/lib/docker/aufs)($$|/)</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/proc:/host/proc:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/sys:/host/sys:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/:/rootfs:ro</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/:/host:ro,rslave</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">prometheus</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">monitoring-prometheus</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">prom/prometheus:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">hostname</span>: <span style="color:#ae81ff">rpi-prometheus</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">user</span>: <span style="color:#e6db74">&#34;nobody&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">command</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;--config.file=/etc/prometheus/prometheus.yml&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;--storage.tsdb.path=/prometheus&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">expose</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">9090</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#75715e"># /!\ To be modified depending on your needs /!\</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./prometheus/data:/prometheus</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./prometheus:/etc/prometheus/</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">depends_on</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cadvisor</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">node-exporter</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">links</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cadvisor:cadvisor</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">node-exporter:node-exporter</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">networks</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">pi</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">external</span>: <span style="color:#66d9ef">true</span>
</span></span></code></pre></div><ul>
<li><strong>Prometheus</strong> expose les métriques systèmes de la RaspberryPI (CPU, RAM&hellip;)</li>
<li><strong>Node-exporter</strong> envoie les métriques au système de monitoring (grafana)</li>
<li><strong>Grafana</strong> expose la donnée au travers du proxy traefik</li>
<li><strong>cAdvisor</strong> monitore les conteneurs Dockers sur la RaspberryPI</li>
</ul>
<p><em>NB: Attention, installez bien une version d&rsquo;Ubuntu ARM 64 bit, sinon certains containers
ne serons pas disponibles !</em></p>
<p>Montez la stack :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>docker-compose up -d
</span></span></code></pre></div><p>Navigez jusqu&rsquo;au dashboard grafana à <a href="">http://yoururl/grafana/</a> et</p>
<ul>
<li>Ouvrez un autre onglet de navigteur et suivez cette url <a href="https://grafana.com/grafana/dashboards/19275-raspberry-pi-docker-monitoring-vef/">Grafana.com Shared Dashboard</a></li>
<li>Cliquez sur <code>COPY ID to clipboard</code> ou <code>Download JSON</code></li>
<li>Allez sur votre propre dashboard à <a href="">http://yoururl/grafana/</a> et clickez sur <code>Import</code> sous
<code>Dashboard tab</code>
<img alt="import" loading="lazy" src="import.png"></li>
<li>Copiez l&rsquo;ID et cliquez sur <code>Load</code> ou <code>Upload JSON file</code> avec le fichier téléchargé</li>
<li>Cliquez sur <code>Load</code></li>
</ul>
<p>Et voilà 🔥</p>
<p>Vous devriez avoir maintenant sous vos yeux émerveillés ceci :
<img alt="grafana1" loading="lazy" src="/posts/2023/07/personal-drive/grafana.png#center">
<img alt="grafana2" loading="lazy" src="/posts/2023/07/personal-drive/grafana2.png#center">
<img alt="grafana3" loading="lazy" src="/posts/2023/07/personal-drive/grafana3.png#center"></p>
<p>Plutôt cool n&rsquo;est-ce pas ? Tous vos dockers sont monitorés et même votre petite RaspberryPI !</p>
<p><img alt="gifhomer" loading="lazy" src="https://media.giphy.com/media/3orieUe6ejxSFxYCXe/giphy.gif#center"></p>
<h3 id="déployer-nextcloudpi">Déployer NextcloudPi</h3>
<p>Désormais, tout est prêt pour héberger Nextcloud sur votre RaspberryPI, préparons votre
disque dur que vous utiliserez comme stockage supplémentaire externe, c&rsquo;est préférable plutôt
que le volume racine de votre Pi.</p>
<p>Cela permet de mieux isoler les différents stockage mais cela n&rsquo;est pas obligatoire,
c&rsquo;est à votre convenance, vous pouvez tout à fait décider de stocker tout sur le volume racine
si vous préférez ou que vous n&rsquo;avez de stockage externe (prévoyez de la place tout de même).</p>
<p>Si vous utiliserez un disque dur externe (magnétique comme moi ou pas)
alors suivez le guide !</p>
<p>D&rsquo;abord il faut identifier le disque à formatter( soyez attentif à ne pas vous tromper
et écraser le stockage d&rsquo;autres disques par mégarde, vérifiez toujours la cible
lors des commandes avant d&rsquo;appliquer quelque opération que ce soit !!)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>lsblk
</span></span></code></pre></div><p>Voici un exemple de mon installation avec 2 HDD (un de 2 To et
un autre de 500 Gb one) attachés à ma RaspberryPI qui tourne sur SSD (grâce à ce
<a href="https://www.cdiscount.com/informatique/clavier-souris-webcam/atolla-hub-usb-3-0-alimente-adaptateur-usb-4-port/f-1070229-ato6974065410521.html">powered USB hub</a>
).</p>
<p><img alt="poweredusbhub" loading="lazy" src="/posts/2023/07/personal-drive/usbhub.png#center"></p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
</span></span><span style="display:flex;"><span>sda      8:0    0 465.8G  0 disk
</span></span><span style="display:flex;"><span>├─sda1   8:1    0   256M  0 part /boot/firmware
</span></span><span style="display:flex;"><span>└─sda2   8:2    0 465.5G  0 part /
</span></span><span style="display:flex;"><span>sdb      8:16   0   1.8T  0 disk
</span></span><span style="display:flex;"><span>└─sdb1   8:17   0   1.8T  0 part
</span></span><span style="display:flex;"><span>sdc      8:32   0 465.7G  0 disk
</span></span><span style="display:flex;"><span>└─sdc1   8:33   0 465.7G  0 part
</span></span></code></pre></div><p>On peut désormais formatter le disque dur avec un système de fichier prenant en charge
les permissions utilisateurs etc..
Attention, tout ce qui est présent sur le disque sera supprimé lors de la manipulation !</p>
<p>En exemple en formattant la partition du disque avec le système de fichier ext4
(système de fichiers GNU/Linux)</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo mkfs -t ext4 /dev/sdc1
</span></span></code></pre></div><p>Maintenant nous avons notre disque de prêt, éditons <code>fstab</code>, i.e. nous
allons indiquer à l&rsquo;OS comment chaque disque doit être monté, et où.</p>
<p>Identifiez l&rsquo;<code>UUID</code> de votre disque formatté, en lançant cette commande :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>lsblk -f
</span></span></code></pre></div><p>Éditez le fichier pour entrer ces valeurs, en remplaçant l&rsquo;UUID et la localisation cible
vers quelque chose d&rsquo;explicite de votre choix :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>UUID=THE-ADDRESS-GOES-HERE /mnt/directory/location ext4 defaults 0
</span></span></code></pre></div><p>Maintenant vous pouvez monter le disque dur (cette opération est
à faire uniquement maintenant,plus tard cela sera fait automatiquement à chaque démarrage
de votre pi) :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>fstab mount -a
</span></span></code></pre></div><p>Changez la propriété de la localisation système cible pour l&rsquo;utilisateur
utilisé par Nextcloud dans l&rsquo;image Docker :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo chown www-data:www-data -R /mnt/directory/location
</span></span></code></pre></div><p>Maintenant, comme on ne change pas une équipe qui gagne
instancions un autre fichier docker-compose pour lancer la stack NextcloudPi.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yml" data-lang="yml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#34;3.4&#34;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">nextcloud</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">container_name</span>: <span style="color:#ae81ff">nextcloudpi</span>
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">image</span>: <span style="color:#ae81ff">ownyourbits/nextcloudpi</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">8880</span>:<span style="color:#ae81ff">80</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">8443</span>:<span style="color:#ae81ff">443</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">4443</span>:<span style="color:#ae81ff">4443</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;/media/backup2to/ncp/:/data&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;ssl/ssl-cert-snakeoil.pem:/etc/ssl/certs/ssl-cert-snakeoil.pem:ro&#39;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#39;ssl/ssl-cert-snakeoil.key:/etc/ssl/private/ssl-cert-snakeoil.key:ro&#39;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">unless-stopped</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">command</span>: <span style="color:#ae81ff">127.0.0.1</span>
</span></span></code></pre></div><p>Mais, où est utilisé traefik ?
Il n&rsquo;y en a pas besoin car nous utilisons le port <code>80</code> et <code>443</code> en binding directement sur l&rsquo;hôte
mais pas sur les <code>80</code> and <code>443</code>, donc votre serveur peut les utiliser
pour Traefik et continuer à héberger des tonnes d&rsquo;autres services !</p>
<p>Pensez bien à ouvrir ces ports dans votre NAT pour autoriser le traffic depuis internet vers Traefik et NextcloudPi
Pas besoin de filtre ici, tout est sécurisé par votre stack Nextcloud et Traefik.</p>
<p>Récupérez le mot de passe d&rsquo;administration avec la commande <code>ncp-config</code> dans votre docker après
votre <code>docker-compose up -d</code> sur la stack.
Prenez le temps d&rsquo;ajouter aussi votre nom de domaine DNS ou votre IP locale au dashboard,
dans <code>trusted-domains</code> sinon vous ne pourrez pas y accéder !</p>
<p>Téléchargez vos données depuis Google Photos avec <a href="https://support.google.com/accounts/answer/9666875?hl=fr">Google Takeout</a>.</p>
<p>Déchargez le contenu du zip dans votre dossier data de Nextcloud :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>unzip <span style="color:#e6db74">&#39;takeout-yourzips-0*.zip&#39;</span> -d /media/backup2to/ncp/ncdata/data/yourusername/files/Photos/Takeout
</span></span></code></pre></div><p>Changer de nouveau la propriété des dossiers data et des photos copiées:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo chown www-data:www-data -R /mnt/directory/location/ncdata/data
</span></span></code></pre></div><p>Scannez le nouveau contenu :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>docker exec -u <span style="color:#ae81ff">33</span> -it sh -c /var/www/nextcloud/occ files:scan --all
</span></span></code></pre></div><p>Si vous utilisez l&rsquo;excellent app Nextcloud <a href="https://memories.gallery/">Memories</a>,
regénérez les métadata EXIF depuis vos nouvelles photos.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>docker exec -u <span style="color:#ae81ff">33</span> -it sh -c /var/www/nextcloud/occ memories:migrate-google-takeout
</span></span></code></pre></div><p>Voici un aperçu de mon propre dashboard (flouté, vie privée oblige),
très sympa n&rsquo;est-ce pas ?</p>
<p><img alt="dashimage" loading="lazy" src="/posts/2023/07/personal-drive/NextcloudPi.png#center"></p>
<p>Bravo, vous hébergez vos propres données à la maison désormais !! 🎊</p>
<p><img alt="owndata" loading="lazy" src="https://media.giphy.com/media/umbIrcUJbmuIUZ1e7M/giphy.gif#center"></p>
<p>Tout est presque terminé, il ne nous reste qu&rsquo;à effecuter un DNS challenge
pour générer un certificat SSL wildcard (permettant d&rsquo;accéder à n&rsquo;importe quel root domain).</p>
<p>Vous ne transféreriez pas vos données, mots de passes, notes, agenda sur des connexions claires
non chiffrées ? Moi, non plus 😄</p>
<p>C&rsquo;est parti pour activer le HTTPS sur traefik et nextcloud !</p>
<p>D&rsquo;abord installons certbot sur notre RaspberryPI,</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo apt update
</span></span><span style="display:flex;"><span>sudo apt install certbot
</span></span></code></pre></div><p>Téléchargez le script du challenge acme et rendez-le executable :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>wget https://github.com/joohoi/acme-dns-certbot-joohoi/raw/master/acme-dns-auth.py
</span></span><span style="display:flex;"><span>chmod +x acme-dns-auth.py
</span></span></code></pre></div><p>Éditez les informations du script pour le lancer avec <code>python3</code>
Et déplacer le script vers le dossier de certbot :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo mv acme-dns-auth.py /etc/letsencrypt/
</span></span></code></pre></div><p>Lancez le acme-dns-certbot :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>sudo certbot certonly --manual --manual-auth-hook /etc/letsencrypt/acme-dns-auth.py --preferred-challenges dns --debug-challenges -d <span style="color:#ae81ff">\*</span>.your-domain -d your-domain
</span></span></code></pre></div><p>Veillez à substituer le nom de domaine et à escaping l&rsquo;asterix avec le backslash !</p>
<p>Regardez les logs de sortie, et ajoutez l&rsquo;entrée DNS CNAME dans votre fournisseur DNS.
Un exemple de sortie :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>Output
</span></span><span style="display:flex;"><span>...
</span></span><span style="display:flex;"><span>Output from acme-dns-auth.py:
</span></span><span style="display:flex;"><span>Please add the following CNAME record to your main DNS zone:
</span></span><span style="display:flex;"><span>_acme-challenge.your-domain CNAME 12345678-9abc-def0-1234-56789abcdef0.auth.acme-dns.io.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>Waiting for verification...
</span></span><span style="display:flex;"><span>...
</span></span></code></pre></div><p>Vous devez ajouter l&rsquo;entrée <code>CNAME 12345678-9abc-def0-1234-56789abcdef0.auth.acme-dns.io</code>.</p>
<p>Dès que le bot a détecté le changement de DNS et généré le certificat publique et privé
avec le wildcard certificates copiez-les le dossier ssl de traefik et de nextcloud.</p>
<p>Dans votre dossier <code>ssl</code> :</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-txt" data-lang="txt"><span style="display:flex;"><span>ssl
</span></span><span style="display:flex;"><span>├── ssl-cert-snakeoil.key
</span></span><span style="display:flex;"><span>└── ssl-cert-snakeoil.pem
</span></span></code></pre></div><p>Ajoutez ce router à votre instance traefik pour ajouter cette configuration dynamique.
Cela dit à traefik de servire ces services avec du SSL par HTTPS.
Traefik va également ré-écrire les URL pour utiliser le bon port, quand vous requêterez <a href="">yoururl/nextcloud</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-toml" data-lang="toml"><span style="display:flex;"><span>[<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">middlewares</span>]
</span></span><span style="display:flex;"><span>  [<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">middlewares</span>.<span style="color:#a6e22e">redirectnextcloud</span>.<span style="color:#a6e22e">redirectRegex</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">regex</span> = <span style="color:#e6db74">&#34;^http(s?)://yoururl.fr/nextcloud(.*)&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">replacement</span> = <span style="color:#e6db74">&#34;https://yoururl.fr:8443&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">routers</span>]
</span></span><span style="display:flex;"><span>  [<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">routers</span>.<span style="color:#a6e22e">nextcloud</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">rule</span> = <span style="color:#e6db74">&#34;PathPrefix(`/nextcloud`)&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">entrypoints</span> = [<span style="color:#e6db74">&#34;websecure&#34;</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">middlewares</span> = [<span style="color:#e6db74">&#34;redirectnextcloud&#34;</span>]
</span></span><span style="display:flex;"><span>    <span style="color:#a6e22e">service</span> = <span style="color:#e6db74">&#34;nextcloud&#34;</span>
</span></span><span style="display:flex;"><span>    [<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">routers</span>.<span style="color:#a6e22e">nextcloud</span>.<span style="color:#a6e22e">tls</span>]
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>[<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">services</span>]
</span></span><span style="display:flex;"><span>  [<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">services</span>.<span style="color:#a6e22e">nextcloud</span>.<span style="color:#a6e22e">loadBalancer</span>]
</span></span><span style="display:flex;"><span>    [<span style="color:#a6e22e">http</span>.<span style="color:#a6e22e">services</span>.<span style="color:#a6e22e">nextcloud</span>.<span style="color:#a6e22e">loadBalancer</span>.<span style="color:#a6e22e">healthCheck</span>]
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">path</span> = <span style="color:#e6db74">&#34;/&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">scheme</span> = <span style="color:#e6db74">&#34;https&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">hostname</span> = <span style="color:#e6db74">&#34;yoururl.fr&#34;</span>
</span></span><span style="display:flex;"><span>      <span style="color:#a6e22e">port</span> = <span style="color:#e6db74">&#34;8443&#34;</span>
</span></span></code></pre></div><p>Vous êtes désormais sur une communication chiffrée par SSL, sécurité et vie
privée respectée 😎</p>
<p><img alt="privacy" loading="lazy" src="https://media.giphy.com/media/e7yNPQmGUozyU/giphy.gif#center"></p>
<h3 id="installation-de-clients-de-synchronisation-sur-smartphones">Installation de clients de synchronisation sur Smartphones</h3>
<p>Pour l&rsquo;usage pratique jusque dans votre poche, vous pouvez installer des apps nextcloud clientes
sur Android (et Mac, non testé ?) pour uploader directement vos fichiers par les apps,
mais aussi y prendre des notes (Drive et Keep sont désormais caduques).</p>
<p>Voici les liens vers les applis Android :</p>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.nextcloud.client&amp;pli=1">Nextcloud</a></li>
<li><a href="https://play.google.com/store/apps/details?id=it.niedermann.owncloud.notes">Nextcloud Notes</a></li>
</ul>
<p>Pour synchroniser votre calendrier, vos tâches et vos contacts, utilisez Davx5</p>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=at.bitfire.davdroid&amp;referrer=utm_source%3Dhomepage">DAVX5 sur Play Store</a></li>
<li><a href="https://f-droid.org/packages/at.bitfire.davdroid/">DAVX5 sur FStore</a></li>
</ul>
<p>Pour utiliser et voir vos photos aussi efficacement que sur l&rsquo;app Google Photos:</p>
<ul>
<li><a href="https://play.google.com/store/apps/details?id=com.nkming.nc_photos">Photos</a></li>
</ul>
<p>Vous pouvez vadrouiller, toutes vos données seront sécuriées dans votre foyer
et dispo dans votre poche à portée de main.</p>
<p>Pour faire l&rsquo;installation des clients et le lien avec le serveur, suivez cette doc <a href="https://www.davx5.com/tested-with/nextcloud">Davx5</a> and
<a href="https://docs.nextcloud.com/server/latest/user_manual/fr/groupware/sync_android.html">Nextcloud</a></p>
<p>Pour m&rsquo;en servir quotidiennement, je vous l&rsquo;assure c&rsquo;est très efficace !</p>
<h3 id="mettre-en-place-une-stratégie-de-sauvegarde-sur-le-modèle-3-2-1">Mettre en place une stratégie de sauvegarde sur le modèle 3-2-1</h3>
<p><img alt="nightmare" loading="lazy" src="https://media.giphy.com/media/l2JdTwp5NFtZq0MuY/giphy.gif#center"></p>
<p>Maintenant que tout est prêt à la maison soyez d&rsquo;avoir une sauvegarde efficace,
ne prenez pas le risque de tout perdre.
Suivons la règle 3-2-1 :</p>
<ul>
<li>Une sauvegarde à <code>3</code> endroits différents</li>
<li>Sur au moins <code>2</code> volumes physiques séparés</li>
<li>Avec au moins <code>1</code> copie stockée à distance (en cas de feu, catastrophe majeure)</li>
</ul>
<p>Gardez en tête qu&rsquo;une véritable sauvegarde est une sauvegarde que l&rsquo;on peut restaurer.
Soyez sur de tester de temps à autre que vous arrivez à faire l&rsquo;exercice de restauration et que
tout se passe bien (avec un docker-compose annexe sur différents ports, très très simple).</p>
<p>Une solution très simple est d&rsquo;utiliser la solution de backup
de <code>ncp-config</code> et de synchroniser le contenu produit vers un autre disque dur.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span> sudo rsync -vlr --info<span style="color:#f92672">=</span>progress2 /media/principalstorage/ncp/backup.tar /media/storagebackup/ncp/backup.tar
</span></span></code></pre></div><p>En cas de problème avec le disque dur, l&rsquo;autre disque contient les données, que l&rsquo;on peut restaurer avec
<code>ncp-config</code>.</p>
<p>Chaque mois, j&rsquo;upload une copie sur mon stockage personnel Uptobox, cela tient lieu de stockage distant.</p>
<p>Récupérez le zip produit, prêt à l&rsquo;envoi, avec <a href="https://github.com/vic-blt/uptobox-cli">uptobox-cli</a>
<em>NB: Utilisez les nameserver Cloudflare, parfois Uptobox est bloqué par les FAI</em></p>
<p>Installez la CLI avec <code>npm install</code> et remplissez <code>config.js</code> avec vos credentials et mettez le champ premium
sur <code>1</code>.</p>
<p>Une fois fait, upload votre fichier et rendez le privé.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-sh" data-lang="sh"><span style="display:flex;"><span>node /home/pi/uptobox-cli/index.js uploadFiles backupnextcloud.zip
</span></span></code></pre></div><h2 id="conclusion">Conclusion</h2>
<p>Bravo, vous avez désormais un système complètement résilient de sauvegarde pour vos documents, photos,
votre calendrier et vos contacts !</p>
<p>En plus, avec Traefik, vous pouvez brancher n&rsquo;importe quelle autre service sur le port <code>80</code> et <code>443</code> très
facilement sur votre serveur, c&rsquo;est l&rsquo;histoire de quelques labels docker-compose.</p>
<p>Pour conclure, Grafana vous permet de visualiser instantanément l&rsquo;état de votre Raspberry Pi et de
vos services conteneurisés, ainsi à tout moment vous savez si vous remplissez trop vos disques ou si un
service sature votre mémoire RAM.</p>
<p>Pensez à mettre en place un système de sauvegarde automatique régulier, jetez un oeil
à <a href="https://doc.ubuntu-fr.org/cron">CRON jobs</a>, vous gagnez un temps fou.</p>
<p>Comme tout est automatique, assurez vous simplement que le job n&rsquo;est pas cassé et continue et essayez de temps
en temps de faire l&rsquo;exercice de restauration, au cas où quelque chose tournait mal.
Je vous encourage aussi vivement à stocker vos docker-compose sur un système de suivi de version privé
comme Github, pour stocker vos IaC.</p>
<p>N&rsquo;hésitez pas à partager en commentaire votre façon d&rsquo;organiser le stockage de données chez vous, vous
avez peut-être choisi une solution que je ne connais pas. Avec votre NextcloudPi vous pouvez aussi
super facilement partager des albums à vos proches ou leur proposer d&rsquo;héberger leurs photos.
C&rsquo;est très facile à faire !</p>
<p>Essayez les apps mobiles &ldquo;Notes&rdquo; et &ldquo;memories&rdquo;, c&rsquo;est bluffant comme c&rsquo;est efficace.
Vous pouvez tester une tonne d&rsquo;autres app Nextcloud dans le panneau d&rsquo;administration,
depuis un compte du groupe admin, jetez-y un oeil !</p>
<p>Partagez moi en commentaire vos astuces de sauvegarde, j&rsquo;ai entendu parler d&rsquo;autres systèmes (CajaOS)
mais je ne connais pas et serais ravi d&rsquo;avoir vos retours.</p>
<p>À bientôt, et merci pour votre temps à me lire.</p>
<h3 id="des-sources-et-références-annexes">Des sources et références annexes</h3>
<p>Ces liens qui m&rsquo;ont bien aidé dans la mise en place du système&hellip;</p>
<p>Un grand merci à tous les devs qui ont pu partager leurs astuces et recommendations !
❤️ à l&rsquo;équipe de Nextcloud</p>
<ul>
<li>
<p><a href="https://help.nextcloud.com/t/guide-to-getting-started-with-nextcloudpi-docker-in-2020/93396">Nextcloud Guide 2020</a></p>
</li>
<li>
<p><a href="https://help.nextcloud.com/t/how-to-configure-lets-encrypt-with-closed-ports-80-and-443/126375">Let&rsquo;s Encrypt and SSL certificates</a></p>
</li>
<li>
<p><a href="https://www.digitalocean.com/community/tutorials/how-to-acquire-a-let-s-encrypt-certificate-using-dns-validation-with-acme-dns-certbot-on-ubuntu-18-04">Wildcard certificate</a></p>
</li>
<li>
<p><a href="https://help.nextcloud.com/t/how-to-get-started-with-ncp-docker/126081">Official Guide NextcloudPI</a></p>
</li>
<li>
<p><a href="https://www.howtoforge.com/backing-up-with-rsync-and-managing-previous-versions-history#local-and-remote">Rsync guide</a></p>
</li>
<li>
<p><a href="https://framablog.org/2021/04/23/sauvegardez/">3-2-1 Model</a></p>
</li>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>
