<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Posts on AveryanAlex's blog</title><link>https://averyan.ru/en/post/</link><description>Recent content in Posts on AveryanAlex's blog</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Wed, 18 Jun 2025 02:47:32 +0300</lastBuildDate><atom:link href="https://averyan.ru/en/post/index.xml" rel="self" type="application/rss+xml"/><item><title>PicSavBot: a bot for saving and searching images</title><link>https://averyan.ru/en/p/picsavbot-a-bot-for-saving-and-searching-images/</link><pubDate>Tue, 02 Apr 2024 12:59:30 +0300</pubDate><guid>https://averyan.ru/en/p/picsavbot-a-bot-for-saving-and-searching-images/</guid><description>&lt;img src="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-question-cucumber.jpg" alt="Featured image of post PicSavBot: a bot for saving and searching images" />&lt;h2 id="why-picsavbot">Why PicSavBot?
&lt;/h2>&lt;p>Have you ever wanted to send a pic in a chat, you remember what was on it, but you can&amp;rsquo;t find it in your gallery? I have. That&amp;rsquo;s exactly why I created the Telegram bot &lt;a class="link" href="https://t.me/picsavbot" target="_blank" rel="noopener"
>@picsavbot&lt;/a> to solve this problem. Just send it the images you like (as well as stickers and videos) and it will save them to your personal library. Now you can use that very pic at the perfect moment in any chat by simply typing &lt;code>@picsavbot description of the pic&lt;/code> in the input field.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-scp-orderly.jpg"
width="1080"
height="695"
srcset="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-scp-orderly_hu_882760aedd0a0ed1.jpg 480w, https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-scp-orderly_hu_147fffadf16ba4f3.jpg 1024w"
loading="lazy"
alt="Searching the meme “Secure. Contain. Cure.” in @picsavbot"
class="gallery-image"
data-flex-grow="155"
data-flex-basis="372px"
>&lt;/p>
&lt;h2 id="how-to-write-good-queries">How to write good queries
&lt;/h2>&lt;p>If you type &amp;ldquo;fat cat&amp;rdquo;, first (provided you have such images) you will see fat cats, then just cats, and then, most likely, other animals. The CLIP neural network is not very good at reading text, but it does understand some English. On the other hand, it often recognises logos — for example, Minecraft or the &lt;a class="link" href="https://scpfoundation.net/" target="_blank" rel="noopener"
>SCP Foundation&lt;/a> — quite well. But it knows almost nothing about memes, so write descriptions of what is in the picture as if you were explaining it to your grandma.&lt;/p>
&lt;table>
&lt;thead>
&lt;tr>
&lt;th>What you want to find&lt;/th>
&lt;th>Good search query&lt;/th>
&lt;/tr>
&lt;/thead>
&lt;tbody>
&lt;tr>
&lt;td>Shlyopa&lt;/td>
&lt;td>Cat with big ears&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Gigachad&lt;/td>
&lt;td>Muscular man&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Gachi meme&lt;/td>
&lt;td>Fight in a locker room&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Mental hospital&lt;/td>
&lt;td>Orderly reaching out his hand&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>It&amp;rsquo;s Wednesday my dudes&lt;/td>
&lt;td>Frog&lt;/td>
&lt;/tr>
&lt;tr>
&lt;td>Among Us&lt;/td>
&lt;td>Red astronaut&lt;/td>
&lt;/tr>
&lt;/tbody>
&lt;/table>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-cute-animal.jpg"
width="1080"
height="864"
srcset="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-cute-animal_hu_b30b97258f42acdc.jpg 480w, https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-cute-animal_hu_8148895ee576c997.jpg 1024w"
loading="lazy"
alt="Searching for “cute animal” in @picsavbot"
class="gallery-image"
data-flex-grow="125"
data-flex-basis="300px"
>&lt;/p>
&lt;h2 id="how-the-bot-works">How the bot works
&lt;/h2>&lt;p>You send an image/sticker/video to the Telegram bot &lt;a class="link" href="https://t.me/picsavbot" target="_blank" rel="noopener"
>@picsavbot&lt;/a>; it passes it to the neural network &lt;a class="link" href="https://openai.com/research/clip" target="_blank" rel="noopener"
>CLIP&lt;/a> (the model used is LAION&amp;rsquo;s &lt;a class="link" href="https://huggingface.co/laion/CLIP-ViT-H-14-laion2B-s32B-b79K" target="_blank" rel="noopener"
>CLIP-ViT-H-14-laion2B-s32B-b79K&lt;/a>) and saves the resulting multi-dimensional vector representing the image content to a PostgreSQL database extended with the &lt;a class="link" href="https://github.com/pgvector/pgvector" target="_blank" rel="noopener"
>pgvector&lt;/a> plugin for vector storage and search. When saving an animated sticker or video, the preview frame (usually the first frame) is taken.&lt;/p>
&lt;p>To find the desired pic among the saved ones, you can type &lt;code>@picsavbot picture description&lt;/code> in the message field of any chat. Using Yandex.Translate, the bot will translate the entered description into English, analyse it with CLIP and find the most suitable images in the database by their &lt;a class="link" href="https://en.wikipedia.org/wiki/Cosine_similarity" target="_blank" rel="noopener"
>cosine similarity&lt;/a>.&lt;/p>
&lt;p>When you send one of the found images, the bot increases its usage count in its database, and if there is no search query (you type &lt;code>@picsavbot&lt;/code> without anything else) it will first show the most frequently used pics and stickers.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-python.jpg"
width="1080"
height="486"
srcset="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-python_hu_f8ac1218fa240b08.jpg 480w, https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-python_hu_aa31867b2bf47f7.jpg 1024w"
loading="lazy"
alt="Searching the meme “it’s more convenient in Python” with the Telegram bot @picsavbot"
class="gallery-image"
data-flex-grow="222"
data-flex-basis="533px"
>&lt;/p>
&lt;h2 id="about-the-project">About the project
&lt;/h2>&lt;p>Source code: &lt;a class="link" href="https://github.com/averyanalex/picsavbot" target="_blank" rel="noopener"
>averyanalex/picsavbot&lt;/a>.&lt;/p>
&lt;p>Programming languages: Rust, Python.&lt;/p>
&lt;p>Key libraries: &lt;a class="link" href="https://tokio.rs/" target="_blank" rel="noopener"
>tokio&lt;/a> (asynchronous runtime), &lt;a class="link" href="https://github.com/teloxide/teloxide" target="_blank" rel="noopener"
>teloxide&lt;/a> (framework for building Telegram bots), &lt;a class="link" href="https://www.sea-ql.org/SeaORM/" target="_blank" rel="noopener"
>seaorm&lt;/a> (database interaction).&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-postman-pechkin.jpg"
width="1080"
height="486"
srcset="https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-postman-pechkin_hu_7e50038ae83b9fe4.jpg 480w, https://averyan.ru/p/%D0%BF%D0%B8%D0%BA%D1%87%D0%B5%D1%85%D1%80%D0%B0%D0%BD%D0%B8%D1%82%D0%B5%D0%BB%D1%8C-%D0%B1%D0%BE%D1%82-%D0%B4%D0%BB%D1%8F-%D1%81%D0%BE%D1%85%D1%80%D0%B0%D0%BD%D0%B5%D0%BD%D0%B8%D1%8F-%D0%B8-%D0%BF%D0%BE%D0%B8%D1%81%D0%BA%D0%B0-%D0%BA%D0%B0%D1%80%D1%82%D0%B8%D0%BD%D0%BE%D0%BA/picsavbot-postman-pechkin_hu_a39ee03df57d397a.jpg 1024w"
loading="lazy"
alt="Postman Pechkin"
class="gallery-image"
data-flex-grow="222"
data-flex-basis="533px"
>&lt;/p></description></item><item><title>How Laziness and Curiosity Saved Me Dozens of Hours</title><link>https://averyan.ru/en/p/how-laziness-and-curiosity-saved-me-dozens-of-hours/</link><pubDate>Tue, 26 Mar 2024 23:08:36 +0300</pubDate><guid>https://averyan.ru/en/p/how-laziness-and-curiosity-saved-me-dozens-of-hours/</guid><description>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/bot-v2-example.png" alt="Featured image of post How Laziness and Curiosity Saved Me Dozens of Hours" />&lt;h2 id="about-the-project">About the Project
&lt;/h2>&lt;p>Source code:
&lt;a class="link" href="https://github.com/averyanalex/matetech-answers-bot" target="_blank" rel="noopener"
>github.com/averyanalex/matetech-answers-bot&lt;/a>.&lt;/p>
&lt;p>Programming languages: Rust, SQL.&lt;/p>
&lt;p>Key libraries:&lt;/p>
&lt;ul>
&lt;li>&lt;a class="link" href="https://tokio.rs/" target="_blank" rel="noopener"
>tokio&lt;/a> (asynchronous runtime)&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/seanmonstar/reqwest" target="_blank" rel="noopener"
>reqwest&lt;/a> (HTTP client)&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/launchbadge/sqlx" target="_blank" rel="noopener"
>sqlx&lt;/a> (database driver)&lt;/li>
&lt;li>&lt;a class="link" href="https://github.com/teloxide/teloxide" target="_blank" rel="noopener"
>teloxide&lt;/a> (framework for building
Telegram bots)&lt;/li>
&lt;/ul>
&lt;h2 id="creation-story">Creation Story
&lt;/h2>&lt;p>In 9th grade I enrolled in an &amp;ldquo;olympiad&amp;rdquo; school—a good one with almost no
&amp;ldquo;extra&amp;rdquo; subjects, so you could peacefully prepare for competitions. Many
non-core subjects, like biology, were given as so-called distance courses that
worked roughly like this: open the e-learning site, watch a 10–15-minute
lecture, take a quiz while &lt;del>searching the answers online&lt;/del>, and get your well-
earned 80–100 % score.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/test-example.png"
width="1284"
height="637"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/test-example_hu_b7d5e18954f46ccb.png 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/test-example_hu_59d84e3edd54f02a.png 1024w"
loading="lazy"
alt="An example of a quiz"
class="gallery-image"
data-flex-grow="201"
data-flex-basis="483px"
>&lt;/p>
&lt;h3 id="the-idea-and-the-first-version">The Idea and the First Version
&lt;/h3>&lt;p>The process was honestly pretty boring. And what do you do when it gets boring
with a browser tab open? Right—you open the developer tools. Poke at the
elements and show your friends how you got 200 % on a quiz in 3 seconds. Open the
Network tab and watch what the site sends where while you&amp;rsquo;re doing the quiz.
Finish a quiz and open the results…&lt;/p>
&lt;p>And it turns out the JSON with the results contains the correct answers, even
though the site itself doesn&amp;rsquo;t show them! Interesting. Let&amp;rsquo;s dig deeper. Copy
the request as &lt;code>curl&lt;/code> and run it in the terminal. Great, we can see that JSON.
Start a new quiz, change the attempt ID in the request, and… we get a response
from the server! With the quiz results (and the right answers) &lt;strong>before
finishing the quiz itself&lt;/strong>.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/result-question.png"
width="498"
height="743"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/result-question_hu_b602e27709dc3883.png 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/result-question_hu_f834d09e6cf964ee.png 1024w"
loading="lazy"
alt="Quiz result with answer options and a mark showing which is correct"
class="gallery-image"
data-flex-grow="67"
data-flex-basis="160px"
>&lt;/p>
&lt;p>The find was interesting, of course. But I also wanted to help my classmates and
not have to open the console every time. I asked a friend to send me the attempt
ID of one of his quizzes, substituted it… it worked! I removed the authorization
header from the request—access error. So the genius developers of the platform
did check for the presence of authorization (as I recall, a valid one—a random
token won&amp;rsquo;t work), but completely skipped the permission check. Well, good job
guys, at least you did something.&lt;/p>
&lt;p>The rest was just engineering. I wrote a simple &lt;a class="link" href="https://github.com/averyanalex/matetech-answers-bot/tree/legacy" target="_blank" rel="noopener"
>Telegram bot in
Python&lt;/a> that,
given a quiz ID, sent all the answers. But I didn&amp;rsquo;t want to &amp;ldquo;out&amp;rdquo; that the
answers were essentially public on the site, or reveal the bot. I rewrote the
bot—now when it sees an attempt ID it hasn&amp;rsquo;t encountered before it posts the
answers to a public Telegram channel, as if the quiz had been solved manually
and the site had no bugs.&lt;/p>
&lt;p>Word-of-mouth did its job—in a year the channel had several hundred subscribers.&lt;/p>
&lt;h3 id="the-second-version">The Second Version
&lt;/h3>&lt;p>The vulnerability—actually a gaping hole—was so obvious that many people found
it. By the next year one &lt;del>brilliant&lt;/del> weird student of the math-IT track made a
project titled something like &amp;ldquo;Vulnerabilities of the Distance Course
Platform.&amp;rdquo; I don&amp;rsquo;t know what exactly was in it, but some issues were fixed
afterwards. First, fetching somebody else&amp;rsquo;s quiz results became impossible.
Second, for multiple-choice questions the correct answer stopped being displayed
in the results.&lt;/p>
&lt;p>It was clear the bot needed to become more sophisticated, and I didn&amp;rsquo;t want to
develop that Python prototype further (it had already worked for more than a
year). A friend and I decided to write a &lt;a class="link" href="https://github.com/averyanalex/matetech-answers-bot" target="_blank" rel="noopener"
>new version in
Rust&lt;/a> since we knew it
better. We implemented login with token saving to the database, so we could get
quiz results for different users.&lt;/p>
&lt;p>The only remaining problem was with multiple-choice questions—unlike text input
ones, there were no answers. But after carefully looking at the JSON I noticed a
&lt;code>score&lt;/code> field. It turned out to be 0 if the current saved answer is wrong and&lt;/p>
&lt;blockquote>
&lt;p>0 if it&amp;rsquo;s correct. Perfect, we can simply iterate over all options until the
score changes.&lt;/p>&lt;/blockquote>
&lt;p>Of course, this required teaching the bot to answer questions on its own. In
general it wasn&amp;rsquo;t too hard, and as a bonus we gained the ability to automatically
complete the quiz, not just fetch the answers. Cool—now &amp;ldquo;quizzes are solved
automatically for everyone, and nobody even opens them!&amp;rdquo; (A reference to a
sketch at the 9th-grade graduation. Back then it wasn&amp;rsquo;t true yet.)&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/bot-solving.png"
width="407"
height="43"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/bot-solving_hu_70d5a14195fee627.png 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/bot-solving_hu_80b72e996bfbc5eb.png 1024w"
loading="lazy"
alt="The bot at work"
class="gallery-image"
data-flex-grow="946"
data-flex-basis="2271px"
>&lt;/p>
&lt;p>That&amp;rsquo;s roughly how, after a couple of evenings of Rust coding, the second
version of the bot for getting distance-course answers was written. We released
it, posted a link in the Telegram channel. Not everyone rushed to sign up—many
were afraid to send their login/password from the course site to our bot. But,
as they say, that&amp;rsquo;s their problem: if they don&amp;rsquo;t want to use it—they don&amp;rsquo;t
have to.&lt;/p>
&lt;h3 id="attempts-to-shut-the-bot-down">Attempts to Shut the Bot Down
&lt;/h3>&lt;p>Soon some enterprising school students decided to try making money off it. They
created their own similar bot (with pay-per-use) and started messaging me with
proposals to shut mine down. Actually, I think they first tried back when instead
of a bot there were Telegram channels, but less actively.&lt;/p>
&lt;p>They offered super &amp;ldquo;profitable&amp;rdquo; (not) deals: make my bot paid with the same
price as theirs, or shut it down and get up to 10 % of their profit. I of course
refused and jokingly offered them a price of 300 k. For some reason they weren&amp;rsquo;t
happy. I thought that was it, but no…&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/paid-bot-idea.jpg"
width="576"
height="661"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/paid-bot-idea_hu_eacaa48721c79de6.jpg 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/paid-bot-idea_hu_f5669e0503aa0904.jpg 1024w"
loading="lazy"
alt="Suggestion to make the bot paid"
class="gallery-image"
data-flex-grow="87"
data-flex-basis="209px"
>&lt;/p>
&lt;p>They created a channel where they started claiming that I, allegedly, made the
bot to steal account credentials and complete quizzes for 0 points. They created
a fake profile of me, screencapped chats supposedly with me where &amp;ldquo;I&amp;rdquo; say that
cheating is bad and therefore I completed their quizzes with zeros. I don&amp;rsquo;t know
who believed them—seems almost no one. I still don&amp;rsquo;t know who those people were
and frankly I don&amp;rsquo;t care.&lt;/p>
&lt;h2 id="examples-of-platform-bugs">Examples of Platform Bugs
&lt;/h2>&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/125-100.jpg"
width="1280"
height="427"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/125-100_hu_388b450ef3c5f32f.jpg 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/125-100_hu_d0a04ed684bd1132.jpg 1024w"
loading="lazy"
alt="3 out of 4 tasks done correctly but 125 % shown"
class="gallery-image"
data-flex-grow="299"
data-flex-basis="719px"
>&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/full-but-not-pass.jpg"
width="1280"
height="306"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/full-but-not-pass_hu_608b8e01959d37a6.jpg 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BB%D0%B5%D0%BD%D1%8C-%D0%B8-%D0%BB%D1%8E%D0%B1%D0%BE%D0%BF%D1%8B%D1%82%D1%81%D1%82%D0%B2%D0%BE-%D1%81%D1%8D%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC%D0%B8%D0%BB%D0%B8-%D0%BC%D0%BD%D0%B5-%D0%B4%D0%B5%D1%81%D1%8F%D1%82%D0%BA%D0%B8-%D1%87%D0%B0%D1%81%D0%BE%D0%B2-%D0%B2%D1%80%D0%B5%D0%BC%D0%B5%D0%BD%D0%B8/full-but-not-pass_hu_54c44d51b6cf9ab0.jpg 1024w"
loading="lazy"
alt="The quiz isn’t passed even though everything is correct. Turned out you can
change answers after finishing the quiz."
class="gallery-image"
data-flex-grow="418"
data-flex-basis="1003px"
>&lt;/p></description></item><item><title>Installing Yggdrasil on Windows</title><link>https://averyan.ru/en/p/installing-yggdrasil-on-windows/</link><pubDate>Wed, 14 Dec 2022 23:33:19 +0300</pubDate><guid>https://averyan.ru/en/p/installing-yggdrasil-on-windows/</guid><description>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/install-process.png" alt="Featured image of post Installing Yggdrasil on Windows" />&lt;h2 id="what-is-yggdrasil">What is Yggdrasil?
&lt;/h2>&lt;p>Yggdrasil is a decentralized mesh network where every participant is equal.
Each computer in the network (a node) is assigned a static public IPv6 address,
and any other participant can reach it directly.&lt;/p>
&lt;p>This can be used, for example, to play network games across different local
networks. One player runs a Minecraft server without paying for an external
(&amp;ldquo;white&amp;rdquo;) IP address, and another player from a different city connects to it
via Yggdrasil.&lt;/p>
&lt;h2 id="installation">Installation
&lt;/h2>&lt;p>Let&amp;rsquo;s get started: we&amp;rsquo;ll download and install Yggdrasil, configure peers to
connect to the rest of the network, check that everything works, and obtain our
own IP address.&lt;/p>
&lt;h3 id="download-the-installer">Download the installer
&lt;/h3>&lt;p>Open the page with the &lt;a class="link" href="https://github.com/yggdrasil-network/yggdrasil-go/releases/latest" target="_blank" rel="noopener"
>latest Yggdrasil release&lt;/a>
on GitHub.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/yggdrasil-releases.png"
width="849"
height="1303"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/yggdrasil-releases_hu_cddd32cdc4b7d75d.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/yggdrasil-releases_hu_7433e092ffce79cd.png 1024w"
loading="lazy"
alt="Yggdrasil latest release page on GitHub"
class="gallery-image"
data-flex-grow="65"
data-flex-basis="156px"
>&lt;/p>
&lt;p>Find the file &lt;code>yggdrasil-x.y.z-x64.msi&lt;/code> (for version 0.4.7 this is
&lt;code>yggdrasil-0.4.7-x64.msi&lt;/code>). If you have a 32-bit system (from the 2000s),
download &lt;code>yggdrasil-x.y.z-x86.msi&lt;/code> instead.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/windows-installers.png"
width="836"
height="62"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/windows-installers_hu_59f6022fb45a2935.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/windows-installers_hu_addc40075fb5952a.png 1024w"
loading="lazy"
alt="Yggdrasil Windows MSI installers on GitHub"
class="gallery-image"
data-flex-grow="1348"
data-flex-basis="3236px"
>&lt;/p>
&lt;h3 id="installing-the-msi">Installing the MSI
&lt;/h3>&lt;p>Open the downloaded MSI file.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-yggdrasil-installer.png"
width="1014"
height="726"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-yggdrasil-installer_hu_562bbbf536f38167.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-yggdrasil-installer_hu_8eb7a424fcdc6e9c.png 1024w"
loading="lazy"
alt="Windows Explorer with the Yggdrasil MSI installer"
class="gallery-image"
data-flex-grow="139"
data-flex-basis="335px"
>&lt;/p>
&lt;p>Confirm the launch by clicking &lt;strong>Run&lt;/strong>.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/installer-security-warning.png"
width="466"
height="359"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/installer-security-warning_hu_9fe42904182d805c.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/installer-security-warning_hu_31591b923c2738b.png 1024w"
loading="lazy"
alt="Windows security warning"
class="gallery-image"
data-flex-grow="129"
data-flex-basis="311px"
>&lt;/p>
&lt;p>When prompted, grant the installer administrator rights.&lt;/p>
&lt;p>The installer window will open and &lt;strong>no additional questions will be asked&lt;/strong>.
After installation finishes (it takes only a few seconds) the window will &lt;strong>close automatically&lt;/strong>.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/install-process.png"
width="394"
height="149"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/install-process_hu_76be2752b3f76de9.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/install-process_hu_45a29169b005c5cd.png 1024w"
loading="lazy"
alt="Yggdrasil installer"
class="gallery-image"
data-flex-grow="264"
data-flex-basis="634px"
>&lt;/p>
&lt;p>That&amp;rsquo;s it for the installation process, now let&amp;rsquo;s proceed to configuration.&lt;/p>
&lt;h4 id="error-2503">Error 2503
&lt;/h4>&lt;p>Sometimes the 2503 error appears when installing MSI files. Open the properties
of the folder &lt;code>C:\Windows\Temp&lt;/code>, go to the &lt;strong>Security&lt;/strong> tab and make sure that
the &lt;strong>Administrators&lt;/strong> group and your user (add it if it isn&amp;rsquo;t listed) have
full permissions. Information taken from &lt;a class="link" href="https://answers.microsoft.com/en-us/windows/forum/all/error-code-2503-2502-when-installing-msi-file/0aa6840f-e625-4075-b1c5-051da100c151" target="_blank" rel="noopener"
>Microsoft Community&lt;/a>.&lt;/p>
&lt;h2 id="configuring-peers">Configuring peers
&lt;/h2>&lt;p>Peers are the servers Yggdrasil connects to in order to reach the rest of the
network.&lt;/p>
&lt;p>It is better to choose one common, stable peer for all players – this minimizes
ping and prevents other people&amp;rsquo;s traffic from passing through your connection
(public peers are responsible for forwarding traffic).&lt;/p>
&lt;h3 id="choosing-peers">Choosing peers
&lt;/h3>&lt;p>There is a repository with a &lt;a class="link" href="https://github.com/yggdrasil-network/public-peers" target="_blank" rel="noopener"
>list of public peers&lt;/a>
on GitHub. Peers are grouped by continent, country and city. Choose peers that
are geographically closer to the host – this will reduce ping for all players.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/public-peers.png"
width="1062"
height="1190"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/public-peers_hu_dfcabb03bc39da0a.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/public-peers_hu_41863254a78a0ce0.png 1024w"
loading="lazy"
alt="List of public Yggdrasil peers in Russia"
class="gallery-image"
data-flex-grow="89"
data-flex-basis="214px"
>&lt;/p>
&lt;p>For example, you can use my peer (Moscow): &lt;code>tls://ygg-msk-1.averyan.ru:8363&lt;/code> or
&lt;code>quic://ygg-msk-1.averyan.ru:8364&lt;/code> (the &lt;code>quic&lt;/code> variant is preferable if it
works for you and isn&amp;rsquo;t blocked).&lt;/p>
&lt;p>However, not all of them may work – you can check the &lt;a class="link" href="https://publicpeers.neilalexander.dev/" target="_blank" rel="noopener"
>list of available
peers&lt;/a> on the developer&amp;rsquo;s website.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/peers-status.png"
width="1113"
height="741"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/peers-status_hu_5afd9932ac2b2961.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/peers-status_hu_6f8a5346533623fa.png 1024w"
loading="lazy"
alt="Status of public Yggdrasil peers"
class="gallery-image"
data-flex-grow="150"
data-flex-basis="360px"
>&lt;/p>
&lt;h3 id="editing-the-config">Editing the config
&lt;/h3>&lt;p>Press &lt;code>Win+R&lt;/code> to open the &lt;strong>Run&lt;/strong> dialog. Enter the path to the config:
&lt;code>%ALLUSERSPROFILE%\Yggdrasil\yggdrasil.conf&lt;/code>&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-config.png"
width="431"
height="208"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-config_hu_9478197588432a66.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-config_hu_b629a1a1f0e6f9e5.png 1024w"
loading="lazy"
alt="Run dialog with the Yggdrasil config path"
class="gallery-image"
data-flex-grow="207"
data-flex-basis="497px"
>&lt;/p>
&lt;p>Click &lt;strong>OK&lt;/strong>. If Windows asks how to open the file, choose Notepad.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/original-config.png"
width="760"
height="590"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/original-config_hu_8c9edf7f72506bf2.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/original-config_hu_81ff9327140d0d63.png 1024w"
loading="lazy"
alt="Yggdrasil config right after installation"
class="gallery-image"
data-flex-grow="128"
data-flex-basis="309px"
>&lt;/p>
&lt;p>Insert the peers you chose into the &lt;strong>Peers&lt;/strong> list:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-fallback" data-lang="fallback">&lt;span class="line">&lt;span class="cl">Peers: [
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> tls://ygg.averyan.ru:8362
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> tcp://box.paulll.cc:13337
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">]
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/peers-config.png"
width="760"
height="590"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/peers-config_hu_1fff84beff57e1ed.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/peers-config_hu_71675be3317a8307.png 1024w"
loading="lazy"
alt="Yggdrasil config with peers"
class="gallery-image"
data-flex-grow="128"
data-flex-basis="309px"
>&lt;/p>
&lt;p>Save the file with &lt;code>Ctrl+S&lt;/code> or via the &lt;strong>File&lt;/strong> menu.&lt;/p>
&lt;h3 id="restarting-yggdrasil">Restarting Yggdrasil
&lt;/h3>&lt;p>For Yggdrasil to apply the new settings, it needs to be restarted. The most
obvious (but slow) way is to reboot the computer. Instead, we&amp;rsquo;ll restart it via
Task Manager.&lt;/p>
&lt;p>Open &lt;strong>Task Manager&lt;/strong> with &lt;code>Ctrl+Shift+Esc&lt;/code> or by right-clicking the Windows
icon (Start button) on the taskbar.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-task-manager.png"
width="374"
height="616"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-task-manager_hu_86133222c8bb7831.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-task-manager_hu_574b1384ca2379c9.png 1024w"
loading="lazy"
alt="Task Manager in Start button context menu"
class="gallery-image"
data-flex-grow="60"
data-flex-basis="145px"
>&lt;/p>
&lt;p>If the simplified Task Manager opens, click &lt;strong>More details&lt;/strong>.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/task-manager-mini.png"
width="365"
height="365"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/task-manager-mini_hu_27aa009e0a19d153.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/task-manager-mini_hu_428c80f553b5c924.png 1024w"
loading="lazy"
alt="Simplified Task Manager"
class="gallery-image"
data-flex-grow="100"
data-flex-basis="240px"
>&lt;/p>
&lt;p>Open the &lt;strong>Services&lt;/strong> tab, find &lt;strong>Yggdrasil&lt;/strong> at the very bottom, right-click it
and choose &lt;strong>Restart&lt;/strong>.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/task-manager-restart-yggdrasil.png"
width="890"
height="541"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/task-manager-restart-yggdrasil_hu_e67e69dbb8f043ff.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/task-manager-restart-yggdrasil_hu_53d6b6b89f68e87a.png 1024w"
loading="lazy"
alt="Restarting the Yggdrasil service in Task Manager"
class="gallery-image"
data-flex-grow="164"
data-flex-basis="394px"
>&lt;/p>
&lt;h2 id="final-steps">Final steps
&lt;/h2>&lt;p>Installation and configuration are complete – let&amp;rsquo;s check that everything works
and find out our IP address.&lt;/p>
&lt;h3 id="checking-functionality">Checking functionality
&lt;/h3>&lt;p>Open &lt;strong>Command Prompt&lt;/strong>.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-cmd.png"
width="800"
height="750"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-cmd_hu_95895407cf3a7ab5.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/open-cmd_hu_e71faaeecaee70c4.png 1024w"
loading="lazy"
alt="Searching for Command Prompt"
class="gallery-image"
data-flex-grow="106"
data-flex-basis="256px"
>&lt;/p>
&lt;p>Enter the command &lt;code>&amp;quot;C:\Program Files\Yggdrasil\yggdrasilctl.exe&amp;quot; getPeers&lt;/code> to
view the list of connected peers. There should be as many as you configured. If
there are fewer, some peers are unavailable.&lt;/p>
&lt;p>If an error occurs when entering this command, try rebooting the computer.&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-getpeers.png"
width="1663"
height="267"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-getpeers_hu_8111f1ea6a7f5f3c.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-getpeers_hu_e0151ad85dcaf771.png 1024w"
loading="lazy"
alt="Running yggdrasilctl getPeers in Command Prompt"
class="gallery-image"
data-flex-grow="622"
data-flex-basis="1494px"
>&lt;/p>
&lt;p>Try opening and pinging the &lt;a class="link" href="http://[319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be]/" target="_blank" rel="noopener"
>Yggdrasil website&lt;/a>
(&lt;strong>available only from the Yggdrasil network&lt;/strong> and may load quite slowly):&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">ping &lt;span class="o">[&lt;/span>319:3cf0:dd1d:47b9:20c:29ff:fe2c:39be&lt;span class="o">]&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-ping.png"
width="1663"
height="514"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-ping_hu_6c7ab97de55b5ce1.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-ping_hu_7e09031ec9776842.png 1024w"
loading="lazy"
alt="Running ping to test Yggdrasil functionality"
class="gallery-image"
data-flex-grow="323"
data-flex-basis="776px"
>&lt;/p>
&lt;h3 id="getting-your-ip-address">Getting your IP address
&lt;/h3>&lt;p>To find out your own IP address, enter the command &lt;code>&amp;quot;C:\Program Files\Yggdrasil\yggdrasilctl.exe&amp;quot; getSelf&lt;/code>:&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-getself.png"
width="772"
height="495"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-getself_hu_f026a988d6fff108.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/cmd-getself_hu_c54ee5f9b349617a.png 1024w"
loading="lazy"
alt="Getting your own IP address in the Yggdrasil network"
class="gallery-image"
data-flex-grow="155"
data-flex-basis="374px"
>&lt;/p>
&lt;p>The highlighted line will show your IPv6 address in the Yggdrasil network.&lt;/p>
&lt;p>You&amp;rsquo;ll notice that the ping to your own address is practically zero.&lt;/p>
&lt;h2 id="configuring-games">Configuring games
&lt;/h2>&lt;p>Yggdrasil is now installed on your computer and running. Let&amp;rsquo;s use it for
network games.&lt;/p>
&lt;h3 id="minecraft">Minecraft
&lt;/h3>&lt;p>Install Yggdrasil on the device that will host the server and on those that
will connect to it.&lt;/p>
&lt;p>Start a LAN game on the host (&lt;strong>Open to LAN&lt;/strong>) and note the port:&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-start-lan-game.png"
width="930"
height="753"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-start-lan-game_hu_58b318b77efed5db.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-start-lan-game_hu_4bcc7fed31e72332.png 1024w"
loading="lazy"
alt="Opening a local server in Minecraft"
class="gallery-image"
data-flex-grow="123"
data-flex-basis="296px"
>&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-server-port.png"
width="708"
height="70"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-server-port_hu_61553f51cbb7219e.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-server-port_hu_36d2964be9cd8d3f.png 1024w"
loading="lazy"
alt="Local Minecraft server port"
class="gallery-image"
data-flex-grow="1011"
data-flex-basis="2427px"
>&lt;/p>
&lt;p>Find out the host&amp;rsquo;s IP address. (In my case it is
&lt;code>200:d08:17f6:af6e:b285:16de:d3ba:387a&lt;/code>)&lt;/p>
&lt;p>Connect to the server (enter the IP &lt;strong>in square brackets&lt;/strong> and specify the port
after the colon):&lt;/p>
&lt;p>&lt;img src="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-connect.png"
width="863"
height="221"
srcset="https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-connect_hu_794b44a8429f3bf2.png 480w, https://averyan.ru/p/%D1%83%D1%81%D1%82%D0%B0%D0%BD%D0%BE%D0%B2%D0%BA%D0%B0-yggdrasil-%D0%BD%D0%B0-windows/minecraft-connect_hu_5088bec9b77b0237.png 1024w"
loading="lazy"
alt="Connecting to a Minecraft server via Yggdrasil"
class="gallery-image"
data-flex-grow="390"
data-flex-basis="937px"
>&lt;/p>
&lt;p>If you can&amp;rsquo;t connect, try configuring the Windows Firewall or turning it off
completely, and also check the ping to the host.&lt;/p>
&lt;p>Done! Now you can play Minecraft with your friends at any time.&lt;/p></description></item><item><title>Nix flakes for Hugo site</title><link>https://averyan.ru/en/p/nix-flakes-for-hugo-site/</link><pubDate>Tue, 29 Nov 2022 15:31:37 +0300</pubDate><guid>https://averyan.ru/en/p/nix-flakes-for-hugo-site/</guid><description>&lt;img src="https://averyan.ru/hugo-build-nix.png" alt="Featured image of post Nix flakes for Hugo site" />&lt;h2 id="advantages-of-managing-hugo-website-with-nix">Advantages of managing Hugo website with Nix
&lt;/h2>&lt;ul>
&lt;li>Reproducible builds: Nix allows you to reproducible build your Hugo website
across multiple machines.&lt;/li>
&lt;li>Dependency management: Nix makes it easy to manage theme, other dependencies
and even Hugo itself for your website.&lt;/li>
&lt;li>Easy deployment: just set root of your nginx virtualHost to site&amp;rsquo;s package.&lt;/li>
&lt;/ul>
&lt;h2 id="setup-your-site">Setup your site
&lt;/h2>&lt;h3 id="write-flakenix">Write flake.nix
&lt;/h3>&lt;p>This is an example of flake.nix I use for this blog, adapt it for your needs.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;span class="lnt">55
&lt;/span>&lt;span class="lnt">56
&lt;/span>&lt;span class="lnt">57
&lt;/span>&lt;span class="lnt">58
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nix" data-lang="nix">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">description&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;AveryanAlex&amp;#39;s personal blog&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">inputs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">nixpkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;github:nixos/nixpkgs/nixos-unstable&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">flake-utils&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;github:numtide/flake-utils&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Import theme&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">stack&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="sd">github:CaiJimmy/hugo-theme-stack&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">flake&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="no">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">outputs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">self&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">nixpkgs&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">flake-utils&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">stack&lt;/span> &lt;span class="p">}:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">flake-utils&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lib&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">eachDefaultSystem&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">system&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">let&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">pkgs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">nixpkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">legacyPackages&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="n">system&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">blog&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdenv&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mkDerivation&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;blog&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Exclude themes and public folder from build sources&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">src&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">builtins&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="nb">filterSource&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">type&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="o">!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">type&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;directory&amp;#34;&lt;/span> &lt;span class="o">&amp;amp;&amp;amp;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="nb">baseNameOf&lt;/span> &lt;span class="n">path&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;themes&amp;#34;&lt;/span> &lt;span class="o">||&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">baseNameOf&lt;/span> &lt;span class="n">path&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;public&amp;#34;&lt;/span>&lt;span class="p">)))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="sr">./.&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Link theme to themes folder and build&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">buildPhase&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> mkdir -p themes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ln -s &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="n">stack&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1"> themes/stack
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="n">pkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hugo&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1">/bin/hugo --minify
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#39;&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">installPhase&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> cp -r public $out
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#39;&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">meta&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="n">pkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lib&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">description&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;AveryanAlex&amp;#39;s personal blog&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">platforms&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">platforms&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">all&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">in&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">packages&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">blog&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">blog&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">default&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">blog&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">devShells&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">default&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mkShell&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">buildInputs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">with&lt;/span> &lt;span class="n">pkgs&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">[&lt;/span> &lt;span class="n">hugo&lt;/span> &lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1"># Link theme to themes folder&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">shellHook&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> mkdir -p themes
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> ln -sf &lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="n">stack&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s1"> themes/stack
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="s1"> &amp;#39;&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="setup-direnv">Setup direnv
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> use flake &amp;gt;&amp;gt; .envrc
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> .direnv &amp;gt;&amp;gt; .gitignore
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">direnv allow
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="add-result-to-gitignore">Add result to .gitignore
&lt;/h3>&lt;p>Result folder is a symlink to built website created by &lt;code>nix build&lt;/code> command.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">echo&lt;/span> result &amp;gt;&amp;gt; .gitignore
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="preview-and-build">Preview and build
&lt;/h2>&lt;p>Run development server:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">hugo server -D
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Build production release with nix:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-shell" data-lang="shell">&lt;span class="line">&lt;span class="cl">nix build
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="deploying-to-nginx-webserver">Deploying to nginx webserver
&lt;/h2>&lt;p>Now we will create nginx virtualHost config for the site.&lt;/p>
&lt;p>Add website to server&amp;rsquo;s flake inputs:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nix" data-lang="nix">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">inputs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">blog&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;github:averyanalex/blog&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Setup nginx virtualHost to serve your site:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-nix" data-lang="nix">&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span> &lt;span class="n">inputs&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">pkgs&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="o">...&lt;/span> &lt;span class="p">}:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">services&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">nginx&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">virtualHosts&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="s2">&amp;#34;averyan.ru&amp;#34;&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">root&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">inputs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">blog&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">defaultPackage&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="si">${&lt;/span>&lt;span class="n">pkgs&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">hostPlatform&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">system&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">useACMEHost&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s2">&amp;#34;averyan.ru&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">forceSSL&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="no">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div></description></item><item><title>How to Check FLAC Quality?</title><link>https://averyan.ru/en/p/how-to-check-flac-quality/</link><pubDate>Sun, 28 Aug 2022 18:19:11 +0300</pubDate><guid>https://averyan.ru/en/p/how-to-check-flac-quality/</guid><description>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/spek.png" alt="Featured image of post How to Check FLAC Quality?" />&lt;h2 id="how-can-we-tell-apart-lossy-codecs-such-as-mp3">How can we tell apart lossy codecs such as MP3?
&lt;/h2>&lt;p>I will not go into detail about how lossy audio codecs work—you can read about it in the
&lt;a class="link" href="https://en.wikipedia.org/wiki/Data_compression#Lossy_compression" target="_blank" rel="noopener"
>Wikipedia article on audio data compression&lt;/a>.
To spot fake FLAC files created by converting from MP3 we will take advantage of the fact
that lossy compression chops off high frequencies.
For example, a 320-kbit MP3 removes everything above 20 kHz (for lower bitrates the cutoff
is even lower). In lossless formats such as FLAC the audio remains in its original form.&lt;/p>
&lt;h2 id="installing-the-spectrum-analysis-program-spek">Installing the spectrum analysis program Spek
&lt;/h2>&lt;p>Spek is a free, open-source spectrum analyzer for audio files that runs on Windows, Linux
and macOS. It will help us identify fake FLAC.&lt;/p>
&lt;p>Windows, macOS: &lt;a class="link" href="https://www.spek.cc/p/download" target="_blank" rel="noopener"
>spek.cc&lt;/a>.&lt;/p>
&lt;p>On Linux, most distributions provide the package &lt;code>spek&lt;/code>.&lt;/p>
&lt;h2 id="checking-flac-files-for-authenticity">Checking FLAC files for authenticity
&lt;/h2>&lt;p>Open the audio file you are interested in with Spek and look at its frequency spectrum.&lt;/p>
&lt;p>As examples we will use Status Quo – &amp;ldquo;In The Army Now&amp;rdquo;, transcoded from a 320-kbit MP3,
and AC/DC – &amp;ldquo;T.N.T.&amp;rdquo; preserved in lossless quality.&lt;/p>
&lt;h3 id="example-spectrum-of-a-genuine-flac">Example spectrum of a genuine FLAC
&lt;/h3>&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/true-flac.png"
width="1920"
height="1080"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/true-flac_hu_ba1715c683f5520b.png 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/true-flac_hu_29d6ad0da77c6333.png 1024w"
loading="lazy"
alt="FLAC audio spectrum"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="426px"
>&lt;/p>
&lt;h3 id="example-spectrum-of-a-fake-flac-transcoded-from-mp3">Example spectrum of a fake FLAC transcoded from MP3
&lt;/h3>&lt;p>&lt;img src="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/fake-flac.png"
width="1920"
height="1080"
srcset="https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/fake-flac_hu_64216afb413f700b.png 480w, https://averyan.ru/p/%D0%BA%D0%B0%D0%BA-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%B8%D1%82%D1%8C-%D0%BA%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE-flac/fake-flac_hu_1279f0103a46380f.png 1024w"
loading="lazy"
alt="MP3 audio spectrum"
class="gallery-image"
data-flex-grow="177"
data-flex-basis="426px"
>&lt;/p>
&lt;p>The MP3 spectrum cutoff at 20 kHz is clearly visible.&lt;/p></description></item></channel></rss>