Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Davydov <lotigara@lotigara.ru>2025-06-24 14:03:34 +0300
committerIvan Davydov <lotigara@lotigara.ru>2025-06-24 14:03:34 +0300
commita2e3bec40f5851be70299e7513967a0f5d042bf9 (patch)
tree5234a58ac93fa6c4752075a5128f183da0725c13
Initial commitmaster
-rw-r--r--conf11
-rw-r--r--imgs/test1
-rw-r--r--input/00000-blog/00000-fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos.html22
-rw-r--r--input/00000-blog/00001-openwrt-24101------keenetic-launcher-kn-1221.html346
-rw-r--r--input/00000-blog/00002-pubnix----prosody--pam-.html191
-rw-r--r--input/00000-blog/00003-download-mods-for-a-steam-game-from-the-steam-workshop.html11
-rw-r--r--input/rss.conf5
-rw-r--r--public/_/imgs/test1
-rw-r--r--public/_/script.js14
-rw-r--r--public/_/style.css80
-rw-r--r--public/blog/0/index.html598
-rw-r--r--public/blog/download-mods-for-a-steam-game-from-the-steam-workshop/index.html35
-rw-r--r--public/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/index.html45
-rw-r--r--public/blog/feed.rss596
-rw-r--r--public/blog/index.html598
-rw-r--r--public/blog/openwrt-24101------keenetic-launcher-kn-1221/index.html370
-rw-r--r--public/blog/pubnix----prosody--pam-/index.html214
-rw-r--r--public/feed.rss14
-rw-r--r--public/index.html598
l---------theme/css/01-responsivity.css1
-rw-r--r--theme/html/index.html13
l---------theme/html/menu.html1
-rw-r--r--theme/html/menu_logo.html3
-rw-r--r--theme/html/menu_section.html10
-rw-r--r--theme/html/page.html9
-rw-r--r--theme/html/post.html8
26 files changed, 3795 insertions, 0 deletions
diff --git a/conf b/conf
new file mode 100644
index 0000000..d046b2e
--- /dev/null
+++ b/conf
@@ -0,0 +1,11 @@
+title: &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara
+logo: false
+posts_per_page: 5
+root: /blog
+rss: true
+rss_level: subsection
+rss_drafts: true
+rss_fullcontent: true
+url: https://www.lotigara.ru
+use_guid: true
+use_pubdate: true
diff --git a/imgs/test b/imgs/test
new file mode 100644
index 0000000..d6a2d5c
--- /dev/null
+++ b/imgs/test
@@ -0,0 +1 @@
+Foo.
diff --git a/input/00000-blog/00000-fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos.html b/input/00000-blog/00000-fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos.html
new file mode 100644
index 0000000..8930962
--- /dev/null
+++ b/input/00000-blog/00000-fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos.html
@@ -0,0 +1,22 @@
+<!--
+ author: Lotigara
+ category: keeneticos
+ category: openwrt
+ category: wifi
+ category: wifi-roaming
+-->
+<h1>Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS</h1>
+
+<h5>tested to not work on KeeneticOS v3.8.7 &amp; OpenWrt v23.05.5</h5>
+
+<p>First, set up FT on your OpenWrt devices.</p>
+
+<p>Then, change the mode of your Keenetic (?) devices to Extender (there are Repeater/Extender and Access Point/Extender, the last is the recommended).</p>
+
+<p>Go to the <code>Access Point/Extender (Repeater/Extender) &gt; Home segment</code> menu. Change the settings of the Wi-Fi network to those ones in OpenWrt.</p>
+
+<p>Scroll below to the "Roaming for wireless devices" section. Enable "Fast transition (802.11r)" and write your mobility domain ID converted to the ASCII format.</p>
+
+<p>You can use an online converter like this one: <a href="https://www.rapidtables.com/convert/number/hex-to-ascii.html">https://www.rapidtables.com/convert/number/hex-to-ascii.html</a>. Keep the "Mobility domain key" field unedited.</p>
+
+<p>Press the "Save" button. Now you have a so-called "Wi-Fi system" with use of both KeeneticOS and OpenWrt!</p>
diff --git a/input/00000-blog/00001-openwrt-24101------keenetic-launcher-kn-1221.html b/input/00000-blog/00001-openwrt-24101------keenetic-launcher-kn-1221.html
new file mode 100644
index 0000000..dde3544
--- /dev/null
+++ b/input/00000-blog/00001-openwrt-24101------keenetic-launcher-kn-1221.html
@@ -0,0 +1,346 @@
+<!--
+ author: Lotigara
+ category: openwrt
+ category: &rcy;&acy;&zcy;&rcy;&acy;&bcy;&ocy;&tcy;&kcy;&acy;
+ category: &icy;&zcy;&mcy;&iecy;&ncy;&iocy;&ncy;&ncy;&ycy;&iecy; &pcy;&rcy;&ocy;&shcy;&icy;&vcy;&kcy;&icy;
+-->
+<h1>OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221)</h1>
+
+<p>Вот оно:
+<summary>
+<details></p>
+
+<pre>
+From ef20327e33fb38220ba0bca4418464749305e555 Mon Sep 17 00:00:00 2001
+From: Ivan Davydov <lotigara@lotigara.ru>
+Date: Tue, 4 Mar 2025 23:54:13 +0300
+Subject: [PATCH] ramips: mt76x8: add support for Keenetic Launcher (KN-1221)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Specification:
+SoC: MediaTek MT7628AN
+RAM: 128M DDR2, ESMT M14D128168A (2Y)
+Flash: 32M, cFeon EN25QH256A (Dual Boot on OEM, concatenated on OpenWrt,
+SPI)
+Switch: MediaTek MT7628AN, 3 ports 100 Mbps
+WiFi: MediaTek MT7628AN 2.4 GHz 802.11n
+USB: 1 port USB 2.0
+GPIO: 1 button (Wi-Fi & Reset on OEM, Reset on OpenWrt), 3 LEDs (Power,
+Internet, Wi-Fi), USB port power controls
+
+Disassembly:
+There are 2 screws at the bottom near the LEDs hidden by rubber mounts.
+After removing the screws, pry the gray plastic part around (it is secured
+with latches) and remove it.
+
+UART Interface:
+The UART interface can be connected to the 5 pin located between LAN
+ports and the WAN one.
+Pins (from the second LAN port to the WAN one): VCC, TX, RX, NC, GND
+Settings: 115200, 8N1
+
+Flashing via TFTP:
+1. Connect your PC and router to the first LAN port, configure PC
+interface using IP 192.168.1.2, mask 255.255.255.0
+2. Serve the firmware image (for OpenWrt it is *-squashfs-factory.bin)
+renamed to KN-1221_recovery.bin via TFTP
+3. Power up the router while pressing Wi-Fi button
+4. Release Wi-Fi button when Power LED starts blinking
+
+To revert back to OEM firmware:
+The return to the OEM firmware is carried out by using the methods
+described above with the help of the appropriate firmware image found on
+osvault.keenetic.net.
+
+When using OEM bootloader, the firmware image size cannot exceed the size
+of one OEM «Firmware_x» partition or Kernel + rootFS size.
+
+Signed-off-by: Ivan Davydov <lotigara@lotigara.ru>
+Link: https://github.com/openwrt/openwrt/pull/18164
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../ramips/dts/mt7628an_keenetic_kn-1221.dts | 209 ++++++++++++++++++
+ target/linux/ramips/image/mt76x8.mk | 12 +
+ .../mt76x8/base-files/etc/board.d/01_leds | 1 +
+ .../mt76x8/base-files/etc/board.d/02_network | 5 +
+ 4 files changed, 227 insertions(+)
+ create mode 100644 target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+
+diff --git a/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+new file mode 100644
+index 00000000000000..6f5cf96856ed21
+--- /dev/null
++++ b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+@@ -0,0 +1,209 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "mt7628an.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ compatible = "keenetic,kn-1221", "mediatek,mt7628an-soc";
++ model = "Keenetic KN-1221";
++
++ aliases {
++ label-mac-device = &ethernet;
++
++ led-boot = &led_power;
++ led-failsafe = &led_power;
++ led-running = &led_power;
++ led-upgrade = &led_power;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,115200";
++ };
++
++ regulator-usb {
++ compatible = "regulator-fixed";
++ regulator-name = "USB-power";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: power {
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
++ };
++
++ internet {
++ function = LED_FUNCTION_WAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
++ };
++
++ fn {
++ function = LED_FUNCTION_WLAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "phy0tpt";
++ };
++ };
++
++ keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "restart";
++ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++
++ virtual_flash {
++ compatible = "mtd-concat";
++ devices = <&firmware1 &firmware2>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ compatible = "denx,uimage";
++ label = "firmware";
++ reg = <0x0 0x1cc0000>;
++ };
++ };
++ };
++};
++
++&state_default {
++ gpio {
++ groups = "i2c", "spi cs1", "gpio", "refclk", "wdt";
++ function = "gpio";
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <32000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-config";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ partition@40000 {
++ label = "rf-eeprom";
++ reg = <0x40000 0x10000>;
++ read-only;
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom_factory_0: eeprom@0 {
++ reg = <0x0 0x400>;
++ };
++
++ macaddr_factory_4: macaddr@4 {
++ reg = <0x4 0x6>;
++ };
++ };
++ };
++
++ firmware1: partition@50000 {
++ label = "firmware_1";
++ reg = <0x50000 0xe60000>;
++ };
++
++ partition@eb0000 {
++ label = "config_1";
++ reg = <0xeb0000 0x40000>;
++ read-only;
++ };
++
++ partition@ef0000 {
++ label = "storage";
++ reg = <0xef0000 0x100000>;
++ read-only;
++ };
++
++ partition@ff0000 {
++ label = "dump";
++ reg = <0xff0000 0x10000>;
++ read-only;
++ };
++
++ partition@1000000 {
++ label = "u-state";
++ reg = <0x1000000 0x30000>;
++ read-only;
++ };
++
++ partition@1030000 {
++ label = "u-config_res";
++ reg = <0x1030000 0x10000>;
++ read-only;
++ };
++
++ partition@1040000 {
++ label = "rf-eeprom_res";
++ reg = <0x1040000 0x10000>;
++ read-only;
++ };
++
++ firmware2: partition@1050000 {
++ label = "firmware_2";
++ reg = <0x1050000 0xe60000>;
++ };
++
++ partition@1eb0000 {
++ label = "Config_2";
++ reg = <0x1eb0000 0x40000>;
++ read-only;
++ };
++ };
++ };
++};
++
++&ethernet {
++ nvmem-cells = <&macaddr_factory_4>;
++ nvmem-cell-names = "mac-address";
++};
++
++&esw {
++ mediatek,portmap = <0x3e>;
++ mediatek,portdisable = <0x38>;
++};
++
++&wmac {
++ status = "okay";
++
++ nvmem-cells = <&eeprom_factory_0>;
++ nvmem-cell-names = "eeprom";
++};
+diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk
+index 8c8cfee23b6cfa..f442148d9ecf10 100644
+--- a/target/linux/ramips/image/mt76x8.mk
++++ b/target/linux/ramips/image/mt76x8.mk
+@@ -366,6 +366,18 @@ define Device/jotale_js76x8-32m
+ endef
+ TARGET_DEVICES += jotale_js76x8-32m
+
++define Device/keenetic_kn-1221
++ BLOCKSIZE := 64k
++ IMAGE_SIZE := 29440k
++ DEVICE_VENDOR := Keenetic
++ DEVICE_MODEL := KN-1221
++ DEVICE_PACKAGES := kmod-usb2
++ IMAGES += factory.bin
++ IMAGE/factory.bin := $$(sysupgrade_bin) | pad-to $$$$(BLOCKSIZE) | \
++ check-size 14720k | zyimage -d 0x801221 -v "KN-1221"
++endef
++TARGET_DEVICES += keenetic_kn-1221
++
+ define Device/keenetic_kn-1613
+ IMAGE_SIZE := 31488k
+ DEVICE_VENDOR := Keenetic
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+index b87062ae3c5ae5..79f78a2a459487 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+@@ -58,4 +58,5 @@ hiwifi,hc5661a|\
+ hiwifi,hc5761a)
+ ucidef_set_led_switch "internet" "internet" "blue:internet" "switch0" "0x10"
+ ;;
++keenetic,kn-1221|\
+ keenetic,kn-1613)
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+index fbdc7fb5a2697a..6e6e1310d3495f 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+@@ -131,5 +131,9 @@ ramips_setup_interfaces()
+ ucidef_add_switch "switch0" \
+ "0:lan" "1:lan" "2:lan" "6@eth0"
+ ;;
++ keenetic,kn-1221)
++ ucidef_add_switch "switch0" \
++ "1:lan" "2:lan" "0:wan" "6@eth0"
++ ;;
+ keenetic,kn-1613|\
+ motorola,mwr03)
+@@ -280,5 +280,6 @@ ramips_setup_macs()
+ totolink,lr1200)
+ wan_mac=$(mtd_get_mac_binary factory 0x2e)
+ ;;
++ keenetic,kn-1221|\
+ keenetic,kn-1613|\
+ zyxel,keenetic-extra-ii)
+</pre>
+
+<p></details>
+</summary></p>
+
+<p>Или в виде файла: <a href="/files/18164.patch.backport-24.10.1">18164.patch.backport-24.10.1</a>.
+Готовые сборки тоже доступны в виде файлов: <a href="/files/openwrt-kn-1221-24.10">openwrt-kn-1221-24.10</a></p>
diff --git a/input/00000-blog/00002-pubnix----prosody--pam-.html b/input/00000-blog/00002-pubnix----prosody--pam-.html
new file mode 100644
index 0000000..bbcf7e4
--- /dev/null
+++ b/input/00000-blog/00002-pubnix----prosody--pam-.html
@@ -0,0 +1,191 @@
+<!--
+ author: Lotigara
+ category: pubnix
+ category: prosody
+ category: xmpp
+ category: &scy;&icy;&scy;&tcy;&iecy;&mcy;&ncy;&ocy;&iecy; &acy;&dcy;&mcy;&icy;&ncy;&icy;&scy;&tcy;&rcy;&icy;&rcy;&ocy;&vcy;&acy;&ncy;&icy;&iecy;
+-->
+<h1>Pubnix - Установка Prosody с PAM-авторизацией</h1>
+
+<h2>Использованные источники</h2>
+
+<ul>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux</a></li>
+ <li><a href="https://landchad.net/prosody">LandChad</a></li>
+ <li><a href="https://prosody.im">Prosody</a></li>
+</ul>
+
+<h2>0. Системные требования</h2>
+
+<ul>
+ <li>Firewall с следующими открытыми портами:</li>
+ <li>
+ <ul>
+ <li>5000/tcp (передача файлов)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5222/tcp (подключение клиента)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5269/tcp (федерация, подключение сервера к серверу)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5281/tcp (по желанию, но рекомендуется)</li>
+ </ul>
+ </li>
+ <li><p>Debian 12 с последними обновлениями и доступом в Интернет</p></li>
+ <li><p>Prosody &gt;= 0.13</p></li>
+</ul>
+
+<hr>
+
+<h2>0,5. Авторизация при помощи ОС</h2>
+<p>PAM (Pluggable Authentication Modules) - API для авторизации в Unix-подобных ОС, по умолчанию использует список пользователей из файла `/etc/passwd`.</p>
+
+<p>Все команды выполняются пользователем <code>root</code>, если не указано иначе.</p>
+
+<h2>1. Установка</h2>
+<p>Выполните эти команды:</p>
+
+<pre>
+# Установить Prosody
+wget https://prosody.im/files/prosody.sources -O/etc/apt/sources.list.d/prosody.sources
+apt update
+apt install prosody lua5.4 liblua5.4-0 liblua5.4-dev luarocks
+# Добавить привилегии демону Prosody
+usermod -aG shadow prosody
+usermod -aG ssl-cert prosody
+# Установить библиотеку для взаимодействия с <abbr title="Portable Operating System Interface">POSIX</abbr>-функциями
+luarocks install luaposix
+# Собрать библиотеку дл/ PAM-аутентификации
+git clone https://github.com/devurandom/lua-pam &amp;&amp; cd lua-pam
+make LUA_VERSION=5.4
+cp pam.so /usr/lib/
+# Установить модуль для PAM-аутентификации
+LUA_INCDIR=5.4 prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_pam
+</pre>
+
+<h2>2. Настройка</h2>
+<p>Начните редактировать файл <code>/etc/prosody/prosody.cfg.lua</code>.
+Следуйте этим инструкциям, заменяя <code>example.net</code> на доменное имя, привязанное к вашему серверу.</p>
+
+<p>Найдите строку, начинающуюся с слова <code>admins</code>, и добавьте ваше будущее имя пользователя в фигурные скобки подобным образом:</p>
+
+<pre>
+admins = { "admin@example.net" }
+</pre>
+
+<p>Где <code>admin</code> - это ваше имя пользователя в вашей системе.</p>
+
+<p>Дальше найдите строку <code>--"mam";</code> и удалите два дефиса, сделайте то же самое с строкой <code>--"turn_external";</code>, находящейся ниже.</p>
+
+<p>Теперь перейдите к строке <code>authentication = "internal_hashed"</code> и замените <code>internal_hashed</code> на <code>pam</code>.</p>
+
+<p>Перейдите к строке, начинающейся с <code>storage</code> и поменяйте <code>sql</code> на <code>internal</code> (по желанию, в этой инструкции я не рассматриваю настройку с базами данных)</p>
+
+<p>По желанию в строке <code>archive_expires_after = "1w"</code> замените <code>1w</code> на <code>never</code>, чтобы истории переписок не удалялись каждую неделю.</p>
+
+<p>Найдите строку, начинающуюся с <code>VirtualHost</code> и замените <code>localhost</code> на <code>example.net</code>.</p>
+
+<p>Если вам нужны многопользовательские переписки, на следующей строке добавьте следущее:</p>
+
+<pre>
+Component "conference.example.net" "muc"
+modules_enabled = { "muc_mam", "vcard_muc" }
+</pre>
+
+<p>Последнюю строку можете опустить, если вам не нужно сохранение истории многопользовательских переписок.</p>
+
+<p>Если нужна возможность загружать файлы на ваш сервер, дополните конфигурацию следующими строками:</p>
+
+<pre>
+Component "upload.example.net" "http_file_share"
+http_file_share_size_limit = 512 * 1024 * 1024 --измеряется в байтах
+http_file_share_expire_after = 60 * 60 * 24 * 31 * 1000 --измеряется в секундах
+</pre>
+
+<p>В данном случае, лимит размера файла - это 512 МиБ (0,5 ГиБ), а удаляться файлы будут через ~1000 лет.
+Если требуется изменить какое-либо из этих свойств, смотрите комментарии (в Lua они начинаются с двух дефисов) и пробуйте изменять значения.</p>
+
+<h2>3. Настройка TLS-сертификата</h2>
+<p>Также заменяйте `example.net` на ваше доменное имя.</p>
+
+<p>ACME (Automatic Certificate Management Environment) - это протокол для получения TLS-сертификатов по Web.
+В этом примере используется ACME-клиент acme.sh, так как эта программа более настраиваемая и удостоверяющий центр (далее УЦ) Let's Encrypt (но вы можете использовать любой другой).</p>
+
+<p>Выполните следующие команды:</p>
+<pre>
+# Эта команда установит acme.sh в директорию ~/.acme.sh, системные
+# файлы не будут затронуты
+wget -O - https://get.acme.sh | sh -s \
+ email=yourveryownlocalpart@example.net
+# Теперь либо перезайдите в систему, либо выполните `exec $0`, если
+# вы уверены в значении переменной `$0`.
+
+# Проверьте, прошла ли установка правильно
+acme.sh -h
+
+# Установить Let's Encrypt в качестве УЦ
+acme.sh --set-default-ca --server \
+ https://acme-v02.api.letsencrypt.org/directory
+
+# Есть два способа подтверждения владения доменом - по HTTP или по
+# DNS.
+# Первый проще, но требует доступ на запись в директорию, содержимое
+# которой доступно по ссылке http://example.net/:
+acme.sh --issue -d example.net -d conference.example.net -d \
+ upload.example.net -w &lt;директория с корнем вашего
+ веб-сервера&gt;
+# А второй, поддерживая Wildcard-сертификаты, позволяет в дальнейшем
+# подключать к вашему XMPP-серверу всевозможные компоненты
+# (транспорты в другие сети, модуль публикации-подписки, он же
+# Publish-Subscribe или просто PubSub и многие другие), но требует
+# доступа к API вашего DNS-регистратора для создания записи,
+# подтверждающей владение доменным именем:
+acme.sh --issue --dnssleep &lt;время в секундах, большее чем TTL&gt; \
+ --dns dns_myapi \
+ -d example.net -d '*.example.net' # Где dns_myapi - это кодовое
+ # имя DNS-провайдера, указанное на
+ # https://github.com/acmesh-official/acme.sh/wiki/dnsapi
+# Но если у вас нет и веб-сервера (или доступа к нему), и доступа к
+# API регистратора, то вы можете внести запись с подтверждением
+# вручную (заметьте, что вам нужно будет это делать каждый раз, когда
+# будет истекать срок действия сертификата):
+# (Перед применением этого способа следует внимательно прочитать
+# следующую страницу:
+# https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode)
+acme.sh --issue --dns -d example.net -d '*.example.net'
+# Теперь примените DNS-запись, выведенную на экран командой выше, и
+# подождите до её распространения. После выполните следующее:
+acme.sh --renew -d example.net -d '*.example.net'
+
+# Почти готово. Теперь осталось установить сертификат:
+mkdir /etc/ssl/private/example.net
+chown root:ssl-cert /etc/ssl/private/example.net
+chmod 750 /etc/ssl/private/example.net
+acme.sh --install-cert \
+ -d example.net -d '*.example.net' \
+ --ca-file /etc/ssl/private/example.net/chain.pem \
+ --cert-file /etc/ssl/private/example.net/cert.pem \
+ --fullchain-file /etc/ssl/private/example.net/fullchain.pem \
+ --key-file /etc/ssl/private/example.net/privkey.pem \
+ --reloadcmd "prosodyctl --root cert import \
+ /etc/ssl/private/example.net"
+</pre>
+
+<h2>Смотрите также</h2>
+
+<ul>
+ <li><a href="https://stupin.su/blog/prosody-dovecot-sasl">Ещё один блог сисадмина - Настройка Jabber-сервера Prosody с аутентификацией пользователей через Dovecot SASL</a>. Статья немного старая, но если вы настраивали Dovecot так же, как и я (см. главную страницу), то это может вам пригодиться для, например, добавление доступа в XMPP совместно с эл. почтой. Также советую посмотреть конец раздела по настройке SSL (5-ый), там есть скрипт, который будет обновлять сертификаты в Prosody вместе с Certbot.</li>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux - Prosody IM and local users - Networks PYMES</a>. Здесь тоже описывается авторизация с помощью PAM, но она выполнена с использованием ещё одной программы, что, конечно, неэффективно. Эта страница указана в начале, так как автор некоторое время использовал именно инструкцию по ссылке выше.</li>
+</ul>
+
+<hr>
+
+<p>В завершении статьи хочется обратить ваше внимание на то, что данная инструкция предоставляется БЕЗ каких-либо гарантий. Если при выполнении указаний из данной инструкции случилось что-то непредвиденное, вы можете обратиться ко мне, но не стоит ожидать какого-либо результата.</p>
diff --git a/input/00000-blog/00003-download-mods-for-a-steam-game-from-the-steam-workshop.html b/input/00000-blog/00003-download-mods-for-a-steam-game-from-the-steam-workshop.html
new file mode 100644
index 0000000..fc180e4
--- /dev/null
+++ b/input/00000-blog/00003-download-mods-for-a-steam-game-from-the-steam-workshop.html
@@ -0,0 +1,11 @@
+<!--
+ author: Lotigara
+ category: openwrt
+ category: sh
+ category: steam
+-->
+<h1>Download mods for a Steam game from the Steam Workshop</h1>
+
+<pre alt="sh">
+steamcmd "+login $USERID" $(for i in $MODLIST; do echo "+download_item $APPID $i"; done)
+</pre>
diff --git a/input/rss.conf b/input/rss.conf
new file mode 100644
index 0000000..64f64b5
--- /dev/null
+++ b/input/rss.conf
@@ -0,0 +1,5 @@
+editor: lotigara@lotigara.ru (lotigara)
+title: &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara
+description:
+language: ru-ru
+copyright: &lpar;c&rpar; Ivan Davydov 2024-2025&period; &Dcy;&iecy;&lcy;&acy;&jcy;&tcy;&iecy; &scy; &ecy;&tcy;&icy;&mcy; &dcy;&ocy;&kcy;&ucy;&mcy;&iecy;&ncy;&tcy;&ocy;&mcy; &vcy;&scy;&iocy;&comma; &chcy;&tcy;&ocy; &khcy;&ocy;&tcy;&icy;&tcy;&iecy;&excl;
diff --git a/public/_/imgs/test b/public/_/imgs/test
new file mode 100644
index 0000000..d6a2d5c
--- /dev/null
+++ b/public/_/imgs/test
@@ -0,0 +1 @@
+Foo.
diff --git a/public/_/script.js b/public/_/script.js
new file mode 100644
index 0000000..05b3b3a
--- /dev/null
+++ b/public/_/script.js
@@ -0,0 +1,14 @@
+(function(){
+var q = document.querySelector.bind(document);
+var qa = document.querySelectorAll.bind(document);
+window.lib = {};
+lib.elems = {};
+lib.isListPage = !!q('.posts');
+lib.isArticle = !lib.isListPage;
+if (lib.isListPage) {
+lib.elems.posts = [].slice.call(qa('.post'));
+lib.elems.postsContainer = q('.posts');
+} else {
+lib.elems.post = q('.post');
+}
+})();
diff --git a/public/_/style.css b/public/_/style.css
new file mode 100644
index 0000000..3cff5f6
--- /dev/null
+++ b/public/_/style.css
@@ -0,0 +1,80 @@
+@media (max-width: 1199px) and (min-width: 401px) {
+ body {
+ font-size: 32pt;
+ }
+
+ div.content_section_text p::first-letter,div.content::first-letter {
+ font-size: 37pt;
+ }
+
+ /* https://css-tricks.com/responsive-data-tables/ */
+
+ /*
+ * Force table to not be like tables anymore
+ */
+ table, thead, tbody, th, td, tr {
+ display: block;
+ }
+
+ /*
+ * Hide table headers (but not display: none;, for accessibility)
+ */
+ thead tr {
+ position: absolute;
+ top: -9999%;
+ left: -9999%;
+ }
+
+ td {
+ /* Behave like a "row" */
+ border: none;
+ position: relative;
+ padding-left: 50%;
+ }
+
+ td::before {
+ /* Now like a table header */
+ position: absolute;
+ /* Top/left values mimic padding */
+ top: 6px;
+ left: 6px;
+ width: 45%;
+ padding-right: 10px;
+ white-space: nowrap;
+ }
+}
+
+@media only screen and (orientation: landscape)
+and (min-width: 992px)
+and (max-width: 1199px) {
+ body {
+ font-size: 14pt;
+ }
+}
+@media only screen and (orientation: landscape)
+and (min-width: 768px)
+and (max-width: 991px) {
+ body {
+ font-size: 14pt;
+ }
+}
+@media only screen and (orientation: landscape)
+and (min-width: 480px)
+and (max-width: 767px) {
+ body {
+ font-size: 11pt;
+ }
+}
+@media only screen and (orientation: landscape)
+and (max-width: 479px) {
+ body {
+ font-size: 8pt;
+ }
+}
+@media only screen and (orientation: landscape)
+and (min-device-width : 375px)
+and (max-device-width : 667px) {
+ body {
+ font-size: 9.5pt;
+ }
+}
diff --git a/public/blog/0/index.html b/public/blog/0/index.html
new file mode 100644
index 0000000..2bda186
--- /dev/null
+++ b/public/blog/0/index.html
@@ -0,0 +1,598 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>blog - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- page -->
+<div class="posts">
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/download-mods-for-a-steam-game-from-the-steam-workshop/">Download mods for a Steam game from the Steam Workshop</a></h1>
+ <div class="content">
+<pre alt="sh">
+steamcmd "+login $USERID" $(for i in $MODLIST; do echo "+download_item $APPID $i"; done)
+</pre>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/pubnix----prosody--pam-/">Pubnix - Установка Prosody с PAM-авторизацией</a></h1>
+ <div class="content">
+<h2>Использованные источники</h2>
+
+<ul>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux</a></li>
+ <li><a href="https://landchad.net/prosody">LandChad</a></li>
+ <li><a href="https://prosody.im">Prosody</a></li>
+</ul>
+
+<h2>0. Системные требования</h2>
+
+<ul>
+ <li>Firewall с следующими открытыми портами:</li>
+ <li>
+ <ul>
+ <li>5000/tcp (передача файлов)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5222/tcp (подключение клиента)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5269/tcp (федерация, подключение сервера к серверу)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5281/tcp (по желанию, но рекомендуется)</li>
+ </ul>
+ </li>
+ <li><p>Debian 12 с последними обновлениями и доступом в Интернет</p></li>
+ <li><p>Prosody &gt;= 0.13</p></li>
+</ul>
+
+<hr>
+
+<h2>0,5. Авторизация при помощи ОС</h2>
+<p>PAM (Pluggable Authentication Modules) - API для авторизации в Unix-подобных ОС, по умолчанию использует список пользователей из файла `/etc/passwd`.</p>
+
+<p>Все команды выполняются пользователем <code>root</code>, если не указано иначе.</p>
+
+<h2>1. Установка</h2>
+<p>Выполните эти команды:</p>
+
+<pre>
+# Установить Prosody
+wget https://prosody.im/files/prosody.sources -O/etc/apt/sources.list.d/prosody.sources
+apt update
+apt install prosody lua5.4 liblua5.4-0 liblua5.4-dev luarocks
+# Добавить привилегии демону Prosody
+usermod -aG shadow prosody
+usermod -aG ssl-cert prosody
+# Установить библиотеку для взаимодействия с <abbr title="Portable Operating System Interface">POSIX</abbr>-функциями
+luarocks install luaposix
+# Собрать библиотеку дл/ PAM-аутентификации
+git clone https://github.com/devurandom/lua-pam &amp;&amp; cd lua-pam
+make LUA_VERSION=5.4
+cp pam.so /usr/lib/
+# Установить модуль для PAM-аутентификации
+LUA_INCDIR=5.4 prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_pam
+</pre>
+
+<h2>2. Настройка</h2>
+<p>Начните редактировать файл <code>/etc/prosody/prosody.cfg.lua</code>.
+Следуйте этим инструкциям, заменяя <code>example.net</code> на доменное имя, привязанное к вашему серверу.</p>
+
+<p>Найдите строку, начинающуюся с слова <code>admins</code>, и добавьте ваше будущее имя пользователя в фигурные скобки подобным образом:</p>
+
+<pre>
+admins = { "admin@example.net" }
+</pre>
+
+<p>Где <code>admin</code> - это ваше имя пользователя в вашей системе.</p>
+
+<p>Дальше найдите строку <code>--"mam";</code> и удалите два дефиса, сделайте то же самое с строкой <code>--"turn_external";</code>, находящейся ниже.</p>
+
+<p>Теперь перейдите к строке <code>authentication = "internal_hashed"</code> и замените <code>internal_hashed</code> на <code>pam</code>.</p>
+
+<p>Перейдите к строке, начинающейся с <code>storage</code> и поменяйте <code>sql</code> на <code>internal</code> (по желанию, в этой инструкции я не рассматриваю настройку с базами данных)</p>
+
+<p>По желанию в строке <code>archive_expires_after = "1w"</code> замените <code>1w</code> на <code>never</code>, чтобы истории переписок не удалялись каждую неделю.</p>
+
+<p>Найдите строку, начинающуюся с <code>VirtualHost</code> и замените <code>localhost</code> на <code>example.net</code>.</p>
+
+<p>Если вам нужны многопользовательские переписки, на следующей строке добавьте следущее:</p>
+
+<pre>
+Component "conference.example.net" "muc"
+modules_enabled = { "muc_mam", "vcard_muc" }
+</pre>
+
+<p>Последнюю строку можете опустить, если вам не нужно сохранение истории многопользовательских переписок.</p>
+
+<p>Если нужна возможность загружать файлы на ваш сервер, дополните конфигурацию следующими строками:</p>
+
+<pre>
+Component "upload.example.net" "http_file_share"
+http_file_share_size_limit = 512 * 1024 * 1024 --измеряется в байтах
+http_file_share_expire_after = 60 * 60 * 24 * 31 * 1000 --измеряется в секундах
+</pre>
+
+<p>В данном случае, лимит размера файла - это 512 МиБ (0,5 ГиБ), а удаляться файлы будут через ~1000 лет.
+Если требуется изменить какое-либо из этих свойств, смотрите комментарии (в Lua они начинаются с двух дефисов) и пробуйте изменять значения.</p>
+
+<h2>3. Настройка TLS-сертификата</h2>
+<p>Также заменяйте `example.net` на ваше доменное имя.</p>
+
+<p>ACME (Automatic Certificate Management Environment) - это протокол для получения TLS-сертификатов по Web.
+В этом примере используется ACME-клиент acme.sh, так как эта программа более настраиваемая и удостоверяющий центр (далее УЦ) Let's Encrypt (но вы можете использовать любой другой).</p>
+
+<p>Выполните следующие команды:</p>
+<pre>
+# Эта команда установит acme.sh в директорию ~/.acme.sh, системные
+# файлы не будут затронуты
+wget -O - https://get.acme.sh | sh -s \
+ email=yourveryownlocalpart@example.net
+# Теперь либо перезайдите в систему, либо выполните `exec $0`, если
+# вы уверены в значении переменной `$0`.
+
+# Проверьте, прошла ли установка правильно
+acme.sh -h
+
+# Установить Let's Encrypt в качестве УЦ
+acme.sh --set-default-ca --server \
+ https://acme-v02.api.letsencrypt.org/directory
+
+# Есть два способа подтверждения владения доменом - по HTTP или по
+# DNS.
+# Первый проще, но требует доступ на запись в директорию, содержимое
+# которой доступно по ссылке http://example.net/:
+acme.sh --issue -d example.net -d conference.example.net -d \
+ upload.example.net -w &lt;директория с корнем вашего
+ веб-сервера&gt;
+# А второй, поддерживая Wildcard-сертификаты, позволяет в дальнейшем
+# подключать к вашему XMPP-серверу всевозможные компоненты
+# (транспорты в другие сети, модуль публикации-подписки, он же
+# Publish-Subscribe или просто PubSub и многие другие), но требует
+# доступа к API вашего DNS-регистратора для создания записи,
+# подтверждающей владение доменным именем:
+acme.sh --issue --dnssleep &lt;время в секундах, большее чем TTL&gt; \
+ --dns dns_myapi \
+ -d example.net -d '*.example.net' # Где dns_myapi - это кодовое
+ # имя DNS-провайдера, указанное на
+ # https://github.com/acmesh-official/acme.sh/wiki/dnsapi
+# Но если у вас нет и веб-сервера (или доступа к нему), и доступа к
+# API регистратора, то вы можете внести запись с подтверждением
+# вручную (заметьте, что вам нужно будет это делать каждый раз, когда
+# будет истекать срок действия сертификата):
+# (Перед применением этого способа следует внимательно прочитать
+# следующую страницу:
+# https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode)
+acme.sh --issue --dns -d example.net -d '*.example.net'
+# Теперь примените DNS-запись, выведенную на экран командой выше, и
+# подождите до её распространения. После выполните следующее:
+acme.sh --renew -d example.net -d '*.example.net'
+
+# Почти готово. Теперь осталось установить сертификат:
+mkdir /etc/ssl/private/example.net
+chown root:ssl-cert /etc/ssl/private/example.net
+chmod 750 /etc/ssl/private/example.net
+acme.sh --install-cert \
+ -d example.net -d '*.example.net' \
+ --ca-file /etc/ssl/private/example.net/chain.pem \
+ --cert-file /etc/ssl/private/example.net/cert.pem \
+ --fullchain-file /etc/ssl/private/example.net/fullchain.pem \
+ --key-file /etc/ssl/private/example.net/privkey.pem \
+ --reloadcmd "prosodyctl --root cert import \
+ /etc/ssl/private/example.net"
+</pre>
+
+<h2>Смотрите также</h2>
+
+<ul>
+ <li><a href="https://stupin.su/blog/prosody-dovecot-sasl">Ещё один блог сисадмина - Настройка Jabber-сервера Prosody с аутентификацией пользователей через Dovecot SASL</a>. Статья немного старая, но если вы настраивали Dovecot так же, как и я (см. главную страницу), то это может вам пригодиться для, например, добавление доступа в XMPP совместно с эл. почтой. Также советую посмотреть конец раздела по настройке SSL (5-ый), там есть скрипт, который будет обновлять сертификаты в Prosody вместе с Certbot.</li>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux - Prosody IM and local users - Networks PYMES</a>. Здесь тоже описывается авторизация с помощью PAM, но она выполнена с использованием ещё одной программы, что, конечно, неэффективно. Эта страница указана в начале, так как автор некоторое время использовал именно инструкцию по ссылке выше.</li>
+</ul>
+
+<hr>
+
+<p>В завершении статьи хочется обратить ваше внимание на то, что данная инструкция предоставляется БЕЗ каких-либо гарантий. Если при выполнении указаний из данной инструкции случилось что-то непредвиденное, вы можете обратиться ко мне, но не стоит ожидать какого-либо результата.</p>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/openwrt-24101------keenetic-launcher-kn-1221/">OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221)</a></h1>
+ <div class="content">
+<p>Вот оно:
+<summary>
+<details></p>
+
+<pre>
+From ef20327e33fb38220ba0bca4418464749305e555 Mon Sep 17 00:00:00 2001
+From: Ivan Davydov <lotigara@lotigara.ru>
+Date: Tue, 4 Mar 2025 23:54:13 +0300
+Subject: [PATCH] ramips: mt76x8: add support for Keenetic Launcher (KN-1221)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Specification:
+SoC: MediaTek MT7628AN
+RAM: 128M DDR2, ESMT M14D128168A (2Y)
+Flash: 32M, cFeon EN25QH256A (Dual Boot on OEM, concatenated on OpenWrt,
+SPI)
+Switch: MediaTek MT7628AN, 3 ports 100 Mbps
+WiFi: MediaTek MT7628AN 2.4 GHz 802.11n
+USB: 1 port USB 2.0
+GPIO: 1 button (Wi-Fi & Reset on OEM, Reset on OpenWrt), 3 LEDs (Power,
+Internet, Wi-Fi), USB port power controls
+
+Disassembly:
+There are 2 screws at the bottom near the LEDs hidden by rubber mounts.
+After removing the screws, pry the gray plastic part around (it is secured
+with latches) and remove it.
+
+UART Interface:
+The UART interface can be connected to the 5 pin located between LAN
+ports and the WAN one.
+Pins (from the second LAN port to the WAN one): VCC, TX, RX, NC, GND
+Settings: 115200, 8N1
+
+Flashing via TFTP:
+1. Connect your PC and router to the first LAN port, configure PC
+interface using IP 192.168.1.2, mask 255.255.255.0
+2. Serve the firmware image (for OpenWrt it is *-squashfs-factory.bin)
+renamed to KN-1221_recovery.bin via TFTP
+3. Power up the router while pressing Wi-Fi button
+4. Release Wi-Fi button when Power LED starts blinking
+
+To revert back to OEM firmware:
+The return to the OEM firmware is carried out by using the methods
+described above with the help of the appropriate firmware image found on
+osvault.keenetic.net.
+
+When using OEM bootloader, the firmware image size cannot exceed the size
+of one OEM «Firmware_x» partition or Kernel + rootFS size.
+
+Signed-off-by: Ivan Davydov <lotigara@lotigara.ru>
+Link: https://github.com/openwrt/openwrt/pull/18164
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../ramips/dts/mt7628an_keenetic_kn-1221.dts | 209 ++++++++++++++++++
+ target/linux/ramips/image/mt76x8.mk | 12 +
+ .../mt76x8/base-files/etc/board.d/01_leds | 1 +
+ .../mt76x8/base-files/etc/board.d/02_network | 5 +
+ 4 files changed, 227 insertions(+)
+ create mode 100644 target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+
+diff --git a/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+new file mode 100644
+index 00000000000000..6f5cf96856ed21
+--- /dev/null
++++ b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+@@ -0,0 +1,209 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "mt7628an.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ compatible = "keenetic,kn-1221", "mediatek,mt7628an-soc";
++ model = "Keenetic KN-1221";
++
++ aliases {
++ label-mac-device = &ethernet;
++
++ led-boot = &led_power;
++ led-failsafe = &led_power;
++ led-running = &led_power;
++ led-upgrade = &led_power;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,115200";
++ };
++
++ regulator-usb {
++ compatible = "regulator-fixed";
++ regulator-name = "USB-power";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: power {
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
++ };
++
++ internet {
++ function = LED_FUNCTION_WAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
++ };
++
++ fn {
++ function = LED_FUNCTION_WLAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "phy0tpt";
++ };
++ };
++
++ keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "restart";
++ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++
++ virtual_flash {
++ compatible = "mtd-concat";
++ devices = <&firmware1 &firmware2>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ compatible = "denx,uimage";
++ label = "firmware";
++ reg = <0x0 0x1cc0000>;
++ };
++ };
++ };
++};
++
++&state_default {
++ gpio {
++ groups = "i2c", "spi cs1", "gpio", "refclk", "wdt";
++ function = "gpio";
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <32000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-config";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ partition@40000 {
++ label = "rf-eeprom";
++ reg = <0x40000 0x10000>;
++ read-only;
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom_factory_0: eeprom@0 {
++ reg = <0x0 0x400>;
++ };
++
++ macaddr_factory_4: macaddr@4 {
++ reg = <0x4 0x6>;
++ };
++ };
++ };
++
++ firmware1: partition@50000 {
++ label = "firmware_1";
++ reg = <0x50000 0xe60000>;
++ };
++
++ partition@eb0000 {
++ label = "config_1";
++ reg = <0xeb0000 0x40000>;
++ read-only;
++ };
++
++ partition@ef0000 {
++ label = "storage";
++ reg = <0xef0000 0x100000>;
++ read-only;
++ };
++
++ partition@ff0000 {
++ label = "dump";
++ reg = <0xff0000 0x10000>;
++ read-only;
++ };
++
++ partition@1000000 {
++ label = "u-state";
++ reg = <0x1000000 0x30000>;
++ read-only;
++ };
++
++ partition@1030000 {
++ label = "u-config_res";
++ reg = <0x1030000 0x10000>;
++ read-only;
++ };
++
++ partition@1040000 {
++ label = "rf-eeprom_res";
++ reg = <0x1040000 0x10000>;
++ read-only;
++ };
++
++ firmware2: partition@1050000 {
++ label = "firmware_2";
++ reg = <0x1050000 0xe60000>;
++ };
++
++ partition@1eb0000 {
++ label = "Config_2";
++ reg = <0x1eb0000 0x40000>;
++ read-only;
++ };
++ };
++ };
++};
++
++&ethernet {
++ nvmem-cells = <&macaddr_factory_4>;
++ nvmem-cell-names = "mac-address";
++};
++
++&esw {
++ mediatek,portmap = <0x3e>;
++ mediatek,portdisable = <0x38>;
++};
++
++&wmac {
++ status = "okay";
++
++ nvmem-cells = <&eeprom_factory_0>;
++ nvmem-cell-names = "eeprom";
++};
+diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk
+index 8c8cfee23b6cfa..f442148d9ecf10 100644
+--- a/target/linux/ramips/image/mt76x8.mk
++++ b/target/linux/ramips/image/mt76x8.mk
+@@ -366,6 +366,18 @@ define Device/jotale_js76x8-32m
+ endef
+ TARGET_DEVICES += jotale_js76x8-32m
+
++define Device/keenetic_kn-1221
++ BLOCKSIZE := 64k
++ IMAGE_SIZE := 29440k
++ DEVICE_VENDOR := Keenetic
++ DEVICE_MODEL := KN-1221
++ DEVICE_PACKAGES := kmod-usb2
++ IMAGES += factory.bin
++ IMAGE/factory.bin := $$(sysupgrade_bin) | pad-to $$$$(BLOCKSIZE) | \
++ check-size 14720k | zyimage -d 0x801221 -v "KN-1221"
++endef
++TARGET_DEVICES += keenetic_kn-1221
++
+ define Device/keenetic_kn-1613
+ IMAGE_SIZE := 31488k
+ DEVICE_VENDOR := Keenetic
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+index b87062ae3c5ae5..79f78a2a459487 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+@@ -58,4 +58,5 @@ hiwifi,hc5661a|\
+ hiwifi,hc5761a)
+ ucidef_set_led_switch "internet" "internet" "blue:internet" "switch0" "0x10"
+ ;;
++keenetic,kn-1221|\
+ keenetic,kn-1613)
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+index fbdc7fb5a2697a..6e6e1310d3495f 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+@@ -131,5 +131,9 @@ ramips_setup_interfaces()
+ ucidef_add_switch "switch0" \
+ "0:lan" "1:lan" "2:lan" "6@eth0"
+ ;;
++ keenetic,kn-1221)
++ ucidef_add_switch "switch0" \
++ "1:lan" "2:lan" "0:wan" "6@eth0"
++ ;;
+ keenetic,kn-1613|\
+ motorola,mwr03)
+@@ -280,5 +280,6 @@ ramips_setup_macs()
+ totolink,lr1200)
+ wan_mac=$(mtd_get_mac_binary factory 0x2e)
+ ;;
++ keenetic,kn-1221|\
+ keenetic,kn-1613|\
+ zyxel,keenetic-extra-ii)
+</pre>
+
+<p></details>
+</summary></p>
+
+<p>Или в виде файла: <a href="/files/18164.patch.backport-24.10.1">18164.patch.backport-24.10.1</a>.
+Готовые сборки тоже доступны в виде файлов: <a href="/files/openwrt-kn-1221-24.10">openwrt-kn-1221-24.10</a></p>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/">Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS</a></h1>
+ <div class="content">
+<h5>tested to not work on KeeneticOS v3.8.7 &amp; OpenWrt v23.05.5</h5>
+
+<p>First, set up FT on your OpenWrt devices.</p>
+
+<p>Then, change the mode of your Keenetic (?) devices to Extender (there are Repeater/Extender and Access Point/Extender, the last is the recommended).</p>
+
+<p>Go to the <code>Access Point/Extender (Repeater/Extender) &gt; Home segment</code> menu. Change the settings of the Wi-Fi network to those ones in OpenWrt.</p>
+
+<p>Scroll below to the "Roaming for wireless devices" section. Enable "Fast transition (802.11r)" and write your mobility domain ID converted to the ASCII format.</p>
+
+<p>You can use an online converter like this one: <a href="https://www.rapidtables.com/convert/number/hex-to-ascii.html">https://www.rapidtables.com/convert/number/hex-to-ascii.html</a>. Keep the "Mobility domain key" field unedited.</p>
+
+<p>Press the "Save" button. Now you have a so-called "Wi-Fi system" with use of both KeeneticOS and OpenWrt!</p>
+ </div>
+</div>
+<!-- /post -->
+
+</div>
+<div class="pagination ">
+ <a class="prev" href="/blog//">Назад</a>
+ <a class="next" href="/blog//">Вперёд</a>
+</div>
+<!-- /page -->
+
+ </body>
+</html>
diff --git a/public/blog/download-mods-for-a-steam-game-from-the-steam-workshop/index.html b/public/blog/download-mods-for-a-steam-game-from-the-steam-workshop/index.html
new file mode 100644
index 0000000..6bbeefb
--- /dev/null
+++ b/public/blog/download-mods-for-a-steam-game-from-the-steam-workshop/index.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>Download mods for a Steam game from the Steam Workshop - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/download-mods-for-a-steam-game-from-the-steam-workshop/">Download mods for a Steam game from the Steam Workshop</a></h1>
+ <div class="content">
+<pre alt="sh">
+steamcmd "+login $USERID" $(for i in $MODLIST; do echo "+download_item $APPID $i"; done)
+</pre>
+ </div>
+</div>
+<!-- /post -->
+
+ </body>
+</html>
diff --git a/public/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/index.html b/public/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/index.html
new file mode 100644
index 0000000..ef7fb37
--- /dev/null
+++ b/public/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/index.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/">Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS</a></h1>
+ <div class="content">
+<h5>tested to not work on KeeneticOS v3.8.7 &amp; OpenWrt v23.05.5</h5>
+
+<p>First, set up FT on your OpenWrt devices.</p>
+
+<p>Then, change the mode of your Keenetic (?) devices to Extender (there are Repeater/Extender and Access Point/Extender, the last is the recommended).</p>
+
+<p>Go to the <code>Access Point/Extender (Repeater/Extender) &gt; Home segment</code> menu. Change the settings of the Wi-Fi network to those ones in OpenWrt.</p>
+
+<p>Scroll below to the "Roaming for wireless devices" section. Enable "Fast transition (802.11r)" and write your mobility domain ID converted to the ASCII format.</p>
+
+<p>You can use an online converter like this one: <a href="https://www.rapidtables.com/convert/number/hex-to-ascii.html">https://www.rapidtables.com/convert/number/hex-to-ascii.html</a>. Keep the "Mobility domain key" field unedited.</p>
+
+<p>Press the "Save" button. Now you have a so-called "Wi-Fi system" with use of both KeeneticOS and OpenWrt!</p>
+ </div>
+</div>
+<!-- /post -->
+
+ </body>
+</html>
diff --git a/public/blog/feed.rss b/public/blog/feed.rss
new file mode 100644
index 0000000..ef515b5
--- /dev/null
+++ b/public/blog/feed.rss
@@ -0,0 +1,596 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+<channel>
+ <title>&ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link>https://www.lotigara.ru/blog/blog</link>
+ <description>language: ru-ru</description>
+ <atom:link href="https://www.lotigara.ru/blog/blog/feed.rss" rel="self" type="application/rss+xml" />
+ <managingEditor>lotigara@lotigara.ru (lotigara)</managingEditor>
+ <copyright>&lpar;c&rpar; Ivan Davydov 2024-2025&period; &Dcy;&iecy;&lcy;&acy;&jcy;&tcy;&iecy; &scy; &ecy;&tcy;&icy;&mcy; &dcy;&ocy;&kcy;&ucy;&mcy;&iecy;&ncy;&tcy;&ocy;&mcy; &vcy;&scy;&iocy;&comma; &chcy;&tcy;&ocy; &khcy;&ocy;&tcy;&icy;&tcy;&iecy;&excl;</copyright>
+ <pubDate>Tue, 24 Jun 2025 13:59:37 +0300</pubDate>
+ <generator>housecat</generator>
+ <docs>https://cyber.harvard.edu/rss/rss.html</docs>
+ <item>
+ <title>Download mods for a Steam game from the Steam Workshop</title>
+ <link>https://www.lotigara.ru/blog/blog/download-mods-for-a-steam-game-from-the-steam-workshop</link>
+ <description><![CDATA[
+<pre alt="sh">
+steamcmd "+login $USERID" $(for i in $MODLIST; do echo "+download_item $APPID $i"; done)
+</pre>
+]]></description>
+ <author>Lotigara</author>
+ <guid isPermaLink="true">https://www.lotigara.ru/blog/blog/download-mods-for-a-steam-game-from-the-steam-workshop</guid>
+ <category>openwrt</category>
+ <category>sh</category>
+ <category>steam</category>
+ </item>
+ <item>
+ <title>Pubnix - Установка Prosody с PAM-авторизацией</title>
+ <link>https://www.lotigara.ru/blog/blog/pubnix----prosody--pam-</link>
+ <description><![CDATA[
+<h2>Использованные источники</h2>
+
+<ul>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux</a></li>
+ <li><a href="https://landchad.net/prosody">LandChad</a></li>
+ <li><a href="https://prosody.im">Prosody</a></li>
+</ul>
+
+<h2>0. Системные требования</h2>
+
+<ul>
+ <li>Firewall с следующими открытыми портами:</li>
+ <li>
+ <ul>
+ <li>5000/tcp (передача файлов)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5222/tcp (подключение клиента)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5269/tcp (федерация, подключение сервера к серверу)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5281/tcp (по желанию, но рекомендуется)</li>
+ </ul>
+ </li>
+ <li><p>Debian 12 с последними обновлениями и доступом в Интернет</p></li>
+ <li><p>Prosody &gt;= 0.13</p></li>
+</ul>
+
+<hr>
+
+<h2>0,5. Авторизация при помощи ОС</h2>
+<p>PAM (Pluggable Authentication Modules) - API для авторизации в Unix-подобных ОС, по умолчанию использует список пользователей из файла `/etc/passwd`.</p>
+
+<p>Все команды выполняются пользователем <code>root</code>, если не указано иначе.</p>
+
+<h2>1. Установка</h2>
+<p>Выполните эти команды:</p>
+
+<pre>
+# Установить Prosody
+wget https://prosody.im/files/prosody.sources -O/etc/apt/sources.list.d/prosody.sources
+apt update
+apt install prosody lua5.4 liblua5.4-0 liblua5.4-dev luarocks
+# Добавить привилегии демону Prosody
+usermod -aG shadow prosody
+usermod -aG ssl-cert prosody
+# Установить библиотеку для взаимодействия с <abbr title="Portable Operating System Interface">POSIX</abbr>-функциями
+luarocks install luaposix
+# Собрать библиотеку дл/ PAM-аутентификации
+git clone https://github.com/devurandom/lua-pam &amp;&amp; cd lua-pam
+make LUA_VERSION=5.4
+cp pam.so /usr/lib/
+# Установить модуль для PAM-аутентификации
+LUA_INCDIR=5.4 prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_pam
+</pre>
+
+<h2>2. Настройка</h2>
+<p>Начните редактировать файл <code>/etc/prosody/prosody.cfg.lua</code>.
+Следуйте этим инструкциям, заменяя <code>example.net</code> на доменное имя, привязанное к вашему серверу.</p>
+
+<p>Найдите строку, начинающуюся с слова <code>admins</code>, и добавьте ваше будущее имя пользователя в фигурные скобки подобным образом:</p>
+
+<pre>
+admins = { "admin@example.net" }
+</pre>
+
+<p>Где <code>admin</code> - это ваше имя пользователя в вашей системе.</p>
+
+<p>Дальше найдите строку <code>--"mam";</code> и удалите два дефиса, сделайте то же самое с строкой <code>--"turn_external";</code>, находящейся ниже.</p>
+
+<p>Теперь перейдите к строке <code>authentication = "internal_hashed"</code> и замените <code>internal_hashed</code> на <code>pam</code>.</p>
+
+<p>Перейдите к строке, начинающейся с <code>storage</code> и поменяйте <code>sql</code> на <code>internal</code> (по желанию, в этой инструкции я не рассматриваю настройку с базами данных)</p>
+
+<p>По желанию в строке <code>archive_expires_after = "1w"</code> замените <code>1w</code> на <code>never</code>, чтобы истории переписок не удалялись каждую неделю.</p>
+
+<p>Найдите строку, начинающуюся с <code>VirtualHost</code> и замените <code>localhost</code> на <code>example.net</code>.</p>
+
+<p>Если вам нужны многопользовательские переписки, на следующей строке добавьте следущее:</p>
+
+<pre>
+Component "conference.example.net" "muc"
+modules_enabled = { "muc_mam", "vcard_muc" }
+</pre>
+
+<p>Последнюю строку можете опустить, если вам не нужно сохранение истории многопользовательских переписок.</p>
+
+<p>Если нужна возможность загружать файлы на ваш сервер, дополните конфигурацию следующими строками:</p>
+
+<pre>
+Component "upload.example.net" "http_file_share"
+http_file_share_size_limit = 512 * 1024 * 1024 --измеряется в байтах
+http_file_share_expire_after = 60 * 60 * 24 * 31 * 1000 --измеряется в секундах
+</pre>
+
+<p>В данном случае, лимит размера файла - это 512 МиБ (0,5 ГиБ), а удаляться файлы будут через ~1000 лет.
+Если требуется изменить какое-либо из этих свойств, смотрите комментарии (в Lua они начинаются с двух дефисов) и пробуйте изменять значения.</p>
+
+<h2>3. Настройка TLS-сертификата</h2>
+<p>Также заменяйте `example.net` на ваше доменное имя.</p>
+
+<p>ACME (Automatic Certificate Management Environment) - это протокол для получения TLS-сертификатов по Web.
+В этом примере используется ACME-клиент acme.sh, так как эта программа более настраиваемая и удостоверяющий центр (далее УЦ) Let's Encrypt (но вы можете использовать любой другой).</p>
+
+<p>Выполните следующие команды:</p>
+<pre>
+# Эта команда установит acme.sh в директорию ~/.acme.sh, системные
+# файлы не будут затронуты
+wget -O - https://get.acme.sh | sh -s \
+ email=yourveryownlocalpart@example.net
+# Теперь либо перезайдите в систему, либо выполните `exec $0`, если
+# вы уверены в значении переменной `$0`.
+
+# Проверьте, прошла ли установка правильно
+acme.sh -h
+
+# Установить Let's Encrypt в качестве УЦ
+acme.sh --set-default-ca --server \
+ https://acme-v02.api.letsencrypt.org/directory
+
+# Есть два способа подтверждения владения доменом - по HTTP или по
+# DNS.
+# Первый проще, но требует доступ на запись в директорию, содержимое
+# которой доступно по ссылке http://example.net/:
+acme.sh --issue -d example.net -d conference.example.net -d \
+ upload.example.net -w &lt;директория с корнем вашего
+ веб-сервера&gt;
+# А второй, поддерживая Wildcard-сертификаты, позволяет в дальнейшем
+# подключать к вашему XMPP-серверу всевозможные компоненты
+# (транспорты в другие сети, модуль публикации-подписки, он же
+# Publish-Subscribe или просто PubSub и многие другие), но требует
+# доступа к API вашего DNS-регистратора для создания записи,
+# подтверждающей владение доменным именем:
+acme.sh --issue --dnssleep &lt;время в секундах, большее чем TTL&gt; \
+ --dns dns_myapi \
+ -d example.net -d '*.example.net' # Где dns_myapi - это кодовое
+ # имя DNS-провайдера, указанное на
+ # https://github.com/acmesh-official/acme.sh/wiki/dnsapi
+# Но если у вас нет и веб-сервера (или доступа к нему), и доступа к
+# API регистратора, то вы можете внести запись с подтверждением
+# вручную (заметьте, что вам нужно будет это делать каждый раз, когда
+# будет истекать срок действия сертификата):
+# (Перед применением этого способа следует внимательно прочитать
+# следующую страницу:
+# https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode)
+acme.sh --issue --dns -d example.net -d '*.example.net'
+# Теперь примените DNS-запись, выведенную на экран командой выше, и
+# подождите до её распространения. После выполните следующее:
+acme.sh --renew -d example.net -d '*.example.net'
+
+# Почти готово. Теперь осталось установить сертификат:
+mkdir /etc/ssl/private/example.net
+chown root:ssl-cert /etc/ssl/private/example.net
+chmod 750 /etc/ssl/private/example.net
+acme.sh --install-cert \
+ -d example.net -d '*.example.net' \
+ --ca-file /etc/ssl/private/example.net/chain.pem \
+ --cert-file /etc/ssl/private/example.net/cert.pem \
+ --fullchain-file /etc/ssl/private/example.net/fullchain.pem \
+ --key-file /etc/ssl/private/example.net/privkey.pem \
+ --reloadcmd "prosodyctl --root cert import \
+ /etc/ssl/private/example.net"
+</pre>
+
+<h2>Смотрите также</h2>
+
+<ul>
+ <li><a href="https://stupin.su/blog/prosody-dovecot-sasl">Ещё один блог сисадмина - Настройка Jabber-сервера Prosody с аутентификацией пользователей через Dovecot SASL</a>. Статья немного старая, но если вы настраивали Dovecot так же, как и я (см. главную страницу), то это может вам пригодиться для, например, добавление доступа в XMPP совместно с эл. почтой. Также советую посмотреть конец раздела по настройке SSL (5-ый), там есть скрипт, который будет обновлять сертификаты в Prosody вместе с Certbot.</li>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux - Prosody IM and local users - Networks PYMES</a>. Здесь тоже описывается авторизация с помощью PAM, но она выполнена с использованием ещё одной программы, что, конечно, неэффективно. Эта страница указана в начале, так как автор некоторое время использовал именно инструкцию по ссылке выше.</li>
+</ul>
+
+<hr>
+
+<p>В завершении статьи хочется обратить ваше внимание на то, что данная инструкция предоставляется БЕЗ каких-либо гарантий. Если при выполнении указаний из данной инструкции случилось что-то непредвиденное, вы можете обратиться ко мне, но не стоит ожидать какого-либо результата.</p>
+]]></description>
+ <author>Lotigara</author>
+ <guid isPermaLink="true">https://www.lotigara.ru/blog/blog/pubnix----prosody--pam-</guid>
+ <category>pubnix</category>
+ <category>prosody</category>
+ <category>xmpp</category>
+ <category>&scy;&icy;&scy;&tcy;&iecy;&mcy;&ncy;&ocy;&iecy; &acy;&dcy;&mcy;&icy;&ncy;&icy;&scy;&tcy;&rcy;&icy;&rcy;&ocy;&vcy;&acy;&ncy;&icy;&iecy;</category>
+ </item>
+ <item>
+ <title>OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221)</title>
+ <link>https://www.lotigara.ru/blog/blog/openwrt-24101------keenetic-launcher-kn-1221</link>
+ <description><![CDATA[
+<p>Вот оно:
+<summary>
+<details></p>
+
+<pre>
+From ef20327e33fb38220ba0bca4418464749305e555 Mon Sep 17 00:00:00 2001
+From: Ivan Davydov <lotigara@lotigara.ru>
+Date: Tue, 4 Mar 2025 23:54:13 +0300
+Subject: [PATCH] ramips: mt76x8: add support for Keenetic Launcher (KN-1221)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Specification:
+SoC: MediaTek MT7628AN
+RAM: 128M DDR2, ESMT M14D128168A (2Y)
+Flash: 32M, cFeon EN25QH256A (Dual Boot on OEM, concatenated on OpenWrt,
+SPI)
+Switch: MediaTek MT7628AN, 3 ports 100 Mbps
+WiFi: MediaTek MT7628AN 2.4 GHz 802.11n
+USB: 1 port USB 2.0
+GPIO: 1 button (Wi-Fi & Reset on OEM, Reset on OpenWrt), 3 LEDs (Power,
+Internet, Wi-Fi), USB port power controls
+
+Disassembly:
+There are 2 screws at the bottom near the LEDs hidden by rubber mounts.
+After removing the screws, pry the gray plastic part around (it is secured
+with latches) and remove it.
+
+UART Interface:
+The UART interface can be connected to the 5 pin located between LAN
+ports and the WAN one.
+Pins (from the second LAN port to the WAN one): VCC, TX, RX, NC, GND
+Settings: 115200, 8N1
+
+Flashing via TFTP:
+1. Connect your PC and router to the first LAN port, configure PC
+interface using IP 192.168.1.2, mask 255.255.255.0
+2. Serve the firmware image (for OpenWrt it is *-squashfs-factory.bin)
+renamed to KN-1221_recovery.bin via TFTP
+3. Power up the router while pressing Wi-Fi button
+4. Release Wi-Fi button when Power LED starts blinking
+
+To revert back to OEM firmware:
+The return to the OEM firmware is carried out by using the methods
+described above with the help of the appropriate firmware image found on
+osvault.keenetic.net.
+
+When using OEM bootloader, the firmware image size cannot exceed the size
+of one OEM «Firmware_x» partition or Kernel + rootFS size.
+
+Signed-off-by: Ivan Davydov <lotigara@lotigara.ru>
+Link: https://github.com/openwrt/openwrt/pull/18164
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../ramips/dts/mt7628an_keenetic_kn-1221.dts | 209 ++++++++++++++++++
+ target/linux/ramips/image/mt76x8.mk | 12 +
+ .../mt76x8/base-files/etc/board.d/01_leds | 1 +
+ .../mt76x8/base-files/etc/board.d/02_network | 5 +
+ 4 files changed, 227 insertions(+)
+ create mode 100644 target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+
+diff --git a/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+new file mode 100644
+index 00000000000000..6f5cf96856ed21
+--- /dev/null
++++ b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+@@ -0,0 +1,209 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "mt7628an.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ compatible = "keenetic,kn-1221", "mediatek,mt7628an-soc";
++ model = "Keenetic KN-1221";
++
++ aliases {
++ label-mac-device = &ethernet;
++
++ led-boot = &led_power;
++ led-failsafe = &led_power;
++ led-running = &led_power;
++ led-upgrade = &led_power;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,115200";
++ };
++
++ regulator-usb {
++ compatible = "regulator-fixed";
++ regulator-name = "USB-power";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: power {
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
++ };
++
++ internet {
++ function = LED_FUNCTION_WAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
++ };
++
++ fn {
++ function = LED_FUNCTION_WLAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "phy0tpt";
++ };
++ };
++
++ keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "restart";
++ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++
++ virtual_flash {
++ compatible = "mtd-concat";
++ devices = <&firmware1 &firmware2>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ compatible = "denx,uimage";
++ label = "firmware";
++ reg = <0x0 0x1cc0000>;
++ };
++ };
++ };
++};
++
++&state_default {
++ gpio {
++ groups = "i2c", "spi cs1", "gpio", "refclk", "wdt";
++ function = "gpio";
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <32000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-config";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ partition@40000 {
++ label = "rf-eeprom";
++ reg = <0x40000 0x10000>;
++ read-only;
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom_factory_0: eeprom@0 {
++ reg = <0x0 0x400>;
++ };
++
++ macaddr_factory_4: macaddr@4 {
++ reg = <0x4 0x6>;
++ };
++ };
++ };
++
++ firmware1: partition@50000 {
++ label = "firmware_1";
++ reg = <0x50000 0xe60000>;
++ };
++
++ partition@eb0000 {
++ label = "config_1";
++ reg = <0xeb0000 0x40000>;
++ read-only;
++ };
++
++ partition@ef0000 {
++ label = "storage";
++ reg = <0xef0000 0x100000>;
++ read-only;
++ };
++
++ partition@ff0000 {
++ label = "dump";
++ reg = <0xff0000 0x10000>;
++ read-only;
++ };
++
++ partition@1000000 {
++ label = "u-state";
++ reg = <0x1000000 0x30000>;
++ read-only;
++ };
++
++ partition@1030000 {
++ label = "u-config_res";
++ reg = <0x1030000 0x10000>;
++ read-only;
++ };
++
++ partition@1040000 {
++ label = "rf-eeprom_res";
++ reg = <0x1040000 0x10000>;
++ read-only;
++ };
++
++ firmware2: partition@1050000 {
++ label = "firmware_2";
++ reg = <0x1050000 0xe60000>;
++ };
++
++ partition@1eb0000 {
++ label = "Config_2";
++ reg = <0x1eb0000 0x40000>;
++ read-only;
++ };
++ };
++ };
++};
++
++&ethernet {
++ nvmem-cells = <&macaddr_factory_4>;
++ nvmem-cell-names = "mac-address";
++};
++
++&esw {
++ mediatek,portmap = <0x3e>;
++ mediatek,portdisable = <0x38>;
++};
++
++&wmac {
++ status = "okay";
++
++ nvmem-cells = <&eeprom_factory_0>;
++ nvmem-cell-names = "eeprom";
++};
+diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk
+index 8c8cfee23b6cfa..f442148d9ecf10 100644
+--- a/target/linux/ramips/image/mt76x8.mk
++++ b/target/linux/ramips/image/mt76x8.mk
+@@ -366,6 +366,18 @@ define Device/jotale_js76x8-32m
+ endef
+ TARGET_DEVICES += jotale_js76x8-32m
+
++define Device/keenetic_kn-1221
++ BLOCKSIZE := 64k
++ IMAGE_SIZE := 29440k
++ DEVICE_VENDOR := Keenetic
++ DEVICE_MODEL := KN-1221
++ DEVICE_PACKAGES := kmod-usb2
++ IMAGES += factory.bin
++ IMAGE/factory.bin := $$(sysupgrade_bin) | pad-to $$$$(BLOCKSIZE) | \
++ check-size 14720k | zyimage -d 0x801221 -v "KN-1221"
++endef
++TARGET_DEVICES += keenetic_kn-1221
++
+ define Device/keenetic_kn-1613
+ IMAGE_SIZE := 31488k
+ DEVICE_VENDOR := Keenetic
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+index b87062ae3c5ae5..79f78a2a459487 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+@@ -58,4 +58,5 @@ hiwifi,hc5661a|\
+ hiwifi,hc5761a)
+ ucidef_set_led_switch "internet" "internet" "blue:internet" "switch0" "0x10"
+ ;;
++keenetic,kn-1221|\
+ keenetic,kn-1613)
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+index fbdc7fb5a2697a..6e6e1310d3495f 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+@@ -131,5 +131,9 @@ ramips_setup_interfaces()
+ ucidef_add_switch "switch0" \
+ "0:lan" "1:lan" "2:lan" "6@eth0"
+ ;;
++ keenetic,kn-1221)
++ ucidef_add_switch "switch0" \
++ "1:lan" "2:lan" "0:wan" "6@eth0"
++ ;;
+ keenetic,kn-1613|\
+ motorola,mwr03)
+@@ -280,5 +280,6 @@ ramips_setup_macs()
+ totolink,lr1200)
+ wan_mac=$(mtd_get_mac_binary factory 0x2e)
+ ;;
++ keenetic,kn-1221|\
+ keenetic,kn-1613|\
+ zyxel,keenetic-extra-ii)
+</pre>
+
+<p></details>
+</summary></p>
+
+<p>Или в виде файла: <a href="/files/18164.patch.backport-24.10.1">18164.patch.backport-24.10.1</a>.
+Готовые сборки тоже доступны в виде файлов: <a href="/files/openwrt-kn-1221-24.10">openwrt-kn-1221-24.10</a></p>
+]]></description>
+ <author>Lotigara</author>
+ <guid isPermaLink="true">https://www.lotigara.ru/blog/blog/openwrt-24101------keenetic-launcher-kn-1221</guid>
+ <category>openwrt</category>
+ <category>&rcy;&acy;&zcy;&rcy;&acy;&bcy;&ocy;&tcy;&kcy;&acy;</category>
+ <category>&icy;&zcy;&mcy;&iecy;&ncy;&iocy;&ncy;&ncy;&ycy;&iecy; &pcy;&rcy;&ocy;&shcy;&icy;&vcy;&kcy;&icy;</category>
+ </item>
+ <item>
+ <title>Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS</title>
+ <link>https://www.lotigara.ru/blog/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos</link>
+ <description><![CDATA[
+<h5>tested to not work on KeeneticOS v3.8.7 &amp; OpenWrt v23.05.5</h5>
+
+<p>First, set up FT on your OpenWrt devices.</p>
+
+<p>Then, change the mode of your Keenetic (?) devices to Extender (there are Repeater/Extender and Access Point/Extender, the last is the recommended).</p>
+
+<p>Go to the <code>Access Point/Extender (Repeater/Extender) &gt; Home segment</code> menu. Change the settings of the Wi-Fi network to those ones in OpenWrt.</p>
+
+<p>Scroll below to the "Roaming for wireless devices" section. Enable "Fast transition (802.11r)" and write your mobility domain ID converted to the ASCII format.</p>
+
+<p>You can use an online converter like this one: <a href="https://www.rapidtables.com/convert/number/hex-to-ascii.html">https://www.rapidtables.com/convert/number/hex-to-ascii.html</a>. Keep the "Mobility domain key" field unedited.</p>
+
+<p>Press the "Save" button. Now you have a so-called "Wi-Fi system" with use of both KeeneticOS and OpenWrt!</p>
+]]></description>
+ <author>Lotigara</author>
+ <guid isPermaLink="true">https://www.lotigara.ru/blog/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos</guid>
+ <category>keeneticos</category>
+ <category>openwrt</category>
+ <category>wifi</category>
+ <category>wifi-roaming</category>
+ </item>
+</channel>
+</rss>
diff --git a/public/blog/index.html b/public/blog/index.html
new file mode 100644
index 0000000..2bda186
--- /dev/null
+++ b/public/blog/index.html
@@ -0,0 +1,598 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>blog - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- page -->
+<div class="posts">
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/download-mods-for-a-steam-game-from-the-steam-workshop/">Download mods for a Steam game from the Steam Workshop</a></h1>
+ <div class="content">
+<pre alt="sh">
+steamcmd "+login $USERID" $(for i in $MODLIST; do echo "+download_item $APPID $i"; done)
+</pre>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/pubnix----prosody--pam-/">Pubnix - Установка Prosody с PAM-авторизацией</a></h1>
+ <div class="content">
+<h2>Использованные источники</h2>
+
+<ul>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux</a></li>
+ <li><a href="https://landchad.net/prosody">LandChad</a></li>
+ <li><a href="https://prosody.im">Prosody</a></li>
+</ul>
+
+<h2>0. Системные требования</h2>
+
+<ul>
+ <li>Firewall с следующими открытыми портами:</li>
+ <li>
+ <ul>
+ <li>5000/tcp (передача файлов)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5222/tcp (подключение клиента)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5269/tcp (федерация, подключение сервера к серверу)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5281/tcp (по желанию, но рекомендуется)</li>
+ </ul>
+ </li>
+ <li><p>Debian 12 с последними обновлениями и доступом в Интернет</p></li>
+ <li><p>Prosody &gt;= 0.13</p></li>
+</ul>
+
+<hr>
+
+<h2>0,5. Авторизация при помощи ОС</h2>
+<p>PAM (Pluggable Authentication Modules) - API для авторизации в Unix-подобных ОС, по умолчанию использует список пользователей из файла `/etc/passwd`.</p>
+
+<p>Все команды выполняются пользователем <code>root</code>, если не указано иначе.</p>
+
+<h2>1. Установка</h2>
+<p>Выполните эти команды:</p>
+
+<pre>
+# Установить Prosody
+wget https://prosody.im/files/prosody.sources -O/etc/apt/sources.list.d/prosody.sources
+apt update
+apt install prosody lua5.4 liblua5.4-0 liblua5.4-dev luarocks
+# Добавить привилегии демону Prosody
+usermod -aG shadow prosody
+usermod -aG ssl-cert prosody
+# Установить библиотеку для взаимодействия с <abbr title="Portable Operating System Interface">POSIX</abbr>-функциями
+luarocks install luaposix
+# Собрать библиотеку дл/ PAM-аутентификации
+git clone https://github.com/devurandom/lua-pam &amp;&amp; cd lua-pam
+make LUA_VERSION=5.4
+cp pam.so /usr/lib/
+# Установить модуль для PAM-аутентификации
+LUA_INCDIR=5.4 prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_pam
+</pre>
+
+<h2>2. Настройка</h2>
+<p>Начните редактировать файл <code>/etc/prosody/prosody.cfg.lua</code>.
+Следуйте этим инструкциям, заменяя <code>example.net</code> на доменное имя, привязанное к вашему серверу.</p>
+
+<p>Найдите строку, начинающуюся с слова <code>admins</code>, и добавьте ваше будущее имя пользователя в фигурные скобки подобным образом:</p>
+
+<pre>
+admins = { "admin@example.net" }
+</pre>
+
+<p>Где <code>admin</code> - это ваше имя пользователя в вашей системе.</p>
+
+<p>Дальше найдите строку <code>--"mam";</code> и удалите два дефиса, сделайте то же самое с строкой <code>--"turn_external";</code>, находящейся ниже.</p>
+
+<p>Теперь перейдите к строке <code>authentication = "internal_hashed"</code> и замените <code>internal_hashed</code> на <code>pam</code>.</p>
+
+<p>Перейдите к строке, начинающейся с <code>storage</code> и поменяйте <code>sql</code> на <code>internal</code> (по желанию, в этой инструкции я не рассматриваю настройку с базами данных)</p>
+
+<p>По желанию в строке <code>archive_expires_after = "1w"</code> замените <code>1w</code> на <code>never</code>, чтобы истории переписок не удалялись каждую неделю.</p>
+
+<p>Найдите строку, начинающуюся с <code>VirtualHost</code> и замените <code>localhost</code> на <code>example.net</code>.</p>
+
+<p>Если вам нужны многопользовательские переписки, на следующей строке добавьте следущее:</p>
+
+<pre>
+Component "conference.example.net" "muc"
+modules_enabled = { "muc_mam", "vcard_muc" }
+</pre>
+
+<p>Последнюю строку можете опустить, если вам не нужно сохранение истории многопользовательских переписок.</p>
+
+<p>Если нужна возможность загружать файлы на ваш сервер, дополните конфигурацию следующими строками:</p>
+
+<pre>
+Component "upload.example.net" "http_file_share"
+http_file_share_size_limit = 512 * 1024 * 1024 --измеряется в байтах
+http_file_share_expire_after = 60 * 60 * 24 * 31 * 1000 --измеряется в секундах
+</pre>
+
+<p>В данном случае, лимит размера файла - это 512 МиБ (0,5 ГиБ), а удаляться файлы будут через ~1000 лет.
+Если требуется изменить какое-либо из этих свойств, смотрите комментарии (в Lua они начинаются с двух дефисов) и пробуйте изменять значения.</p>
+
+<h2>3. Настройка TLS-сертификата</h2>
+<p>Также заменяйте `example.net` на ваше доменное имя.</p>
+
+<p>ACME (Automatic Certificate Management Environment) - это протокол для получения TLS-сертификатов по Web.
+В этом примере используется ACME-клиент acme.sh, так как эта программа более настраиваемая и удостоверяющий центр (далее УЦ) Let's Encrypt (но вы можете использовать любой другой).</p>
+
+<p>Выполните следующие команды:</p>
+<pre>
+# Эта команда установит acme.sh в директорию ~/.acme.sh, системные
+# файлы не будут затронуты
+wget -O - https://get.acme.sh | sh -s \
+ email=yourveryownlocalpart@example.net
+# Теперь либо перезайдите в систему, либо выполните `exec $0`, если
+# вы уверены в значении переменной `$0`.
+
+# Проверьте, прошла ли установка правильно
+acme.sh -h
+
+# Установить Let's Encrypt в качестве УЦ
+acme.sh --set-default-ca --server \
+ https://acme-v02.api.letsencrypt.org/directory
+
+# Есть два способа подтверждения владения доменом - по HTTP или по
+# DNS.
+# Первый проще, но требует доступ на запись в директорию, содержимое
+# которой доступно по ссылке http://example.net/:
+acme.sh --issue -d example.net -d conference.example.net -d \
+ upload.example.net -w &lt;директория с корнем вашего
+ веб-сервера&gt;
+# А второй, поддерживая Wildcard-сертификаты, позволяет в дальнейшем
+# подключать к вашему XMPP-серверу всевозможные компоненты
+# (транспорты в другие сети, модуль публикации-подписки, он же
+# Publish-Subscribe или просто PubSub и многие другие), но требует
+# доступа к API вашего DNS-регистратора для создания записи,
+# подтверждающей владение доменным именем:
+acme.sh --issue --dnssleep &lt;время в секундах, большее чем TTL&gt; \
+ --dns dns_myapi \
+ -d example.net -d '*.example.net' # Где dns_myapi - это кодовое
+ # имя DNS-провайдера, указанное на
+ # https://github.com/acmesh-official/acme.sh/wiki/dnsapi
+# Но если у вас нет и веб-сервера (или доступа к нему), и доступа к
+# API регистратора, то вы можете внести запись с подтверждением
+# вручную (заметьте, что вам нужно будет это делать каждый раз, когда
+# будет истекать срок действия сертификата):
+# (Перед применением этого способа следует внимательно прочитать
+# следующую страницу:
+# https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode)
+acme.sh --issue --dns -d example.net -d '*.example.net'
+# Теперь примените DNS-запись, выведенную на экран командой выше, и
+# подождите до её распространения. После выполните следующее:
+acme.sh --renew -d example.net -d '*.example.net'
+
+# Почти готово. Теперь осталось установить сертификат:
+mkdir /etc/ssl/private/example.net
+chown root:ssl-cert /etc/ssl/private/example.net
+chmod 750 /etc/ssl/private/example.net
+acme.sh --install-cert \
+ -d example.net -d '*.example.net' \
+ --ca-file /etc/ssl/private/example.net/chain.pem \
+ --cert-file /etc/ssl/private/example.net/cert.pem \
+ --fullchain-file /etc/ssl/private/example.net/fullchain.pem \
+ --key-file /etc/ssl/private/example.net/privkey.pem \
+ --reloadcmd "prosodyctl --root cert import \
+ /etc/ssl/private/example.net"
+</pre>
+
+<h2>Смотрите также</h2>
+
+<ul>
+ <li><a href="https://stupin.su/blog/prosody-dovecot-sasl">Ещё один блог сисадмина - Настройка Jabber-сервера Prosody с аутентификацией пользователей через Dovecot SASL</a>. Статья немного старая, но если вы настраивали Dovecot так же, как и я (см. главную страницу), то это может вам пригодиться для, например, добавление доступа в XMPP совместно с эл. почтой. Также советую посмотреть конец раздела по настройке SSL (5-ый), там есть скрипт, который будет обновлять сертификаты в Prosody вместе с Certbot.</li>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux - Prosody IM and local users - Networks PYMES</a>. Здесь тоже описывается авторизация с помощью PAM, но она выполнена с использованием ещё одной программы, что, конечно, неэффективно. Эта страница указана в начале, так как автор некоторое время использовал именно инструкцию по ссылке выше.</li>
+</ul>
+
+<hr>
+
+<p>В завершении статьи хочется обратить ваше внимание на то, что данная инструкция предоставляется БЕЗ каких-либо гарантий. Если при выполнении указаний из данной инструкции случилось что-то непредвиденное, вы можете обратиться ко мне, но не стоит ожидать какого-либо результата.</p>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/openwrt-24101------keenetic-launcher-kn-1221/">OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221)</a></h1>
+ <div class="content">
+<p>Вот оно:
+<summary>
+<details></p>
+
+<pre>
+From ef20327e33fb38220ba0bca4418464749305e555 Mon Sep 17 00:00:00 2001
+From: Ivan Davydov <lotigara@lotigara.ru>
+Date: Tue, 4 Mar 2025 23:54:13 +0300
+Subject: [PATCH] ramips: mt76x8: add support for Keenetic Launcher (KN-1221)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Specification:
+SoC: MediaTek MT7628AN
+RAM: 128M DDR2, ESMT M14D128168A (2Y)
+Flash: 32M, cFeon EN25QH256A (Dual Boot on OEM, concatenated on OpenWrt,
+SPI)
+Switch: MediaTek MT7628AN, 3 ports 100 Mbps
+WiFi: MediaTek MT7628AN 2.4 GHz 802.11n
+USB: 1 port USB 2.0
+GPIO: 1 button (Wi-Fi & Reset on OEM, Reset on OpenWrt), 3 LEDs (Power,
+Internet, Wi-Fi), USB port power controls
+
+Disassembly:
+There are 2 screws at the bottom near the LEDs hidden by rubber mounts.
+After removing the screws, pry the gray plastic part around (it is secured
+with latches) and remove it.
+
+UART Interface:
+The UART interface can be connected to the 5 pin located between LAN
+ports and the WAN one.
+Pins (from the second LAN port to the WAN one): VCC, TX, RX, NC, GND
+Settings: 115200, 8N1
+
+Flashing via TFTP:
+1. Connect your PC and router to the first LAN port, configure PC
+interface using IP 192.168.1.2, mask 255.255.255.0
+2. Serve the firmware image (for OpenWrt it is *-squashfs-factory.bin)
+renamed to KN-1221_recovery.bin via TFTP
+3. Power up the router while pressing Wi-Fi button
+4. Release Wi-Fi button when Power LED starts blinking
+
+To revert back to OEM firmware:
+The return to the OEM firmware is carried out by using the methods
+described above with the help of the appropriate firmware image found on
+osvault.keenetic.net.
+
+When using OEM bootloader, the firmware image size cannot exceed the size
+of one OEM «Firmware_x» partition or Kernel + rootFS size.
+
+Signed-off-by: Ivan Davydov <lotigara@lotigara.ru>
+Link: https://github.com/openwrt/openwrt/pull/18164
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../ramips/dts/mt7628an_keenetic_kn-1221.dts | 209 ++++++++++++++++++
+ target/linux/ramips/image/mt76x8.mk | 12 +
+ .../mt76x8/base-files/etc/board.d/01_leds | 1 +
+ .../mt76x8/base-files/etc/board.d/02_network | 5 +
+ 4 files changed, 227 insertions(+)
+ create mode 100644 target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+
+diff --git a/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+new file mode 100644
+index 00000000000000..6f5cf96856ed21
+--- /dev/null
++++ b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+@@ -0,0 +1,209 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "mt7628an.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ compatible = "keenetic,kn-1221", "mediatek,mt7628an-soc";
++ model = "Keenetic KN-1221";
++
++ aliases {
++ label-mac-device = &ethernet;
++
++ led-boot = &led_power;
++ led-failsafe = &led_power;
++ led-running = &led_power;
++ led-upgrade = &led_power;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,115200";
++ };
++
++ regulator-usb {
++ compatible = "regulator-fixed";
++ regulator-name = "USB-power";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: power {
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
++ };
++
++ internet {
++ function = LED_FUNCTION_WAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
++ };
++
++ fn {
++ function = LED_FUNCTION_WLAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "phy0tpt";
++ };
++ };
++
++ keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "restart";
++ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++
++ virtual_flash {
++ compatible = "mtd-concat";
++ devices = <&firmware1 &firmware2>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ compatible = "denx,uimage";
++ label = "firmware";
++ reg = <0x0 0x1cc0000>;
++ };
++ };
++ };
++};
++
++&state_default {
++ gpio {
++ groups = "i2c", "spi cs1", "gpio", "refclk", "wdt";
++ function = "gpio";
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <32000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-config";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ partition@40000 {
++ label = "rf-eeprom";
++ reg = <0x40000 0x10000>;
++ read-only;
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom_factory_0: eeprom@0 {
++ reg = <0x0 0x400>;
++ };
++
++ macaddr_factory_4: macaddr@4 {
++ reg = <0x4 0x6>;
++ };
++ };
++ };
++
++ firmware1: partition@50000 {
++ label = "firmware_1";
++ reg = <0x50000 0xe60000>;
++ };
++
++ partition@eb0000 {
++ label = "config_1";
++ reg = <0xeb0000 0x40000>;
++ read-only;
++ };
++
++ partition@ef0000 {
++ label = "storage";
++ reg = <0xef0000 0x100000>;
++ read-only;
++ };
++
++ partition@ff0000 {
++ label = "dump";
++ reg = <0xff0000 0x10000>;
++ read-only;
++ };
++
++ partition@1000000 {
++ label = "u-state";
++ reg = <0x1000000 0x30000>;
++ read-only;
++ };
++
++ partition@1030000 {
++ label = "u-config_res";
++ reg = <0x1030000 0x10000>;
++ read-only;
++ };
++
++ partition@1040000 {
++ label = "rf-eeprom_res";
++ reg = <0x1040000 0x10000>;
++ read-only;
++ };
++
++ firmware2: partition@1050000 {
++ label = "firmware_2";
++ reg = <0x1050000 0xe60000>;
++ };
++
++ partition@1eb0000 {
++ label = "Config_2";
++ reg = <0x1eb0000 0x40000>;
++ read-only;
++ };
++ };
++ };
++};
++
++&ethernet {
++ nvmem-cells = <&macaddr_factory_4>;
++ nvmem-cell-names = "mac-address";
++};
++
++&esw {
++ mediatek,portmap = <0x3e>;
++ mediatek,portdisable = <0x38>;
++};
++
++&wmac {
++ status = "okay";
++
++ nvmem-cells = <&eeprom_factory_0>;
++ nvmem-cell-names = "eeprom";
++};
+diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk
+index 8c8cfee23b6cfa..f442148d9ecf10 100644
+--- a/target/linux/ramips/image/mt76x8.mk
++++ b/target/linux/ramips/image/mt76x8.mk
+@@ -366,6 +366,18 @@ define Device/jotale_js76x8-32m
+ endef
+ TARGET_DEVICES += jotale_js76x8-32m
+
++define Device/keenetic_kn-1221
++ BLOCKSIZE := 64k
++ IMAGE_SIZE := 29440k
++ DEVICE_VENDOR := Keenetic
++ DEVICE_MODEL := KN-1221
++ DEVICE_PACKAGES := kmod-usb2
++ IMAGES += factory.bin
++ IMAGE/factory.bin := $$(sysupgrade_bin) | pad-to $$$$(BLOCKSIZE) | \
++ check-size 14720k | zyimage -d 0x801221 -v "KN-1221"
++endef
++TARGET_DEVICES += keenetic_kn-1221
++
+ define Device/keenetic_kn-1613
+ IMAGE_SIZE := 31488k
+ DEVICE_VENDOR := Keenetic
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+index b87062ae3c5ae5..79f78a2a459487 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+@@ -58,4 +58,5 @@ hiwifi,hc5661a|\
+ hiwifi,hc5761a)
+ ucidef_set_led_switch "internet" "internet" "blue:internet" "switch0" "0x10"
+ ;;
++keenetic,kn-1221|\
+ keenetic,kn-1613)
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+index fbdc7fb5a2697a..6e6e1310d3495f 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+@@ -131,5 +131,9 @@ ramips_setup_interfaces()
+ ucidef_add_switch "switch0" \
+ "0:lan" "1:lan" "2:lan" "6@eth0"
+ ;;
++ keenetic,kn-1221)
++ ucidef_add_switch "switch0" \
++ "1:lan" "2:lan" "0:wan" "6@eth0"
++ ;;
+ keenetic,kn-1613|\
+ motorola,mwr03)
+@@ -280,5 +280,6 @@ ramips_setup_macs()
+ totolink,lr1200)
+ wan_mac=$(mtd_get_mac_binary factory 0x2e)
+ ;;
++ keenetic,kn-1221|\
+ keenetic,kn-1613|\
+ zyxel,keenetic-extra-ii)
+</pre>
+
+<p></details>
+</summary></p>
+
+<p>Или в виде файла: <a href="/files/18164.patch.backport-24.10.1">18164.patch.backport-24.10.1</a>.
+Готовые сборки тоже доступны в виде файлов: <a href="/files/openwrt-kn-1221-24.10">openwrt-kn-1221-24.10</a></p>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/">Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS</a></h1>
+ <div class="content">
+<h5>tested to not work on KeeneticOS v3.8.7 &amp; OpenWrt v23.05.5</h5>
+
+<p>First, set up FT on your OpenWrt devices.</p>
+
+<p>Then, change the mode of your Keenetic (?) devices to Extender (there are Repeater/Extender and Access Point/Extender, the last is the recommended).</p>
+
+<p>Go to the <code>Access Point/Extender (Repeater/Extender) &gt; Home segment</code> menu. Change the settings of the Wi-Fi network to those ones in OpenWrt.</p>
+
+<p>Scroll below to the "Roaming for wireless devices" section. Enable "Fast transition (802.11r)" and write your mobility domain ID converted to the ASCII format.</p>
+
+<p>You can use an online converter like this one: <a href="https://www.rapidtables.com/convert/number/hex-to-ascii.html">https://www.rapidtables.com/convert/number/hex-to-ascii.html</a>. Keep the "Mobility domain key" field unedited.</p>
+
+<p>Press the "Save" button. Now you have a so-called "Wi-Fi system" with use of both KeeneticOS and OpenWrt!</p>
+ </div>
+</div>
+<!-- /post -->
+
+</div>
+<div class="pagination ">
+ <a class="prev" href="/blog//">Назад</a>
+ <a class="next" href="/blog//">Вперёд</a>
+</div>
+<!-- /page -->
+
+ </body>
+</html>
diff --git a/public/blog/openwrt-24101------keenetic-launcher-kn-1221/index.html b/public/blog/openwrt-24101------keenetic-launcher-kn-1221/index.html
new file mode 100644
index 0000000..e25be72
--- /dev/null
+++ b/public/blog/openwrt-24101------keenetic-launcher-kn-1221/index.html
@@ -0,0 +1,370 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221) - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/openwrt-24101------keenetic-launcher-kn-1221/">OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221)</a></h1>
+ <div class="content">
+<p>Вот оно:
+<summary>
+<details></p>
+
+<pre>
+From ef20327e33fb38220ba0bca4418464749305e555 Mon Sep 17 00:00:00 2001
+From: Ivan Davydov <lotigara@lotigara.ru>
+Date: Tue, 4 Mar 2025 23:54:13 +0300
+Subject: [PATCH] ramips: mt76x8: add support for Keenetic Launcher (KN-1221)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Specification:
+SoC: MediaTek MT7628AN
+RAM: 128M DDR2, ESMT M14D128168A (2Y)
+Flash: 32M, cFeon EN25QH256A (Dual Boot on OEM, concatenated on OpenWrt,
+SPI)
+Switch: MediaTek MT7628AN, 3 ports 100 Mbps
+WiFi: MediaTek MT7628AN 2.4 GHz 802.11n
+USB: 1 port USB 2.0
+GPIO: 1 button (Wi-Fi & Reset on OEM, Reset on OpenWrt), 3 LEDs (Power,
+Internet, Wi-Fi), USB port power controls
+
+Disassembly:
+There are 2 screws at the bottom near the LEDs hidden by rubber mounts.
+After removing the screws, pry the gray plastic part around (it is secured
+with latches) and remove it.
+
+UART Interface:
+The UART interface can be connected to the 5 pin located between LAN
+ports and the WAN one.
+Pins (from the second LAN port to the WAN one): VCC, TX, RX, NC, GND
+Settings: 115200, 8N1
+
+Flashing via TFTP:
+1. Connect your PC and router to the first LAN port, configure PC
+interface using IP 192.168.1.2, mask 255.255.255.0
+2. Serve the firmware image (for OpenWrt it is *-squashfs-factory.bin)
+renamed to KN-1221_recovery.bin via TFTP
+3. Power up the router while pressing Wi-Fi button
+4. Release Wi-Fi button when Power LED starts blinking
+
+To revert back to OEM firmware:
+The return to the OEM firmware is carried out by using the methods
+described above with the help of the appropriate firmware image found on
+osvault.keenetic.net.
+
+When using OEM bootloader, the firmware image size cannot exceed the size
+of one OEM «Firmware_x» partition or Kernel + rootFS size.
+
+Signed-off-by: Ivan Davydov <lotigara@lotigara.ru>
+Link: https://github.com/openwrt/openwrt/pull/18164
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../ramips/dts/mt7628an_keenetic_kn-1221.dts | 209 ++++++++++++++++++
+ target/linux/ramips/image/mt76x8.mk | 12 +
+ .../mt76x8/base-files/etc/board.d/01_leds | 1 +
+ .../mt76x8/base-files/etc/board.d/02_network | 5 +
+ 4 files changed, 227 insertions(+)
+ create mode 100644 target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+
+diff --git a/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+new file mode 100644
+index 00000000000000..6f5cf96856ed21
+--- /dev/null
++++ b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+@@ -0,0 +1,209 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "mt7628an.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ compatible = "keenetic,kn-1221", "mediatek,mt7628an-soc";
++ model = "Keenetic KN-1221";
++
++ aliases {
++ label-mac-device = &ethernet;
++
++ led-boot = &led_power;
++ led-failsafe = &led_power;
++ led-running = &led_power;
++ led-upgrade = &led_power;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,115200";
++ };
++
++ regulator-usb {
++ compatible = "regulator-fixed";
++ regulator-name = "USB-power";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: power {
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
++ };
++
++ internet {
++ function = LED_FUNCTION_WAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
++ };
++
++ fn {
++ function = LED_FUNCTION_WLAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "phy0tpt";
++ };
++ };
++
++ keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "restart";
++ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++
++ virtual_flash {
++ compatible = "mtd-concat";
++ devices = <&firmware1 &firmware2>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ compatible = "denx,uimage";
++ label = "firmware";
++ reg = <0x0 0x1cc0000>;
++ };
++ };
++ };
++};
++
++&state_default {
++ gpio {
++ groups = "i2c", "spi cs1", "gpio", "refclk", "wdt";
++ function = "gpio";
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <32000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-config";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ partition@40000 {
++ label = "rf-eeprom";
++ reg = <0x40000 0x10000>;
++ read-only;
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom_factory_0: eeprom@0 {
++ reg = <0x0 0x400>;
++ };
++
++ macaddr_factory_4: macaddr@4 {
++ reg = <0x4 0x6>;
++ };
++ };
++ };
++
++ firmware1: partition@50000 {
++ label = "firmware_1";
++ reg = <0x50000 0xe60000>;
++ };
++
++ partition@eb0000 {
++ label = "config_1";
++ reg = <0xeb0000 0x40000>;
++ read-only;
++ };
++
++ partition@ef0000 {
++ label = "storage";
++ reg = <0xef0000 0x100000>;
++ read-only;
++ };
++
++ partition@ff0000 {
++ label = "dump";
++ reg = <0xff0000 0x10000>;
++ read-only;
++ };
++
++ partition@1000000 {
++ label = "u-state";
++ reg = <0x1000000 0x30000>;
++ read-only;
++ };
++
++ partition@1030000 {
++ label = "u-config_res";
++ reg = <0x1030000 0x10000>;
++ read-only;
++ };
++
++ partition@1040000 {
++ label = "rf-eeprom_res";
++ reg = <0x1040000 0x10000>;
++ read-only;
++ };
++
++ firmware2: partition@1050000 {
++ label = "firmware_2";
++ reg = <0x1050000 0xe60000>;
++ };
++
++ partition@1eb0000 {
++ label = "Config_2";
++ reg = <0x1eb0000 0x40000>;
++ read-only;
++ };
++ };
++ };
++};
++
++&ethernet {
++ nvmem-cells = <&macaddr_factory_4>;
++ nvmem-cell-names = "mac-address";
++};
++
++&esw {
++ mediatek,portmap = <0x3e>;
++ mediatek,portdisable = <0x38>;
++};
++
++&wmac {
++ status = "okay";
++
++ nvmem-cells = <&eeprom_factory_0>;
++ nvmem-cell-names = "eeprom";
++};
+diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk
+index 8c8cfee23b6cfa..f442148d9ecf10 100644
+--- a/target/linux/ramips/image/mt76x8.mk
++++ b/target/linux/ramips/image/mt76x8.mk
+@@ -366,6 +366,18 @@ define Device/jotale_js76x8-32m
+ endef
+ TARGET_DEVICES += jotale_js76x8-32m
+
++define Device/keenetic_kn-1221
++ BLOCKSIZE := 64k
++ IMAGE_SIZE := 29440k
++ DEVICE_VENDOR := Keenetic
++ DEVICE_MODEL := KN-1221
++ DEVICE_PACKAGES := kmod-usb2
++ IMAGES += factory.bin
++ IMAGE/factory.bin := $$(sysupgrade_bin) | pad-to $$$$(BLOCKSIZE) | \
++ check-size 14720k | zyimage -d 0x801221 -v "KN-1221"
++endef
++TARGET_DEVICES += keenetic_kn-1221
++
+ define Device/keenetic_kn-1613
+ IMAGE_SIZE := 31488k
+ DEVICE_VENDOR := Keenetic
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+index b87062ae3c5ae5..79f78a2a459487 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+@@ -58,4 +58,5 @@ hiwifi,hc5661a|\
+ hiwifi,hc5761a)
+ ucidef_set_led_switch "internet" "internet" "blue:internet" "switch0" "0x10"
+ ;;
++keenetic,kn-1221|\
+ keenetic,kn-1613)
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+index fbdc7fb5a2697a..6e6e1310d3495f 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+@@ -131,5 +131,9 @@ ramips_setup_interfaces()
+ ucidef_add_switch "switch0" \
+ "0:lan" "1:lan" "2:lan" "6@eth0"
+ ;;
++ keenetic,kn-1221)
++ ucidef_add_switch "switch0" \
++ "1:lan" "2:lan" "0:wan" "6@eth0"
++ ;;
+ keenetic,kn-1613|\
+ motorola,mwr03)
+@@ -280,5 +280,6 @@ ramips_setup_macs()
+ totolink,lr1200)
+ wan_mac=$(mtd_get_mac_binary factory 0x2e)
+ ;;
++ keenetic,kn-1221|\
+ keenetic,kn-1613|\
+ zyxel,keenetic-extra-ii)
+</pre>
+
+<p></details>
+</summary></p>
+
+<p>Или в виде файла: <a href="/files/18164.patch.backport-24.10.1">18164.patch.backport-24.10.1</a>.
+Готовые сборки тоже доступны в виде файлов: <a href="/files/openwrt-kn-1221-24.10">openwrt-kn-1221-24.10</a></p>
+ </div>
+</div>
+<!-- /post -->
+
+ </body>
+</html>
diff --git a/public/blog/pubnix----prosody--pam-/index.html b/public/blog/pubnix----prosody--pam-/index.html
new file mode 100644
index 0000000..2c49631
--- /dev/null
+++ b/public/blog/pubnix----prosody--pam-/index.html
@@ -0,0 +1,214 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>Pubnix - Установка Prosody с PAM-авторизацией - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/pubnix----prosody--pam-/">Pubnix - Установка Prosody с PAM-авторизацией</a></h1>
+ <div class="content">
+<h2>Использованные источники</h2>
+
+<ul>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux</a></li>
+ <li><a href="https://landchad.net/prosody">LandChad</a></li>
+ <li><a href="https://prosody.im">Prosody</a></li>
+</ul>
+
+<h2>0. Системные требования</h2>
+
+<ul>
+ <li>Firewall с следующими открытыми портами:</li>
+ <li>
+ <ul>
+ <li>5000/tcp (передача файлов)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5222/tcp (подключение клиента)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5269/tcp (федерация, подключение сервера к серверу)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5281/tcp (по желанию, но рекомендуется)</li>
+ </ul>
+ </li>
+ <li><p>Debian 12 с последними обновлениями и доступом в Интернет</p></li>
+ <li><p>Prosody &gt;= 0.13</p></li>
+</ul>
+
+<hr>
+
+<h2>0,5. Авторизация при помощи ОС</h2>
+<p>PAM (Pluggable Authentication Modules) - API для авторизации в Unix-подобных ОС, по умолчанию использует список пользователей из файла `/etc/passwd`.</p>
+
+<p>Все команды выполняются пользователем <code>root</code>, если не указано иначе.</p>
+
+<h2>1. Установка</h2>
+<p>Выполните эти команды:</p>
+
+<pre>
+# Установить Prosody
+wget https://prosody.im/files/prosody.sources -O/etc/apt/sources.list.d/prosody.sources
+apt update
+apt install prosody lua5.4 liblua5.4-0 liblua5.4-dev luarocks
+# Добавить привилегии демону Prosody
+usermod -aG shadow prosody
+usermod -aG ssl-cert prosody
+# Установить библиотеку для взаимодействия с <abbr title="Portable Operating System Interface">POSIX</abbr>-функциями
+luarocks install luaposix
+# Собрать библиотеку дл/ PAM-аутентификации
+git clone https://github.com/devurandom/lua-pam &amp;&amp; cd lua-pam
+make LUA_VERSION=5.4
+cp pam.so /usr/lib/
+# Установить модуль для PAM-аутентификации
+LUA_INCDIR=5.4 prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_pam
+</pre>
+
+<h2>2. Настройка</h2>
+<p>Начните редактировать файл <code>/etc/prosody/prosody.cfg.lua</code>.
+Следуйте этим инструкциям, заменяя <code>example.net</code> на доменное имя, привязанное к вашему серверу.</p>
+
+<p>Найдите строку, начинающуюся с слова <code>admins</code>, и добавьте ваше будущее имя пользователя в фигурные скобки подобным образом:</p>
+
+<pre>
+admins = { "admin@example.net" }
+</pre>
+
+<p>Где <code>admin</code> - это ваше имя пользователя в вашей системе.</p>
+
+<p>Дальше найдите строку <code>--"mam";</code> и удалите два дефиса, сделайте то же самое с строкой <code>--"turn_external";</code>, находящейся ниже.</p>
+
+<p>Теперь перейдите к строке <code>authentication = "internal_hashed"</code> и замените <code>internal_hashed</code> на <code>pam</code>.</p>
+
+<p>Перейдите к строке, начинающейся с <code>storage</code> и поменяйте <code>sql</code> на <code>internal</code> (по желанию, в этой инструкции я не рассматриваю настройку с базами данных)</p>
+
+<p>По желанию в строке <code>archive_expires_after = "1w"</code> замените <code>1w</code> на <code>never</code>, чтобы истории переписок не удалялись каждую неделю.</p>
+
+<p>Найдите строку, начинающуюся с <code>VirtualHost</code> и замените <code>localhost</code> на <code>example.net</code>.</p>
+
+<p>Если вам нужны многопользовательские переписки, на следующей строке добавьте следущее:</p>
+
+<pre>
+Component "conference.example.net" "muc"
+modules_enabled = { "muc_mam", "vcard_muc" }
+</pre>
+
+<p>Последнюю строку можете опустить, если вам не нужно сохранение истории многопользовательских переписок.</p>
+
+<p>Если нужна возможность загружать файлы на ваш сервер, дополните конфигурацию следующими строками:</p>
+
+<pre>
+Component "upload.example.net" "http_file_share"
+http_file_share_size_limit = 512 * 1024 * 1024 --измеряется в байтах
+http_file_share_expire_after = 60 * 60 * 24 * 31 * 1000 --измеряется в секундах
+</pre>
+
+<p>В данном случае, лимит размера файла - это 512 МиБ (0,5 ГиБ), а удаляться файлы будут через ~1000 лет.
+Если требуется изменить какое-либо из этих свойств, смотрите комментарии (в Lua они начинаются с двух дефисов) и пробуйте изменять значения.</p>
+
+<h2>3. Настройка TLS-сертификата</h2>
+<p>Также заменяйте `example.net` на ваше доменное имя.</p>
+
+<p>ACME (Automatic Certificate Management Environment) - это протокол для получения TLS-сертификатов по Web.
+В этом примере используется ACME-клиент acme.sh, так как эта программа более настраиваемая и удостоверяющий центр (далее УЦ) Let's Encrypt (но вы можете использовать любой другой).</p>
+
+<p>Выполните следующие команды:</p>
+<pre>
+# Эта команда установит acme.sh в директорию ~/.acme.sh, системные
+# файлы не будут затронуты
+wget -O - https://get.acme.sh | sh -s \
+ email=yourveryownlocalpart@example.net
+# Теперь либо перезайдите в систему, либо выполните `exec $0`, если
+# вы уверены в значении переменной `$0`.
+
+# Проверьте, прошла ли установка правильно
+acme.sh -h
+
+# Установить Let's Encrypt в качестве УЦ
+acme.sh --set-default-ca --server \
+ https://acme-v02.api.letsencrypt.org/directory
+
+# Есть два способа подтверждения владения доменом - по HTTP или по
+# DNS.
+# Первый проще, но требует доступ на запись в директорию, содержимое
+# которой доступно по ссылке http://example.net/:
+acme.sh --issue -d example.net -d conference.example.net -d \
+ upload.example.net -w &lt;директория с корнем вашего
+ веб-сервера&gt;
+# А второй, поддерживая Wildcard-сертификаты, позволяет в дальнейшем
+# подключать к вашему XMPP-серверу всевозможные компоненты
+# (транспорты в другие сети, модуль публикации-подписки, он же
+# Publish-Subscribe или просто PubSub и многие другие), но требует
+# доступа к API вашего DNS-регистратора для создания записи,
+# подтверждающей владение доменным именем:
+acme.sh --issue --dnssleep &lt;время в секундах, большее чем TTL&gt; \
+ --dns dns_myapi \
+ -d example.net -d '*.example.net' # Где dns_myapi - это кодовое
+ # имя DNS-провайдера, указанное на
+ # https://github.com/acmesh-official/acme.sh/wiki/dnsapi
+# Но если у вас нет и веб-сервера (или доступа к нему), и доступа к
+# API регистратора, то вы можете внести запись с подтверждением
+# вручную (заметьте, что вам нужно будет это делать каждый раз, когда
+# будет истекать срок действия сертификата):
+# (Перед применением этого способа следует внимательно прочитать
+# следующую страницу:
+# https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode)
+acme.sh --issue --dns -d example.net -d '*.example.net'
+# Теперь примените DNS-запись, выведенную на экран командой выше, и
+# подождите до её распространения. После выполните следующее:
+acme.sh --renew -d example.net -d '*.example.net'
+
+# Почти готово. Теперь осталось установить сертификат:
+mkdir /etc/ssl/private/example.net
+chown root:ssl-cert /etc/ssl/private/example.net
+chmod 750 /etc/ssl/private/example.net
+acme.sh --install-cert \
+ -d example.net -d '*.example.net' \
+ --ca-file /etc/ssl/private/example.net/chain.pem \
+ --cert-file /etc/ssl/private/example.net/cert.pem \
+ --fullchain-file /etc/ssl/private/example.net/fullchain.pem \
+ --key-file /etc/ssl/private/example.net/privkey.pem \
+ --reloadcmd "prosodyctl --root cert import \
+ /etc/ssl/private/example.net"
+</pre>
+
+<h2>Смотрите также</h2>
+
+<ul>
+ <li><a href="https://stupin.su/blog/prosody-dovecot-sasl">Ещё один блог сисадмина - Настройка Jabber-сервера Prosody с аутентификацией пользователей через Dovecot SASL</a>. Статья немного старая, но если вы настраивали Dovecot так же, как и я (см. главную страницу), то это может вам пригодиться для, например, добавление доступа в XMPP совместно с эл. почтой. Также советую посмотреть конец раздела по настройке SSL (5-ый), там есть скрипт, который будет обновлять сертификаты в Prosody вместе с Certbot.</li>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux - Prosody IM and local users - Networks PYMES</a>. Здесь тоже описывается авторизация с помощью PAM, но она выполнена с использованием ещё одной программы, что, конечно, неэффективно. Эта страница указана в начале, так как автор некоторое время использовал именно инструкцию по ссылке выше.</li>
+</ul>
+
+<hr>
+
+<p>В завершении статьи хочется обратить ваше внимание на то, что данная инструкция предоставляется БЕЗ каких-либо гарантий. Если при выполнении указаний из данной инструкции случилось что-то непредвиденное, вы можете обратиться ко мне, но не стоит ожидать какого-либо результата.</p>
+ </div>
+</div>
+<!-- /post -->
+
+ </body>
+</html>
diff --git a/public/feed.rss b/public/feed.rss
new file mode 100644
index 0000000..4e07de9
--- /dev/null
+++ b/public/feed.rss
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+<channel>
+ <title>&ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link>https://www.lotigara.ru/blog/</link>
+ <description>language: ru-ru</description>
+ <atom:link href="https://www.lotigara.ru/blog/feed.rss" rel="self" type="application/rss+xml" />
+ <managingEditor>lotigara@lotigara.ru (lotigara)</managingEditor>
+ <copyright>&lpar;c&rpar; Ivan Davydov 2024-2025&period; &Dcy;&iecy;&lcy;&acy;&jcy;&tcy;&iecy; &scy; &ecy;&tcy;&icy;&mcy; &dcy;&ocy;&kcy;&ucy;&mcy;&iecy;&ncy;&tcy;&ocy;&mcy; &vcy;&scy;&iocy;&comma; &chcy;&tcy;&ocy; &khcy;&ocy;&tcy;&icy;&tcy;&iecy;&excl;</copyright>
+ <pubDate>Tue, 24 Jun 2025 13:59:37 +0300</pubDate>
+ <generator>housecat</generator>
+ <docs>https://cyber.harvard.edu/rss/rss.html</docs>
+</channel>
+</rss>
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 0000000..2bda186
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,598 @@
+<!DOCTYPE html>
+<html class="blog" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>blog - &ZHcy;&ucy;&rcy;&ncy;&acy;&lcy; &commat; &vcy;&iecy;&bcy;-&scy;&acy;&jcy;&tcy;&iecy; &scy;&acy;&mcy;&ocy;&khcy;&ocy;&scy;&tcy;&iecy;&rcy;&acy; Lotigara</title>
+ <link rel="stylesheet" href="/blog/_/style.css">
+ <body>
+<header><center>
+ <h1>Веб-сайт самохостера Lotigara</h1>
+ <nav>
+ <a href="https://www.lotigara.ru/">главная|main page</a>
+ <a href="https://www.lotigara.ru/status.php">состояние|status</a>
+ <a href="https://www.lotigara.ru/blog">журнал|journal</a>
+ <a href="https://www.lotigara.ru/files">файлы|files</a>
+ <a href="https://git.lotigara.ru">программы|software</a>
+ <br>
+ <a href="https://www.lotigara.ru/archive">архив|archive</a>
+ </nav>
+</center></header>
+
+<!-- page -->
+<div class="posts">
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/download-mods-for-a-steam-game-from-the-steam-workshop/">Download mods for a Steam game from the Steam Workshop</a></h1>
+ <div class="content">
+<pre alt="sh">
+steamcmd "+login $USERID" $(for i in $MODLIST; do echo "+download_item $APPID $i"; done)
+</pre>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/pubnix----prosody--pam-/">Pubnix - Установка Prosody с PAM-авторизацией</a></h1>
+ <div class="content">
+<h2>Использованные источники</h2>
+
+<ul>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux</a></li>
+ <li><a href="https://landchad.net/prosody">LandChad</a></li>
+ <li><a href="https://prosody.im">Prosody</a></li>
+</ul>
+
+<h2>0. Системные требования</h2>
+
+<ul>
+ <li>Firewall с следующими открытыми портами:</li>
+ <li>
+ <ul>
+ <li>5000/tcp (передача файлов)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5222/tcp (подключение клиента)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5269/tcp (федерация, подключение сервера к серверу)</li>
+ </ul>
+ </li>
+ <li>
+ <ul>
+ <li>5281/tcp (по желанию, но рекомендуется)</li>
+ </ul>
+ </li>
+ <li><p>Debian 12 с последними обновлениями и доступом в Интернет</p></li>
+ <li><p>Prosody &gt;= 0.13</p></li>
+</ul>
+
+<hr>
+
+<h2>0,5. Авторизация при помощи ОС</h2>
+<p>PAM (Pluggable Authentication Modules) - API для авторизации в Unix-подобных ОС, по умолчанию использует список пользователей из файла `/etc/passwd`.</p>
+
+<p>Все команды выполняются пользователем <code>root</code>, если не указано иначе.</p>
+
+<h2>1. Установка</h2>
+<p>Выполните эти команды:</p>
+
+<pre>
+# Установить Prosody
+wget https://prosody.im/files/prosody.sources -O/etc/apt/sources.list.d/prosody.sources
+apt update
+apt install prosody lua5.4 liblua5.4-0 liblua5.4-dev luarocks
+# Добавить привилегии демону Prosody
+usermod -aG shadow prosody
+usermod -aG ssl-cert prosody
+# Установить библиотеку для взаимодействия с <abbr title="Portable Operating System Interface">POSIX</abbr>-функциями
+luarocks install luaposix
+# Собрать библиотеку дл/ PAM-аутентификации
+git clone https://github.com/devurandom/lua-pam &amp;&amp; cd lua-pam
+make LUA_VERSION=5.4
+cp pam.so /usr/lib/
+# Установить модуль для PAM-аутентификации
+LUA_INCDIR=5.4 prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_pam
+</pre>
+
+<h2>2. Настройка</h2>
+<p>Начните редактировать файл <code>/etc/prosody/prosody.cfg.lua</code>.
+Следуйте этим инструкциям, заменяя <code>example.net</code> на доменное имя, привязанное к вашему серверу.</p>
+
+<p>Найдите строку, начинающуюся с слова <code>admins</code>, и добавьте ваше будущее имя пользователя в фигурные скобки подобным образом:</p>
+
+<pre>
+admins = { "admin@example.net" }
+</pre>
+
+<p>Где <code>admin</code> - это ваше имя пользователя в вашей системе.</p>
+
+<p>Дальше найдите строку <code>--"mam";</code> и удалите два дефиса, сделайте то же самое с строкой <code>--"turn_external";</code>, находящейся ниже.</p>
+
+<p>Теперь перейдите к строке <code>authentication = "internal_hashed"</code> и замените <code>internal_hashed</code> на <code>pam</code>.</p>
+
+<p>Перейдите к строке, начинающейся с <code>storage</code> и поменяйте <code>sql</code> на <code>internal</code> (по желанию, в этой инструкции я не рассматриваю настройку с базами данных)</p>
+
+<p>По желанию в строке <code>archive_expires_after = "1w"</code> замените <code>1w</code> на <code>never</code>, чтобы истории переписок не удалялись каждую неделю.</p>
+
+<p>Найдите строку, начинающуюся с <code>VirtualHost</code> и замените <code>localhost</code> на <code>example.net</code>.</p>
+
+<p>Если вам нужны многопользовательские переписки, на следующей строке добавьте следущее:</p>
+
+<pre>
+Component "conference.example.net" "muc"
+modules_enabled = { "muc_mam", "vcard_muc" }
+</pre>
+
+<p>Последнюю строку можете опустить, если вам не нужно сохранение истории многопользовательских переписок.</p>
+
+<p>Если нужна возможность загружать файлы на ваш сервер, дополните конфигурацию следующими строками:</p>
+
+<pre>
+Component "upload.example.net" "http_file_share"
+http_file_share_size_limit = 512 * 1024 * 1024 --измеряется в байтах
+http_file_share_expire_after = 60 * 60 * 24 * 31 * 1000 --измеряется в секундах
+</pre>
+
+<p>В данном случае, лимит размера файла - это 512 МиБ (0,5 ГиБ), а удаляться файлы будут через ~1000 лет.
+Если требуется изменить какое-либо из этих свойств, смотрите комментарии (в Lua они начинаются с двух дефисов) и пробуйте изменять значения.</p>
+
+<h2>3. Настройка TLS-сертификата</h2>
+<p>Также заменяйте `example.net` на ваше доменное имя.</p>
+
+<p>ACME (Automatic Certificate Management Environment) - это протокол для получения TLS-сертификатов по Web.
+В этом примере используется ACME-клиент acme.sh, так как эта программа более настраиваемая и удостоверяющий центр (далее УЦ) Let's Encrypt (но вы можете использовать любой другой).</p>
+
+<p>Выполните следующие команды:</p>
+<pre>
+# Эта команда установит acme.sh в директорию ~/.acme.sh, системные
+# файлы не будут затронуты
+wget -O - https://get.acme.sh | sh -s \
+ email=yourveryownlocalpart@example.net
+# Теперь либо перезайдите в систему, либо выполните `exec $0`, если
+# вы уверены в значении переменной `$0`.
+
+# Проверьте, прошла ли установка правильно
+acme.sh -h
+
+# Установить Let's Encrypt в качестве УЦ
+acme.sh --set-default-ca --server \
+ https://acme-v02.api.letsencrypt.org/directory
+
+# Есть два способа подтверждения владения доменом - по HTTP или по
+# DNS.
+# Первый проще, но требует доступ на запись в директорию, содержимое
+# которой доступно по ссылке http://example.net/:
+acme.sh --issue -d example.net -d conference.example.net -d \
+ upload.example.net -w &lt;директория с корнем вашего
+ веб-сервера&gt;
+# А второй, поддерживая Wildcard-сертификаты, позволяет в дальнейшем
+# подключать к вашему XMPP-серверу всевозможные компоненты
+# (транспорты в другие сети, модуль публикации-подписки, он же
+# Publish-Subscribe или просто PubSub и многие другие), но требует
+# доступа к API вашего DNS-регистратора для создания записи,
+# подтверждающей владение доменным именем:
+acme.sh --issue --dnssleep &lt;время в секундах, большее чем TTL&gt; \
+ --dns dns_myapi \
+ -d example.net -d '*.example.net' # Где dns_myapi - это кодовое
+ # имя DNS-провайдера, указанное на
+ # https://github.com/acmesh-official/acme.sh/wiki/dnsapi
+# Но если у вас нет и веб-сервера (или доступа к нему), и доступа к
+# API регистратора, то вы можете внести запись с подтверждением
+# вручную (заметьте, что вам нужно будет это делать каждый раз, когда
+# будет истекать срок действия сертификата):
+# (Перед применением этого способа следует внимательно прочитать
+# следующую страницу:
+# https://github.com/acmesh-official/acme.sh/wiki/dns-manual-mode)
+acme.sh --issue --dns -d example.net -d '*.example.net'
+# Теперь примените DNS-запись, выведенную на экран командой выше, и
+# подождите до её распространения. После выполните следующее:
+acme.sh --renew -d example.net -d '*.example.net'
+
+# Почти готово. Теперь осталось установить сертификат:
+mkdir /etc/ssl/private/example.net
+chown root:ssl-cert /etc/ssl/private/example.net
+chmod 750 /etc/ssl/private/example.net
+acme.sh --install-cert \
+ -d example.net -d '*.example.net' \
+ --ca-file /etc/ssl/private/example.net/chain.pem \
+ --cert-file /etc/ssl/private/example.net/cert.pem \
+ --fullchain-file /etc/ssl/private/example.net/fullchain.pem \
+ --key-file /etc/ssl/private/example.net/privkey.pem \
+ --reloadcmd "prosodyctl --root cert import \
+ /etc/ssl/private/example.net"
+</pre>
+
+<h2>Смотрите также</h2>
+
+<ul>
+ <li><a href="https://stupin.su/blog/prosody-dovecot-sasl">Ещё один блог сисадмина - Настройка Jabber-сервера Prosody с аутентификацией пользователей через Dovecot SASL</a>. Статья немного старая, но если вы настраивали Dovecot так же, как и я (см. главную страницу), то это может вам пригодиться для, например, добавление доступа в XMPP совместно с эл. почтой. Также советую посмотреть конец раздела по настройке SSL (5-ый), там есть скрипт, который будет обновлять сертификаты в Prosody вместе с Certbot.</li>
+ <li><a href="https://blog.desdelinux.net/en/prosody-im-local-users-SME-networks">DesdeLinux - Prosody IM and local users - Networks PYMES</a>. Здесь тоже описывается авторизация с помощью PAM, но она выполнена с использованием ещё одной программы, что, конечно, неэффективно. Эта страница указана в начале, так как автор некоторое время использовал именно инструкцию по ссылке выше.</li>
+</ul>
+
+<hr>
+
+<p>В завершении статьи хочется обратить ваше внимание на то, что данная инструкция предоставляется БЕЗ каких-либо гарантий. Если при выполнении указаний из данной инструкции случилось что-то непредвиденное, вы можете обратиться ко мне, но не стоит ожидать какого-либо результата.</p>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/openwrt-24101------keenetic-launcher-kn-1221/">OpenWrt 24.10.1 - исправление, добавляющее поддержку Keenetic Launcher (KN-1221)</a></h1>
+ <div class="content">
+<p>Вот оно:
+<summary>
+<details></p>
+
+<pre>
+From ef20327e33fb38220ba0bca4418464749305e555 Mon Sep 17 00:00:00 2001
+From: Ivan Davydov <lotigara@lotigara.ru>
+Date: Tue, 4 Mar 2025 23:54:13 +0300
+Subject: [PATCH] ramips: mt76x8: add support for Keenetic Launcher (KN-1221)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Specification:
+SoC: MediaTek MT7628AN
+RAM: 128M DDR2, ESMT M14D128168A (2Y)
+Flash: 32M, cFeon EN25QH256A (Dual Boot on OEM, concatenated on OpenWrt,
+SPI)
+Switch: MediaTek MT7628AN, 3 ports 100 Mbps
+WiFi: MediaTek MT7628AN 2.4 GHz 802.11n
+USB: 1 port USB 2.0
+GPIO: 1 button (Wi-Fi & Reset on OEM, Reset on OpenWrt), 3 LEDs (Power,
+Internet, Wi-Fi), USB port power controls
+
+Disassembly:
+There are 2 screws at the bottom near the LEDs hidden by rubber mounts.
+After removing the screws, pry the gray plastic part around (it is secured
+with latches) and remove it.
+
+UART Interface:
+The UART interface can be connected to the 5 pin located between LAN
+ports and the WAN one.
+Pins (from the second LAN port to the WAN one): VCC, TX, RX, NC, GND
+Settings: 115200, 8N1
+
+Flashing via TFTP:
+1. Connect your PC and router to the first LAN port, configure PC
+interface using IP 192.168.1.2, mask 255.255.255.0
+2. Serve the firmware image (for OpenWrt it is *-squashfs-factory.bin)
+renamed to KN-1221_recovery.bin via TFTP
+3. Power up the router while pressing Wi-Fi button
+4. Release Wi-Fi button when Power LED starts blinking
+
+To revert back to OEM firmware:
+The return to the OEM firmware is carried out by using the methods
+described above with the help of the appropriate firmware image found on
+osvault.keenetic.net.
+
+When using OEM bootloader, the firmware image size cannot exceed the size
+of one OEM «Firmware_x» partition or Kernel + rootFS size.
+
+Signed-off-by: Ivan Davydov <lotigara@lotigara.ru>
+Link: https://github.com/openwrt/openwrt/pull/18164
+Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
+---
+ .../ramips/dts/mt7628an_keenetic_kn-1221.dts | 209 ++++++++++++++++++
+ target/linux/ramips/image/mt76x8.mk | 12 +
+ .../mt76x8/base-files/etc/board.d/01_leds | 1 +
+ .../mt76x8/base-files/etc/board.d/02_network | 5 +
+ 4 files changed, 227 insertions(+)
+ create mode 100644 target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+
+diff --git a/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+new file mode 100644
+index 00000000000000..6f5cf96856ed21
+--- /dev/null
++++ b/target/linux/ramips/dts/mt7628an_keenetic_kn-1221.dts
+@@ -0,0 +1,209 @@
++// SPDX-License-Identifier: GPL-2.0-or-later OR MIT
++
++#include "mt7628an.dtsi"
++
++#include <dt-bindings/gpio/gpio.h>
++#include <dt-bindings/input/input.h>
++#include <dt-bindings/leds/common.h>
++
++/ {
++ compatible = "keenetic,kn-1221", "mediatek,mt7628an-soc";
++ model = "Keenetic KN-1221";
++
++ aliases {
++ label-mac-device = &ethernet;
++
++ led-boot = &led_power;
++ led-failsafe = &led_power;
++ led-running = &led_power;
++ led-upgrade = &led_power;
++ };
++
++ chosen {
++ bootargs = "console=ttyS0,115200";
++ };
++
++ regulator-usb {
++ compatible = "regulator-fixed";
++ regulator-name = "USB-power";
++ regulator-min-microvolt = <5000000>;
++ regulator-max-microvolt = <5000000>;
++ gpios = <&gpio 6 GPIO_ACTIVE_HIGH>;
++ enable-active-high;
++ regulator-always-on;
++ };
++
++ leds {
++ compatible = "gpio-leds";
++
++ led_power: power {
++ function = LED_FUNCTION_POWER;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 11 GPIO_ACTIVE_LOW>;
++ };
++
++ internet {
++ function = LED_FUNCTION_WAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 38 GPIO_ACTIVE_LOW>;
++ };
++
++ fn {
++ function = LED_FUNCTION_WLAN;
++ color = <LED_COLOR_ID_GREEN>;
++ gpios = <&gpio 4 GPIO_ACTIVE_LOW>;
++ linux,default-trigger = "phy0tpt";
++ };
++ };
++
++ keys {
++ compatible = "gpio-keys";
++
++ reset {
++ label = "restart";
++ gpios = <&gpio 37 GPIO_ACTIVE_LOW>;
++ linux,code = <KEY_RESTART>;
++ };
++ };
++
++ virtual_flash {
++ compatible = "mtd-concat";
++ devices = <&firmware1 &firmware2>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ compatible = "denx,uimage";
++ label = "firmware";
++ reg = <0x0 0x1cc0000>;
++ };
++ };
++ };
++};
++
++&state_default {
++ gpio {
++ groups = "i2c", "spi cs1", "gpio", "refclk", "wdt";
++ function = "gpio";
++ };
++};
++
++&spi0 {
++ status = "okay";
++
++ flash@0 {
++ compatible = "jedec,spi-nor";
++ reg = <0>;
++ spi-max-frequency = <32000000>;
++
++ partitions {
++ compatible = "fixed-partitions";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ partition@0 {
++ label = "u-boot";
++ reg = <0x0 0x30000>;
++ read-only;
++ };
++
++ partition@30000 {
++ label = "u-config";
++ reg = <0x30000 0x10000>;
++ read-only;
++ };
++
++ partition@40000 {
++ label = "rf-eeprom";
++ reg = <0x40000 0x10000>;
++ read-only;
++
++ nvmem-layout {
++ compatible = "fixed-layout";
++ #address-cells = <1>;
++ #size-cells = <1>;
++
++ eeprom_factory_0: eeprom@0 {
++ reg = <0x0 0x400>;
++ };
++
++ macaddr_factory_4: macaddr@4 {
++ reg = <0x4 0x6>;
++ };
++ };
++ };
++
++ firmware1: partition@50000 {
++ label = "firmware_1";
++ reg = <0x50000 0xe60000>;
++ };
++
++ partition@eb0000 {
++ label = "config_1";
++ reg = <0xeb0000 0x40000>;
++ read-only;
++ };
++
++ partition@ef0000 {
++ label = "storage";
++ reg = <0xef0000 0x100000>;
++ read-only;
++ };
++
++ partition@ff0000 {
++ label = "dump";
++ reg = <0xff0000 0x10000>;
++ read-only;
++ };
++
++ partition@1000000 {
++ label = "u-state";
++ reg = <0x1000000 0x30000>;
++ read-only;
++ };
++
++ partition@1030000 {
++ label = "u-config_res";
++ reg = <0x1030000 0x10000>;
++ read-only;
++ };
++
++ partition@1040000 {
++ label = "rf-eeprom_res";
++ reg = <0x1040000 0x10000>;
++ read-only;
++ };
++
++ firmware2: partition@1050000 {
++ label = "firmware_2";
++ reg = <0x1050000 0xe60000>;
++ };
++
++ partition@1eb0000 {
++ label = "Config_2";
++ reg = <0x1eb0000 0x40000>;
++ read-only;
++ };
++ };
++ };
++};
++
++&ethernet {
++ nvmem-cells = <&macaddr_factory_4>;
++ nvmem-cell-names = "mac-address";
++};
++
++&esw {
++ mediatek,portmap = <0x3e>;
++ mediatek,portdisable = <0x38>;
++};
++
++&wmac {
++ status = "okay";
++
++ nvmem-cells = <&eeprom_factory_0>;
++ nvmem-cell-names = "eeprom";
++};
+diff --git a/target/linux/ramips/image/mt76x8.mk b/target/linux/ramips/image/mt76x8.mk
+index 8c8cfee23b6cfa..f442148d9ecf10 100644
+--- a/target/linux/ramips/image/mt76x8.mk
++++ b/target/linux/ramips/image/mt76x8.mk
+@@ -366,6 +366,18 @@ define Device/jotale_js76x8-32m
+ endef
+ TARGET_DEVICES += jotale_js76x8-32m
+
++define Device/keenetic_kn-1221
++ BLOCKSIZE := 64k
++ IMAGE_SIZE := 29440k
++ DEVICE_VENDOR := Keenetic
++ DEVICE_MODEL := KN-1221
++ DEVICE_PACKAGES := kmod-usb2
++ IMAGES += factory.bin
++ IMAGE/factory.bin := $$(sysupgrade_bin) | pad-to $$$$(BLOCKSIZE) | \
++ check-size 14720k | zyimage -d 0x801221 -v "KN-1221"
++endef
++TARGET_DEVICES += keenetic_kn-1221
++
+ define Device/keenetic_kn-1613
+ IMAGE_SIZE := 31488k
+ DEVICE_VENDOR := Keenetic
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+index b87062ae3c5ae5..79f78a2a459487 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/01_leds
+@@ -58,4 +58,5 @@ hiwifi,hc5661a|\
+ hiwifi,hc5761a)
+ ucidef_set_led_switch "internet" "internet" "blue:internet" "switch0" "0x10"
+ ;;
++keenetic,kn-1221|\
+ keenetic,kn-1613)
+diff --git a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+index fbdc7fb5a2697a..6e6e1310d3495f 100644
+--- a/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
++++ b/target/linux/ramips/mt76x8/base-files/etc/board.d/02_network
+@@ -131,5 +131,9 @@ ramips_setup_interfaces()
+ ucidef_add_switch "switch0" \
+ "0:lan" "1:lan" "2:lan" "6@eth0"
+ ;;
++ keenetic,kn-1221)
++ ucidef_add_switch "switch0" \
++ "1:lan" "2:lan" "0:wan" "6@eth0"
++ ;;
+ keenetic,kn-1613|\
+ motorola,mwr03)
+@@ -280,5 +280,6 @@ ramips_setup_macs()
+ totolink,lr1200)
+ wan_mac=$(mtd_get_mac_binary factory 0x2e)
+ ;;
++ keenetic,kn-1221|\
+ keenetic,kn-1613|\
+ zyxel,keenetic-extra-ii)
+</pre>
+
+<p></details>
+</summary></p>
+
+<p>Или в виде файла: <a href="/files/18164.patch.backport-24.10.1">18164.patch.backport-24.10.1</a>.
+Готовые сборки тоже доступны в виде файлов: <a href="/files/openwrt-kn-1221-24.10">openwrt-kn-1221-24.10</a></p>
+ </div>
+</div>
+<!-- /post -->
+<!-- post -->
+<div class="post">
+ <h1><a href="/blog/blog/fast-transition-wi-fi-roaming-with-openwrt-and-keeneticos/">Fast Transition (Wi-Fi Roaming) with OpenWrt and KeeneticOS</a></h1>
+ <div class="content">
+<h5>tested to not work on KeeneticOS v3.8.7 &amp; OpenWrt v23.05.5</h5>
+
+<p>First, set up FT on your OpenWrt devices.</p>
+
+<p>Then, change the mode of your Keenetic (?) devices to Extender (there are Repeater/Extender and Access Point/Extender, the last is the recommended).</p>
+
+<p>Go to the <code>Access Point/Extender (Repeater/Extender) &gt; Home segment</code> menu. Change the settings of the Wi-Fi network to those ones in OpenWrt.</p>
+
+<p>Scroll below to the "Roaming for wireless devices" section. Enable "Fast transition (802.11r)" and write your mobility domain ID converted to the ASCII format.</p>
+
+<p>You can use an online converter like this one: <a href="https://www.rapidtables.com/convert/number/hex-to-ascii.html">https://www.rapidtables.com/convert/number/hex-to-ascii.html</a>. Keep the "Mobility domain key" field unedited.</p>
+
+<p>Press the "Save" button. Now you have a so-called "Wi-Fi system" with use of both KeeneticOS and OpenWrt!</p>
+ </div>
+</div>
+<!-- /post -->
+
+</div>
+<div class="pagination ">
+ <a class="prev" href="/blog//">Назад</a>
+ <a class="next" href="/blog//">Вперёд</a>
+</div>
+<!-- /page -->
+
+ </body>
+</html>
diff --git a/theme/css/01-responsivity.css b/theme/css/01-responsivity.css
new file mode 120000
index 0000000..27c2fa4
--- /dev/null
+++ b/theme/css/01-responsivity.css
@@ -0,0 +1 @@
+/var/www/html/css/responsivity.css \ No newline at end of file
diff --git a/theme/html/index.html b/theme/html/index.html
new file mode 100644
index 0000000..8685a45
--- /dev/null
+++ b/theme/html/index.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html class="{{section}}" lang="ru">
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></meta>
+ <meta name="color-scheme" content="dark light"></meta>
+
+ <title>{{title}} - {{s_title}}</title>
+ <link rel="stylesheet" href="{{s_root}}/_/style.css">
+ <body>
+{{menu}}
+{{page}}
+ </body>
+</html>
diff --git a/theme/html/menu.html b/theme/html/menu.html
new file mode 120000
index 0000000..1796574
--- /dev/null
+++ b/theme/html/menu.html
@@ -0,0 +1 @@
+/var/www/html/files/header.html \ No newline at end of file
diff --git a/theme/html/menu_logo.html b/theme/html/menu_logo.html
new file mode 100644
index 0000000..25e5bdb
--- /dev/null
+++ b/theme/html/menu_logo.html
@@ -0,0 +1,3 @@
+<a class="logo" href="{{s_root}}">
+ <img src="{{s_root}}/_/imgs/logo.png">
+</a>
diff --git a/theme/html/menu_section.html b/theme/html/menu_section.html
new file mode 100644
index 0000000..c4f44d3
--- /dev/null
+++ b/theme/html/menu_section.html
@@ -0,0 +1,10 @@
+<!-- menu_section -->
+<div class="section {{current}}">
+ <a class="title" href="{{s_root}}/{{url}}/">
+{{title}}
+ </a>
+ <div class="subs">
+{{subs}}
+ </div>
+</div>
+<!-- /menu_section-->
diff --git a/theme/html/page.html b/theme/html/page.html
new file mode 100644
index 0000000..2fc1ebd
--- /dev/null
+++ b/theme/html/page.html
@@ -0,0 +1,9 @@
+<!-- page -->
+<div class="posts">
+{{posts}}
+</div>
+<div class="pagination {{has-prev}} {{has-next}}">
+ <a class="prev" href="{{s_root}}/{{prev-url}}/">Назад</a>
+ <a class="next" href="{{s_root}}/{{next-url}}/">Вперёд</a>
+</div>
+<!-- /page -->
diff --git a/theme/html/post.html b/theme/html/post.html
new file mode 100644
index 0000000..05d76c3
--- /dev/null
+++ b/theme/html/post.html
@@ -0,0 +1,8 @@
+<!-- post -->
+<div class="post">
+ <h1><a href="{{s_root}}/{{url}}/">{{title}}</a></h1>
+ <div class="content">
+{{html}}
+ </div>
+</div>
+<!-- /post -->