<?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Andrei Telteu</title><link>https://telteu.ro/ro/</link><description>Recent content on Andrei Telteu</description><generator>Hugo -- gohugo.io</generator><language>ro</language><copyright>Andrei Telteu 2024</copyright><lastBuildDate>Sat, 25 Jan 2025 20:04:00 +0200</lastBuildDate><atom:link href="https://telteu.ro/ro/index.xml" rel="self" type="application/rss+xml"/><item><title>Cum să configurezi Headscale și Traefik ca să faci proxy la orice serviciu</title><link>https://telteu.ro/ro/posts/headscale-cu-traefik/</link><pubDate>Sat, 25 Jan 2025 20:04:00 +0200</pubDate><guid>https://telteu.ro/ro/posts/headscale-cu-traefik/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/headscale-cu-traefik/ -&lt;h2 id="requirements">Requirements:&lt;/h2>
&lt;ul>
&lt;li>a linux server with a public IPv4 address&lt;/li>
&lt;li>docker and docker compose installed&lt;/li>
&lt;li>a domain/subdomain with a A DNS record pointing to your IP&lt;/li>
&lt;/ul>
&lt;p>I will use &lt;strong>example.com&lt;/strong> as the domain name in this example, please replace it with your domain/subdomain.&lt;/p>
&lt;h2 id="traefik">Traefik&lt;/h2>
&lt;p>Ssh to your public server where you want to host your vpn, make a folder called &lt;code>traefik&lt;/code> with the following files:
&lt;code>mkdir traefik &amp;amp;&amp;amp; cd traefik&lt;/code>&lt;/p>
&lt;h3 id="1-an-empty-letsencrypt-folder-mkdir-letsencrypt">1. An empty &lt;code>letsencrypt&lt;/code> folder: &lt;code>mkdir letsencrypt&lt;/code>&lt;/h3>
&lt;h3 id="2-an-empty-file-touch-dynamicyml-for-future-expansion">2. An empty file &lt;code>touch dynamic.yml&lt;/code> (for future expansion)&lt;/h3>
&lt;h3 id="3-the-static-config-nano-staticyml">3. The static config: &lt;code>nano static.yml&lt;/code>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">api&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">insecure&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">dashboard&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">providers&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">docker&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">exposedByDefault&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">entryPoints&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">web&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">address&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;:80&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">http2&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">maxConcurrentStreams&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">250&lt;/span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># fix for network error on the proxy to my immich instance&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">http3&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">advertisedPort&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">443&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># http:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># redirections:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># entryPoint:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># to: websecure&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># scheme: https&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">forwardedHeaders&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">trustedIPs&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">10.0.0.0&lt;/span>/8&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">172.16.0.0&lt;/span>/12&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">192.168.0.0&lt;/span>/16&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- fc00::/7&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">proxyProtocol&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">trustedIPs&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">10.0.0.0&lt;/span>/8&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">172.16.0.0&lt;/span>/12&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">192.168.0.0&lt;/span>/16&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">32&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- fc00::/7&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">33&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">websecure&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">34&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">address&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;:443&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">35&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">http2&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">36&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">maxConcurrentStreams&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">250&lt;/span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># fix for network error on the proxy to my immich instance&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">37&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">http3&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">38&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">advertisedPort&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">443&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">39&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">forwardedHeaders&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">40&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">trustedIPs&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">41&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">10.0.0.0&lt;/span>/8&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">42&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">172.16.0.0&lt;/span>/12&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">43&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">192.168.0.0&lt;/span>/16&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">44&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- fc00::/7&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">45&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">proxyProtocol&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">46&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">trustedIPs&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">47&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">10.0.0.0&lt;/span>/8&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">48&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">172.16.0.0&lt;/span>/12&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">49&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">192.168.0.0&lt;/span>/16&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">50&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- fc00::/7&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">51&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">52&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">certificatesResolvers&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">53&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">myresolver&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">54&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">acme&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">55&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">email&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;your-email-goes-here@tutorial.example&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">56&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">storage&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;/letsencrypt/acme.json&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">57&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">httpChallenge&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">58&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">entryPoint&lt;/span>:&lt;span style="color:#666"> &lt;/span>web&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Replace &lt;code>your-email-goes-here@tutorial.example&lt;/code> with your email address. Let&amp;rsquo;s Encrypt send you notifications when your ssl certificate expires.&lt;/p>
&lt;/blockquote>
&lt;h3 id="4-the-docker-compose-config-nano-composeyml">4. The docker compose config: &lt;code>nano compose.yml&lt;/code>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">services&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">traefik&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">image&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;traefik:v3.2&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">container_name&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;traefik&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">restart&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;always&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">ports&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;80:80&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;443:443&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">networks&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- pub&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;./letsencrypt:/letsencrypt&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;/var/run/docker.sock:/var/run/docker.sock:ro&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;./static.yml:/etc/traefik/traefik.yml:ro&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;./dynamic.yml:/etc/traefik/dynamic.yaml:ro&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">labels&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.dashboard.rule=Host(`example.com`) &amp;amp;&amp;amp; (PathPrefix(`/dashboard`) || PathPrefix(`/api/overview`) || PathPrefix(`/api/version`) || PathPrefix(`/api/http`) || PathPrefix(`/api/entrypoints`) || PathPrefix(`/api/tcp`) || PathPrefix(`/api/udp`))&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.dashboard.entrypoints=websecure&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.dashboard.tls.certresolver=myresolver&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.dashboard.service=api@internal&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># # if you want to password protect your traefik dashboard uncomment the following and change the user:pass&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic">#- &amp;#34;traefik.http.routers.dashboard.middlewares=auth&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic">#- &amp;#34;traefik.http.middlewares.auth.basicauth.users=&amp;#34; # to create user and pass: bash -c &amp;#39;echo $(htpasswd -nB admin) | sed -e s/\\$/\\$\\$/g&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">networks&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">pub&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">external&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Create the &lt;code>pub&lt;/code> network first using the command &lt;code>docker network create pub&lt;/code>&lt;/p>
&lt;p>Now we can start the traefik instance: &lt;code>docker compose up -d&lt;/code>&lt;/p>
&lt;h2 id="headscale">HeadScale&lt;/h2>
&lt;p>Let&amp;rsquo;s make a separate folder for headscale: &lt;code>cd .. &amp;amp;&amp;amp; mkdir headscale&lt;/code>&lt;/p>
&lt;h3 id="1-2-empty-folders-mkdir-data--mkdir-tailscale-client">1. 2 empty folders: &lt;code>mkdir data &amp;amp;&amp;amp; mkdir tailscale-client&lt;/code>&lt;/h3>
&lt;h3 id="2-the-headscale-config-nano-configyml">2. The headscale config: &lt;code>nano config.yml&lt;/code>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#447fcf;text-decoration:underline">---&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># The url clients will connect to.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">server_url&lt;/span>:&lt;span style="color:#666"> &lt;/span>https://example.com&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Address to listen to / bind to on the server&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">listen_addr&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">0.0.0.0&lt;/span>:&lt;span style="color:#3677a9">8080&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Address to listen to /metrics, you may want&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">metrics_listen_addr&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">127.0.0.1&lt;/span>:&lt;span style="color:#3677a9">9090&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 10&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 11&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Address to listen for gRPC.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 12&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">grpc_listen_addr&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">127.0.0.1&lt;/span>:&lt;span style="color:#3677a9">50443&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 13&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 14&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Allow the gRPC admin interface to run in INSECURE mode.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 15&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">grpc_allow_insecure&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 16&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 17&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">noise&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 18&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># The Noise private key is used to encrypt the traffic&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 19&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">private_key_path&lt;/span>:&lt;span style="color:#666"> &lt;/span>/var/lib/headscale/noise_private.key&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 20&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 21&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># List of IP prefixes to allocate tailaddresses from.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 22&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Each prefix consists of either an IPv4 or IPv6 address,&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 23&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">prefixes&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 24&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">v6&lt;/span>:&lt;span style="color:#666"> &lt;/span>fd7a:115c:a1e0::/48&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 25&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">v4&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">100.64.0.0&lt;/span>/10&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 26&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Strategy used for allocation of IPs to nodes, available options:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 27&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - sequential (default): assigns the next free IP from the previous given IP.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 28&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - random: assigns the next free IP from a pseudo-random IP generator (crypto/rand).&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 29&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">allocation&lt;/span>:&lt;span style="color:#666"> &lt;/span>sequential&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 30&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 31&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># DERP is a relay system that Tailscale uses when a direct connection cannot be established.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 32&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">derp&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 33&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">server&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 34&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">enabled&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 35&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Region ID to use for the embedded DERP server.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 36&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">region_id&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">999&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 37&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">region_code&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;headscale&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 38&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">region_name&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;Headscale Embedded DERP&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 39&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Listens over UDP at the configured address for STUN connections - to help with NAT traversal.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 40&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">stun_listen_addr&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;0.0.0.0:3478&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 41&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Private key used to encrypt the traffic between headscale DERP and Tailscale clients.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 42&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">private_key_path&lt;/span>:&lt;span style="color:#666"> &lt;/span>/var/lib/headscale/derp_server_private.key&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 43&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># This flag can be used, so the DERP map entry for the embedded DERP server is not written automatically,&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 44&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">automatically_add_embedded_derp_region&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 45&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># For better connection stability (especially when using an Exit-Node and DNS is not working),&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 46&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">ipv4&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">1.2.3.4&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 47&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">ipv6&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">2001&lt;/span>:db8::1&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 48&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># List of externally available DERP maps encoded in JSON&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 49&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">urls&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 50&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- https://controlplane.tailscale.com/derpmap/default&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 51&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Locally available DERP map files encoded in YAML&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 52&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">paths&lt;/span>:&lt;span style="color:#666"> &lt;/span>[]&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 53&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># If enabled, a worker will be set up to periodically refresh the given sources and update the derpmap&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 54&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">auto_update_enabled&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 55&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># How often should we check for DERP updates?&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 56&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">update_frequency&lt;/span>:&lt;span style="color:#666"> &lt;/span>24h&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 57&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Disables the automatic check for headscale updates on startup&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 58&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">disable_check_updates&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 59&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Time before an inactive ephemeral node is deleted?&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 60&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">ephemeral_node_inactivity_timeout&lt;/span>:&lt;span style="color:#666"> &lt;/span>30m&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 61&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">database&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 62&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">type&lt;/span>:&lt;span style="color:#666"> &lt;/span>sqlite&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 63&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Enable debug mode. This setting requires the log.level to be set to &amp;#34;debug&amp;#34; or &amp;#34;trace&amp;#34;.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 64&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">debug&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 65&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">gorm&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 66&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">prepare_stmt&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 67&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">parameterized_queries&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 68&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">skip_err_record_not_found&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 69&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">slow_threshold&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">1000&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 70&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">sqlite&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 71&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">path&lt;/span>:&lt;span style="color:#666"> &lt;/span>/var/lib/headscale/db.sqlite&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 72&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">write_ahead_log&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 73&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 74&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic">### TLS configuration Let&amp;#39;s encrypt / ACME&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 75&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">acme_url&lt;/span>:&lt;span style="color:#666"> &lt;/span>https://acme-v02.api.letsencrypt.org/directory&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 76&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">acme_email&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;your-email-goes-here@tutorial.example&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 77&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">tls_letsencrypt_hostname&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 78&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Path to store certificates and metadata needed by letsencrypt&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 79&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">tls_letsencrypt_cache_dir&lt;/span>:&lt;span style="color:#666"> &lt;/span>/var/lib/headscale/cache&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 80&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 81&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Type of ACME challenge to use, currently supported types: HTTP-01 or TLS-ALPN-01&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 82&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">tls_letsencrypt_challenge_type&lt;/span>:&lt;span style="color:#666"> &lt;/span>HTTP-01&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 83&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># When HTTP-01 challenge is chosen, letsencrypt must set up a verification endpoint, and it will be listening on:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 84&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">tls_letsencrypt_listen&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;:http&amp;#34;&lt;/span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># :http = port 80&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 85&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">tls_cert_path&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 86&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">tls_key_path&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 87&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 88&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">log&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 89&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">format&lt;/span>:&lt;span style="color:#666"> &lt;/span>text&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># text or json&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 90&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">level&lt;/span>:&lt;span style="color:#666"> &lt;/span>info&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 91&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 92&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">policy&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 93&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">mode&lt;/span>:&lt;span style="color:#666"> &lt;/span>file&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 94&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">path&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 95&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 96&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">dns&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 97&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">magic_dns&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 98&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Defines the base domain to create the hostnames for MagicDNS.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 99&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">base_domain&lt;/span>:&lt;span style="color:#666"> &lt;/span>head.local&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">100&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">nameservers&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">101&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">global&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">102&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">1.1.1.1&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">103&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">1.0.0.1&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">104&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">2606&lt;/span>:&lt;span style="color:#3677a9">4700&lt;/span>:&lt;span style="color:#3677a9">4700&lt;/span>::&lt;span style="color:#3677a9">1111&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">105&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#3677a9">2606&lt;/span>:&lt;span style="color:#3677a9">4700&lt;/span>:&lt;span style="color:#3677a9">4700&lt;/span>::&lt;span style="color:#3677a9">1001&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">106&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">split&lt;/span>:&lt;span style="color:#666"> &lt;/span>{}&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">107&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">search_domains&lt;/span>:&lt;span style="color:#666"> &lt;/span>[]&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">108&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Extra DNS records&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">109&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">extra_records&lt;/span>:&lt;span style="color:#666"> &lt;/span>[]&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">110&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">111&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">unix_socket&lt;/span>:&lt;span style="color:#666"> &lt;/span>/var/run/headscale/headscale.sock&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">112&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">unix_socket_permission&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;0770&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">113&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">logtail&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">114&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># Enable logtail for this headscales clients.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">115&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">enabled&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">116&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#999;font-style:italic"># Enabling this option makes devices prefer a random port for WireGuard traffic over the default static port 41641.&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">117&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">randomize_client_port&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">false&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>It&amp;rsquo;s the default config, I removed some comments and replaced &lt;code>server_url&lt;/code>, &lt;code>acme_email&lt;/code> and the &lt;code>base_domain&lt;/code> from dns section. This last config is the Magic DNS that headscale uses to create a DNS entry for every device you connect to your tailscale vpn.&lt;/p>
&lt;/blockquote>
&lt;h3 id="3-the-docker-compose-config-nano-composeyml">3. The docker compose config: &lt;code>nano compose.yml&lt;/code>&lt;/h3>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yaml" data-lang="yaml">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">services&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">headscale&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">container_name&lt;/span>:&lt;span style="color:#666"> &lt;/span>headscale&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">image&lt;/span>:&lt;span style="color:#666"> &lt;/span>headscale/headscale&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">command&lt;/span>:&lt;span style="color:#666"> &lt;/span>serve&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">restart&lt;/span>:&lt;span style="color:#666"> &lt;/span>always&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">ports&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;8080:8080&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">networks&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- pub&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;./data:/var/lib/headscale&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;./config.yml:/etc/headscale/config.yaml&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">cap_add&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- NET_ADMIN&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- SYS_MODULE&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">sysctls&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- net.ipv4.ip_forward=1&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- net.ipv4.conf.all.src_valid_mark=1&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">labels&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.headscale.rule=Host(`example.com`)&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.headscale.entrypoints=websecure&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.headscale.tls.certresolver=myresolver&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.services.headscale.loadbalancer.server.port=8080&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">headplane&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">container_name&lt;/span>:&lt;span style="color:#666"> &lt;/span>headplane&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">image&lt;/span>:&lt;span style="color:#666"> &lt;/span>ghcr.io/tale/headplane:0.3.2&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">restart&lt;/span>:&lt;span style="color:#666"> &lt;/span>unless-stopped&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">32&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">ports&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">33&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#39;3000:3000&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">34&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">networks&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">35&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- pub&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">36&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">depends_on&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">37&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- headscale&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">38&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">volumes&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">39&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;./config.yml:/etc/headscale/config.yaml&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">40&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">environment&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">41&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">HEADSCALE_URL&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;http://headscale:8080&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">42&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">API_KEY&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">43&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">CONFIG_FILE&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;/etc/headscale/config.yaml&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">44&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">COOKIE_SECRET&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;put-some-random-string-here-32j564b64kl6n34lk&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">45&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">DISABLE_API_KEY_LOGIN&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;true&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">46&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">COOKIE_SECURE&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;false&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">47&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">HOST&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;0.0.0.0&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">48&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">PORT&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;3000&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">49&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">labels&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">50&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.enable=true&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">51&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.headplane.rule=Host(`example.com`) &amp;amp;&amp;amp; PathPrefix(`/admin`)&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">52&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.headplane.entrypoints=websecure&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">53&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.routers.headplane.tls.certresolver=myresolver&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">54&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#34;traefik.http.services.headplane.loadbalancer.server.port=3000&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">55&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic">#- &amp;#34;traefik.http.routers.headplane.middlewares=auth&amp;#34; # uncomment this only if you generated a password in traefik step 4&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">56&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">57&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># client:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">58&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># container_name: tailscale-client&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">59&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># image: tailscale/tailscale&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">60&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># restart: unless-stopped&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">61&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># environment:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">62&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - &amp;#34;TS_AUTHKEY=&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">63&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - &amp;#34;TS_STATE_DIR=/var/lib/tailscale&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">64&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - &amp;#34;TS_USERSPACE=false&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">65&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - &amp;#34;TS_EXTRA_ARGS=--login-server=https://example.com --advertise-exit-node --hostname=server-client --shields-up=false&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">66&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># networks:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">67&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - pub&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">68&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># volumes:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">69&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - &amp;#34;./tailscale-client:/var/lib/tailscale&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">70&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - &amp;#34;/dev/net/tun:/dev/net/tun&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">71&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># cap_add:&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">72&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - net_admin&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">73&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># - sys_module&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">74&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">75&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">networks&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">76&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">pub&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">77&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">external&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">true&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>We can start headscale now: &lt;code>docker compose up -d&lt;/code>&lt;/p>
- https://telteu.ro/ro/posts/headscale-cu-traefik/ - Andrei Telteu 2024</description></item><item><title>MiniPC rack Partea 1: pc și carcasă</title><link>https://telteu.ro/ro/posts/minipc-rack-partea-1/</link><pubDate>Tue, 19 Nov 2024 00:16:30 +0000</pubDate><guid>https://telteu.ro/ro/posts/minipc-rack-partea-1/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/minipc-rack-partea-1/ -&lt;h2 id="hardware">Hardware&lt;/h2>
&lt;p>Căutam să încep un homelab cu un mini pc și în sfârșit am găsit o oferta bună second hand:&lt;/p>
&lt;p>HP EliteDesk 705 G4 cu AMD Ryzen 5 2400GE, &lt;strong>16GB&lt;/strong> RAM DDR4 2666 Mhz (sodimm/laptop), cu sursă de 90W pentru doar &lt;strong>450 lei (~90€ / ~95$)&lt;/strong>.&lt;/p>
&lt;p>Oferă un balanț bun între preț și performanță pentru că procesorul are &lt;strong>4 nuclee 8 thread-uri la 3.8 GHz&lt;/strong>. Performanța procesorului este cel mai important lucru pentru mine.
&lt;br>Am cumpărat unu ca să îl testez, apoi am cumpărat încă 2:&lt;/p>
&lt;p>
&lt;a href="https://telteu.ro/posts/minipc-rack-part-1/minipcs-horizontal.b398660b22bde58bceace0fd595c4de2.jpg" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/minipc-rack-part-1/minipcs-horizontal_hu2609188977948449556.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/minipc-rack-part-1/minipcs-horizontal.b398660b22bde58bceace0fd595c4de2.jpg" alt="minipcs" loading="lazy" height="930" width="3961" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>Apoi am găsit altă ofertă pentru SSD TeamGroup 512 GB M.2 NVMe pentru doar &lt;strong>120 lei (~24€ / ~25$)&lt;/strong> (nou/sigilat).&lt;/p>
&lt;p>
&lt;a href="https://telteu.ro/posts/minipc-rack-part-1/ssds.1fe86705afcbc2c58ecb6ae4aa1c75fe.jpeg" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/minipc-rack-part-1/ssds_hu7805926632893103691.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/minipc-rack-part-1/ssds.1fe86705afcbc2c58ecb6ae4aa1c75fe.jpeg" alt="ssd image" loading="lazy" height="933" width="1874" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>&lt;strong>Perfect !&lt;/strong>&lt;/p>
&lt;h2 id="software">Software&lt;/h2>
&lt;p>Am început să caut un hypervisor bun, gratuit și ușor de configurare și de folosit.
&lt;br/>Am încercat
&lt;a href="https://www.proxmox.com/" target="_blank" rel="noopener">Proxmox&lt;/a>
dar apoi am găsit
&lt;a href="https://xcp-ng.org/" target="_blank" rel="noopener">XCP-NG&lt;/a>
cu
&lt;a href="https://xen-orchestra.com/" target="_blank" rel="noopener">XEN Orchestra&lt;/a>
pe canalul de youtube
&lt;a href="https://youtube.com/playlist?list=PLjGQNuuUzvmsrt8VrocFvN2DaZlwk8sgz&amp;amp;si=p8WJCt4I9TRDOrgO" target="_blank" rel="noopener">Lawrence Systems&lt;/a>
și căutarea s-a încheiat. Are multe funcții care m-au convins că este cea mai bună alegere pentru mine:&lt;/p>
&lt;ul>
&lt;li>Gratis și open source&lt;/li>
&lt;li>Interfață ușor de folosit și oarecum similară cu interfața altor provideri de VPS&lt;/li>
&lt;li>Funcția de replicare și migrare a unui VM pe alt host&lt;/li>
&lt;li>Snapshot-uri&lt;/li>
&lt;/ul>
&lt;h2 id="carcasă-printată-3d">Carcasă printată 3D&lt;/h2>
&lt;p>După ceva timp am găsit o ofertă bună pentru o imprimantă 3D și am început să învăț cum să printez, optimizez setări, apoi am învățat cum să modelez câteva componente simple.&lt;/p>
&lt;p>Am început să caut pe
&lt;a href="https://www.yeggi.com/" target="_blank" rel="noopener">yeggi.com&lt;/a>
(motor de căutare pentru modele 3D) pentru modele de carcase compatibile cu modelul meu și l-am găsit pe cel mai bun:&lt;/p>
&lt;p>
&lt;a href="https://www.printables.com/model/827617-hp-mini-staggered-rack-mount" target="_blank" rel="noopener">&amp;ldquo;HP Mini Staggered Rack Mount&amp;rdquo; de @dsluo_362876&lt;/a>
&lt;/p>
&lt;p>
&lt;a href="https://telteu.ro/posts/minipc-rack-part-1/minipc-case-model.69a466ada23ca1f6a9bb70391120309a.jpg" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/minipc-rack-part-1/minipc-case-model_hu17320638519990072788.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/minipc-rack-part-1/minipc-case-model.69a466ada23ca1f6a9bb70391120309a.jpg" alt="imagine model carcasă minipc" loading="lazy" height="1357" width="2432" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>Idea e perfectă: încorporează MiniPC-ul și sursa lui în aceeași carcasă compactă. Execuția e perfectă ! Modelul este foarte bine gândit.&lt;/p>
&lt;p>O singură problemă: Imprimanta mea BambuLab A1 Mini are o dimensiune mică de printare de 180x180x180 mm și a trebuit să rotesc modelul la 45 de grade și să șterg partea groasă de sus a casei.&lt;/p>
&lt;p>
&lt;a href="https://telteu.ro/posts/minipc-rack-part-1/model-too-big.f7d9a2a5a92c9651436d1911a94a0700.png" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/minipc-rack-part-1/model-too-big_hu5611133157586873853.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/minipc-rack-part-1/model-too-big.f7d9a2a5a92c9651436d1911a94a0700.png" alt="modelul prea mare rotit" loading="lazy" height="721" width="1220" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>&lt;strong>Problemă rezolvată&lt;/strong> ! Încape la milimetru pe imprimantă ! Să dăm drumul la printare !&lt;/p>
&lt;p>Am oprit printarea după 2-3 cm ca să verific că se potriveste bine modelul și să nu îl printez degeaba dacă nu se potrivește.
&lt;br/>Este o practică &lt;strong>foarte bună&lt;/strong> și îți recomand să faci la fel !
&lt;br/>Bine că l-am oprit să verific că mi-am dat seama că &lt;strong>sursa mea este mai mare&lt;/strong> decât cea a autorului în toate dimensiunile. Autorul a scris dimensiunile sursei în descrierea modelului dar nu am citit.&lt;/p>
&lt;p>Acum sunt blocat. Trebuie să modific modelul ca să încapă sursa mea de 90W dar nu știu cum să îl modific și nu am fișierele sursă, am doar fișierele STL mesh.&lt;/p>
&lt;p>&lt;strong>Va urma&amp;hellip;&lt;/strong> citește partea 2&lt;/p>
- https://telteu.ro/ro/posts/minipc-rack-partea-1/ - Andrei Telteu 2024</description></item><item><title>Cum să controlezi ventilatorul Noctua din Raspberry Pi</title><link>https://telteu.ro/ro/posts/cum-sa-controlezi-ventilator-noctua-din-raspberry-pi/</link><pubDate>Mon, 18 Nov 2024 00:14:52 +0200</pubDate><guid>https://telteu.ro/ro/posts/cum-sa-controlezi-ventilator-noctua-din-raspberry-pi/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/cum-sa-controlezi-ventilator-noctua-din-raspberry-pi/ -&lt;p>
&lt;a href="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/noctua-pwm-pi-ezgif.com-optimize.e400dfe08b35d68aee56e4e16fae8785.gif" class="fancybox">
&lt;picture>
&lt;img class="img-fluid" src="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/noctua-pwm-pi-ezgif.com-optimize.e400dfe08b35d68aee56e4e16fae8785.gif" alt="ventilator Noctua NF-A20 PWM" loading="lazy" height="895" width="1711" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>Îmi construiesc
&lt;a href="https://telteu.ro/ro/posts/minipc-rack-partea-1/">un homelab&lt;/a>
și am nevoie să controlez ventilatorul
&lt;a href="https://noctua.at/en/nf-a20-pwm-chromax-black-swap" target="_blank" rel="noopener">Noctua NF-A20 PWM chromax.black.swap 200x200mm&lt;/a>
folosind Raspberry Pi. Așa am reușit să fac asta.&lt;/p>
&lt;h2 id="componente-necesare">Componente necesare:&lt;/h2>
&lt;ul>
&lt;li>Un Raspberry Pi&lt;/li>
&lt;li>Ventilatorul Noctua NF-A20 PWM (ar trebui să funcționeze la fel și cu alte ventilatoare de 12V)&lt;/li>
&lt;li>Un multimetru&lt;/li>
&lt;li>
&lt;a href="https://www.optimusdigital.ro/ro/surse-ridicatoare-reglabile/12534-sursa-ridicatoare-lm2577-dc-dc.html" target="_blank" rel="noopener">Sursă Ridicătoare LM2577 DC-DC&lt;/a>
&lt;/li>
&lt;li>
&lt;a href="https://www.optimusdigital.ro/ro/componente-electronice-tranzistoare/935-tranzistor-s9013-npn-50-pcs-set.html" target="_blank" rel="noopener">Transistor NPN&lt;/a>
&lt;/li>
&lt;li>Rezistență de 1K Ohm&lt;/li>
&lt;/ul>
&lt;h2 id="diagramă">Diagramă:&lt;/h2>
&lt;p>
&lt;a href="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/diagram.6b98eb62e389136c2a1f5c245243f014.png" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/diagram_hu240544990833317495.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/diagram.6b98eb62e389136c2a1f5c245243f014.png" alt="imagine diagramă" loading="lazy" height="1824" width="1883" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;h2 id="să-începem-de-la-pi">Să începem de la Pi:&lt;/h2>
&lt;p>1- Conectează un fir de la pin-ul GPIO 16, sau orice pin simplu, la rezistența de 1k, apoi conectează celălalt capăt la tranzistor pe pin-ul din mijloc.&lt;/p>
&lt;p>2- Un fir de la pin-ul din dreapta al tranzistorului la orice pin Ground sau minus/negativ al Pi-ului. Fața tranzistorului este cea plată.&lt;/p>
&lt;p>3- Un fir de la pin-ul din dreapta al tranzistorului la conectorul negativ/minus de 5V marcat &amp;ldquo;IN-&amp;rdquo; al sursei ridicătoare.&lt;/p>
&lt;p>4- Un fir de la orice pin de 5V al Pi-ului (le găsești în parea de sus, dreapta) la conectorul pozitiv/plus de 5V marcat &amp;ldquo;IN+&amp;rdquo; al sursei ridicătoare.&lt;/p>
&lt;p>5- &lt;strong>Important&lt;/strong>: ajustează sursa la 12V sau mai puțin.
&lt;br/>NU conecta ventilatorul acum pentru că îl poți arde instant dacă îl conectezi la o tensiune mai mare decat 12V.
&lt;br/>    A- Ca să pornești sursa ridicătoare temporar conectează un fir de la un pin ground/minus/negativ al Pi-ului direct la teminalul marcat &amp;ldquo;IN-&amp;rdquo; al sursei SAU poți executa codul python din urmatoarea secțiune. Trebuie doar să execuți &lt;code>speed(fan, 100) / time.sleep(180)&lt;/code>.
&lt;br/>    B- Conectează multimetru la conectorii marcați &amp;ldquo;OUT+&amp;rdquo; și &amp;ldquo;OUT-&amp;rdquo; apoi selectează măsurarea voltajului la multimetru (de obicei marcat cu &amp;ldquo;2V&amp;rdquo;).
&lt;br/>    C- Pe sursă învârte șurubul mic și galben de pe componenta albastră până când multimetrul arată 12V sau puțin mai mic, ca să fim siguri ca nu se strică. Eu l-am lăsat pe al meu la 11.5V.&lt;/p>
&lt;p>
&lt;a href="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/power-converter-nob.09666e2f6a0cb904a3d9dbb80a0fa25b.png" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/power-converter-nob_hu2864229298055400022.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/power-converter-nob.09666e2f6a0cb904a3d9dbb80a0fa25b.png" alt="șurubel de ajustare tensiune sursă" loading="lazy" height="255" width="999" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>    D- Când ești gata deconectează multimetrul și firul conectat la ground, sau oprește programul python.&lt;/p>
&lt;p>Am găsit schema pin-urilor ventilatorului Noctua aici:
&lt;a href="https://faqs.noctua.at/en/support/solutions/articles/101000081757-what-pin-configuration-do-noctua-fans-use-" target="_blank" rel="noopener">https://faqs.noctua.at/en/support/solutions/articles/101000081757-what-pin-configuration-do-noctua-fans-use-&lt;/a>
&lt;a href="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/noctua-pinout.db5471cf55cd488e3de87f4205f2f44e.png" class="fancybox">
&lt;picture>
&lt;source srcset="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/noctua-pinout_hu15230658805204666452.webp" type="image/webp" />
&lt;img class="img-fluid" src="https://telteu.ro/posts/how-to-control-a-noctua-nf-a20-pwm-fan-from-raspberry-pi/noctua-pinout.db5471cf55cd488e3de87f4205f2f44e.png" alt="schemă pin-uri noctua" loading="lazy" height="160" width="1037" />
&lt;/picture>
&lt;/a>&lt;/p>
&lt;p>5- Un fir de la conectorul marcat &amp;ldquo;OUT-&amp;rdquo; (12V negativ) al sursei la pin-ul 1 al conectorului noctua.&lt;/p>
&lt;p>6- Un fir de la conectorul marcat &amp;ldquo;OUT+&amp;rdquo; (12V pozitiv) al sursei la pin-ul 2 al conectorului noctua.&lt;/p>
&lt;p>5- Un fir de la pin-ul 4 al conectorului noctua la pin-ul GPIO 12 al Pi-ului.
&lt;a href="https://pinout.xyz/pinout/pin32_gpio12/" target="_blank" rel="noopener">Acest pin are capabilitate PWM&lt;/a>
.&lt;/p>
&lt;h2 id="codul-python">Codul python:&lt;/h2>
&lt;p>Am folosit următorul cod din acest
&lt;a href="https://www.the-diy-life.com/connecting-a-pwm-fan-to-a-raspberry-pi/" target="_blank" rel="noopener">tutorial publicat pe the-diy-life.com de Michael Klements&lt;/a>
(
&lt;a href="https://github.com/mklements/PWMFanControl/blob/main/FanProportional.py" target="_blank" rel="noopener">cod sursă&lt;/a>
), și l-am modificat ca să folosească tranzistorul ca să oprească ventilatorul pentru că ventilatorul nu poate scădea viteza până la 0 RPM.
&lt;a href="https://noctua.at/en/nf-a20-pwm-chromax-black-swap/specification" target="_blank" rel="noopener">Viteza minimă de rotație este de 20%&lt;/a>
(350RPM).&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-python" data-lang="python">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">#!/usr/bin/env python3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> &lt;span style="color:#447fcf;text-decoration:underline">RPi.GPIO&lt;/span> &lt;span style="color:#6ab825;font-weight:bold">as&lt;/span> &lt;span style="color:#447fcf;text-decoration:underline">GPIO&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> &lt;span style="color:#447fcf;text-decoration:underline">time&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> &lt;span style="color:#447fcf;text-decoration:underline">signal&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> &lt;span style="color:#447fcf;text-decoration:underline">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic"># Ventilatorul Noctua PWM are nevoie de 25 kHz (kilo!), vezi pagina 6 de pe:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic"># https://noctua.at/pub/media/wysiwyg/Noctua_PWM_specifications_white_paper.pdf&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>PWM_FREQ = &lt;span style="color:#3677a9">25&lt;/span> &lt;span style="color:#999;font-style:italic"># [Hz] frecvență PWM&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>FAN_PIN = &lt;span style="color:#3677a9">12&lt;/span> &lt;span style="color:#999;font-style:italic"># pin BCM pentru control ventilator PWM&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>TRAN_PIN = &lt;span style="color:#3677a9">16&lt;/span> &lt;span style="color:#999;font-style:italic"># NPN Transistor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">def&lt;/span> &lt;span style="color:#447fcf">speed&lt;/span>(fan, percent):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span> &lt;span style="color:#24909d">print&lt;/span>(&lt;span style="color:#ed9d13">&amp;#34;set fan to&amp;#34;&lt;/span>, percent)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> (percent &amp;lt; &lt;span style="color:#3677a9">20&lt;/span>):
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span> GPIO.output(TRAN_PIN, &lt;span style="color:#6ab825;font-weight:bold">False&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span> fan.ChangeDutyCycle(&lt;span style="color:#3677a9">20&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">else&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span> GPIO.output(TRAN_PIN, &lt;span style="color:#6ab825;font-weight:bold">True&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span> fan.ChangeDutyCycle(percent)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">try&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span> signal.signal(signal.SIGTERM, &lt;span style="color:#6ab825;font-weight:bold">lambda&lt;/span> *args: sys.exit(&lt;span style="color:#3677a9">0&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span> GPIO.setwarnings(&lt;span style="color:#6ab825;font-weight:bold">True&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span> GPIO.setmode(GPIO.BCM)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span> GPIO.setup(TRAN_PIN, GPIO.OUT)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span> GPIO.setup(FAN_PIN, GPIO.OUT, initial=GPIO.LOW)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span> fan = GPIO.PWM(FAN_PIN, PWM_FREQ)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic"># facem cateva cicluri pentru testare&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span> speed(fan, &lt;span style="color:#3677a9">100&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">32&lt;/span>&lt;span> time.sleep(&lt;span style="color:#3677a9">30&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">33&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">34&lt;/span>&lt;span> speed(fan, &lt;span style="color:#3677a9">50&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">35&lt;/span>&lt;span> time.sleep(&lt;span style="color:#3677a9">30&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">36&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">37&lt;/span>&lt;span> speed(fan, &lt;span style="color:#3677a9">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">38&lt;/span>&lt;span> time.sleep(&lt;span style="color:#3677a9">30&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">39&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">40&lt;/span>&lt;span> speed(fan, &lt;span style="color:#3677a9">20&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">41&lt;/span>&lt;span> time.sleep(&lt;span style="color:#3677a9">30&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">42&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">43&lt;/span>&lt;span> speed(fan, &lt;span style="color:#3677a9">70&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">44&lt;/span>&lt;span> time.sleep(&lt;span style="color:#3677a9">30&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">45&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">46&lt;/span>&lt;span> speed(fan, &lt;span style="color:#3677a9">100&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">47&lt;/span>&lt;span> time.sleep(&lt;span style="color:#3677a9">30&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">48&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">49&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">except&lt;/span> &lt;span style="color:#bbb">KeyboardInterrupt&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">50&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">pass&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">51&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">52&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">finally&lt;/span>:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">53&lt;/span>&lt;span> GPIO.cleanup()
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Finalizat!&lt;/p>
- https://telteu.ro/ro/posts/cum-sa-controlezi-ventilator-noctua-din-raspberry-pi/ - Andrei Telteu 2024</description></item><item><title>Cum să folosești Templ în Goravel</title><link>https://telteu.ro/ro/posts/cum-sa-folosesti-templ-in-goravel/</link><pubDate>Mon, 18 Nov 2024 00:12:52 +0200</pubDate><guid>https://telteu.ro/ro/posts/cum-sa-folosesti-templ-in-goravel/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/cum-sa-folosesti-templ-in-goravel/ -&lt;h2 id="instaleaza-framework-ul-si-pluginuri">Instaleaza framework-ul si pluginuri&lt;/h2>
&lt;p>Primul pas este să instalăm
&lt;a href="https://goravel.dev/" target="_blank" rel="noopener">Goravel&lt;/a>
. Este un framework complet cu foarte multe funcții scris în Go pentru programatorii familiari cu framework-ul Laravel.&lt;/p>
&lt;p>Pașii din documentația
&lt;a href="https://github.com/goravel/docs/blob/master/getting-started/installation.md" target="_blank" rel="noopener">Getting started&lt;/a>
:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>// Descarcă framework-ul
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>git clone https://github.com/goravel/goravel.git
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>rm -rf goravel/.git*
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>// Instalează dependențele
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#24909d">cd&lt;/span> goravel
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>go mod tidy
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>// Crează fișierul .env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>cp .env.example .env
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>// Generează cheia aplicației
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>go run . artisan key:generate
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Acum instalează
&lt;a href="https://templ.guide/quick-start/installation" target="_blank" rel="noopener">templ&lt;/a>
pentru randare html și
&lt;a href="https://github.com/cosmtrek/air?tab=readme-ov-file#installation" target="_blank" rel="noopener">air&lt;/a>
pentru hot reloading:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>go install github.com/a-h/templ/cmd/templ@latest
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span>go install github.com/cosmtrek/air@latest
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="configurare-structură-front-end">Configurare structură front-end&lt;/h2>
&lt;p>(încă în lucru - voi actualiza tutorialul cu variabile globale și script push)&lt;/p>
&lt;p>• În fișierul &lt;code>/.gitignore&lt;/code> adaugă această linie: &lt;code>*_templ.go&lt;/code>&lt;/p>
&lt;p>• Șterge fișierul &lt;code>resources/views/welcome.tmpl&lt;/code>&lt;/p>
&lt;p>• Creează 2 foldere în &lt;code>resources/views/&lt;/code> cu numele &lt;code>home&lt;/code> și &lt;code>parts&lt;/code>&lt;/p>
&lt;p>• În folderul &lt;code>resources/views/parts/&lt;/code> creează 3 fișiere:&lt;/p>
&lt;p>   1. &lt;code>resources/views/parts/header.templ&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> parts
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span>templ &lt;span style="color:#447fcf">Header&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">4&lt;/span>&lt;span> &amp;lt;h1&amp;gt;Header&amp;lt;/h1&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">5&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>   2. &lt;code>resources/views/parts/footer.templ&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> parts
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span>templ &lt;span style="color:#447fcf">Footer&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">4&lt;/span>&lt;span> &amp;lt;footer&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">5&lt;/span>&lt;span> &amp;lt;p&amp;gt;&amp;amp;copy; &lt;span style="color:#3677a9">2024&lt;/span> MyProject&amp;lt;/p&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">6&lt;/span>&lt;span> &amp;lt;/footer&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">7&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>   3. &lt;code>resources/views/parts/template.templ&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> parts
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>templ &lt;span style="color:#447fcf">Template&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span> &amp;lt;!DOCTYPE html&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span> &amp;lt;html&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span> &amp;lt;head&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span> &amp;lt;title&amp;gt;My Page&amp;lt;/title&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span> &amp;lt;meta charset=&lt;span style="color:#ed9d13">&amp;#34;utf-8&amp;#34;&lt;/span>/&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> &amp;lt;meta http-equiv=&lt;span style="color:#ed9d13">&amp;#34;Content-Type&amp;#34;&lt;/span> content=&lt;span style="color:#ed9d13">&amp;#34;text/html; charset=utf-8&amp;#34;&lt;/span>/&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span> &amp;lt;meta name=&lt;span style="color:#ed9d13">&amp;#34;viewport&amp;#34;&lt;/span> content=&lt;span style="color:#ed9d13">&amp;#34;width=device-width, initial-scale=1&amp;#34;&lt;/span>/&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span> &amp;lt;!-- Your styles &lt;span style="color:#6ab825;font-weight:bold">go&lt;/span> here --&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span> &amp;lt;/head&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span> &amp;lt;body&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span> &lt;span style="color:#a61717;background-color:#e3d2d2">@&lt;/span>&lt;span style="color:#447fcf">Header&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span> { children... }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span> &lt;span style="color:#a61717;background-color:#e3d2d2">@&lt;/span>&lt;span style="color:#447fcf">Footer&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span> &amp;lt;!-- Your scripts &lt;span style="color:#6ab825;font-weight:bold">go&lt;/span> here --&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span> &amp;lt;script src=&lt;span style="color:#ed9d13">&amp;#34;//unpkg.com/alpinejs&amp;#34;&lt;/span> &lt;span style="color:#6ab825;font-weight:bold">defer&lt;/span>&amp;gt;&amp;lt;/script&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span> &amp;lt;/body&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span> &amp;lt;/html&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>• Creează componenta de pagină principală: &lt;code>resources/views/home/index.templ&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> home
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;goravel/resources/views/parts&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>templ &lt;span style="color:#447fcf">Index&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span> &lt;span style="color:#a61717;background-color:#e3d2d2">@&lt;/span>parts.&lt;span style="color:#447fcf">Template&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span> &amp;lt;h1&amp;gt;Homepage&amp;lt;/h1&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span> &amp;lt;div&amp;gt;Templ is awesome&amp;lt;/div&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Documentația templ pentru
&lt;a href="https://templ.guide/syntax-and-usage/template-composition" target="_blank" rel="noopener">componente copii este aici&lt;/a>
. Există un exemplu pentru o structură layout dar mie îmi place mai mult metoda cu componentă copil.&lt;/p>
&lt;h2 id="folosește-componenta-pagina-principală-în-controller">Folosește componenta pagina principală în controller&lt;/h2>
&lt;p>Am facut un fișier &lt;code>app/http/controllers/controller.go&lt;/code> unde pot salva cateva funcții ajutătoare care vor fii accesibile din orice controller.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> controllers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span> &lt;span style="color:#ed9d13">&amp;#34;github.com/a-h/templ&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span> &lt;span style="color:#ed9d13">&amp;#34;github.com/goravel/framework/contracts/http&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">func&lt;/span> &lt;span style="color:#447fcf">RenderTempl&lt;/span>(c http.Context, comp templ.Component) http.Response {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> c.&lt;span style="color:#447fcf">Response&lt;/span>().&lt;span style="color:#447fcf">Status&lt;/span>(&lt;span style="color:#3677a9">200&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span> c.&lt;span style="color:#447fcf">Response&lt;/span>().&lt;span style="color:#447fcf">Header&lt;/span>(&lt;span style="color:#ed9d13">&amp;#34;Content-Type&amp;#34;&lt;/span>, &lt;span style="color:#ed9d13">&amp;#34;text/html&amp;#34;&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span> comp.&lt;span style="color:#447fcf">Render&lt;/span>(c, c.&lt;span style="color:#447fcf">Response&lt;/span>().&lt;span style="color:#447fcf">Writer&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> &lt;span style="color:#6ab825;font-weight:bold">nil&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Funcția asta randează componenta templ în response buffer cu status http 200 Ok.
Acum putem folosii funcția în &lt;code>app/http/controllers/home_controller.go&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> controllers
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span> &lt;span style="color:#ed9d13">&amp;#34;goravel/resources/views/home&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span> &lt;span style="color:#ed9d13">&amp;#34;github.com/goravel/framework/contracts/http&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">type&lt;/span> HomeController &lt;span style="color:#6ab825;font-weight:bold">struct&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">//Dependent services
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">func&lt;/span> &lt;span style="color:#447fcf">NewHomeController&lt;/span>() *HomeController {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> &amp;amp;HomeController{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">//Inject services
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">func&lt;/span> (r *HomeController) &lt;span style="color:#447fcf">Index&lt;/span>(ctx http.Context) http.Response {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">// doing awesome stuff here
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">&lt;/span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> &lt;span style="color:#447fcf">RenderTempl&lt;/span>(ctx, home.&lt;span style="color:#447fcf">Index&lt;/span>())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Acum adaugăm o nouă rută:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-go" data-lang="go">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">package&lt;/span> routes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span> &lt;span style="color:#ed9d13">&amp;#34;goravel/app/http/controllers&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span> &lt;span style="color:#ed9d13">&amp;#34;github.com/goravel/framework/facades&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">func&lt;/span> &lt;span style="color:#447fcf">Web&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> homeController := controllers.&lt;span style="color:#447fcf">NewHomeController&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span> facades.&lt;span style="color:#447fcf">Route&lt;/span>().&lt;span style="color:#447fcf">Get&lt;/span>(&lt;span style="color:#ed9d13">&amp;#34;/&amp;#34;&lt;/span>, homeController.Index)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="configurare-hot-reloading-folosind-air">Configurare hot reloading folosind Air&lt;/h2>
&lt;p>Goravel are deja configurația pentru Air în fișierul &lt;code>.air.toml&lt;/code>, trebuie doar să adăugăm comanda &lt;code>templ generate&lt;/code> în parametrul cmd, ca în exemplu:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-diff" data-lang="diff">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>[build]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span> bin = &amp;#34;./storage/temp/main&amp;#34;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span>&lt;span style="color:#d22323">- cmd = &amp;#34;go build -o ./storage/temp/main .&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">4&lt;/span>&lt;span>&lt;span style="color:#d22323">&lt;/span>&lt;span style="color:#589819">+ cmd = &amp;#34;templ generate &amp;amp;&amp;amp; go build -o ./storage/temp/main .&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Dacă lucrezi pe Windows adaugă &lt;code>.exe&lt;/code> dupa cuvantul &lt;code>main&lt;/code> și pentru parametrul &lt;code>bin&lt;/code> și &lt;code>cmd&lt;/code>:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-toml" data-lang="toml">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>[build]
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span> bin = &lt;span style="color:#ed9d13">&amp;#34;./storage/temp/main.exe&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span> cmd = &lt;span style="color:#ed9d13">&amp;#34;templ generate &amp;amp;&amp;amp; go build -o ./storage/temp/main.exe .&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Gata ! Happy coding !&lt;/p>
- https://telteu.ro/ro/posts/cum-sa-folosesti-templ-in-goravel/ - Andrei Telteu 2024</description></item><item><title>Docker Compose script scurtaturi</title><link>https://telteu.ro/ro/posts/docker-compose-script-scurtaturi/</link><pubDate>Mon, 18 Nov 2024 00:10:52 +0200</pubDate><guid>https://telteu.ro/ro/posts/docker-compose-script-scurtaturi/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/docker-compose-script-scurtaturi/ -&lt;p>Make a new file at the root folder called &lt;code>dc&lt;/code> without extension.&lt;/p>
&lt;p>Content example. Modify for your needs.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#cd2828;font-weight:bold">#!/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#cd2828;font-weight:bold">&lt;/span>&lt;span style="color:#24909d">trap&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;exit&amp;#34;&lt;/span> &lt;span style="color:#3677a9">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#40ffff">DC&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;docker compose&amp;#34;&lt;/span> &lt;span style="color:#999;font-style:italic"># add `-f docker/compose.yml` if it&amp;#39;s in another folder&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [ &lt;span style="color:#40ffff">$#&lt;/span> -eq &lt;span style="color:#3677a9">0&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> ps -a
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">elif&lt;/span> [ &lt;span style="color:#40ffff">$1&lt;/span> == &lt;span style="color:#ed9d13">&amp;#34;up&amp;#34;&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> up -d
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">elif&lt;/span> [ &lt;span style="color:#40ffff">$1&lt;/span> == &lt;span style="color:#ed9d13">&amp;#34;php&amp;#34;&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [ &lt;span style="color:#40ffff">$#&lt;/span> -gt &lt;span style="color:#3677a9">1&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> &lt;span style="color:#24909d">exec&lt;/span> php su app -c &lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#ed9d13">${&lt;/span>*:&lt;span style="color:#40ffff">2&lt;/span>&lt;span style="color:#ed9d13">}&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> &lt;span style="color:#24909d">exec&lt;/span> php su app
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">elif&lt;/span> [ &lt;span style="color:#40ffff">$1&lt;/span> == &lt;span style="color:#ed9d13">&amp;#34;c&amp;#34;&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> &lt;span style="color:#24909d">exec&lt;/span> php su app -c &lt;span style="color:#ed9d13">&amp;#34;composer &lt;/span>&lt;span style="color:#ed9d13">${&lt;/span>*:&lt;span style="color:#40ffff">2&lt;/span>&lt;span style="color:#ed9d13">}&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">elif&lt;/span> [ &lt;span style="color:#40ffff">$1&lt;/span> == &lt;span style="color:#ed9d13">&amp;#34;ci&amp;#34;&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> &lt;span style="color:#24909d">exec&lt;/span> php su app -c &lt;span style="color:#ed9d13">&amp;#39;composer install&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">elif&lt;/span> [ &lt;span style="color:#40ffff">$1&lt;/span> == &lt;span style="color:#ed9d13">&amp;#34;recreate&amp;#34;&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> up -d --force-recreate &lt;span style="color:#ed9d13">${&lt;/span>*:&lt;span style="color:#40ffff">2&lt;/span>&lt;span style="color:#ed9d13">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">elif&lt;/span> [ &lt;span style="color:#40ffff">$1&lt;/span> == &lt;span style="color:#ed9d13">&amp;#34;build&amp;#34;&lt;/span> ]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> up -d --force-recreate --build &lt;span style="color:#ed9d13">${&lt;/span>*:&lt;span style="color:#40ffff">2&lt;/span>&lt;span style="color:#ed9d13">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span> &lt;span style="color:#40ffff">$DC&lt;/span> &lt;span style="color:#40ffff">$*&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">32&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Give execute permission with &lt;code>chmod +x ./dc&lt;/code>&lt;/p>
&lt;p>And now you can run:&lt;/p>
&lt;ul>
&lt;li>&lt;code>./dc&lt;/code> - to show all containers with status&lt;/li>
&lt;li>&lt;code>./dc up&lt;/code> - to start in detached mode&lt;/li>
&lt;li>&lt;code>./dc ci&lt;/code> - to run composer install in the php container as user app&lt;/li>
&lt;li>&lt;code>./dc c require spatie/image&lt;/code> - to run any composer command inside php container&lt;/li>
&lt;li>&lt;code>./dc php&lt;/code> - interactive exec inside php container&lt;/li>
&lt;li>&lt;code>./dc php ls -alh&lt;/code> - run any command inside php container&lt;/li>
&lt;li>&lt;code>./dc recreate&lt;/code> - applies any modifications to docker-compose.yml&lt;/li>
&lt;li>&lt;code>./dc recreate php&lt;/code> - applies modifications to compose, only for php container&lt;/li>
&lt;li>&lt;code>./dc build&lt;/code> - if you have a custom dockerfile, does run dc up with a fresh build.&lt;/li>
&lt;li>&lt;code>./dc logs -n 10 -f php&lt;/code> - any other docker-compose command works as expected.&lt;/li>
&lt;/ul>
- https://telteu.ro/ro/posts/docker-compose-script-scurtaturi/ - Andrei Telteu 2024</description></item><item><title>Backup incremental pentru fișiere și MySQL</title><link>https://telteu.ro/ro/posts/backup-incremental-pentru-fisiere-si-mysql/</link><pubDate>Mon, 18 Nov 2024 00:09:52 +0200</pubDate><guid>https://telteu.ro/ro/posts/backup-incremental-pentru-fisiere-si-mysql/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/backup-incremental-pentru-fisiere-si-mysql/ -&lt;h2 id="1-instalează">1. Instalează&lt;/h2>
&lt;p>Instalează autorestic de aici:
&lt;a href="https://autorestic.vercel.app/installation" target="_blank" rel="noopener">https://autorestic.vercel.app/installation&lt;/a>
&lt;/p>
&lt;p>În tutorialul ăsta folosim următoarea structură de fișiere: &lt;code>/root/backup&lt;/code> pentru parole și configurația autorestic, un folder &lt;code>data&lt;/code> înauntru unde se salvează backup-urile efective (restic repository), și folderul database unde se salvează temporar exportul din baza de date.&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>mkdir /root/backup
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span>mkdir /root/backup/data
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span>mkdir /root/backup/database
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">4&lt;/span>&lt;span>&lt;span style="color:#24909d">cd&lt;/span> /root/backup
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="2-fisier-env-pentru-parole">2. Fisier env pentru parole&lt;/h2>
&lt;p>Creează fisierul environment &lt;code>nano .autorestic.env&lt;/code> și completează datele de access la baza de date:&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-env" data-lang="env">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>&lt;span style="color:#40ffff">AUTORESTIC_LOCAL_RESTIC_PASSWORD&lt;/span>=
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span>&lt;span style="color:#40ffff">AUTORESTIC_PROD_DB_MYSQL_HOST&lt;/span>=localhost
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">4&lt;/span>&lt;span>&lt;span style="color:#40ffff">AUTORESTIC_PROD_DB_MYSQL_PORT&lt;/span>=&lt;span style="color:#3677a9">3306&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">5&lt;/span>&lt;span>&lt;span style="color:#40ffff">AUTORESTIC_PROD_DB_MYSQL_DATABASE&lt;/span>=
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">6&lt;/span>&lt;span>&lt;span style="color:#40ffff">AUTORESTIC_PROD_DB_MYSQL_USER&lt;/span>=
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">7&lt;/span>&lt;span>&lt;span style="color:#40ffff">AUTORESTIC_PROD_DB_MYSQL_PASS&lt;/span>=
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Completează la &lt;code>AUTORESTIC_LOCAL_RESTIC_PASSWORD&lt;/code> o cheie/parolă random generată. Cu parola asta o să fie encriptate toate backup-urile. Salvează această cheie în alt loc (password manager sau în alt fișier undeva sigur).&lt;/p>
&lt;h2 id="3-script-pentru-mysql-backup">3. Script pentru MySQL backup&lt;/h2>
&lt;p>Creeaza scriptul bash pentru backup MySQL: &lt;code>nano backup-db-hook.sh&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#cd2828;font-weight:bold">#!/usr/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#cd2828;font-weight:bold">&lt;/span>&lt;span style="color:#40ffff">BACKUP_PATH&lt;/span>=./database
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>mkdir &lt;span style="color:#40ffff">$BACKUP_PATH&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#24909d">export&lt;/span> &lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>cat .autorestic.env | xargs&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#40ffff">MYSQL&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>which mysql&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#40ffff">MYSQLDUMP&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>which mysqldump&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#40ffff">GZIP&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>which gzip&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>&lt;span style="color:#40ffff">MYSQL_PERMS&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34; --protocol tcp &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>&lt;span style="color:#40ffff">MYSQL_PERMS&lt;/span>+=&lt;span style="color:#ed9d13">&amp;#34; -h &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>&lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#40ffff">$AUTORESTIC_PROD_DB_MYSQL_HOST&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13"> &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>&lt;span style="color:#40ffff">MYSQL_PERMS&lt;/span>+=&lt;span style="color:#ed9d13">&amp;#34; -P &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>&lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#40ffff">$AUTORESTIC_PROD_DB_MYSQL_PORT&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13"> &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>&lt;span style="color:#40ffff">MYSQL_PERMS&lt;/span>+=&lt;span style="color:#ed9d13">&amp;#34; -u &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>&lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#40ffff">$AUTORESTIC_PROD_DB_MYSQL_USER&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13"> &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>&lt;span style="color:#40ffff">DB&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#40ffff">$AUTORESTIC_PROD_DB_MYSQL_DATABASE&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span>&lt;span style="color:#24909d">export&lt;/span> &lt;span style="color:#40ffff">MYSQL_PWD&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#40ffff">$AUTORESTIC_PROD_DB_MYSQL_PASS&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span>&lt;span style="color:#40ffff">DUMP_OPTIONS&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;--single-transaction --no-tablespaces&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>&lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>date +&lt;span style="color:#ed9d13">&amp;#34;%d-%m-%Y %H:%M:%S&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13"> Backing up &lt;/span>&lt;span style="color:#40ffff">$DB&lt;/span>&lt;span style="color:#ed9d13"> to &lt;/span>&lt;span style="color:#40ffff">$BACKUP_PATH&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#40ffff">TABLES&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>&lt;span style="color:#40ffff">$MYSQL&lt;/span> &lt;span style="color:#40ffff">$MYSQL_PERMS&lt;/span> &lt;span style="color:#40ffff">$DB&lt;/span> -Bse &lt;span style="color:#ed9d13">&amp;#39;SHOW TABLES FROM &amp;#39;&lt;/span>&lt;span style="color:#40ffff">$DB&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">for&lt;/span> TABLE in &lt;span style="color:#40ffff">$TABLES&lt;/span> ; &lt;span style="color:#6ab825;font-weight:bold">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span> &lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>date +&lt;span style="color:#ed9d13">&amp;#34;%d-%m-%Y %H:%M:%S&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13"> Backing up &lt;/span>&lt;span style="color:#40ffff">$TABLE&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span> &lt;span style="color:#40ffff">FILE&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#40ffff">$BACKUP_PATH&lt;/span>&lt;span style="color:#ed9d13">/&lt;/span>&lt;span style="color:#ed9d13">${&lt;/span>&lt;span style="color:#40ffff">TABLE&lt;/span>&lt;span style="color:#ed9d13">}&lt;/span>&lt;span style="color:#ed9d13">.sql.gz&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span> &lt;span style="color:#40ffff">$MYSQLDUMP&lt;/span> &lt;span style="color:#40ffff">$MYSQL_PERMS&lt;/span> &lt;span style="color:#40ffff">$DUMP_OPTIONS&lt;/span> &lt;span style="color:#40ffff">$DB&lt;/span> &lt;span style="color:#40ffff">$TABLE&lt;/span> | &lt;span style="color:#40ffff">$GZIP&lt;/span> -9 &amp;gt; &lt;span style="color:#40ffff">$FILE&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">done&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span>&lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">$(&lt;/span>date +&lt;span style="color:#ed9d13">&amp;#34;%d-%m-%Y %H:%M:%S&amp;#34;&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">)&lt;/span>&lt;span style="color:#ed9d13"> ...done!&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>(script de backup în fișiere separate pentru tabele copiat de la
&lt;a href="https://gist.github.com/jeremyharris/3085738" target="_blank" rel="noopener">jeremyharris/backup.sh&lt;/a>
)&lt;/p>
&lt;h2 id="4-configurație-autorestic">4. Configurație Autorestic&lt;/h2>
&lt;p>Creează fișierul config pentru autorestic: &lt;code>nano auto.yml&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-yml" data-lang="yml">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">version&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">2&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">backends&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">local&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">type&lt;/span>:&lt;span style="color:#666"> &lt;/span>local&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">path&lt;/span>:&lt;span style="color:#666"> &lt;/span>/root/backup/data&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># aici se salveaza backup-urile in sine&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">global&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">forget&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">keep-daily&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">7&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">keep-weekly&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#3677a9">4&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span>&lt;span style="color:#666">&lt;/span>&lt;span style="color:#6ab825;font-weight:bold">locations&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">prod&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">from&lt;/span>:&lt;span style="color:#666"> &lt;/span>/var/www/html&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># calea catre fisierele site&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">to&lt;/span>:&lt;span style="color:#666"> &lt;/span>local&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">cron&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;0 1 * * *&amp;#39;&lt;/span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># backup fisiere la ora 01:00&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">forget&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;yes&amp;#34;&lt;/span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># sau &amp;#34;prune&amp;#34;. Optiunea &amp;#34;Yes&amp;#34; trebuie să fie în ghilimele, altfel este boolean&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">options&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">backup&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">exclude&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- &lt;span style="color:#ed9d13">&amp;#39;vendor&amp;#39;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">prod-db&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">from&lt;/span>:&lt;span style="color:#666"> &lt;/span>/root/backup/database/&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">to&lt;/span>:&lt;span style="color:#666"> &lt;/span>local&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">cron&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#39;0 0 * * *&amp;#39;&lt;/span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#999;font-style:italic"># backup baza de date la ora 00:00&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">forget&lt;/span>:&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#ed9d13">&amp;#34;yes&amp;#34;&lt;/span>&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">hooks&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>&lt;span style="color:#6ab825;font-weight:bold">before&lt;/span>:&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span>&lt;span style="color:#666"> &lt;/span>- bash backup-db-hook.sh&lt;span style="color:#666">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;blockquote>
&lt;p>Notă: Numele backend-ului trebuie să fie la fel ca în numele cheii din env: (cum e &lt;code>&lt;b>EXAMPLE&lt;/b>&lt;/code>)
&lt;br />AUTORESTIC_&lt;code>&lt;b>EXAMPLE&lt;/b>&lt;/code>_RESTIC_PASSWORD=
&lt;br />backends:
&lt;br />  &lt;code>&lt;b>example&lt;/b>&lt;/code>:
&lt;br />    type: local&lt;/p>
&lt;/blockquote>
&lt;h2 id="5-inițializează-folderul-cu-comanda">5. Inițializează folderul cu comanda&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>autorestic -c auto.yml -v check
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Comanda asta validează configurația și inițiază un nou repository in folderul destinație.&lt;/p>
&lt;h2 id="6-cron-job">6. Cron Job&lt;/h2>
&lt;p>Adaugă cron job ca să facă automat backup și purge. Autorestic recomandă cron jobul să fie setat la 5 minute.&lt;/p>
&lt;p>&lt;code>crontab -e&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>*/5 * * * * &lt;span style="color:#24909d">cd&lt;/span> /root/backup; /usr/local/bin/autorestic -c /root/backup/auto.yml --ci cron --lean
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h3 id="note">Note:&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>Salvează cheia&lt;/strong> (&lt;code>RESTIC_PASSWORD&lt;/code> din env) undeva extern, în afara serverului, într-un password manager sau ceva similar. Dacă pierzi cheia backup-urile sunt inutile, nu le poți decripta.&lt;/li>
&lt;li>Ca să vezi lista de backup-uri intră în folderul &lt;code>/root/backup&lt;/code> și scrie comanda &lt;code>autorestic exec -av snapshots&lt;/code>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">1&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">## lista backup-urilor&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">2&lt;/span>&lt;span>autorestic -c auto.yml &lt;span style="color:#24909d">exec&lt;/span> -av snapshots
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">3&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">4&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">## alege un snapshot id, afișează toate fișierele din acesta&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">5&lt;/span>&lt;span>autorestic -c auto.yml &lt;span style="color:#24909d">exec&lt;/span> -av -- ls --long 041c88da
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">6&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">7&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">## acum poți alege să restaurezi doar un fișier, de exemplu, in folderul ./restore/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">8&lt;/span>&lt;span>autorestic -c auto.yml &lt;span style="color:#24909d">exec&lt;/span> -av -- restore --target=./restore/ --include=/root/backup/database/example.sql.gz 041c88da
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>- https://telteu.ro/ro/posts/backup-incremental-pentru-fisiere-si-mysql/ - Andrei Telteu 2024</description></item><item><title>Dinamic max_connections pentru MySQL</title><link>https://telteu.ro/ro/posts/mysql-max-connections-dinamic/</link><pubDate>Mon, 18 Nov 2024 00:08:54 +0200</pubDate><guid>https://telteu.ro/ro/posts/mysql-max-connections-dinamic/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/mysql-max-connections-dinamic/ -&lt;p>Put the following script in a .sh file, for example in &lt;code>/root/watch-mysql.sh&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-bash" data-lang="bash">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#cd2828;font-weight:bold">#!/usr/bin/bash
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#cd2828;font-weight:bold">&lt;/span>&lt;span style="color:#24909d">trap&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;exit&amp;#34;&lt;/span> &lt;span style="color:#3677a9">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#40ffff">MAXCONN&lt;/span>=&lt;span style="color:#3677a9">1000&lt;/span> &lt;span style="color:#999;font-style:italic"># set this to whatever base max_connections you have defined in your my.conf setting&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">while&lt;/span> true; &lt;span style="color:#6ab825;font-weight:bold">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">#mysql -e &amp;#34;SHOW VARIABLES LIKE &amp;#39;max_connections&amp;#39;;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span> &lt;span style="color:#40ffff">THREADS&lt;/span>=&lt;span style="color:#ed9d13">`&lt;/span>mysqladmin status | awk &lt;span style="color:#ed9d13">&amp;#39;{print $4}&amp;#39;&lt;/span>&lt;span style="color:#ed9d13">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span> &lt;span style="color:#40ffff">THREADSINT&lt;/span>=&lt;span style="color:#ed9d13">`&lt;/span>&lt;span style="color:#24909d">echo&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;&lt;/span>&lt;span style="color:#40ffff">$THREADS&lt;/span>&lt;span style="color:#ed9d13">&amp;#34;&lt;/span> | bc&lt;span style="color:#ed9d13">`&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">#echo &amp;#34;Load is: $THREADS&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span> &lt;span style="color:#40ffff">NEWMAX&lt;/span>=&lt;span style="color:#40ffff">$MAXCONN&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [[ &lt;span style="color:#40ffff">$THREADSINT&lt;/span> -ge &lt;span style="color:#3677a9">1&lt;/span> ]]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span> &lt;span style="color:#40ffff">NEWMAX&lt;/span>=&lt;span style="color:#3677a9">1000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [[ &lt;span style="color:#40ffff">$THREADSINT&lt;/span> -ge &lt;span style="color:#3677a9">600&lt;/span> ]]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span> &lt;span style="color:#40ffff">NEWMAX&lt;/span>=&lt;span style="color:#3677a9">2000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [[ &lt;span style="color:#40ffff">$THREADSINT&lt;/span> -ge &lt;span style="color:#3677a9">1400&lt;/span> ]]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span> &lt;span style="color:#40ffff">NEWMAX&lt;/span>=&lt;span style="color:#3677a9">3000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [[ &lt;span style="color:#40ffff">$THREADSINT&lt;/span> -ge &lt;span style="color:#3677a9">2400&lt;/span> ]]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span> &lt;span style="color:#40ffff">NEWMAX&lt;/span>=&lt;span style="color:#3677a9">4000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [[ &lt;span style="color:#40ffff">$THREADSINT&lt;/span> -ge &lt;span style="color:#3677a9">3400&lt;/span> ]]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span> &lt;span style="color:#40ffff">NEWMAX&lt;/span>=&lt;span style="color:#3677a9">5000&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">if&lt;/span> [[ &lt;span style="color:#40ffff">$NEWMAX&lt;/span> -ne &lt;span style="color:#40ffff">$MAXCONN&lt;/span> ]]; &lt;span style="color:#6ab825;font-weight:bold">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span> mysql -e &lt;span style="color:#ed9d13">&amp;#34;set global max_connections = &lt;/span>&lt;span style="color:#40ffff">$NEWMAX&lt;/span>&lt;span style="color:#ed9d13">;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">#echo &amp;#34;increased: $NEWMAX&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span> &lt;span style="color:#40ffff">MAXCONN&lt;/span>=&lt;span style="color:#40ffff">$NEWMAX&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">fi&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span> sleep &lt;span style="color:#3677a9">3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">32&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">done&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>If &lt;code>mysqladmin status&lt;/code> gives error &amp;ldquo;connect to server at &amp;rsquo;localhost&amp;rsquo; failed&amp;rdquo;, make sure you have your credentials stored in &lt;code>~/.my.cnf&lt;/code>&lt;/p>
&lt;p>I have a separate mysql server, runing PerconaDB inside docker, so in my case my &lt;code>~/.my.cnf&lt;/code> looks like this:&lt;/p>
&lt;pre tabindex="0">&lt;code>[client]
protocol=tcp
port=3306
user=root
password=&amp;#34;secret&amp;#34;
&lt;/code>&lt;/pre>&lt;hr>
&lt;p>You can run this script on startup by creating a
&lt;a href="https://linuxconfig.org/how-to-run-script-on-startup-on-ubuntu-20-04-focal-fossa-server-desktop" target="_blank" rel="noopener">systemd service&lt;/a>
or by using
&lt;a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-manage-supervisor-on-ubuntu-and-debian-vps" target="_blank" rel="noopener">supervisor&lt;/a>
.&lt;/p>
&lt;hr>
&lt;p>An easier setup is by runing a cron job every minute. If you do a while loop in a cron job, you will end up with unlimited proceses spawned and we don&amp;rsquo;t want that. Instead we will replace while with a for loop:&lt;/p>
&lt;pre tabindex="0">&lt;code># replace `while true; do` with
for i in {1..20}; do
&lt;/code>&lt;/pre>&lt;p>For loop for 20 iterations because each loop sleeps for 3 seconds. So &lt;code>20 * 3 = 60&lt;/code> seconds assuming our code does not take too long to execute.&lt;/p>
&lt;p>Now run command &lt;code>crontab -e&lt;/code> and add a cron job for this:&lt;/p>
&lt;pre tabindex="0">&lt;code>* * * * * bash /root/watch-mysql.sh
&lt;/code>&lt;/pre>- https://telteu.ro/ro/posts/mysql-max-connections-dinamic/ - Andrei Telteu 2024</description></item><item><title>Calendar complet în Solid JS</title><link>https://telteu.ro/ro/posts/solid-js-calendar-complet/</link><pubDate>Mon, 18 Nov 2024 00:07:59 +0200</pubDate><guid>https://telteu.ro/ro/posts/solid-js-calendar-complet/</guid><description>Andrei Telteu https://telteu.ro/ro/posts/solid-js-calendar-complet/ -&lt;div class="highlight">&lt;pre tabindex="0" style="color:#d0d0d0;background-color:#202020;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-tsx" data-lang="tsx">&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 1&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> { Component, For } &lt;span style="color:#6ab825;font-weight:bold">from&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;solid-js&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 2&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">import&lt;/span> moment &lt;span style="color:#6ab825;font-weight:bold">from&lt;/span> &lt;span style="color:#ed9d13">&amp;#34;moment&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 3&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">// import &amp;#34;moment/dist/locale/ro&amp;#34;; // if you need to change the locale
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 4&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">// moment.locale(&amp;#34;ro&amp;#34;);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 5&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 6&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">const&lt;/span> FullCalendar: &lt;span style="color:#6ab825;font-weight:bold">Component&lt;/span> = () =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 7&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">const&lt;/span> weekdays = moment.weekdaysMin();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 8&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">const&lt;/span> months = moment.months();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868"> 9&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">const&lt;/span> fullYear = &lt;span style="color:#24909d">Object&lt;/span>.fromEntries(
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">10&lt;/span>&lt;span> months.map((monthName, monthIndex) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">11&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> [
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">12&lt;/span>&lt;span> monthName,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">13&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">new&lt;/span> &lt;span style="color:#24909d">Array&lt;/span>(&lt;span style="color:#3677a9">6&lt;/span>).fill(&lt;span style="color:#3677a9">1&lt;/span>).map((i, rowIndex) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">14&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> weekdays.map((dayName, colIndex) =&amp;gt; {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">15&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">const&lt;/span> day = moment()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">16&lt;/span>&lt;span> &lt;span style="color:#999;font-style:italic">// .year(2024) // if you need to change the year
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">17&lt;/span>&lt;span>&lt;span style="color:#999;font-style:italic">&lt;/span> .month(monthIndex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">18&lt;/span>&lt;span> .date(rowIndex * &lt;span style="color:#3677a9">7&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">19&lt;/span>&lt;span> .weekday(colIndex);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">20&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> day.month() == monthIndex ? day.format(&lt;span style="color:#ed9d13">&amp;#34;D&amp;#34;&lt;/span>) : &lt;span style="color:#ed9d13">&amp;#34;&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">21&lt;/span>&lt;span> });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">22&lt;/span>&lt;span> }),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">23&lt;/span>&lt;span> ];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">24&lt;/span>&lt;span> })
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">25&lt;/span>&lt;span> );
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">26&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">27&lt;/span>&lt;span> &lt;span style="color:#6ab825;font-weight:bold">return&lt;/span> (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">28&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-container&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">29&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span> &lt;span style="color:#bbb">each&lt;/span>={&lt;span style="color:#24909d">Object&lt;/span>.keys(fullYear)}&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">30&lt;/span>&lt;span> {(monthName) =&amp;gt; (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">31&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-month&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">32&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-monthname&amp;#34;&lt;/span>&amp;gt;{monthName}&amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">33&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-weekdays&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">34&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span> &lt;span style="color:#bbb">each&lt;/span>={weekdays}&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">35&lt;/span>&lt;span> {(weekDayName) =&amp;gt; (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">36&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-weekday solidcalendar-column&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">37&lt;/span>&lt;span> {weekDayName}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">38&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">39&lt;/span>&lt;span> )}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">40&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">41&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">42&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">43&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span> &lt;span style="color:#bbb">each&lt;/span>={fullYear[monthName]}&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">44&lt;/span>&lt;span> {(days) =&amp;gt; (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">45&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-week&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">46&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span> &lt;span style="color:#bbb">each&lt;/span>={days}&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">47&lt;/span>&lt;span> {(day) =&amp;gt; (
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">48&lt;/span>&lt;span> &amp;lt;&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span> &lt;span style="color:#bbb">class&lt;/span>=&lt;span style="color:#ed9d13">&amp;#34;solidcalendar-weekday solidcalendar-column&amp;#34;&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">49&lt;/span>&lt;span> {day}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">50&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">51&lt;/span>&lt;span> )}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">52&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">53&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">54&lt;/span>&lt;span> )}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">55&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">56&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">57&lt;/span>&lt;span> )}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">58&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">For&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">59&lt;/span>&lt;span> &amp;lt;/&lt;span style="color:#6ab825;font-weight:bold">div&lt;/span>&amp;gt;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">60&lt;/span>&lt;span> );
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">61&lt;/span>&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">62&lt;/span>&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#686868">63&lt;/span>&lt;span>&lt;span style="color:#6ab825;font-weight:bold">export&lt;/span> &lt;span style="color:#6ab825;font-weight:bold">default&lt;/span> FullCalendar;
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>- https://telteu.ro/ro/posts/solid-js-calendar-complet/ - Andrei Telteu 2024</description></item></channel></rss>