<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>@kright</title><subtitle>программист</subtitle><author><name>@kright</name></author><id>https://teletype.in/atom/kright</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/kright?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@kright?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=kright"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/kright?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-07T22:33:32.426Z</updated><entry><id>kright:FH4</id><link rel="alternate" type="text/html" href="https://teletype.in/@kright/FH4?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=kright"></link><title>Впечатления от Forza Horizon 4 на руле</title><published>2022-06-05T22:29:04.176Z</published><updated>2022-06-05T22:29:04.176Z</updated><summary type="html">TLDR: игра создана под клавиатуру/джойстик, лучше играть на них.</summary><content type="html">
  &lt;p id=&quot;firstHeading&quot;&gt;&lt;strong&gt;TLDR&lt;/strong&gt;: игра создана под клавиатуру/джойстик, лучше играть на них.&lt;/p&gt;
  &lt;h3 id=&quot;OL6m&quot;&gt;Суть проблемы&lt;/h3&gt;
  &lt;p id=&quot;jzsF&quot;&gt;Я когда-то играл на клавиатуре в разные игры и горя не знал, а потом купил руль, и с ним впечатления от игр кардинально поменялись. Например, симуляторы типа Dirt Rally 2.0 или Asseto Corsa при игре на клавиатуре не впечатляют, но буквально расцветают при подключении руля и педалей. А вот с форзой, к моему сожалению, получилось ровно наоборот. Обратные реакции на руле кажутся искусственными и вообще складывается впечатление, что руль сделан &amp;quot;для галочки&amp;quot;.&lt;/p&gt;
  &lt;p id=&quot;uL0Y&quot;&gt;Ниже я по пунктам распишу, что же мне не понравилось.&lt;/p&gt;
  &lt;h3 id=&quot;prPR&quot;&gt;Кривые дефолтные настройки руля.&lt;/h3&gt;
  &lt;p id=&quot;QepW&quot;&gt;По умолчанию руль нелинейный. Повернули наполовину - колёса поворачиваются намного слабее, а вот в конце поворота - очень даже сильно. Мой руль поворачивается от упора до упора на 1080 градусов, и с нелинейной настройкой играть мягко говоря проблематично - из положения &amp;quot;около нуля&amp;quot; надо очень далеко крутить руль, чтобы машина хоть как-то начала поворачивать. Итак, лезем в &amp;quot;продвинутые&amp;quot; настройки руля и делаем его снова линейным. После такого force feedback становится чуточку адекватнее, а руль начинает влиять на угол поворота колёс как на нормальном автомобиле.  Ещё можно в настройках сложности отключить traction control, abs и прочие &amp;quot;улучшения&amp;quot;, чтобы получить максимум ощущений. Но это нас не спасёт :(&lt;/p&gt;
  &lt;h2 id=&quot;aUHE&quot;&gt;Физика, которую мы потеряли&lt;/h2&gt;
  &lt;p id=&quot;QFNH&quot;&gt;Игры forza motorsport и forza horizon используют один и тот же физический движок. Окно тюнинга автомобиля создаёт обманчивое ощущения, что модель поведения автомобиля глубоко проработана и приближена к реальности. К сожалению, эксперименты с рулём показали, что это не так. Во имя аркадности в физику воткнуты очень большие костыли, радикально упрощающие геймплей и сводящие на нет удовольствие от игры на руле. Дальше я перечислю различные отдельные эффекты, которые упрощены или отсутствуют. &lt;/p&gt;
  &lt;p id=&quot;t0o6&quot;&gt;Не то чтобы я был радикально против и хотел сделать из форзы симулятор в открытом мире, но эти особенности больше всего чувствуются в игре на руле. Хотя вру - очень даже хотел бы симулятор с графикой форзы и открытым миром.&lt;/p&gt;
  &lt;h3 id=&quot;olN9&quot;&gt;Машина после столкновения не вращается&lt;/h3&gt;
  &lt;p id=&quot;Gr3f&quot;&gt;Например, если влететь в дерево левой фарой, машина мгновенно остановится. Она не будет красиво кувыркаться, вращаться и лететь куда-то дальше. Собственно, при игровых 200+ км/ч машина может очень далеко лететь. Я не против такого введения, но это очень хорошая иллюстрация того, как можно вмешаться в физику и сделать её менее честной.&lt;/p&gt;
  &lt;h3 id=&quot;Oogs&quot;&gt;Езда по разным покрытиям&lt;/h3&gt;
  &lt;p id=&quot;akdg&quot;&gt;В assetto corsa при заезде парой колёс на траву очень легко улететь с трассы. А если нажать на газ или тормоз - тем более. В реальной жизни, впрочем, так же - не стоит &amp;quot;наполовину&amp;quot; съезжать с дороги и резко нажимать на тормоз. Те колёса, которые на асфальте - затормозят, а другие - нет, автомобиль начнёт разворачивать носом в сторону асфальта.&lt;/p&gt;
  &lt;p id=&quot;etMz&quot;&gt;В форзе этого эффекта вообще не чувствуется - я специально вставал парой колёс на асфальт и парой на обочину, пробовал укоряться-замедляться с отключенными трекшеном и абс - ничего подобного, машина едет прямо. Кроме того, я пробовал на переднеприводной машине с полностью разблокированным дифференциалом в таких условиях разгоняться и смотрел телеметрию. Оба передних колеса начинали проскальзывать одновременно.&lt;/p&gt;
  &lt;p id=&quot;HtFU&quot;&gt;В реальном мире при таком разгоне колесо на обочине начнёт проскальзывать, дифференциал направит движение на него, а второе ведущее колесо будет без проскальзывания катиться по асфальту.&lt;/p&gt;
  &lt;p id=&quot;kVqa&quot;&gt;У меня сложилось впечатление, что для машины просто берут центральную точку, смотрят покрытие под ней - асфальт/трава/гравий - и при дальнейших рассчётах предполагают, что под всеми колёсами это покрытие. В forza motorsport скорее всего не так.&lt;/p&gt;
  &lt;p id=&quot;qvVs&quot;&gt;Зачем это может быть сделано? А как раз ради аркадности, чтобы не вписавшийся в поворот игрок спокойно ехал дальше и не боялся развернуться при съезде с асфальта.&lt;/p&gt;
  &lt;p id=&quot;hkmy&quot;&gt;Но, на мой взгляд, это упрощение фатально портит игру. В ней есть разные времена года и попадаются дождь, снег и т.п. В них важно покрытие под каждым колесом и то, как оно меняется. Но разработчики заруинили этот момент, поведение на них скучное и не совпадающее с картинкой.&lt;/p&gt;
  &lt;p id=&quot;XbEs&quot;&gt;В качестве примера &amp;quot;честной&amp;quot; реализации приведу Dirt Rally 2.0 на трассе в Монте-Карло. На &lt;a href=&quot;https://www.youtube.com/watch?v=n7AS-6CLMBQ&quot; target=&quot;_blank&quot;&gt;видео&lt;/a&gt; есть смысл смотреть третью минуту - чередуются асфальт со снегом и льдом, на последних машина едет и ощущается совсем по-другому. Приходится творчески перестраивать траекторию поворотов, чтобы избежать пятен снега - на них машина скользит и не особо управляется. И да - если наехать одной стороной на лёд и нажать на газ, то можно очень хорошо почувствовать настройку дифференциала: машина со свободным диффом шлифует лёд одним колесом и не ускоряется, машина с заблокированным дифференциалом толкается колесом от асфальта и её уводит в сторону. &lt;/p&gt;
  &lt;p id=&quot;aPio&quot;&gt;А ещё на льду руль становится очень лёгким - впрочем, как и на реальном автомобиле.&lt;/p&gt;
  &lt;p id=&quot;RX0f&quot;&gt;В форзе всего этого нет.&lt;/p&gt;
  &lt;h3 id=&quot;60MF&quot;&gt;Езда на трёх колёсах&lt;/h3&gt;
  &lt;p id=&quot;EjTo&quot;&gt;Если посмотреть, как ездят в реальном спорте, то там есть неочевидные решения. &lt;/p&gt;
  &lt;p id=&quot;berX&quot;&gt;Например, в картинге задний привод и нет дифференциала. В повороте карт едет на трёх колёсах - двух передних и внешнем заднем. Заднее внутреннее висит в воздухе и свободно крутится. Благодаря этому вся мощность двигателя идёт на заднее внешнее колесо, а заднее внутреннее не мешает карту ехать. Кроме того, при нажатии на газ заднее внешнее колесо толкает карт вперёд и помогает ему поворачивать.&lt;/p&gt;
  &lt;p id=&quot;Dd2f&quot;&gt;В форзе этого эффекта толком нет. Технически можно в машину поставить жёсткий задний стабилизатор, заблокировать дифференциал и т.п., но оно ощущается совсем не так и доворачивать машину газом толком не получится.&lt;/p&gt;
  &lt;p id=&quot;MspR&quot;&gt;Кроме того, в реальном спорте для переднеприводных автомобилей встречается и другая схема - заблокированный дифференциал, жёсткие стабилизаторы спереди и автомобиль, который в повороте под газом поднимает переднее внутреннее колесо в воздух. Вся мощность двигателя идёт на передне внешнее колесо и позволяет максимально ускориться на выходе из поворота.&lt;/p&gt;
  &lt;p id=&quot;5fSf&quot;&gt;Я попробовал сделать такое в форзе. На клавиатуре или джойстике без шансов - при нажатии в повороте на газ игра решает, что отрыв внутреннего колеса - что-то экстраординарное и при зажатой кнопке поворота машина начинает ехать более прямо. Там эта схема в принципе не рабочая.&lt;/p&gt;
  &lt;p id=&quot;l1Pk&quot;&gt;Попробовал на руле - технически, оно работает, на некоторых машинах даже удавалось поднять переднее колесо в воздух. Вот только машина от этого лучше поворачивать не стала и на добавление газа в повороте толком никак не реагировала. Она ускорялась, но не было чувства, что внешнее колесо тянет машину вперёд и заодно её поворачивает.&lt;/p&gt;
  &lt;p id=&quot;c05r&quot;&gt;У меня сложилось впечатление, что такие &amp;quot;закручивающие&amp;quot; силы в игре зачем-то убрали. А жаль, на руле их реально не хватает.&lt;/p&gt;
  &lt;p id=&quot;JmUp&quot;&gt;По факту для переднего привода в форзе хорошо работает только одна схема - разблокировать дифференциал, убрать передний стабилизатор и поставить максимально жёсткий задний. &lt;/p&gt;
  &lt;h3 id=&quot;coTq&quot;&gt;Баланс тормозов и увод колёс&lt;/h3&gt;
  &lt;p id=&quot;Govo&quot;&gt;Резиновые шина под нагрузками гнётся и может ехать на совсем прямо. Для сликов в формуле 1 &amp;quot;не совсем прямо&amp;quot; может быть отклонено на 10 градусов в сторону. На резине с протектором эффект слабее, но он тоже есть. Он зависит от давления в колесе, высоты профиля, мягкости резины и прочих характеристик. Вот тут &lt;a href=&quot;https://youtu.be/ZZ1uCH9ay1k?t=58&quot; target=&quot;_blank&quot;&gt;показано&lt;/a&gt;, как сильно может деформироваться резина. &lt;/p&gt;
  &lt;p id=&quot;FEnD&quot;&gt;При росте нагрузки шины не сразу начинают скользить. Есть переходные состояния, когда шины гнутся, деформируются, отклоняются от прямого направления, но всё ещё держатся за асфальт. &lt;/p&gt;
  &lt;p id=&quot;P27h&quot;&gt;К сожалению, в форзе я этого не чувствую. Машина либо едет, либо скользит. Нету плавного соскальзывания под нагрузкой.&lt;/p&gt;
  &lt;p id=&quot;N2VB&quot;&gt;Как это можно было бы использовать в гонках? &lt;/p&gt;
  &lt;ul id=&quot;mgVX&quot;&gt;
    &lt;li id=&quot;UdCy&quot;&gt;баланс тормозов смещён назад: В повороте можно немножно нажать на тормоз и добавить машине избыточной поворачиваемости. Задние колёса начнёт плавно уводить, машина охотнее ввинтится в поворот.&lt;/li&gt;
    &lt;li id=&quot;cu4N&quot;&gt;баланс тормозов смещён вперёд: Добавление тормоза в повороте приведёт к недостаточной поворачиваемости и машина будет выпрямляться. Поведение не самое интересное, но зато позволяет стабильно тормозить и не бояться развернуться.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;9cvV&quot;&gt;Чем лучше сцепление с дорогой, тем сильнее надо тормозить передними колёсами и слабее задними, так как при торможении больше веса уйдёт вперёд. Если брать ралли с разнообразными участками, то выбор баланса тормозов добавляет ещё один &amp;quot;слой&amp;quot; планирования и вышеописанные эффекты разнообразят геймплей. Но не в форзе(&lt;/p&gt;
  &lt;p id=&quot;YfHY&quot;&gt;Кроме того, на переднем приводе есть интересный приём по смещению баланса - можно одновременно нажать газ и тормоз. На передних колёсах тормоза будут бороться с двигателем, а задние будут тормозить в полную силу. Баланс тормозов сместится назад и машина очень охотно зарулит в поворот. В Dirt Rally 2.0 я этот приём как-то интуитивно начал использовать, в форзе этого эффекта в принципе не чувствуется. Жаль :(&lt;/p&gt;
  &lt;h3 id=&quot;cDPJ&quot;&gt;Скучный оффроад&lt;/h3&gt;
  &lt;p id=&quot;MDMP&quot;&gt;При езде по пересечённой местности трясётся руль и машина капельку хуже разгоняется. И всё, можно на lamborgini катить по полю 200 км/ч, почему нет? &lt;/p&gt;
  &lt;p id=&quot;MENe&quot;&gt;На самом деле в игре нет маленьких неровностей. Они даже не нарисованы! У просёлочной дороги в лучшем случае будет обочина на другой высоте. Никаких колей, ухабов, уклонов дороги. А значит - никакого микроконтроля автомобиля, никаких приёмов типа зацепления колёсами за колею и т.п. &lt;/p&gt;
  &lt;h3 id=&quot;0rEO&quot;&gt;Жёсткая задемпфировання подвеска&lt;/h3&gt;
  &lt;p id=&quot;Dnjl&quot;&gt;Управление клавиатурой или джойстиком состоит из очень резких нажатий. Какие-нибудь раскачивания кузова или большие ходы подвески сделают игру неудобной, машина будет болтаться и не поворачивать. &lt;/p&gt;
  &lt;p id=&quot;EJy2&quot;&gt;Поэтому в форзе подвеска жёсткая и задемпфированная, никаких раскачиваний. &lt;/p&gt;
  &lt;p id=&quot;SdeO&quot;&gt;А на руле хочется чувствовать машину! В том, что подвеска работает и в разных условиях машина рулится по-разному - самый кайф! Нажать на тормоз, загрузить передние колёса, повернуть руль одновременно с отпусканием тормоза, добавить газу. Реакции на всё это должны быть не мгновенными, а чуть-чуть размазанными по времени.&lt;/p&gt;
  &lt;p id=&quot;a1vZ&quot;&gt;Частично проблему можно решить, если специально сделать машине мягкую подвеску. Управляемость станет чуточку интереснее, но всё равно очень далёкой от симуляторов.&lt;/p&gt;
  &lt;h3 id=&quot;oktF&quot;&gt;Быстрее, выше, сильнее&lt;/h3&gt;
  &lt;p id=&quot;IOQe&quot;&gt;В форзе доступны гиперкары под 1000+л.с., скорости под 400 км/ч, широкие дороги...  А нужно ли это всё для получения удовольствия? Нет! &lt;/p&gt;
  &lt;p id=&quot;Ci58&quot;&gt;В Dirt Rally 2.0 езда на старом миникупере по узкой скользкой дороге со скоростью 60 км/ч оказывается куда более увлекательной. Как так получается?&lt;/p&gt;
  &lt;p id=&quot;xwB0&quot;&gt;Здесь особенности сплетаются в взаимосвязанный клубок, и в идеале надо бы менять сразу все аспекты.&lt;/p&gt;
  &lt;p id=&quot;kBlM&quot;&gt;Во-первых, в игре есть куча очень быстрых и мощных машин и игра всеми силами предлагает кататься именно на них.&lt;/p&gt;
  &lt;p id=&quot;vYlt&quot;&gt;Но есть нюанс: длина тормозного пути пропорциональна квадрату скорости. На 100 км/ч - около 30 метров на асфальте, на 200 - 120 метров, на 300 - 270м, на 400 - 480м. Ой, как-то неинтересно за полкилометра до поворота тормозить, что же нам делать? &lt;/p&gt;
  &lt;p id=&quot;wtzP&quot;&gt;А давайте накрутим коэффициент трения с поверхностью, пускай машина тормозит с ускорением не 1g, а все 2-3! Ух, заживём! И перед поворотами станет можно тормозить не так сильно. И для дождя/земли/снега тоже, мы же не хотим зимой 100 км/ч тащиться, хотим сразу 200-300.&lt;/p&gt;
  &lt;p id=&quot;xrK5&quot;&gt;Только есть нюанс. Машина в поворотах быстрая и дерзкая, теперь сложно по прямой ехать. Нажмёшь клавишу поворота на мгновение, и машина уже на пару метров вбок отклоняется. Надо бы дорогу пошире сделать. Нарисуем две полосы, а по ширине сделаем как все 4, чтобы игрок в них как-нибудь поместился.&lt;/p&gt;
  &lt;p id=&quot;i1vI&quot;&gt;И ещё нюанс. Проблему с тормозным путём решили, но 360 км/ч - это 100 метров в секунду. Даже если игрок затормозит на 0.2 секунды позже, чем требуется, он пролетит мимо поворота на 20 метров. Что же делать? А не беда, дороги и так широкие, добавим ещё возможность ехать по обочине и срезать, вот 20 метров и компенсируем.&lt;/p&gt;
  &lt;p id=&quot;Hrx6&quot;&gt;Впрочем, 100 м/с от нас всё никак не отстанут. Например, чтобы думать вперёд на 3-5 секунд, неплохо бы видеть трассу вперёд на 300-500 метров. Ну ничего, камеру от третьего лица повесим повыше, будет видно далеко и скорость визуально будет поменьше казаться.&lt;/p&gt;
  &lt;p id=&quot;D6Ux&quot;&gt;И да, если на дороге каждые 100 метров будет новый поворот, придётся каждую секунду маневрировать. Вряд ли игроки обрадуются, так что сделаем дороги более прямыми, а повороты - плавными.&lt;/p&gt;
  &lt;p id=&quot;HB03&quot;&gt;Ой, наш &amp;quot;огромный&amp;quot; мир можно проехать за несколько минут. Как же так получилось? Ну ничё, в следующей игре сделаем её раза в полтора больше и максимальную скорость автомобилей до 400-500 км/ч поднимем. Прогресс!&lt;/p&gt;
  &lt;p id=&quot;RY5z&quot;&gt;На мой взгляд, форза пошла куда-то не туда. Всякими &amp;quot;космолётами&amp;quot; на руле играть неинтересно и малореально. На более медленных машинах оказывается, что карта не такая уж и насыщенная, повороты и элементы рельефа крупные и расставлены далеко друг от друга. Техничных извилистых трасс толком нет. Дороги слишком широкие. Машина не живая, на движения руля реагирует очень резко и неестественно, подвески как будто нет.&lt;/p&gt;
  &lt;h2 id=&quot;OVkU&quot;&gt;Выводы&lt;/h2&gt;
  &lt;p id=&quot;0Ejs&quot;&gt;В форзу лучше играть на джойстике с видом от третьего лица. Вся игра сбалансирована и настроена под это.&lt;/p&gt;
  &lt;p id=&quot;WVEy&quot;&gt;В игре есть какая-то физика, но разработчики её сознательно упростили в пользу аркадности. &lt;/p&gt;
  &lt;p id=&quot;A1h5&quot;&gt;Играть на руле совершенно неинтересно, для этого есть совсем другие игры.&lt;/p&gt;

</content></entry><entry><id>kright:UXCTBmq4xsm</id><link rel="alternate" type="text/html" href="https://teletype.in/@kright/UXCTBmq4xsm?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=kright"></link><title>Input lag в мониторе</title><published>2022-05-30T13:11:26.869Z</published><updated>2022-05-30T13:13:25.608Z</updated><summary type="html">В моём мониторе есть настройки - fast и normal, и я решил померять разницу. </summary><content type="html">
  &lt;p id=&quot;yO4A&quot;&gt;В моём мониторе есть настройки - fast и normal, и я решил померять разницу. &lt;/p&gt;
  &lt;p id=&quot;flQy&quot;&gt;Способ измерения - подключить два монитора в режиме mirror, чтобы на них отправлялась одинаковая картинка. Открыть что-то типа отображения часов с миллисекундной точностью и сфотографировать оба экрана.&lt;/p&gt;
  &lt;p id=&quot;OSkj&quot;&gt;Такие часы можно открыть прям в браузере: &lt;a href=&quot;https://cdpn.io/robertschulze/fullpage/yLOgryr&quot; target=&quot;_blank&quot;&gt;https://cdpn.io/robertschulze/fullpage/yLOgryr&lt;/a&gt; &lt;/p&gt;
  &lt;h3 id=&quot;adtu&quot;&gt;Объективный результат&lt;/h3&gt;
  &lt;p id=&quot;cWWK&quot;&gt;Между fast и normal режимами отображения разница около 16 миллисекунд. Монитор Dell P2418D. &lt;/p&gt;
  &lt;p id=&quot;yPRT&quot;&gt;Мне кажется, это вполне сочетается с частотой обновления экрана в 60 гц, изображение рисуется на один кадр позже. Видимо, монитор для какого-то улучшения картинки ждёт её целиком и только потом рисует.&lt;/p&gt;
  &lt;h3 id=&quot;BsLm&quot;&gt;Субъективные ощущения&lt;/h3&gt;
  &lt;p id=&quot;fuxp&quot;&gt;Курсор мышки более чётко двигается по экрану. Разница небольшая, на грани ощущений.&lt;/p&gt;
  &lt;p id=&quot;JG0X&quot;&gt;Я попросил второго человека включить какой-то режим, дать мне подвигать мышкой, потом поменять режим на другой и снова дать подвигать мышкой. Я смог почувствовать разницу и правильно назвать режим. Но есть нюанс - после первого &amp;quot;измерения&amp;quot; я не мог почувствовать, в каком из режимов нахожусь, разница чувствовалась только на контрасте.&lt;/p&gt;
  &lt;p id=&quot;VHIe&quot;&gt;Разницы в &amp;quot;красивости картинки&amp;quot; я не заметил.&lt;/p&gt;
  &lt;h3 id=&quot;bp5w&quot;&gt;Выводы&lt;/h3&gt;
  &lt;p id=&quot;k5Bq&quot;&gt;16 мс - вроде бы мелочь, но я включил быстрый режим и сижу довольный.&lt;/p&gt;
  &lt;p id=&quot;nfsi&quot;&gt;У типичного пользователя &amp;quot;нормальный&amp;quot; режим монитора, &amp;quot;двойная&amp;quot; или даже &amp;quot;тройная буферизация&amp;quot; на стороне видеокарты, включена вертикальная синхронизация, как-то подтормаживающий компьютер, какая-то задержка при действиях клавиатурой/мышкой - и вот на мониторе 60 гц получатся запаздывание картинки на 2-4 кадра. Ну т.е., реакция запаздывает на 1/30 - 1/15 секунды и складывается из нескольких факторов. Один из них я улучшил)&lt;/p&gt;
  &lt;p id=&quot;a3mT&quot;&gt;И да - я сейчас не про игры, а просто про комфорт работы за компьютером.&lt;/p&gt;

</content></entry><entry><id>kright:scala3_transparent_inline_with_dynamic</id><link rel="alternate" type="text/html" href="https://teletype.in/@kright/scala3_transparent_inline_with_dynamic?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=kright"></link><title>Scala 3: transparent inline with Dynamic</title><published>2022-05-08T13:38:56.092Z</published><updated>2022-05-08T13:38:56.092Z</updated><summary type="html">В скале есть интерфейс Dynamic. От него можно унаследоваться и получить динамическую типизацию - при отсутствии поля в классе компилятор подставит вызов специального метода.</summary><content type="html">
  &lt;h2 id=&quot;wfES&quot;&gt;динамическая типизация внутри статической&lt;/h2&gt;
  &lt;p id=&quot;bp9p&quot;&gt;В скале есть интерфейс Dynamic. От него можно унаследоваться и получить динамическую типизацию - при отсутствии поля в классе компилятор подставит вызов специального метода.&lt;/p&gt;
  &lt;pre id=&quot;XuLa&quot; data-lang=&quot;scala&quot;&gt;import scala 
import scala.language.dynamics

class MyClass extends Dynamic

val a = MyClass
a.x 
// a.selectDynamic(&amp;quot;x&amp;quot;)
a.x = 2
// a.updateDynamic(&amp;quot;x&amp;quot;)(2)&lt;/pre&gt;
  &lt;p id=&quot;eXKP&quot;&gt;Класс MyClass может быть любым, например таким:&lt;/p&gt;
  &lt;pre id=&quot;7wjz&quot; data-lang=&quot;scala&quot;&gt;class MyClass extends Dynamic {
  private var x: Int = 0
	
  def selectDynamic(fieldName: String): Int = {
	fieldName match 
	  case &amp;quot;x&amp;quot; =&amp;gt; return x 
  }
	
  def updateDynamic(fieldName: String)(value: Int): Unit = {
	fieldName match 
	  case &amp;quot;x&amp;quot; =&amp;gt; x = value
  }
}&lt;/pre&gt;
  &lt;p id=&quot;8SRv&quot;&gt;Конкретно такой класс получился не особо полезным - по поведению он похож на &lt;/p&gt;
  &lt;pre id=&quot;EVUV&quot; data-lang=&quot;scala&quot;&gt;class MyClass(){var x: Int = 0}&lt;/pre&gt;
  &lt;p id=&quot;r5ut&quot;&gt;только хуже - во время компиляции мы не увидим ошибок, если обратимся к несуществующему полю, и код упадёт в рантайме. Впрочем, этот код нужен для иллюстрации возожностей языка.&lt;/p&gt;
  &lt;p id=&quot;1pFL&quot;&gt;Что, если нам захочется сделать класс с полями разных типов?&lt;/p&gt;
  &lt;pre id=&quot;ZXLe&quot; data-lang=&quot;scala&quot;&gt;class MyClass() {
    var x: Int = 0 
	var b: Boolean = false
}&lt;/pre&gt;
  &lt;p id=&quot;6liI&quot;&gt;Если попробуем написать альтернативу этому классу с помощью Dynamic, в качестве принимаемых и возвращаемых типов придётся указывать Any и кастовать к какому-то типу.&lt;br /&gt;Впрочем, у нас тут Scala 3, в которой появились Union types, можно указать в качестве типа поля Int | Boolean и что-то иное типа строки компилятор не даст присвоить.&lt;/p&gt;
  &lt;pre id=&quot;8EzS&quot; data-lang=&quot;scala&quot;&gt;class MyClass extends Dynamic {  
  private var x: Int = 0  
  private var b: Boolean = false  
  
  def selectDynamic(field: String): Int | Boolean = {  
    field match  
      case &amp;quot;x&amp;quot; =&amp;gt; x  
      case &amp;quot;b&amp;quot; =&amp;gt; b  
  }  
  
  def updateDynamic(field: String)(value: Int | Boolean): Unit = {  
    field match  
      case &amp;quot;x&amp;quot; =&amp;gt;  
        value match  
          case v: Int =&amp;gt; x = v  
      case &amp;quot;y&amp;quot; =&amp;gt;  
        value match  
          case v: Boolean =&amp;gt; b = v  
  }  
}&lt;/pre&gt;
  &lt;p id=&quot;DBc0&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;20C3&quot;&gt;Но появилась ещё проблема - мы всё равно можем попробовать присвоить Boolean в x или Int в b, а потом упадём в рантайме. Такова участь динамической типизации, ничего не поделать.&lt;/p&gt;
  &lt;p id=&quot;Z0ks&quot;&gt;И тут c ноги врывается transparent inline! Перепишем метод selectDynamic:&lt;/p&gt;
  &lt;pre id=&quot;juUV&quot; data-lang=&quot;scala&quot;&gt;import scala.compiletime.error

MyClass { 
    ...
	transparent inline def selectDynamic(inline field: String): Int | Boolean = {  
	  inline field match  
		case &amp;quot;x&amp;quot; =&amp;gt; x
		case &amp;quot;b&amp;quot; =&amp;gt; b
		case _ =&amp;gt; error(&amp;quot;unknown field in MyClass&amp;quot;)
	}
}&lt;/pre&gt;
  &lt;p id=&quot;xhmJ&quot;&gt;Что будет дальше? В месте вызова&lt;/p&gt;
  &lt;pre id=&quot;Pghl&quot; data-lang=&quot;scala&quot;&gt;a.x&lt;/pre&gt;
  &lt;p id=&quot;E3vG&quot;&gt;компилятор подставит вызов функции selectDynamic, пойдёт внутрь, в inline match, найдёт там подходящую строку &amp;quot;x&amp;quot; и заменит всё-всё-всё на простое обращение к полю x с типом Int.&lt;/p&gt;
  &lt;p id=&quot;ciql&quot;&gt;Если быть точным и посмотреть байткод - у MyClass появится метод - геттер&lt;/p&gt;
  &lt;pre id=&quot;GvJ8&quot; data-lang=&quot;scala&quot;&gt;def inline$x(): Int&lt;/pre&gt;
  &lt;p id=&quot;qY81&quot;&gt; который будет вызываться напрямую.&lt;/p&gt;
  &lt;p id=&quot;VrTZ&quot;&gt;Ну либо на это можно смотреть так&lt;/p&gt;
  &lt;pre id=&quot;cQSQ&quot; data-lang=&quot;scala&quot;&gt;val x: Int = a.selectDynamic(&amp;quot;x&amp;quot;)
val b: Boolean = a.selectDynamic(&amp;quot;b&amp;quot;)&lt;/pre&gt;
  &lt;p id=&quot;niBi&quot;&gt;Возвращаемый тип зависит от аргумента!&lt;/p&gt;
  &lt;p id=&quot;XWV6&quot;&gt;Кроме того, если обратиться к несуществующему полю, прямо во время компиляции подставится compiletime.error и компилятор покажет ошибку.&lt;/p&gt;
  &lt;p id=&quot;YMD9&quot;&gt;Поздравляю, мы снова вернулись к статической типизации. Какие выводы можно сделать?&lt;/p&gt;
  &lt;ul id=&quot;soyT&quot;&gt;
    &lt;li id=&quot;3WJr&quot;&gt; transparent inline - очень мощный инструмент, позволяющий гибко работать с типами. В scala 2.0 такое невозможно.&lt;/li&gt;
    &lt;li id=&quot;ZtKn&quot;&gt;Нет строго дуализма между runtime и compiletime преобразованиями, гибкость scala позволяет в какой-то мере заменить первое на второе. В С++ похожая ситуация.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;tGtS&quot;&gt;Для полноты картины покажу, как можно переписать второй метод:&lt;/p&gt;
  &lt;pre id=&quot;IkXP&quot; data-lang=&quot;scala&quot;&gt;transparent inline def updateDynamic(inline field: String)(inline value: Int | Boolean): Unit = { 
  inline field match  
    case &amp;quot;x&amp;quot; =&amp;gt;  
      inline value match  
        case v: Int =&amp;gt; x = v  
        case _ =&amp;gt; error(&amp;quot;should be int&amp;quot;)  
    case &amp;quot;y&amp;quot; =&amp;gt;  
      inline value match  
        case v: Boolean =&amp;gt; b = v  
        case _ =&amp;gt; error(&amp;quot;should be boolean&amp;quot;)  
    case _ =&amp;gt; error(&amp;quot;unknown field&amp;quot;)  
}&lt;/pre&gt;
  &lt;p id=&quot;hm1r&quot;&gt;Посмотрите на переход от динамической типизации обратно к статической при помощи более &amp;quot;умного&amp;quot; компилятора! Что-то подобное можно попробовать в динамических языках типа Python, чтобы ловить ошибки как можно раньше. Не все, но какую-то часть.&lt;/p&gt;
  &lt;p id=&quot;oFpp&quot;&gt;Пример кода выше не очень практичен - можно сделать обычный класс с полями x: Int, b:Boolean и он будет прекрасно работать. В классе c Dynamic уже известные поля можно заменить на реальные поля и это тоже будет прекрасно работать, компилятор будет обращаться напрямую к ним вместо вызова selectDynamic:&lt;/p&gt;
  &lt;p id=&quot;l5dh&quot;&gt;&lt;/p&gt;
  &lt;pre id=&quot;oaf3&quot; data-lang=&quot;scala&quot;&gt;class MyDynamic extends Dynamic{
    var x: Double = 0
	var b: Boolean = 0
	def selectDynamic(...) ...
}&lt;/pre&gt;
  &lt;p id=&quot;Ybsq&quot;&gt;В общем, код выше дублирует базовые возможности языка, бесполезен сам по себе, но, надеюсь, полезен для иллюстрации.&lt;/p&gt;
  &lt;p id=&quot;pAZY&quot;&gt;Для чего использовать transparent inline в реальном коде - не знаю. Люди как-то жили без этой возможности и прекрасно решали свои задачи. Но я точно уверен, что часть этих задач теперь можно решить более гибко и красиво.&lt;/p&gt;

</content></entry><entry><id>kright:raspberry-pi-4b-nas</id><link rel="alternate" type="text/html" href="https://teletype.in/@kright/raspberry-pi-4b-nas?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=kright"></link><title>Моё домашнее сетевое хранилище из raspberry pi 4b</title><published>2022-01-24T17:43:17.103Z</published><updated>2022-09-15T22:10:12.871Z</updated><summary type="html">Не уверен, что мой способ оптимальный по надёжности или расходам, но для истории запишу его здесь, включая особенности и подводные камни.</summary><content type="html">
  &lt;p id=&quot;cUNo&quot;&gt;Не уверен, что мой способ оптимальный по надёжности или расходам, но для истории запишу его здесь, включая особенности и подводные камни.&lt;/p&gt;
  &lt;p id=&quot;bcke&quot;&gt;P.S. Время от времени пробую сделать с малинкой что-нибудь новое и дополняю статью.&lt;/p&gt;
  &lt;h3 id=&quot;qbQO&quot;&gt;Установка ОС&lt;/h3&gt;
  &lt;p id=&quot;ZSnL&quot;&gt;Есть готовая штука - raspberry pi imager, в которой можно выбрать желаемую ОС и залить её на sd-карту. В случае с малинкой на 8 гб оперативной памяти стоит обратить внимание на битность ОС. Якобы видеодрайвера в 64битной ОС работают плохо, но в дальнейшем мне они и не нужны. Я выбрал 64-битную версию Ubuntu server.&lt;/p&gt;
  &lt;p id=&quot;yfSO&quot;&gt;Можно установить ОС, не подключая монитор/клавиатуру/мышь. Чтобы она подключилась к сети, где-то в файлике на sd-карточке с ОС придётся прописать имя и пароль от wifi сети. Но ещё лучше (и на мой взгляд проще) подключить сеть через кабель к роутеру. В малинке гигабитный порт, для нужд домашнего хранилища самое то. Вышеописанные шаги с паролем не нужны, зато неплохо бы иметь доступ на роутер, чтобы узнать, по какому адресу доступна малинка.&lt;/p&gt;
  &lt;p id=&quot;Ncah&quot;&gt;Либо можно просканировать локальную сеть и так узнать адрес:&lt;/p&gt;
  &lt;pre id=&quot;lsYn&quot; data-lang=&quot;bash&quot;&gt;sudo nmap -sn 192.168.1.0/24&lt;/pre&gt;
  &lt;p id=&quot;RP1j&quot;&gt;При самом первом запуске ОС грузится несколько минут, а я поначалу думал что что-то делаю не так. Вся дальнейшая работа и настройка делается через ssh&lt;/p&gt;
  &lt;h3 id=&quot;3xLP&quot;&gt;Внешний жёсткий диск&lt;/h3&gt;
  &lt;p id=&quot;TKac&quot;&gt;Я купил внешний жёсткий диск на 4Тб: HDD WD Elements Desktop WDBWLG0040HBK-EESN. Из особенностей - у него есть отдельный провод для питания от розетки и он не должен тащить энергию из малинки. Из минусов - в розетку придётся втыкать два девайса. У малинки синие разъёмы - usb 3.0, диск лучше втыкать в них.&lt;/p&gt;
  &lt;p id=&quot;GVbQ&quot;&gt;Дальше начинаются приключения: raspberry pi imager при установке ОС размечает сд-карточку в MBR. Можно вместо карточки подключить жёсткий диск, но MBR позволит использовать только первые 2 Тб диска. А ещё хочется отказаться от sd карточки. Почему-то полностью переселить ОС на диск c GPT разметкой у меня не получилось, ОС не грузилась. В качестве полумеры я оставил загрузочный раздел на sd карточке и раздел с ОС перенёс на диск. Количество записей на карточку будет минимальным, и в случае потери я смогу вставить новую карточку памяти с загрузчиком и работать дальше. &lt;/p&gt;
  &lt;p id=&quot;qgA3&quot;&gt;Самое странное, что в сдругим жёстким диском toshiba на 2 гб с gpt внезапно загрузиться получилось. Я потратил около дня, но так и не понял, почему с одного диска грузится, а с другого - нет.&lt;/p&gt;
  &lt;p id=&quot;2Ki7&quot;&gt;Можно взять раздел с ОС прямо с сд карточки (зря что ли на неё ОС ставили и настраивали) и скопировать на диск. Дальше понадобится узнать айдишники для разделов. &lt;/p&gt;
  &lt;pre id=&quot;b1NP&quot; data-lang=&quot;bash&quot;&gt;sudo blkid&lt;/pre&gt;
  &lt;p id=&quot;PXqh&quot;&gt;Примерное описание тут: &lt;a href=&quot;https://linuxtut.com/en/7af17f1272ca0c558d47/&quot; target=&quot;_blank&quot;&gt;https://linuxtut.com/en/7af17f1272ca0c558d47/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;mkNM&quot;&gt;Эти айдишники надо будет обновить в двух местах:&lt;/p&gt;
  &lt;ol id=&quot;MqCg&quot;&gt;
    &lt;li id=&quot;JHWW&quot;&gt;В загрузчике boot/cmdline.txt указывает, откуда грузить ОС.&lt;/li&gt;
    &lt;li id=&quot;2XoT&quot;&gt;В самой ОС в еtc/fstab монтируются и загрузчик, и раздел с ОС&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;g4hr&quot;&gt;Как я потом узнал - не обязательно использовать PARTUUID, можно вместо него указать PARTLABEL. Название раздела можно сделать любое, и мне это показалось более удобным. Но надо проследить, чтобы не было двух разделов с одинаковым названием.&lt;/p&gt;
  &lt;p id=&quot;S1o2&quot;&gt;В малинке целых 2 usb порта, поэтому можно включить рядышком второй диск и сделать софтовый RAID1. На двух дисках будут лежать идентичные копии данных, чтение теоретически может ускориться в два раза, запись будет со скоростью самого медленного и некоторыми приколами дисков с черепичной записью. К сожалению, о современных дисках производители эту информацию не особо публикуют, в одной &amp;quot;модели&amp;quot; может оказаться как одно, так и другое, и я RAID делать не стал. В планах организовать резервное копирование с домашнего ПК на малинку - тогда отказ одного из дисков или устройств не будет фатальным.&lt;/p&gt;
  &lt;h2 id=&quot;bZlU&quot;&gt;Применение&lt;/h2&gt;
  &lt;ol id=&quot;GSSN&quot;&gt;
    &lt;li id=&quot;LQOM&quot;&gt;sshfs для доступа из Линукса для тех, кто не осилил нормальную настройку самбы. (это я)&lt;/li&gt;
    &lt;li id=&quot;UpIW&quot;&gt;Samba для доступа к папкам из локальной сети не только из линукса&lt;/li&gt;
    &lt;li id=&quot;lxQi&quot;&gt;QBittorrent с возможностью управлять им из браузера&lt;/li&gt;
    &lt;li id=&quot;oUWW&quot;&gt;24/7 крутить своего телеграм бота. (это тоже я)&lt;/li&gt;
    &lt;li id=&quot;OCyr&quot;&gt;Хранить git-репозитории&lt;/li&gt;
    &lt;li id=&quot;Atna&quot;&gt;Подключить второй массив и организовать raid&lt;/li&gt;
    &lt;li id=&quot;9KEU&quot;&gt;Настроить резервное копирование с помощью rsync и cron&lt;/li&gt;
    &lt;li id=&quot;kzri&quot;&gt;Раздобыть вторую малинку и организовать загрузку по сети, вообще без sd- карты&lt;/li&gt;
    &lt;li id=&quot;pQBx&quot;&gt;Добавить пассивное охлаждение&lt;/li&gt;
    &lt;li id=&quot;BQNL&quot;&gt;Настроить LUKS шифрование для дисков&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;yf98&quot;&gt;Скорость копирования по проводу через sshfs получилась 44-47 мегабайт в секунду. Почти полгигабита! У меня есть подозрение, что сеть на малинке быстрее, а это тормозит жёсткий диск или роутер, но пруфов не будет.&lt;/p&gt;
  &lt;h3 id=&quot;Ppaf&quot;&gt;Автозапуск бота и торрентов&lt;/h3&gt;
  &lt;p id=&quot;S80U&quot;&gt;Ниже будет упрощённый пересказ того, что я узнал по этой ссылке: &lt;a href=&quot;https://obu4alka.ru/ustanovka-qbittorrent-na-ubuntu-server-20-04-lts.html&quot; target=&quot;_blank&quot;&gt;https://obu4alka.ru/ustanovka-qbittorrent-na-ubuntu-server-20-04-lts.html&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;JscX&quot;&gt;Кстати, qbittorrent в браузере выглядит практически так же, как и приложение. И ещё он качает/раздаёт круглые сутки, так что можно оживить полузабытые раздачи.&lt;/p&gt;
  &lt;p id=&quot;kb84&quot;&gt;В ubuntu есть systemd, которая запускает сервисы при старте ОС. Чтобы бот и торрент тоже запускались, сделаем текстовые файлики:&lt;/p&gt;
  &lt;p id=&quot;U2Bs&quot;&gt;etc/systemd/system/qbittorrent-nox.service&lt;/p&gt;
  &lt;pre id=&quot;Bqez&quot;&gt;[Unit]
Description=qBittorrent Command Line Client
After=network.target

[Service]
Type=forking
User=qbittorrent-nox
Group=qbittorrent-nox
UMask=007
ExecStart=/usr/bin/qbittorrent-nox -d --webui-port=8080
Restart=on-failure

[Install]
WantedBy=multi-user.target&lt;/pre&gt;
  &lt;p id=&quot;iB7s&quot;&gt;и ещё один для моего бота:&lt;/p&gt;
  &lt;pre id=&quot;cFuL&quot;&gt;[Unit]
Description = Runs my bot

Wants=network-online.target
After=network-online.target nss-lookup.target

[Service]
Type=simple
ExecStart=/home/ubuntu/bot/run.sh

[Install]
WantedBy=multi-user.target&lt;/pre&gt;
  &lt;p id=&quot;8RAb&quot;&gt;В случае qbittorrent я создал отдельного пользователя, но если честно не особо понял смысл. Ну да, так вроде безопаснее. А потом самба не cможет открыть файл, т.к. у неё нет прав на чтение и вас ждут красота и изучение того как в линуксе работают пользователи, группы и разрешения.&lt;/p&gt;
  &lt;p id=&quot;G3Y9&quot;&gt;В настройках qbittorrent (прямо в веб-интерфейсе) есть смысл поменять дефолтную папку для хранения торрентов, а так же залезть во вкладку webUI и убрать там галочку &amp;quot;Use UPnP / NAT-PMP to forward the port from my router&amp;quot;, чтобы запретить вход в веб-интерфейс из сети снаружи роутера. Ещё там есть опция &amp;quot;Bypass authentication for clients on localhost&amp;quot;, её наоборот удобнее включить для доступа из локальной сети без пароля. &lt;/p&gt;
  &lt;p id=&quot;gICq&quot;&gt;&lt;strong&gt;Самба&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;GkAF&quot;&gt;В windows 10 отключили старую версию протокола smb, который позволял заходить без авторизации. Но с самбой всё как-то криво складывается, я сделал readonly шару и забил, потому что из линукса достаточно sshfs.&lt;/p&gt;
  &lt;p id=&quot;cP22&quot;&gt;Для того, чтобы самба переходила по символьным ссылкам, придётся ещё какие-то опции указывать. Их тут нет. /etc/samba/smb.conf&lt;/p&gt;
  &lt;pre id=&quot;Kmn8&quot;&gt;[share]
  path = /mnt/data/share/
  read only = yes
  guest ok = yes
  guest only = yes&lt;/pre&gt;
  &lt;h3 id=&quot;IiXh&quot;&gt;sshfs&lt;/h3&gt;
  &lt;p id=&quot;YaVq&quot;&gt;Очень удобный вариант, можно удалённую папку примонтировать как папку у себя. Я даже alias завёл: &lt;/p&gt;
  &lt;pre id=&quot;AgQR&quot;&gt;alias mount-pi8=&amp;quot;sshfs -o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3 ubuntu@192.168.1.120:/ /home/me/Desktop/pi8&amp;quot;
alias umount-pi8=&amp;quot;umount /home/me/Desktop/pi8&amp;quot;&lt;/pre&gt;
  &lt;p id=&quot;pJj6&quot;&gt;Единственное - несмотря на параметры, оно как-то криво работает при покидании домашней сети. Ноутбук был не рад, пришлось перезагружать. По тем же причинам в автозапуск такое ставить не надо. Руками каждый раз монтировать - чуточку лень. Возможно, я всё-таки донастрою самбу или ещё что-то.&lt;/p&gt;
  &lt;p id=&quot;0Xnd&quot;&gt;В остальном - шикарно, скорость работы близка к скорости жёсткого диска (возможно, не современного, а десятилетней давности, но всё же).&lt;/p&gt;
  &lt;h3 id=&quot;Dbx3&quot;&gt;Хранение git-репозиториев&lt;/h3&gt;
  &lt;p id=&quot;zfAx&quot;&gt;Я не стал использовать что-то типа gitlab и пошёл по максимально простому пути. В git сервер и клиент равноправны, на клиенте хранится своя копия данных. Между ними нет большой разницы, и я под сервером подразумеваю круглосуточно работающий ПК, и предполагаю что клиент запускается время от времени и закидывает на сервер свои изменения.&lt;/p&gt;
  &lt;p id=&quot;bUZn&quot;&gt;Адресов для скачивания/заливания репозитория может быть несколько. Обычно он один и называется origin. Но никто не запретит добавить несколько адресов, выкачать ветку с одного и потом её влить по другому адресу. И даже в совершенно другой репозиторий так можно, лишь бы имена веток не пересекались. Гибкость впечатляет, хоть про неё и не все знают.&lt;/p&gt;
  &lt;p id=&quot;Vd6q&quot;&gt;Если есть ssh доступ к серверу, то добавить туда репозиторий очень просто:&lt;/p&gt;
  &lt;p id=&quot;KoQF&quot;&gt;На сервере: создать папку, в ней вызвать&lt;/p&gt;
  &lt;pre id=&quot;RbBG&quot;&gt;git init --bare&lt;/pre&gt;
  &lt;p id=&quot;p4P5&quot;&gt;На клиенте:&lt;/p&gt;
  &lt;pre id=&quot;1Ytd&quot;&gt;git remote add pi8 ssh://user@ip/path-to-repo
git push pi8 master&lt;/pre&gt;
  &lt;p id=&quot;eLjl&quot;&gt;В идеале ещё можно создать отдельного пользователя для git и т.п., но для локального домашнего применения не вижу смысла. &lt;/p&gt;
  &lt;p id=&quot;U0jz&quot;&gt;Подробнее можно прочитать тут: &lt;a href=&quot;https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server&quot; target=&quot;_blank&quot;&gt;https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server&lt;/a&gt;&lt;/p&gt;
  &lt;h3 id=&quot;r25n&quot;&gt;RAID массив&lt;/h3&gt;
  &lt;p id=&quot;izyF&quot;&gt;В итоге я отказался от этой идеи.&lt;br /&gt;С помощью mdadm можно сделать raid1 массив, в котором данные будут лежать в двух копиях. Одна на одном диске и другая на другом. Т.к. диски обычно неравных размеров, лучше вместо указания дисков (типа /dev/sda) использовать разделы: например /dev/sda1. Само собой, разделы должны быть на разных дисках. В случае отказа одного из дисков массив с данными продолжит работать как ни в чём ни бывало, пока не откажет второй диск. В общем, за статусом raid массива надо будет следить (и мне кажется, это неудобно).&lt;/p&gt;
  &lt;p id=&quot;ljVg&quot;&gt;Вдобавок, я сделал раздел с raid только для важных данных, и при отказе основного диска ОС похерится и малинка всё равно не запустится. Я подумал над этим безобразием и решил вместо этого сделать бэкапы.&lt;/p&gt;
  &lt;h3 id=&quot;SyH7&quot;&gt;Бэкапы&lt;/h3&gt;
  &lt;p id=&quot;0S5t&quot;&gt;В отличие от raid массива, у бэкапов есть очень полезное свойство - при случайном удалении файлов их можно будет восстановить.&lt;/p&gt;
  &lt;p id=&quot;MEyU&quot;&gt;Я подумал над возможными вариантами:&lt;/p&gt;
  &lt;ul id=&quot;JM36&quot;&gt;
    &lt;li id=&quot;8lkr&quot;&gt;есть специальное ПО типа &lt;a href=&quot;https://ru.wikipedia.org/wiki/Bacula&quot; target=&quot;_blank&quot;&gt;https://ru.wikipedia.org/wiki/Bacula&lt;/a&gt;. Инкрементальные бэкапы хранятся в каком-то бинарном формате, само ПО надо ставить и настраивать.&lt;/li&gt;
    &lt;li id=&quot;HGVy&quot;&gt;rsync + cron. Внезапно, rsync умеет делать инкрементальные бэкапы. Чтобы не хранить один файл по многу раз, используюся жёсткие ссылки. С точки зрения меня как пользователя получатся папки типа backup1, backup2, и т.д, в каждой из которых лежат все файлы на момент копирования. &lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;cyAJ&quot;&gt;На мой взгляд, с rsync самый удобный вариант  - я смогу вставить диск с бэкапами в любой комп и вытащить данные обратно. &lt;/p&gt;
  &lt;p id=&quot;BRCy&quot;&gt;Я вдохновлялся вот этой статьёй: &lt;a href=&quot;https://linuxconfig.org/how-to-create-incremental-backups-using-rsync-on-linux&quot; target=&quot;_blank&quot;&gt;https://linuxconfig.org/how-to-create-incremental-backups-using-rsync-on-linux&lt;/a&gt;, но сделал немножко по-другому:&lt;/p&gt;
  &lt;pre id=&quot;dxlH&quot;&gt;readonly DATETIME=&amp;quot;$(date &amp;#x27;+%Y-%m-%d_%H:%M:%S&amp;#x27;)&amp;quot;
readonly LOG_FILE=&amp;quot;/mnt/backup/logs/backup_safedata_${DATETIME}.txt&amp;quot;

printf &amp;quot;start at ${DATETIME}\n&amp;quot; &amp;gt;&amp;gt; $LOG_FILE

rsync -av --delete /mnt/safedata --link-dest ../latest --exclude &amp;quot;lost+found&amp;quot; /mnt/backup/safedata/${DATETIME} &amp;gt;&amp;gt; $LOG_FILE

df &amp;gt;&amp;gt; $LOG_FILE
echo &amp;quot;finished at $(date &amp;#x27;+%Y-%m-%d_%H:%M:%S&amp;#x27;)&amp;quot; &amp;gt;&amp;gt; $LOG_FILE

cd /mnt/backup/safedata
rm latest
ln -s ${DATETIME} latest

python3 -c &amp;#x27;
import os
import shutil
listdir = os.listdir(&amp;quot;.&amp;quot;)
files = sorted([f for f in listdir if f.startswith(&amp;quot;20&amp;quot;)])
to_preserve = set(files[-31:])
monthly = {f[:7]: f for f in reversed(files)}
to_preserve.update(monthly.values())
for f in sorted(to_preserve):
	print(f&amp;quot;keep &amp;#x27;{f}&amp;#x27;&amp;quot;)
for f in set(files) - to_preserve:
    print(f&amp;quot;remove &amp;#x27;{f}&amp;#x27;&amp;quot;)
    shutil.rmtree(f)
&amp;#x27; &amp;gt;&amp;gt; $LOG_FILE
&lt;/pre&gt;
  &lt;p id=&quot;bxkE&quot;&gt;latest - мягкая ссылка на последний бэкап. В --link-dest путь должен быть абсолютный или относительный для папки с бэкапом, поэтому надо выскочить на директорию вверх: ../latest&lt;/p&gt;
  &lt;p id=&quot;VyB4&quot;&gt;если ссылки нет, то rsync всё ещё работает.&lt;/p&gt;
  &lt;p id=&quot;8CFS&quot;&gt;Логи я решил каждый раз писать в отдельный файл, так как иначе при добавлении большого количества файлов он превращается в многомегабайтный лог и в нём сложно найти, что в какой день происходило. Папка для логов сама не создастся, надо добавить её вручную&lt;/p&gt;
  &lt;p id=&quot;MNMs&quot;&gt;скрипт на питоне хранит последние 30 версий бэкапа и первую версию каждого месяца, остальные удаляет.&lt;/p&gt;
  &lt;p id=&quot;vGp9&quot;&gt;Для отладки есть полезные опции &lt;code&gt;--dry-run&lt;/code&gt; для запуска без реальных изменений, а так же можно опцию &lt;code&gt;--verbose&lt;/code&gt; указать дважды и получить более подробный вывод: &lt;code&gt;-vv&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;gSt0&quot;&gt;Опция -a раскрывается в кучу настроек, которые пытаются перетащить время, пользователя файла, права доступа и т.п. Я попробовал запускать rsync между компом и малинкой и несмотря на &lt;code&gt;--link-dest&lt;/code&gt; создавались копии файлов. Я потратил кучу времени на то, чтобы понять, что все эти опции мешают и в итоге между машинами копировал с опциями &lt;code&gt;-rl --size-only&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;1pVs&quot;&gt;В этом случае время игнорируется, а файл с тем же размером считается не требующим копирования. Можно ещё указать --checksum, но тогда и передающая и принимающая стороны будут считать md5 чексуммы для файлов, что потребует их полного прочтения. Я решил забить и ограничиться проверкой размера.&lt;/p&gt;
  &lt;p id=&quot;29vR&quot;&gt;C помощью cron можно будет настроить бэкапы на каждый день или каждую неделю:&lt;/p&gt;
  &lt;pre id=&quot;RKHP&quot;&gt;crontab -e&lt;/pre&gt;
  &lt;p id=&quot;O2Th&quot;&gt;и там написать&lt;/p&gt;
  &lt;pre id=&quot;aP0d&quot;&gt;20 4 * * * /mnt/backup/backup.sh&lt;/pre&gt;
  &lt;p id=&quot;4Hxg&quot;&gt;Чтобы каждую ночь в 4:20 делать бэкап.&lt;/p&gt;
  &lt;h2 id=&quot;DGEW&quot;&gt;Загрузка по сети*&lt;/h2&gt;
  &lt;p id=&quot;YIPK&quot;&gt;*Задание со звёздочкой, будут приключения.&lt;/p&gt;
  &lt;p id=&quot;rr40&quot;&gt;Заливать образ на флешку, вставлять в малинку, ждать пока загрузится - не самое весёлое занятие. После того, как перевая малинка стала работающим 24/7 полноценным сервером, я раздобыл вторую и решил попробовать загрузку по сети.&lt;/p&gt;
  &lt;p id=&quot;Ydto&quot;&gt;Глобально это состоит из двух шагов:&lt;/p&gt;
  &lt;ol id=&quot;9Zfw&quot;&gt;
    &lt;li id=&quot;JDe5&quot;&gt;включить на клиентской малинке загрузку по сети&lt;/li&gt;
    &lt;li id=&quot;oApB&quot;&gt;настроить на сервере dhcp и nfs, чтобы они работали&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;ZWJl&quot;&gt;Из принципиальных ограничений - клиентская малинка должна быть подключена к сети по проводу, а не через wifi.&lt;/p&gt;
  &lt;p id=&quot;9oSG&quot;&gt;Список команд и т.п. несложный, но в процессе я нашёл кучу подводных камней, и настройка заняла у меня целый вечер.&lt;/p&gt;
  &lt;p id=&quot;6MMR&quot;&gt;&lt;a href=&quot;https://www.raspberrypi.com/documentation/computers/remote-access.html#network-boot-your-raspberry-pi&quot; target=&quot;_blank&quot;&gt;https://www.raspberrypi.com/documentation/computers/remote-access.html#network-boot-your-raspberry-pi&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;mYHu&quot;&gt;Вот ссылка на документацию, но делать надо далеко не всё, что в ней написано.&lt;/p&gt;
  &lt;h3 id=&quot;2hMC&quot;&gt;Настройка клиента&lt;/h3&gt;
  &lt;p id=&quot;wtoa&quot;&gt;На 4B, загрузку включать надо, причём процесс отличается от предыдущих версий.&lt;/p&gt;
  &lt;p id=&quot;PZDa&quot;&gt;Во-первых, понадобится поставить именно raspbian os. В принципе, можно обойтись и без подключения мышки-клавиатуры, если в rpi Imager нажать ctrl+shift+x (или какое-то ещё неочевидное сочетание клавиш), оказаться в настройках и там указать ключ для ssh. Экран я советую всё-таки подключить, он потом пригодится.&lt;/p&gt;
  &lt;p id=&quot;7P0N&quot;&gt;Запускаем штуку для настройки (прям из консоли)&lt;/p&gt;
  &lt;pre id=&quot;m47G&quot;&gt;sudo raspi-config&lt;/pre&gt;
  &lt;p id=&quot;bPjV&quot;&gt;В ней в менюшках надо выбрать &lt;code&gt;Advanced Options&lt;/code&gt;, &lt;code&gt;Boot Order&lt;/code&gt;, &lt;code&gt;Network Boot&lt;/code&gt;и в ней выбрать загрузку по сети (что странно - с загрузкой по сети вариант ровно один - малинка попытается загрузиться с sd карты, если не получится - то по сети).&lt;/p&gt;
  &lt;p id=&quot;mPau&quot;&gt;Чтобы изменения применились, придётся перезагрузиться.&lt;/p&gt;
  &lt;p id=&quot;c3sx&quot;&gt;И потом командой &lt;/p&gt;
  &lt;pre id=&quot;6FKR&quot;&gt;vcgencmd bootloader_config&lt;/pre&gt;
  &lt;p id=&quot;UK51&quot;&gt;можно посмотреть, что в BOOT_ORDER. В идеале там должно быть 0xf21. Тут можно посмотреть подробнее, что же число значит:&lt;/p&gt;
  &lt;p id=&quot;Zapr&quot;&gt;&lt;a href=&quot;https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-4-bootloader-configuration&quot; target=&quot;_blank&quot;&gt;https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-4-bootloader-configuration&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;G6ES&quot;&gt;Я так понял, они справа налево идут.&lt;/p&gt;
  &lt;p id=&quot;ZuFa&quot;&gt;После этого малинку можно выключить, выдернуть из неё sd-карту и снова включить. Выше я советовал включить экран - малинка на нём покажет текстом свой ip адрес и потихоньку растущее количество неудачных попыток загрузки по сети.&lt;/p&gt;
  &lt;h3 id=&quot;ixri&quot;&gt;Настройка сервера&lt;/h3&gt;
  &lt;p id=&quot;k4QE&quot;&gt;Дальше инструкции с официального сайта следовать не обязательно.&lt;/p&gt;
  &lt;p id=&quot;W623&quot;&gt;Во-первых, можно просто взять и на на домашнем роутере во вкладочке с настройками DHCP указать статические ip адреса для сервера (давно уже так сделал) и для клиента (сделал сейчас).&lt;/p&gt;
  &lt;p id=&quot;9bxc&quot;&gt;Во вторых, у меня клиент - raspbian os, а сервер ubuntu. На сайте происходит кунг-фу по включению той же самой sd-карты в сервер, загрузке с неё и дальнейшей модификации для того, чтобы клиент и сервер различались. Спасибо, но я воздержусь.&lt;/p&gt;
  &lt;p id=&quot;W4c2&quot;&gt;Итак, можно смело листать сайт до инструкции &lt;/p&gt;
  &lt;pre id=&quot;yrYk&quot;&gt;sudo apt install tcpdump dnsmasq
sudo systemctl enable dnsmasq
sudo tcpdump -i eth0 port bootpc&lt;/pre&gt;
  &lt;p id=&quot;wDam&quot;&gt;Но dnsmasq ставить пока не надо.&lt;/p&gt;
  &lt;p id=&quot;nS9U&quot;&gt;С помощью tcpdump можно убедиться, что малинка при загрузке действительно посылает запросы всем в локальной сети.&lt;/p&gt;
  &lt;p id=&quot;YId5&quot;&gt;С dnsmasq меня ждал сюрприз. Это в одном лице и dns сервер, и нужные нам dhcp и tftp сервера. В ubuntu уже есть свой dns-резолвер, systemd-resolved, и он, как нетрудно догадаться, тоже dns сервер, который слушает порт 53 и не даёт слушать его другим. &lt;/p&gt;
  &lt;p id=&quot;g0VB&quot;&gt;После установки dnsmasq полезет на 53 порт и не сможет - тот уже занят. Всё что надо сделать - залезть в /etc/dnsmasq.conf и указать там port=0, чтобы dns-составляющая не запускалась и не мешалась.&lt;/p&gt;
  &lt;p id=&quot;s7ud&quot;&gt;&lt;a href=&quot;https://askubuntu.com/questions/191226/dnsmasq-failed-to-create-listening-socket-for-port-53-address-already-in-use&quot; target=&quot;_blank&quot;&gt;https://askubuntu.com/questions/191226/dnsmasq-failed-to-create-listening-socket-for-port-53-address-already-in-use&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;WubI&quot;&gt;Я вместо этого воспользовался первым нагугленным советом и отключил systemd-resolved. В итоге dns работать перестал, я узнал, что команде sudo без dns работается плохо и потом возвращал всё обратно.&lt;/p&gt;
  &lt;p id=&quot;PIxB&quot;&gt;так вот, в dnsmasq.conf должно в итоге быть&lt;/p&gt;
  &lt;pre id=&quot;ItJr&quot;&gt;port=0
dhcp-range=192.168.1.255,proxy
log-dhcp
enable-tftp
tftp-root=/tftpboot
pxe-service=0,&amp;quot;Raspberry Pi Boot&amp;quot;&lt;/pre&gt;
  &lt;p id=&quot;501o&quot;&gt;tftp-root - путь к папке с загрузчиком на сервере&lt;/p&gt;
  &lt;h3 id=&quot;LAfv&quot;&gt;как скопировать системный раздел на сервер&lt;/h3&gt;
  &lt;p id=&quot;ye9z&quot;&gt;В оригинальной статье они обходятся одной sd-картой, но я по понятным причинам включил sd-карту в ноутбук и задумался, как же скопировать её на сервер. Суть проблемы в том, что &lt;/p&gt;
  &lt;pre id=&quot;Y7sI&quot;&gt;rsync from to&lt;/pre&gt;
  &lt;p id=&quot;Bm1i&quot;&gt;не может скопировать файлы, принадлежащие root и запрещённые другим для чтения. А поскольку мы копируем системный раздел, там такие файлы будут.&lt;/p&gt;
  &lt;p id=&quot;68ib&quot;&gt;Можно написать так:&lt;/p&gt;
  &lt;pre id=&quot;HPZm&quot;&gt;sudo rsync from to&lt;/pre&gt;
  &lt;p id=&quot;d6sm&quot;&gt;Тогда получится скопировать файлы с владельцем root, но не получится их записать по двум причинам:&lt;/p&gt;
  &lt;ol id=&quot;zO6R&quot;&gt;
    &lt;li id=&quot;dD9C&quot;&gt;у рута своя папка .ssh и там может не быть ключа для ssh&lt;/li&gt;
    &lt;li id=&quot;M3mm&quot;&gt;на системе, куда копируем, rsync работает не из под-рута&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;uNjz&quot;&gt;Красота и удобство. Указать root@ip:/path у меня тоже не получилось. Первая проблема решается копированием ~/.ssh/id_rsa, вторая - хитрой опцией. Для хитрой опции требуется, чтобы на другой машине команда sudo не спрашивала пароль. Рабочая команда выглядит так:&lt;/p&gt;
  &lt;pre id=&quot;qpeM&quot;&gt;sudo rsync --progress -ax -e &amp;quot;ssh&amp;quot; --rsync-path=&amp;quot;sudo rsync&amp;quot; rootfs/ ubuntu@192.168.1.142:/nfs/client1&lt;/pre&gt;
  &lt;p id=&quot;Gxml&quot;&gt;Таким незамысловатым образом можно скопировать загрузчик в /nfs/nfsboot, а системный раздел в /nfs/client1&lt;/p&gt;
  &lt;p id=&quot;2chM&quot;&gt;Идею и команду взял отсюда: &lt;a href=&quot;https://superuser.com/questions/605425/rsync-root-files-between-systems-without-specifying-password&quot; target=&quot;_blank&quot;&gt;https://superuser.com/questions/605425/rsync-root-files-between-systems-without-specifying-password&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;HBUd&quot;&gt;После этого надо будет в nfsboot/cmdline.txt заменить указание на root: у меня получилось так:&lt;/p&gt;
  &lt;pre id=&quot;gr7g&quot;&gt;console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.1.142:/nfs/client1,vers=4.1,proto=tcp rw ip=dhcp rootwait&lt;/pre&gt;
  &lt;p id=&quot;FxxZ&quot;&gt;и поправить etc/fstab&lt;/p&gt;
  &lt;pre id=&quot;wmEy&quot;&gt;192.168.1.142:/nfs/tftpboot	/boot	nfs	defaults,vers=4.1,proto=tcp 0 0&lt;/pre&gt;
  &lt;p id=&quot;npPF&quot;&gt;То, что есть только boot без корневой системы - нормально, так и должно быть&lt;/p&gt;
  &lt;p id=&quot;uumZ&quot;&gt;Кроме того, надо ещё включить rpcbind, настроить nfs-kernel-server и в /etc/exports указать пути для nfs:&lt;/p&gt;
  &lt;pre id=&quot;IlSx&quot;&gt;/nfs/client1 *(rw,sync,no_subtree_check,no_root_squash)
/nfs/tftpboot *(rw,sync,no_subtree_check,no_root_squash)&lt;/pre&gt;
  &lt;p id=&quot;hoUE&quot;&gt;В результате малинка без SD-карты загружается по сети из файлов в папке. При желании ту папку можно будет копировать, хранить несколько разных версий ОС и т.п.&lt;/p&gt;
  &lt;h3 id=&quot;W2jL&quot;&gt;Пассивное охлаждение&lt;/h3&gt;
  &lt;p id=&quot;wYen&quot;&gt;Температуру можно узнать так:&lt;/p&gt;
  &lt;pre id=&quot;BkTV&quot;&gt;vcgencmd measure_temp&lt;/pre&gt;
  &lt;p id=&quot;MQXT&quot;&gt;У меня она была 64 градуса (с нагрузкой из описанного выше софта), после - 57. Я купил корпус Qumo Aluminum RS001, который заодно является радиатором. Охлаждение пассивное, вентилятора нет и ломаться нечему. И шуметь тоже. Сам корпус, кажется, сделан из аллюминия. Смотрится красиво и солидно. В комплекте шли два маленьких кусочка термопрокладки, болтики и шестигранный ключик - в общём, всё необходимое. &lt;/p&gt;
  &lt;p id=&quot;812W&quot;&gt;Эффектом немного разочарован, думал будет градусов 10-15 разницы, а получилось около 7. Сам корпус ощутимо горячий во всех местах&lt;/p&gt;
  &lt;h3 id=&quot;38Fs&quot;&gt;LUKS шифрование раздела&lt;/h3&gt;
  &lt;p id=&quot;Vmkh&quot;&gt;Опциональная часть, надо чётко понимать, нужно ли шифрование. Цель - чтобы содержимое диска было невозможно прочитать при включении в посторонний пк.&lt;/p&gt;
  &lt;p id=&quot;bHSm&quot;&gt;Если пароль от раздела будет храниться где-то на малинке, то затея бессмысленная. Я планирую заходить на малинку по ssh и руками подключать зашифрованный раздел. Кроме того - для самой малинки, пока она работает, пароль известен. Если сама малинка скомпроментирована - то злоумышленник и имеет доступ к диску, и может утащить к себе пароль.&lt;/p&gt;
  &lt;p id=&quot;oxf6&quot;&gt;Шифрование спасает только от сценария, когда постороний забирает диск и пытается прочитать с него данные. Всё, ничего больше.&lt;/p&gt;
  &lt;p id=&quot;t0qL&quot;&gt;Я где-то видел, чтобы на малине как-то хитро шифровали прям диск с системой, но я так извращаться не буду. В малинке негде хранить пароль, и я хочу, чтобы она могла сама включиться без моего участия. Шифрую только отдельный раздел с данными.&lt;/p&gt;
  &lt;p id=&quot;F01J&quot;&gt;Итак, если шифрование всё-таки нужно, начнём:&lt;/p&gt;
  &lt;p id=&quot;TaEl&quot;&gt;Скорее всего, cryptsetup уже установлен, если нет, ставим:&lt;/p&gt;
  &lt;pre id=&quot;anca&quot;&gt;sudo apt install cryptsetup&lt;/pre&gt;
  &lt;p id=&quot;0qAC&quot;&gt;Особенности малинки - нет хардварной поддержки aes, скорость шифровки и дешифровки будет медленная, советуют вместо него использовать adiantum. &lt;/p&gt;
  &lt;p id=&quot;TLu9&quot;&gt;Проверить скорость шифрования (без записи на диск, всё в RAM):&lt;/p&gt;
  &lt;pre id=&quot;Z3ng&quot;&gt;cryptsetup benchmark
# Tests are approximate using memory only (no storage IO).
PBKDF2-sha1       386643 iterations per second for 256-bit key
PBKDF2-sha256     630912 iterations per second for 256-bit key
PBKDF2-sha512     510007 iterations per second for 256-bit key
PBKDF2-ripemd160  324034 iterations per second for 256-bit key
PBKDF2-whirlpool  142935 iterations per second for 256-bit key
argon2i       4 iterations, 333516 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
argon2id      4 iterations, 335222 memory, 4 parallel threads (CPUs) for 256-bit key (requested 2000 ms time)
#     Algorithm |       Key |      Encryption |      Decryption
        aes-cbc        128b        85.6 MiB/s        98.5 MiB/s
    serpent-cbc        128b        42.7 MiB/s        44.4 MiB/s
    twofish-cbc        128b        63.3 MiB/s        69.1 MiB/s
        aes-cbc        256b        76.0 MiB/s        77.5 MiB/s
    serpent-cbc        256b        43.8 MiB/s        44.4 MiB/s
    twofish-cbc        256b        68.1 MiB/s        69.2 MiB/s
        aes-xts        256b        84.4 MiB/s       101.8 MiB/s
    serpent-xts        256b        43.1 MiB/s        44.8 MiB/s
    twofish-xts        256b        67.9 MiB/s        70.7 MiB/s
        aes-xts        512b        78.6 MiB/s        79.8 MiB/s
    serpent-xts        512b        44.9 MiB/s        44.7 MiB/s
    twofish-xts        512b        70.5 MiB/s        70.6 MiB/s
&lt;/pre&gt;
  &lt;p id=&quot;FIrA&quot;&gt;И померять aes-adiantum, который должен быть быстрее&lt;/p&gt;
  &lt;pre id=&quot;6qa8&quot;&gt;cryptsetup benchmark -c xchacha12,aes-adiantum
# Tests are approximate using memory only (no storage IO).
#            Algorithm |       Key |      Encryption |      Decryption
xchacha12,aes-adiantum        256b       188.1 MiB/s       189.2 MiB/s


cryptsetup benchmark -c xchacha20,aes-adiantum
# Tests are approximate using memory only (no storage IO).
#            Algorithm |       Key |      Encryption |      Decryption
xchacha20,aes-adiantum        256b       161.0 MiB/s       162.2 MiB/s

&lt;/pre&gt;
  &lt;p id=&quot;qQmr&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;syTj&quot;&gt;Ссылки, которыми я руководствовался:&lt;/p&gt;
  &lt;p id=&quot;pLPI&quot;&gt;&lt;a href=&quot;https://gist.github.com/palopezv/792b9f0100484186c3f74cbee7b07630&quot; target=&quot;_blank&quot;&gt;https://gist.github.com/palopezv/792b9f0100484186c3f74cbee7b07630&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;EKny&quot;&gt;&lt;a href=&quot;https://wiki.davidl.me/index.php?title=LUKS&amp;mobileaction=toggle_view_desktop&quot; target=&quot;_blank&quot;&gt;https://wiki.davidl.me/index.php?title=LUKS&amp;amp;mobileaction=toggle_view_desktop&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;Ddnt&quot;&gt;Я выбрал xchacha20, т.к. разница в скорости не критичная, а оно вроде как надёжнее. &lt;/p&gt;
  &lt;p id=&quot;Dfi8&quot;&gt;xchacha20 отличается в xchacha12 количеством раундов шифрования - 20 вместо 12.&lt;/p&gt;
  &lt;p id=&quot;fEvh&quot;&gt;Где почитать: &lt;a href=&quot;https://www.reddit.com/r/cryptography/comments/p3dflu/fulldiskencryption_xchacha12_vs_xchacha20/&quot; target=&quot;_blank&quot;&gt;https://www.reddit.com/r/cryptography/comments/p3dflu/fulldiskencryption_xchacha12_vs_xchacha20/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;f5BJ&quot;&gt;Создадим раздел:&lt;/p&gt;
  &lt;pre id=&quot;mZQS&quot;&gt;sudo cryptsetup luksFormat --type=luks2 --sector-size=4096 -c xchacha20,aes-adiantum-plain64 -s 256 -h sha512 --use-urandom /dev/sdXX&lt;/pre&gt;
  &lt;p id=&quot;trwy&quot;&gt;Тут вместо sdXX написать реальный раздел как он показывается в lsblk&lt;/p&gt;
  &lt;p id=&quot;WN2y&quot;&gt;Дальше был забавный момент - после всего программа требует написать YES большими буковками. Просто чтобы убедиться, что человек внимательно посмотрел на команду и случайно не похерит нужный раздел.&lt;/p&gt;
  &lt;p id=&quot;qLht&quot;&gt;Дальше надо подключить раздел и отформатировать&lt;/p&gt;
  &lt;pre id=&quot;Ptnd&quot;&gt;sudo cryptsetup open /dev/sdXX NAME
sudo mkfs.ext4 /dev/mapper/NAME&lt;/pre&gt;
  &lt;p id=&quot;K8iX&quot;&gt;Примонтировать раздел:&lt;/p&gt;
  &lt;pre id=&quot;s1fz&quot;&gt;# Open the encrypted drive
sudo cryptsetup open /dev/sdXX NAME
# Mount your partition
mount -t ext4 /dev/mapper/NAME MOUNT_LOCATION&lt;/pre&gt;
  &lt;p id=&quot;MMi3&quot;&gt;Размонтировать:&lt;/p&gt;
  &lt;pre id=&quot;0c77&quot;&gt;# Unmount your partition
umount MOUNT_LOCATION
# Close the decrypted drive
cryptsetup close NAME&lt;/pre&gt;
  &lt;h2 id=&quot;dJaY&quot;&gt;Выводы&lt;/h2&gt;
  &lt;p id=&quot;VIDG&quot;&gt;Если хочется только домашнее хранилище - проще и дешевле подключить диск напрямую к роутеру (некоторые роутеры так умеют). Но мне хотелось иметь полноценный сервер, хоть и маленький. Своей цели я достиг и очень доволен.&lt;/p&gt;

</content></entry></feed>