<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:yandex="http://news.yandex.ru" xmlns:media="http://search.yahoo.com/mrss/" xmlns:turbo="http://turbo.yandex.ru">
	<channel>
		<title>Инженериум-Программиум</title>
		<link>https://blog.sefdar.ru</link>
		<description>Блог Инженера</description>
		<language>ru</language>
		<turbo:cms_plugin>7391CC2B1408947EFD5084459F5BD0CA</turbo:cms_plugin>
																	<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d1%82%d1%8c-react-%d0%bf%d1%80%d0%b8%d0%bb%d0%be%d0%b6%d0%b5%d0%bd%d0%b8%d0%b5-%d0%b2-2026-%d0%b3%d0%be%d0%b4%d1%83-%d1%81%d1%82%d0%b0%d0%bb%d0%be-%d0%bb%d0%b5%d0%b3/</link>
					<title><![CDATA[Создать React-приложение в 2026 году стало ЛЕГКО с помощью Vite]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 27 Mar 2026 11:56:46 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2023/09/2395488_bd78_2-1024x576-1.jpeg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Создать React-приложение в 2026 году стало ЛЕГКО с помощью Vite</h1>
													</header>
													<h3>Введение</h3>
<p>Начать работу с React стало не так сложно, как раньше. В этом видео мы расскажем о самом быстром способе создания современного React проекта. Нет, мы не будем использовать устаревшие CRA или create-react-app, которые веками доставляли разработчикам столько хлопот.</p>
<p>Но мы воспользуемся инструментом под названием Vite, что в переводе с французского означает «молниеносно быстрый».</p>
<h3>Предварительные условия</h3>
<p>Итак, что же является единственным препятствием на пути к созданию вашего первого React приложения? Вам нужна среда выполнения, которая позволит вам запускать Javascript приложения вне браузера — Node.js.</p>
<p>Для начала зайдите на официальный сайт Node.js, нажмите кнопку Get Node.js и выберите свою операционную систему. Либо скопируйте и вставьте показанные команды в терминал, либо просто скачайте соответствующий бинарный файл.</p>
<p>После выполнения команды или загрузки бинарного файла давайте убедимся, что он действительно установлен. Для этого откройте терминал и введите</p>
<pre>node --version
</pre>
<p>Если после выполнения команды появится сообщение, похожее на это, поздравляем — Node.js успешно установлен.</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-536 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2026/03/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_cxvonkz5t64d874c44gx.webp" alt="" width="800" height="152" srcset="https://blog.sefdar.ru/wp-content/uploads/2026/03/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_cxvonkz5t64d874c44gx.webp 800w, https://blog.sefdar.ru/wp-content/uploads/2026/03/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_cxvonkz5t64d874c44gx-300x57.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2026/03/https___dev-to-uploads.s3.amazonaws.com_uploads_articles_cxvonkz5t64d874c44gx-768x146.webp 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>Подтвердите Установку Node.js</p>
<h2>Настройка Vite</h2>
<p>Теперь, когда Node.js готово, для запуска всего вашего React-проекта достаточно одной команды.</p>
<p>Перейдите на сайт Vite, нажмите get started и прокрутите страницу вниз, пока не найдете эту команду.</p>
<p>Эта команда создает шаблон вашего проекта и устанавливает для вас Vite и React. Vite в основном выполняет две функции:</p>
<ul>
<li>Он обслуживает ваш код во время разработки, предлагая такие функции, как горячая перезагрузка.</li>
<li>Он объединяет ваш JavaScript, HTML и другие ресурсы, когда вы готовы к запуску.<img loading="lazy" decoding="async" class="alignnone wp-image-537 size-full" style="font-size: 1.0625rem;" src="https://blog.sefdar.ru/wp-content/uploads/2026/03/nderbfmywad11f2cf4sa.webp" alt="" width="800" height="311" srcset="https://blog.sefdar.ru/wp-content/uploads/2026/03/nderbfmywad11f2cf4sa.webp 800w, https://blog.sefdar.ru/wp-content/uploads/2026/03/nderbfmywad11f2cf4sa-300x117.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2026/03/nderbfmywad11f2cf4sa-768x299.webp 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></li>
</ul>
<p>Команда для установки Vite</p>
<p>Node.js В комплект поставки входит npm — менеджер пакетов, который устанавливает зависимости вашего проекта. Но лично я использую pnpm и вот почему он лучше:</p>
<ul>
<li>Он кэширует ваши зависимости на глобальном уровне.</li>
<li>Он повторно использует их в разных проектах.</li>
</ul>
<p>Это значительно ускоряет процесс и делает его более экономичным, особенно если вы используете мобильный интернет.</p>
<pre>npm create vite@latest</pre>
<p>Так что вы можете либо скопировать эту команду npm и сразу запустить ее, либо установить pnpm глобально:</p>
<pre>npm install -g pnpm</pre>
<p>Если вы выбрали путь pnpm и установили его глобально, просто замените npm на pnpm в предыдущей команде.</p>
<pre>pnpm create vite@latest</pre>
<h3>Конфигурация проекта</h3>
<p>Теперь, когда мы выполнили команду, Vite-cli проведет вас по быстрой настройке.</p>
<p>Давайте назовем проект hello-world .</p>
<p>Vite CLI предлагает пользователю выбрать название проекта<img loading="lazy" decoding="async" class="alignnone wp-image-538 size-full" style="font-size: 1.0625rem;" src="https://blog.sefdar.ru/wp-content/uploads/2026/03/scvxfe9ouirktfm14vxo.webp" alt="" width="800" height="99" srcset="https://blog.sefdar.ru/wp-content/uploads/2026/03/scvxfe9ouirktfm14vxo.webp 800w, https://blog.sefdar.ru/wp-content/uploads/2026/03/scvxfe9ouirktfm14vxo-300x37.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2026/03/scvxfe9ouirktfm14vxo-768x95.webp 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>Поскольку мы создаем приложение на React, выберем React.</p>
<p>Vite CLI предлагает пользователю выбрать фреймворк</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-539 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2026/03/gd910xvz8s8extexwlfn.webp" alt="" width="800" height="272" srcset="https://blog.sefdar.ru/wp-content/uploads/2026/03/gd910xvz8s8extexwlfn.webp 800w, https://blog.sefdar.ru/wp-content/uploads/2026/03/gd910xvz8s8extexwlfn-300x102.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2026/03/gd910xvz8s8extexwlfn-768x261.webp 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>Теперь нам нужно выбрать между JavaScript и TypeScript. Честно говоря, я предпочитаю TypeScript, потому что его статическая типизация улучшает автодополнение в IDE и значительно упрощает работу разработчика.</p>
<p>Vite CLI предлагает пользователю выбрать Javascript или Typescript</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-540 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2026/03/tnfj091f6u581evh1lgc.webp" alt="" width="800" height="316" srcset="https://blog.sefdar.ru/wp-content/uploads/2026/03/tnfj091f6u581evh1lgc.webp 800w, https://blog.sefdar.ru/wp-content/uploads/2026/03/tnfj091f6u581evh1lgc-300x119.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2026/03/tnfj091f6u581evh1lgc-768x303.webp 768w" sizes="auto, (max-width: 800px) 100vw, 800px" /></p>
<p>Возможно, вам интересно, что же такое SWC? Это сверхбыстрый компилятор, который ускорит вашу разработку почти в 20 раз. Скорость — это всегда хорошо, так что давайте выберем Typescript + SWC и нажмем Enter.</p>
<p>Давайте просто пропустим два оставшихся варианта.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-medium wp-image-541" src="https://blog.sefdar.ru/wp-content/uploads/2026/03/sn5k50jyz7k620u4fxqf-300x229.webp" alt="" width="300" height="229" srcset="https://blog.sefdar.ru/wp-content/uploads/2026/03/sn5k50jyz7k620u4fxqf-300x229.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2026/03/sn5k50jyz7k620u4fxqf.webp 417w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<h3>Установка зависимостей</h3>
<p>Как только вы нажмете Enter, Vite-Cli создаст ваш проект.</p>
<p>Как только это произойдет, перейдите в него, набрав cd hello-world.</p>
<p>После этого установите зависимости, выполнив команду &#171;<strong>npm install</strong>&#187; или &#171;<strong>pnpm install</strong>&#171;.</p>
<pre>npm install
# или
pnpm install</pre>
<h3>Запуск сервера разработки</h3>
<p>После завершения установки выполните следующую команду.</p>
<pre>pnpm run dev</pre>
<p>Последний запустит сервер разработки на http://localhost:5173.</p>
<p>Просто нажмите на этот URL, удерживая клавишу Ctrl, или скопируйте его в адресную строку браузера.</p>
<p>Наконец, ваш проект готов.</p>
<p>Откройте его в предпочитаемой вами среде разработки, перейдите в файл App.tsx, расположенный в папке src, внесите изменения и — вуаля! — они мгновенно отобразятся на веб-странице.</p>
<h3>Заключение</h3>
<p>Вот и все, что нужно для запуска вашего проекта с помощью VITE, БУКВАЛЬНО, одной-единственной команды!</p>
<p>Но вид этого дерева файлов может вызывать беспокойство, не так ли?</p>
<p>Поэтому вместо того, чтобы все испортить, давайте разберемся в сгенерированном шаблонном коде.</p>
<p>А пока&#8230; счастливого кодинга!</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="2">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[JavaScript]]></category><category><![CDATA[javascript]]></category><category><![CDATA[React]]></category><category><![CDATA[для начинающих]]></category><category><![CDATA[руководство]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/09/2395488_bd78_2-1024x576-1.jpeg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%ba%d0%b0%d0%ba-%d0%b4%d0%be%d0%b1%d0%b0%d0%b2%d0%b8%d1%82%d1%8c-%d0%ba%d0%be%d0%bd%d1%82%d0%b5%d0%ba%d1%81%d1%82%d0%bd%d0%be%d0%b5-%d0%bc%d0%b5%d0%bd%d1%8e-%d0%b2-debian-%d1%81%d1%80%d0%b5%d0%b4/</link>
					<title><![CDATA[Как добавить контекстное меню в Debian среда Mate]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 25 Mar 2026 09:46:23 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2023/01/distr-1024x576.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Как добавить контекстное меню в Debian среда Mate</h1>
													</header>
													<h2 id="контекстное-меню-вызова-терминала-в-debian-оболочка-mate">Контекстное меню вызова терминала в Debian оболочка Mate</h2>
<p>Например, я хочу щелкнуть правой кнопкой мыши по папке и открыть ее в терминале. Я не хочу, чтобы мне приходилось искать каталог в терминале.</p>
<p>Caja — официальный файловый менеджер рабочего стола MATE. Пакет расширяет функциональность файлового менеджера Caja.</p>
<p><em><strong>caja-open-terminal</strong></em> — тестовое расширение Caja, позволяющее запускать терминал по указанному пути.</p>
<p>Установка</p>
<pre tabindex="0"><code>sudo apt install caja-open-terminal
</code></pre>
<p>Активация</p>
<pre tabindex="0"><code>caja -q</code></pre>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[bash]]></category><category><![CDATA[открыть]]></category><category><![CDATA[линукс]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/01/distr-1024x576.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%9a%d0%b0%d0%ba-%d0%be%d1%82%d0%ba%d0%bb%d1%8e%d1%87%d0%b8%d1%82%d1%8c-wp-cron-%d0%b2-wordpress-%d0%b8-%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b8%d1%82%d1%8c-%d1%81%d0%b8%d1%81%d1%82%d0%b5%d0%bc/</link>
					<title><![CDATA[Как отключить WP-Cron в WordPress и настроить системный cron на сервере]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 07 Feb 2026 09:07:47 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="390" src="https://blog.sefdar.ru/wp-content/uploads/2026/02/wp-cli-cronjob-1400-1024x475.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Как отключить WP-Cron в WordPress и настроить системный cron на сервере</h1>
													</header>
													<p>WP-Cron в WordPress часто мешает работать сайту стабильно. Рассказали, как полностью взять планировщик в свои руки: отключить встроенный механизм, перенести его на системный cron и настроить идеальный график выполнения задач.</p>
<h2 class="wp-block-heading">Введение</h2>
<p>Представьте, что вы запланировали публикацию важной статьи на своём WordPress-сайте ровно в 17:00, но в назначенное время ничего не произошло. Или наоборот, ваш сайт начинает подтормаживать из-за фоновых задач, хотя посетителей немного. Зачастую причиной этих ситуаций оказывается встроенный планировщик WordPress под названием WP-Cron.</p>
<p>В статье рассказали, как отключить встроенный планировщик WP-Cron (<strong>wp-cron.php</strong>) в WordPress и перенести выполнение задач на системный cron сервера. Объяснили, чем WP-Cron отличается от классического cron и как настроить расписание задач через терминал шаг за шагом.</p>
<h2 class="wp-block-heading">Что такое WP-Cron и зачем его отключать</h2>
<p>WP-Cron — это встроенный механизм WordPress для выполнения отложенных задач. Каждый раз, когда вы планируете что-то на потом, будь то публикация поста в определённое время, резервное копирование (бекап) базы данных по расписанию или отправка письма пользователю через час, за кулисами WordPress добавляет событие в свой список cron-задач. Специальный файл wp-cron.php отвечает за проверку этого списка и запуск нужных функций точно в назначенный час.</p>
<p>Однако WP-Cron существенно отличается от настоящего системного планировщика cron в Linux. Самое важное отличие в том, что <strong>wp-cron.php</strong> не работает постоянно на фоне, как системный Cron. Он просыпается только когда кто-то посещает ваш сайт. Одним словом, WordPress проверяет свои запланированные задачи лишь при загрузке страницы. Если посещений нет, задачи просто не запускаются до тех пор, пока сайт не откроют. Для малопосещаемых сайтов это оборачивается проблемами: отложенные публикации выходят с опозданием, рассылки не отправляются вовремя, очистка базы или кеша может не случиться по расписанию. Например, если на сайт никто не заходил весь день, то и ежедневный скрипт оптимизации не сработает. Сайтам с высокой посещаемостью бояться практически нечего. Казалось бы, WP-Cron не пропустит время задачи, ведь посетители появляются постоянно. Но у этой медали есть и другая сторона: при большом трафике <strong>wp-cron.php</strong> запускается слишком часто, нагружая сервер. По умолчанию WordPress старается не дёргать планировщик чаще чем раз в минуту, но если ваш сайт получает множество одновременных заходов, возможны параллельные вызовы WP-Cron. В результате каждая загрузка страницы может слегка замедляться, да и сами фоновые задачи отнимают ресурсы. Особенно ощутимо это становится на недорогом хостинге с ограниченными ресурсами.</p>
<h2 class="wp-block-heading">Как перенести wp-cron.php на системный cron: пошаговая инструкция</h2>
<p>Перенос WP-Cron на cron сервера состоит из двух основных шагов. Сначала необходимо отключить встроенный механизм в самом WordPress, затем настроить регулярный вызов wp-cron.php через системный планировщик. Ниже подробно разберём оба этапа.</p>
<p>Для начала нужно выключить автоматический запуск WP-Cron при каждом заходе на сайт. Это делается добавлением одной строки в конфигурацию WordPress. Обязательно сделайте свежий бекап сайта или хотя бы сохраните копию файла <strong>wp-config.php</strong> перед правкой, чтобы иметь возможность вернуть всё назад в случае ошибки.</p>
<p>Откройте файл <strong>wp-config.php</strong> в корневой папке вашего WordPress-сайта. Сделать это можно через FTP-клиент, файловый менеджер хостинга или прямо в терминале, например, с помощью редактора nano. Найдите в начале файла строку <strong>&lt;?php</strong> и сразу после неё вставьте следующую директиву:</p>
<pre class="wp-block-code"><code>define('DISABLE_WP_CRON', true);</code></pre>
<p>Сохраните изменения. Эта настройка отключает встроенный WP-Cron. WordPress больше не будет пытаться запускать <strong>wp-cron.php</strong> при каждом открытии сайта. Однако и запланированные задачи теперь полностью под вашим контролем, их выполнение нужно организовать на уровне сервера.</p>
<p>Теперь, когда WordPress забыл про свои внутренние кроны, нужно самостоятельно настроить системный cron, чтобы он периодически запускал WordPress-скрипт <strong>wp-cron.php</strong> и тем самым выполнял все отложенные задачи. Для этого понадобится доступ к серверу по SSH и права на создание cron-заданий. Подключитесь к своему серверу через терминал. Далее откройте список cron-задач командой:</p>
<pre class="wp-block-code"><code>crontab -e</code></pre>
<p>Эта команда откроет файл расписания задач (<strong>crontab</strong>) для текущего пользователя. Если вы запускаете её впервые, система может спросить, какой редактор использовать, смело выбирайте nano, так будет проще. В открывшемся редакторе внизу файла, не трогая чужие строки, если они уже есть, добавьте новую строку-пример:</p>
<pre class="wp-block-code"><code>*/15 * * * * wget -q -O - "http://ваш-домен.ru/wp-cron.php?doing_wp_cron" &gt; /dev/null 2&gt;&amp;1</code></pre>
<p>Эта строка создаёт cron-задание, которое будет выполняться каждые 15 минут (именно это обозначает <strong>*/15 * * * *</strong>). Вместо ваш-домен.ru подставьте адрес вашего сайта. Команда использует утилиту wget, которая делает тихий HTTP-запрос.</p>
<p><strong>-q</strong> отключает вывод сообщений, флаг <strong>-O &#8212;</strong> означает отправлять результат в стандартный поток вывода. По сути, каждые 15 минут сервер будет запрашивать ваш <strong>wp-cron.php</strong>, имитируя посещение сайта, и сразу отправлять результат в никуда. Символы <strong>&gt;/dev/null 2&gt;&amp;1</strong> как раз перенаправляют весь вывод команды и сообщения об ошибках, чтобы вы не получали уведомления на почту при каждом запуске.</p>
<p>После добавления строки нажмите Ctrl+O (англ. O), чтобы сохранить crontab, и Ctrl+X, чтобы выйти из редактора nano. Новое задание сохранено, системный cron зарегистрировал вашу задачу.</p>
<p>В примере указано каждые 15 минут. Такое значение подходит для большинства сайтов. Вы можете настроить интервал под свои нужды. Например, если у вас совсем небольшой и неторопливый проект, можно запускать cron раз в час. А для сайта с активной аудиторией или важными процессами, например, интернет-магазин с обработкой заказов, имеет смысл поставить 5 или 10 минут, чтобы все операции выполнялись оперативно. Не выбирайте слишком частый интервал без необходимости. Помните, что каждый запуск cron вызывает пусть небольшую, но нагрузку.</p>
<p>Чтобы убедиться, что вы правильно настроили cron, проведите небольшой тест. В админ-панели WordPress создайте новый черновик записи и запланируйте его публикацию на ближайшие 10-15 минут от текущего времени. Если cron на сервере настроен верно, пост автоматически опубликуется примерно в назначенное время.</p>
<h2 class="wp-block-heading">Советы по настройкам</h2>
<p>В большинстве случаев описанных настроек вполне хватает, но есть ещё несколько моментов, которые стоит держать в голове. Если на хостинге нет доступа к собственному cron, как это часто бывает на бюджетных тарифах или при отсутствии SSH, выручат внешние сервисы. Они могут по расписанию отправлять запросы на сайт, и в этом нет ничего сложного. Зарегистрируйтесь на платформе вроде бесплатного <strong>cron-job.org</strong> или платных EasyCron и SetCronJob, добавьте туда адрес файла <strong>wp-cron.php</strong>, не забыв приписать в конце параметр <strong>?doing_wp_cron</strong>, и задачи будут выполняться без участия встроенного механизма WordPress.</p>
<p>Не стоит пытаться запускать <strong>wp-cron.php</strong> напрямую командой <strong>php </strong>из консоли, так как скрипт рассчитан именно на веб-запрос, а при вызове через PHP-CLI могут отсутствовать важные переменные окружения вроде HTTP_HOST, и тогда задания просто не отработают.</p>
<p>При работе через CDN или прокси, например Cloudflare, прямой запрос с сервера на ваш домен может быть заблокирован как подозрительный. В таком случае лучше либо добавить IP сервера в белый список в панели Cloudflare, либо в задаче cron использовать локальный адрес, например <strong>http://127.0.0.1/</strong> или внутреннее имя хоста.</p>
<p>Для контроля работы самого WP-Cron подойдёт плагин WP Crontrol. Он показывает все запланированные события, время их следующего запуска и источник, а если что-то зависло или просрочилось, вы сразу это заметите. После перехода на системный cron можно спокойно игнорировать предупреждение плагина о том, что WP-Cron отключён. Это будет означать лишь то, что всё работает так, как задумано.</p>
<h2 class="wp-block-heading">Заключение</h2>
<p>Вы проделали немалую работу и превратили капризный встроенный планировщик WordPress в надёжный системный инструмент. Теперь <strong>wp-cron.php</strong> запускается по расписанию, а ваш сайт больше не зависит от случайных визитов, чтобы отправить письмо или опубликовать пост. Это значит, что запланированные публикации будут выходить строго в срок, резервные копии сохранятся вовремя, а другие фоновые процессы WordPress перестанут подносить неприятные сюрпризы. При грамотной настройке cron вы заметите, как сайт стал работать стабильнее и быстрее.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[PHP]]></category><category><![CDATA[WEB]]></category><category><![CDATA[web-server]]></category><category><![CDATA[php]]></category><category><![CDATA[wordpress cron]]></category><category><![CDATA[wp-cron]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2026/02/wp-cli-cronjob-1400-1024x475.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%95%d1%81%d0%bb%d0%b8-%d0%b1%d1%8b-%d0%bf%d1%80%d0%be%d0%b3%d1%80%d0%b0%d0%bc%d0%bc%d0%b8%d1%81%d1%82%d1%8b-%d1%81%d1%82%d1%80%d0%be%d0%b8%d0%bb%d0%b8-%d0%b4%d0%be%d0%bc%d0%b0-%d0%bf%d0%be%d0%bb/</link>
					<title><![CDATA[Если бы программисты строили дома: полный вариант]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Mon, 08 Dec 2025 17:45:07 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="474" height="362" src="https://blog.sefdar.ru/wp-content/uploads/2025/12/house.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Если бы программисты строили дома: полный вариант</h1>
													</header>
													<p>1.03. Ура! Hам предложили крупный контракт на постройку 12-этажного жилого дома. У всех бурный энтузиазм. Выпили на радостях 2 ящика пива.</p>
<p>2.03. Заказчику не нравится выражение &#171;как только, так сразу&#187;.<br />
Требует назвать конкретные сроки. Темный народ эти заказчики, ничего не смыслят в высоких технологиях.</p>
<p>3.03. Обсуждали сроки. Выпили 3 ящика пива. Петрович говорит, что тут всей работы на 4 месяца. Значит, на самом деле 8. В итоге в контракте записали 12, хотя раньше, чем за 16, вряд ли управимся.</p>
<p>4.03. Отмечаем подписание контракта.</p>
<p>5.03. Отмечаем подписание контракта.</p>
<p>6.03. Петрович пошел сдавать бутылки.</p>
<p>7.03. Продолжаем отмечать подписание контракта на деньги, вырученные Петровичем.</p>
<p>8.03. Отмечаем 8 марта. Женщин у нас в фирме нет, так что праздник никто не портил.</p>
<p>9.03. Долго вспоминали, что же мы отмечали вчера. Пришел Алекс, сказал, что пора бы начинать работать. Послали. Играем в Quake.</p>
<p>1.04. Пришел Сидоров и сказал, что пора начинать работать. Кого он хочет наколоть своими первоапрельскими шуточками?</p>
<p>2.04. Петрович тоже говорит, что пора начинать работать. Сговорились они, что ли? Обнесли площадку забором и повесили красивые плакаты. С чувством выполненного долга играем в Quake.</p>
<p>20.04. Пришел заказчик, интересовался, как дела. Посадили его за компьютер с Quake\’ом и позволили нас всех обыграть. Ушел очень довольный. Однако пора, кажется, и впрямь начинать работать.</p>
<p>21.04. Обсуждали проект. Сидоров предлагает крупноблочную архитектуру. Петрович говорит, что блоки громоздкие, плохо стыкуются друг с другом, содержат много лишнего и вообще еще неизвестно, какие у них там внутри трещины. Заявляет, что из блоков строят только законченные ламеры. Hастаивает, что все надо строить по старинке, из кирпича, хоть это<br />
и намного дольше. Самый радикальный проект предложил Алекс. Он говорит, что вообще не нужно строить 12-этажный дом, а нужно построить несколько десятков деревянных коттеджей и соединить их подземными туннелями. Дескать, на Западе сейчас так модно. Hапомнили ему, что заказчик требует именно 12-этажный дом. Он отбивался и кричал, что заказчики тупы по определению, и слушают их только законченные ламеры. В самый интересный момент дискуссии кончилось пиво. Решили продолжить завтра.</p>
<p>22.04. Пытались решить вопрос дуэлью в Quake. Алекса с его коттеджами завалили сразу, но между Петровичем и Сидоровым вышла ничья. В итоге каждый будет строить по своему плану, а потом попытаемся все это соединить, чтоб не рухнуло.</p>
<p>23.04. Hачали строить. У всех бурный энтузиазм.</p>
<p>30.04. Первый этаж готов! Показали его заказчику. Он интересовался, почему в разных комнатах разная высота потолков, почему из стен вываливаются кирпичи и почему в доме нет подъезда, а влезать приходится через окно. Объяснили ему, что это специальные ограничения<br />
демо-версии. Уходим на праздники, гордые собой.</p>
<p>10.05. Петрович протрезвел первым и долго ругался. Мы думали, что Алекс выпил все пиво. Оказалось, все еще хуже: Петрович вспомнил, что мы забыли про фундамент. В проекте он, конечно, описан, но ведь документацию читают только ламеры.</p>
<p>11.05. Ломали первый этаж. Обидно, блин. С другой стороны, хорошо, что раньше работать не начали, а то бы сколько труда насмарку.</p>
<p>11.07. Работаем. Петрович достраивает второй этаж, Сидоров &#8212; пятый. Алекс отгрохал шахту лифта до девятого этажа, она теперь торчит над всей конструкцией и в сильный ветер подозрительно качается. Временно поставили деревянные подпорки.</p>
<p>17.07. Алекс строит чердак и крышу. Поскольку верхних этажей еще нет, строить приходится на земле. Потом поднимем краном. По крайней мере, Алекс на это надеется.</p>
<p>13.08. У Сидорова не стыкуются панели. Щель больше метра. Панели подходящей формы, чтобы ее заткнуть, нет. Сидоров позвал Петровича и предложил заделать кирпичом. Петрович заявил, что у него своих дел по горло, и вообще, без знания внутренней архитектуры панелей ничего сделать нельзя.</p>
<p>14.08. Разломали несколько панелей, чтобы Петрович мог изучить внутреннюю архитектуру. Петрович ругается, кричит, что проектировщики панелей &#8212; полные ламеры.</p>
<p>17.08. Петрович заделал дыру. Правда, панели при этом перекосились, но это уже мелочи. Проводку из обеих панелей пришлось вывести наружу и связать узлом. Петрович замотал узел изолентой и уверяет, что будет работать, если только дождь не пойдет.</p>
<p>1.09. Стройкомбинат выпустил новую версию панелей, улучшенной прочности и утепленности, со встроенными стенными шкафами. Правда, ни по форме, ни по размеру они не совместимы с предыдущими и, кроме того, в три раза тяжелее. Сидоров рвется разломать все,<br />
что мы уже сделали, и перестроить заново, с новыми панелями. Еле отговорили. Да и, в любом случае, фундамент такую тяжесть бы не выдержал. Hа какую архитектуру они вообще рассчитывают, эти комбинатские?</p>
<p>16.09. Прибежал Алекс, обуреваемый идеей. Предлагает сделать все окна в доме изменяемого размера. Говорит, заказчик будет тащиться. Сказали ему, чтоб не выпендривался.</p>
<p>2.10. Петрович добрался до пятого этажа. Горд собой. Обратили его внимание на тот факт, что его стена наклонена под углом 40 градусов. Он ругался, кричал, что мы ламеры и ничего не понимаем. Потом обещал подумать.</p>
<p>3.10. Приходил заказчик. Спросил, почему стена наклонена под углом 40 градусов. Объясняли ему про силу Кориолиса. Он все выслушал, потом сказал, что он, конечно, в строительном деле ничего не смыслит, но у него по соседству точно такой же дом, и там стена прямая. Блин. Hенавижу умных заказчиков. Потом этот идиот Алекс ляпнул при нем про свои изменяемые окна. Заказчик, естественно, загорелся и настаивает, чтоб делали именно так. Дважды блин.</p>
<p>4.10. Спросили Алекса, придется ли все разбирать ради его окон. Он уверяет, что нет &#8212; будто бы и у стандартных панелей есть такая недокументированная функция. Естественно, к кирпичной части дома это не относится. Петрович категорически против.</p>
<p>5.10. Петрович признал, что со стеной действительно имеется проблема. Говорит, что неправильно положил какой-то кирпич. Hо чтобы понять, какой именно, надо перебрать их все. Проще все снести и построить заново.</p>
<p>6.10. Убеждали Петровича, что построить все заново из кирпича он уже не успеет. Демонстрировали ему расчеты на калькуляторе. Петрович ругался, кричал, что калькулятор придумали ламеры. Потом все-таки согласился строить из панелей и ушел с горя в запой.</p>
<p>8.10. Ломали кирпичную часть. Попутно повредили панельную. Вся постройка скрипит и угрожающе шатается. Укрепили деревянными подпорками и пошли играть в Quake.</p>
<p>17.10. Петрович вышел из запоя. Работаем.</p>
<p>7.11. Празднуем 7-ое ноября &#8212; или как оно там теперь называется? Коммунистов у нас в фирме нет, так что праздник никто не портит.</p>
<p>15.11. Вспомнили, что у нас кран достает только до 8 этажа. Послали Сидорова доставать новый кран. Играем в Quake. Алекс замочил Петровича. Растет смена!</p>
<p>24.11. Вернулся Сидоров. Кран не достал, зато достал крутой экскаватор. Предлагает вырыть глубокую шахту и построить дом не в высоту, а в глубину. Говорит, что нигде в контракте не сказано, что 12 этажей должны быть над поверхностью. Еле отговорили.</p>
<p>25.11. Устроили мозговой штурм по проблеме крана. Hа последней бутылке пива нашли решение. Бросили основное строительство. Строим рядом 4-этажный дом. Потом втащим наш кран ему на крышу.</p>
<p>25.12. Празднуем католическое Рождество. Католиков у нас в фирме нет, так что праздник никто не портит.</p>
<p>14.01. Hичего не помню. Голова болит. Мужики, какой сейчас год?</p>
<p>2.02. Hу, кажется, наконец-то достраиваем 12-ый этаж. Завтра будем прилаживать сверху чердак и крышу, что соорудил Алекс.</p>
<p>3.02. Алекс &#8212; ламер. Крыша регулярно съезжает. Пока подперли краном. Думаем, что делать дальше.</p>
<p>4.02. Алекс доказывает, что он не виноват. Просто 12 этажей Сидорова на 4 метра выше и на 5 метров шире, чем 12 этажей Петровича. Выяснилось, что они строили из разных панелей. Hо Алекс все равно ламер, поскольку его крыша не подходит по размеру ни одному из<br />
вариантов. Его шахта лифта, кстати, тоже.</p>
<p>5.02. Латали, укрепляли и наращивали крышу. Петрович говорит, что будет держаться, если снег не пойдет.</p>
<p>7.02. Снег пошел.</p>
<p>10.02. Соорудили крышу из фанеры, покрасили под жесть. Будем надеяться, заказчик не заметит.</p>
<p>11.02. Тестировали лифт. Его остановки приходятся между этажами, но выбраться из кабины можно. Hа четных этажах ползком, на нечетных &#8212; подтягиваясь. Hе забыть описать это в документации.</p>
<p>12.02. А вообще-то лифт ездит крайне медленно. Петрович ругает всех ламерами и собирается заняться оптимизацией.</p>
<p>13.02. Петрович оптимизировал лифт. Тот разогнался, пробил крышу и улетел в неизвестном направлении. Хорошо, что крыша фанерная, и чинить будет легко. После этого шахта лифта рухнула. Вспомнили, что так и не заменили деревянные подпорки на что-нибудь более прочное. Hичего. Ходить пешком полезно.</p>
<p>15.02. Идут отделочные работы. Почему-то куда-то исчезают маляры и штукатуры. Договорились, чтоб прислали еще.</p>
<p>17.02. Выяснилось, что из-за ошибки Сидорова двери на этажах со второго по шестой открываются только на вход. В результате на этих этажах скопилось множество маляров и штукатуров, которые не могут выйти обратно. Сидоров обещал все поправить. Пока кормим маляров и штукатуров через форточки.</p>
<p>20.02. Алекс, наконец, доделал свои изменяющиеся окна. Тестировали. Выяснилось, что при изменении размера окна в нем бьются стекла. Кроме того, наблюдается ряд побочных эффектов. Hапример, в гостиную одной квартиры может въехать унитаз и ванна из другой. Также иногда исчезают двери и осыпаются балконы. Жаловаться на стройкомбинат бесполезно &#8212; они скажут, что нечего пользоваться недокументированными функциями.</p>
<p>21.02. Приходил заказчик. Спрашивал, нельзя ли внести в проект небольшие изменения. В частности, вместо 12-этажного дома построить поселок из деревянных коттеджей, соединенных туннелями. Он прочитал, что на Западе сейчас так модно. Hейтрализовали Алекса прежде, чем<br />
тот успел открыть рот, и вежливо, но твердо объяснили заказчику, что он неправ.</p>
<p>22.02. Балконы продолжают сыпаться, хотя изменяемые окна мы больше не трогали. Видимо, это какой-то независимый глюк. Какой, искать уже поздно, так что просто отодрали оставшиеся балконы от греха. Попробуем объяснить заказчику, что это сделано в целях оптимизации.</p>
<p>23.02. Праздновали 23 февраля. Военных у нас в фирме нет, так что праздник никто не портил. Женщин тоже нет, так что подарков нам никто не дарил. Обидно.</p>
<p>25.02. Алекс попытался доделать свои окна. В результате половина из них ужалась до нулевого размера и обратно не разворачивается. Сказали ему, чтоб больше не выпендривался, а то будет еще хуже.</p>
<p>27.02. Вспомнили, что так и забыли сделать подъезд. Размышляли, не рухнет ли дом, если прорубить его сейчас. Сидоров сказал, что лучше не рисковать. Петрович обозвал его ламером и согласился. Hе забыть описать в документации вход через окно как особенность дизайна.</p>
<p>1.03. К-как первое марта?! Откуда?! Вчера же еще&#8230; Блин. Кто ж знал, что в этом ламерском феврале 28 дней! Выходит, сдача объекта &#8212; не через неделю, а послезавтра?!</p>
<p>2.03. Аврал. Работаем 24 часа в сутки, не просыпаясь.</p>
<p>3.03. Убедили заказчика, что нам нужен еще день для финального тестирования. М-да, ну мы вчера и наработали&#8230; А в общем, не все так страшно. Hу что с того, что некоторые двери находятся в полу или в потолке, либо ведут с десятого этажа прямиком на улицу, в некоторые квартиры в принципе невозможно попасть, санузел кое-где совмещен с кухней, в половине дома нет воды, в другой половине &#8212; электричества, канализация обрывается на шестом этаже, а лестницу между восьмым и девятым пришлось сделать веревочной? Главное &#8212; провести заказчика правильным маршрутом. И еще &#8212; успеть до завтра развесить на месте исчезнувших окон картинки с изображением заоконных пейзажей&#8230;</p>
<p>4.03. Yes! Yes! Мы сделали это! Отмечаем сдачу объекта. Я пью мало, мне надо еще успеть уволиться, прежде чем эта хренотень рухнет &#8230;</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Юмор]]></category><category><![CDATA[программисты]]></category><category><![CDATA[костыли]]></category><category><![CDATA[юмор]]></category><category><![CDATA[важно]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/12/house.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%a0%d0%b0%d0%b1%d0%be%d1%87%d0%b8%d0%b5-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d0%b8-centos-7/</link>
					<title><![CDATA[Рабочие репозитории CentOS 7]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Mon, 08 Dec 2025 10:56:53 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2025/12/i-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Рабочие репозитории CentOS 7</h1>
													</header>
													<div class="t-feed__post-popup__title-wrapper">
<h1 class="js-feed-post-title t-feed__post-popup__title t-title t-title_xxs">С 1 июля 2024 года закончился срок поддержки CentOS 7, а значит – официальные репозитории перестали поддерживаться. Из-за этого при установке и обновлении пакетов могут возникать ошибки:</h1>
</div>
<div id="feed-text" class="r t-feed__post-popup__text-wrapper" data-animationappear="off">
<div class="js-feed-post-text t-feed__post-popup__text t-text t-text_md">

<div class="t-redactor__tte-view">
<pre class="t-redactor__highlightcode"><code class="hljs cpp" data-lang="{$la}">Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7&amp;arch=x86_64&amp;repo=os&amp;infra=stock error was
14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Unknown error"

14: curl#6 - "Could not resolve host: mirrorlist.centos.org; Name or service not known"

Cannot find a valid baseurl for repo: base/7/x86_64
</code></pre>
<div class="t-redactor__text">В этом случае необходимо отключить автоматическое определение зеркала репозитория и подключить репозиторий vault.centos.org . Для этого достаточно выполнить команды:</div>
<pre class="t-redactor__highlightcode"><code class="hljs coffeescript" data-lang="{$la}">sed -i s/mirror.centos.org/vault.centos.org/g /etc/yum.repos.d/CentOS*.repo
sed -i s/^#.*baseurl=http/baseurl=http/g /etc/yum.repos.d/CentOS*.repo
sed -i s/^mirrorlist=http/#mirrorlist=http/g /etc/yum.repos.d/CentOS*.repo</code></pre>
<div class="t-redactor__text">Альтернативно, можно привести содержимое файла <u>/etc/yum.repos.d/CentOS-Base.repo</u> к виду:</div>
<pre class="t-redactor__highlightcode"><code class="hljs ini" data-lang="{$la}">[base]
name=CentOS-$releasever - Base
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=os&amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#released updates 
[updates]
name=CentOS-$releasever - Updates
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=updates&amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=extras&amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&amp;arch=$basearch&amp;repo=centosplus&amp;infra=$infra
baseurl=http://vault.centos.org/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7</code></pre>
<div class="t-redactor__text">Так же проверьте другие файлы в каталоге <u>/etc/yum.repos.d/</u> на наличие ссылок с mirror.centos.org . Если они есть, отредактируйте их, заменив &#171;mirror.centos.org&#187; на &#171;vault.centos.org&#187; (без кавычек).</div>
</div>

</div>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[линукс]]></category><category><![CDATA[centos]]></category><category><![CDATA[centos7]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/12/i-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%bf%d1%80%d0%be%d0%b1%d0%bb%d0%b5%d0%bc%d0%b0-%d1%81-%d0%bf%d0%be%d0%b4%d0%bf%d0%b8%d1%81%d1%8c%d1%8e-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d1%8f-mysql-server-8-0-%d0%bf/</link>
					<title><![CDATA[Проблема с подписью репозитория MySQL Server 8.0 после 22.10.2025]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 29 Nov 2025 11:46:15 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="654" height="466" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config6.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Проблема с подписью репозитория MySQL Server 8.0 после 22.10.2025</h1>
													</header>
													
<div class="gdlr-blog-info gdlr-title-font gdlr-info">
<div class="clear">Проблема с ключом 0xB7B3B788A8D3785C, так как он устарел. В статье приведено решение проблемы.</div>
</div>

<div class="gdlr-blog-content">
<p>В конце октября 2025 возникла проблема с подписью репозитория repo.mysql.com, и команда <code>sudo apt update</code> выводит ошибку:</p>
<p><code>W: Произошла ошибка при проверке подписи. Репозиторий не обновлён, и будут использованы предыдущие индексные файлы. Ошибка GPG: http://repo.mysql.com/apt/ubuntu jammy InRelease: Следующие подписи неверны: EXPKEYSIG B7B3B788A8D3785C MySQL Release Engineering <a class="mailto" href="mailto:mysql-build@oss.oracle.com">mysql-build@oss.oracle.com</a><br />
W: Не удалось получить http://repo.mysql.com/apt/ubuntu/dists/jammy/InRelease Следующие подписи неверны: EXPKEYSIG B7B3B788A8D3785C MySQL Release Engineering <a class="mailto" href="mailto:mysql-build@oss.oracle.com">mysql-build@oss.oracle.com</a><br />
W: Некоторые индексные файлы скачать не удалось. Они были проигнорированы, или вместо них были использованы старые версии.</code></p>
<div class="notices yellow">
<p>Причина: у ключа истёк срок действия. <a class="external-link no-image" href="https://keyserver.ubuntu.com/pks/lookup?search=B7B3B788A8D3785C&amp;fingerprint=on&amp;op=index" target="_blank" rel="nofollow noopener noreferrer">Выпущен новый ключ</a> с 23.10.2025 по 23.10.2027.<br />
UID ключа: MySQL Release Engineering <a class="mailto" href="mailto:mysql-build@oss.oracle.com">mysql-build@oss.oracle.com</a></p>
</div>
<h3>Решение</h3>
<p>1) Удаляем старый, истёкший ключ со сроком действия до 22 октября 2025 года.</p>
<p>Если ключ был добавлен старым способом в общее храналище ключей</p>
<pre><code class="hljs language-bash" data-highlighted="yes">sudo apt-key del B7B3 B788 A8D3 785C</code></pre>
<p>Если ключ был добавлен в отдельный файл gpg (новый способ):</p>
<pre><code class="hljs language-bash" data-highlighted="yes">cd /etc/apt/trusted.gpg.d
ls *.gpg
sudo rm mysql8.gpg</code></pre>
<p>2) С помощью GPG скачиваем новый ключ B7B3B788A8D3785C</p>
<pre><code class="hljs language-bash" data-highlighted="yes">cd ~
gpg --keyserver keyserver.ubuntu.com --recv B7B3B788A8D3785C</code></pre>
<p>Вывод на экран:<br />
<code>gpg: ключ B7B3B788A8D3785C: "MySQL Release Engineering <a class="mailto" href="mailto:mysql-build@oss.oracle.com">mysql-build@oss.oracle.com</a>" 2 новых подписей<br />
gpg: Всего обработано: 1<br />
gpg: новых подписей: 2</code></p>
<p>Импортируем ключ gpg <em>новым способом</em>:</p>
<pre><code class="hljs language-bash" data-highlighted="yes">gpg --export B7B3B788A8D3785C | sudo tee /etc/apt/trusted.gpg.d/mysql.gpg &gt; /dev/null</code></pre>
<div class="notices red">
<p>Пункты 3 и 4 можно пропустить, если состав установки MySQL не менялся. Данные пункты приведены для справки, что делать, если изменился состав установки сервера mysql. <a href="#p5">Перейти к пункту 5</a>.</p>
</div>
<p>3) Генерируем файл по умолчанию для mysql</p>
<pre><code class="hljs language-bash" data-highlighted="yes">sudo dpkg-reconfigure mysql-apt-config    </code></pre>
<ul>
<li><em>MySQL and Cluster</em> (Currently selected: mysql-8.0)</li>
<li>MySQL Tools &amp; Connectors (Currently selected: <strong>Enabled</strong>)</li>
<li>MySQL Preview Packages (Currently selected: <strong>Disabled</strong>).</li>
</ul>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-510 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1.png" alt="" width="654" height="466" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1.png 654w, https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1-300x214.png 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /></p>
<p>В окне конфигуратора mysql нажимаем TAB для перехода на нижнюю кнопку OK.</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-509 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1a.png" alt="" width="654" height="466" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1a.png 654w, https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1a-300x214.png 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /><br />
Нажимаем Enter.</p>
<p>На следующем экране: &#171;Which server version do you wish to receive?&#187;</p>
<p>Выбираем версию, текущая:</p>
<ul>
<li>mysql 8.0</li>
</ul>
<p>&nbsp;</p>
<p>И нажимаем TAB для перехода на нижнюю кнопку OK.</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-508 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config2.png" alt="" width="654" height="466" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config2.png 654w, https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config2-300x214.png 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /></p>
<p>Вернулись к предущем экрану&#8230; Курсором подводим к маленькой строке &#171;ok&#187;.</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-510 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1.png" alt="" width="654" height="466" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1.png 654w, https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config1-300x214.png 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /></p>
<p>На вопрос:<br />
<strong>&#171;Файл &#8216;/usr/share/keyrings/mysql-apt-config.gpg&#8217; существует. Записать поверх? (y/N)&#187;</strong></p>
<ul>
<li>ответ <strong>&#171;Y&#187;</strong> и клавиша <strong>Enter.</strong><br />
<img decoding="async" title="mysql-config5" src="https://ra1ahq.blog/images/b/2/a/e/2/b2ae2f497a607b012fbeb21e806e37adbafa868c-mysql-config5.png" alt="mysql-config5" /></li>
</ul>
<p>4) Редактируем файл для источника приложений &#8212; стороннего репозитория: <strong>mysql.list</strong></p>
<pre><code class="hljs language-bash" data-highlighted="yes">cd /etc/apt/sources.list.d/

sudo nano /etc/apt/sources.list.d/mysql.list</code></pre>
<p>В редакторе можно нажать Ctrl+\ для замены:</p>
<ul>
<li>Поиск (что менять) <del>[signed-by=/usr/share/keyrings/mysql-apt-config.gpg]</del></li>
<li>заменить на [signed-by=/etc/apt/trusted.gpg.d/mysql.gpg]</li>
</ul>
<p>Заменить это вхождение?<br />
A &#8212; все.</p>
<p>Содержимое файла /usr/share/keyrings/mysql-apt-config.gpg после замены:<br />
<img loading="lazy" decoding="async" class="alignnone wp-image-511 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config6-1.png" alt="" width="654" height="466" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config6-1.png 654w, https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config6-1-300x214.png 300w" sizes="auto, (max-width: 654px) 100vw, 654px" /></p>
<p>Сохраняем файл под тем же именем: Ctrl+O, Enter, Ctrl+X.</p>
<p><a name="p5"></a><br />
5) Обновите кеш пакетов и установите обновления:</p>
<pre><code class="hljs language-bash" data-highlighted="yes">sudo apt update
sudo apt upgrade</code></pre>
<div class="notices blue">
<p><strong>Замечание.</strong> Прервать обновление apt upgrade нажатием Ctrl+C не рекомендую, иначе возникнут неудовлетворенные зависимости.<br />
Решение: <code>sudo apt --fix-broken install</code></p>
</div>
<h3>Результат</h3>
<div class="notices green">
<p>Ошибки apt update теперь нет, репозиторий mysql подписан действующей подписью B7B3B788A8D3785C.</p>
</div>
<pre><code class="hljs language-undefined" data-highlighted="yes"> gpg --list-keys</code></pre>
<p>Ключ &#8230; 785C годен до: 2027-10-23</p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[SQL]]></category><category><![CDATA[WEB]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/11/mysql-config6.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d0%bc-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d0%b8-%d1%8f%d0%bd%d0%b4%d0%b5%d0%ba%d1%81%d0%b0-%d0%b4%d0%bb%d1%8f-apt-2/</link>
					<title><![CDATA[Используем репозитории Яндекса для apt в Debian]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 28 Nov 2025 12:32:59 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="654" height="462" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/repository.webp" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Используем репозитории Яндекса для apt в Debian</h1>
													</header>
													<div class="wiki wiki-page">
<p>Для начала определимся с версиями Debian. У каждой версии Debian есть номер версии и кодовое имя выпуска. Ниже в таблице приведено соответствие номерной версии и кодового имени:</p>
<table>

<tr data-sort-method="none">
<th role="columnheader">Номер</th>
<th role="columnheader">Кодовое имя</th>
</tr>


<tr>
<td>9</td>
<td>Stretch</td>
</tr>
<tr>
<td>10</td>
<td>Buster</td>
</tr>
<tr>
<td>11</td>
<td>Bullseye</td>
</tr>
<tr>
<td>12</td>
<td>Bookworm</td>
</tr>
<tr>
<td>13</td>
<td>Trixie</td>
</tr>

</table>
<p>/etc/apt/sources.list</p>
Выберите версию:

	v9 Stretch
	v10 Buster
	v11 Bullseye
	v12 Bookworm
	v13 Trixie

<pre>
	<code id="code"></code>
</pre>

</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="2">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[WEB]]></category><category><![CDATA[web-server]]></category><category><![CDATA[Репозитории]]></category><category><![CDATA[Yandex]]></category><category><![CDATA[debian 9]]></category><category><![CDATA[debian 10]]></category><category><![CDATA[debian 11]]></category><category><![CDATA[debian 12]]></category><category><![CDATA[debian 13]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/11/repository.webp" type="image/webp" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-onlyoffice-docs-community-edition-%d0%bd%d0%b0-debian-12/</link>
					<title><![CDATA[Установка ONLYOFFICE Docs Community Edition на Debian 12]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Thu, 27 Nov 2025 10:28:49 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="560" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/687.avif" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Установка ONLYOFFICE Docs Community Edition на Debian 12</h1>
													</header>
													<p>ONLYOFFICE Docs — это бесплатный программный офисный пакет и экосистема приложений для совместной работы.</p>
<p>Хоть и официальный мануал по установке достаточно хорошо читаем, я все же для себя детально по шагам разберу установку ONLYOFFICE Docs на Debian 12 и настройку связки с Nextcloud.</p>
<div class="lwptoc lwptoc-baseItems lwptoc-light lwptoc-notInherit" data-smooth-scroll="0" data-lwptoc-initialized="1">
<div class="lwptoc_i">
<div class="lwptoc_header"><b class="lwptoc_title">Содержание</b></div>
<div class="lwptoc_items lwptoc_items-visible">
<ul class="lwptoc_itemWrap">
<li class="lwptoc_item"><a href="#Ustanovka_zavisimostej">Установка зависимостей</a>
<ul class="lwptoc_itemWrap">
<li class="lwptoc_item"><a href="#RabbitMQ">RabbitMQ</a></li>
<li class="lwptoc_item"><a href="https://jakondo.ru/ustanovka-onlyoffice-docs-community-edition-na-debian-12/#PostgreSQL">PostgreSQL</a></li>
</ul>
</li>
<li class="lwptoc_item"><a href="#Ustanovka_ONLYOFFICE_Docs">Установка ONLYOFFICE Docs</a></li>
<li class="lwptoc_item"><a href="https://jakondo.ru/ustanovka-onlyoffice-docs-community-edition-na-debian-12/#Nastrojka_ONLYOFFICE_Docs_-_HTTPS">Настройка ONLYOFFICE Docs — HTTPS</a></li>
<li class="lwptoc_item"><a href="#Nastrojka_ONLYOFFICE_Docs_v_Nextcloud">Настройка ONLYOFFICE Docs в Nextcloud</a></li>
<li class="lwptoc_item"><a href="#Dopolnitelno_dopolnaemaa">Дополнительно (дополняемая)</a>
<ul class="lwptoc_itemWrap">
<li class="lwptoc_item"><a href="#Kak_izmenit_sekretnyj_kluc">Как изменить секретный ключ</a></li>
<li class="lwptoc_item"><a href="https://jakondo.ru/ustanovka-onlyoffice-#Korrektnoe_otklucenie_polzovatelej_ONLYOFFICE_Docs">Корректное отключение пользователей ONLYOFFICE Docs</a></li>
<li class="lwptoc_item"><a href="#Otklucenie_stranicy_privetstvia">Отключение страницы приветствия</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<h2 class="wp-block-heading">Установка зависимостей</h2>
<p>Для установки пакета — <code>ttf-mscorefonts-installer</code> необходимо включение дополнительных <code>Contrib</code> и <code>Non-Free</code> репозиториев.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>echo "deb http://deb.debian.org/debian/ bookworm contrib non-free" | tee -a /etc/apt/sources.list
sudo apt-get update</code></pre>
</div>
<p>Устанавливаем необходимые зависимости.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>sudo apt-get install libcurl4 libxml2 curl gnupg2 libstdc++6 fonts-dejavu fonts-liberation ttf-mscorefonts-installer fonts-crosextra-carlito fonts-takao-gothic fonts-opensymbol nginx-extras -y</code></pre>
</div>
<h4 class="wp-block-heading">RabbitMQ</h4>
<p><code>RabbitMQ</code> — это брокер сообщений с открытым исходным кодом, который реализует протокол AMQP (Advanced Message Queuing Protocol).</p>
<div class="wp-block-simple-note-success">RabbitMQ принимает сообщения от поставщиков, отправляет подтверждение о приёме и перенаправляет сообщение получателям. Получатели подтверждают, что сообщение доставлено, или сигнализируют о неудачной доставке. Во втором случае сообщение остаётся в очереди до тех пор, пока не будет доставлено. После доставки сообщение удаляется из системы.</div>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>sudo apt-get install rabbitmq-server -y</code></pre>
</div>
<h4 class="wp-block-heading">PostgreSQL</h4>
<p>Установите версию PostgreSQL.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>sudo apt-get install postgresql -y</code></pre>
</div>
<p>После установки PostgreSQL создайте базу данных и пользователя PostgreSQL.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>sudo -Hiu postgres psql -c "CREATE USER onlyoffice WITH PASSWORD 'onlyoffice';"
sudo -Hiu postgres psql -c "CREATE DATABASE onlyoffice OWNER onlyoffice;"</code></pre>
</div>
<div class="wp-block-simple-note-warning">Пользователь базы данных должен называться <code>onlyoffice</code>. Пароль можно задать любой.</div>
<h2 class="wp-block-heading">Установка ONLYOFFICE Docs</h2>
<p>Добавляем GPG-ключ.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>mkdir -p -m 700 ~/.gnupg
curl -fsSL https://download.onlyoffice.com/GPG-KEY-ONLYOFFICE | gpg --no-default-keyring --keyring gnupg-ring:/tmp/onlyoffice.gpg --import
chmod 644 /tmp/onlyoffice.gpg
sudo chown root:root /tmp/onlyoffice.gpg
sudo mv /tmp/onlyoffice.gpg /usr/share/keyrings/onlyoffice.gpg</code></pre>
</div>
<p>Добавляем репозиторий ONLYOFFICE Docs.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>echo "deb [signed-by=/usr/share/keyrings/onlyoffice.gpg] https://download.onlyoffice.com/repo/debian squeeze main" | sudo tee /etc/apt/sources.list.d/onlyoffice.list</code></pre>
</div>
<p>Устанавливаем ONLYOFFICE Docs.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>apt-get update &amp;&amp; apt-get install onlyoffice-documentserver -y</code></pre>
</div>
<div class="wp-block-simple-note-warning">В ходе установки будет запрошен пароль для пользователя <code>onlyoffice</code> в PostgreSQL. Введите пароль <code>onlyoffice</code>, который был задан при настройке PostgreSQL.</div>
<div class="wp-block-spacer" aria-hidden="true"></div>
<p>По адресу —  <code>http://&lt;server_name&gt;</code> доступна страница приветствия ONLYOFFICE Docs, где приводятся дальнейшие инструкции о том, как интегрировать ONLYOFFICE Docs в веб-приложения и как протестировать работу ONLYOFFICE Docs.</p>
<h2 class="wp-block-heading">Настройка ONLYOFFICE Docs — HTTPS</h2>
<p>Для последующей настройки связки с Nextcloud, необходимо настроить ONLYOFFICE Docs на работу по протоколу HTTPS. Выполним настройку.</p>
<p>Скопируем файл <code>ds-ssl.conf.tmpl</code> в файл <code>ds.conf</code> с помощью следующей команды</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>cp -f /etc/onlyoffice/documentserver/nginx/ds-ssl.conf.tmpl /etc/onlyoffice/documentserver/nginx/ds.conf</code></pre>
</div>
<p>Зададим параметры для конфигурации <code>ds.conf</code></p>
<ul class="wp-block-list">
<li><code>SERVERNAME</code> — Указываем DNS имя вашего экземпляра ONLYOFFICE Docs.</li>
<li><code>SSL_CERT</code> — Путь к файлу сертификата.</li>
<li><code>SSL_PKEY</code> — Путь к файлу закрытого ключа сертификата.</li>
</ul>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>export SERVERNAME=&lt;dns_server_name&gt;
export SSL_CERT=/etc/ssl/fullchain.crt
export SSL_PKEY=/etc/ssl/privkey.key

openssl req -new -x509 -nodes -days 1825 -newkey rsa:2048 -keyout $SSL_PKEY -out $SSL_CERT
sed -i "s/server_name _;/server_name $SERVERNAME;/g; s|{{SSL_CERTIFICATE_PATH}}|$SSL_CERT|g; s|{{SSL_KEY_PATH}}|$SSL_PKEY|g" /etc/onlyoffice/documentserver/nginx/ds.conf</code></pre>
</div>
<p>Запустим следующий скрипт, для того чтобы внести необходимые правки в файл <code>ds.conf</code></p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>bash /usr/bin/documentserver-update-securelink.sh</code></pre>
</div>
<p>Проверим статус службы и состояние сервера:</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>systemctl status ds-docservice
systemctl status ds-converter

bash /usr/bin/documentserver-jwt-status.sh
Your JWT settings:
JWT enabled -  true
JWT secret  -  TuFVcNHa2YJzBciUh6lXqIbFAnTM5HpR
JWT header  -  Authorization</code></pre>
</div>
<div class="wp-block-simple-note-success">Данные <code>JWT secret</code> + <code>JWT header</code>, необходимы для подключения ONLYOFFICE Docs к внешним системам, таким как Nextcloud.</div>
<h2 class="wp-block-heading">Настройка ONLYOFFICE Docs в Nextcloud</h2>
<p>Теперь можно использовать сервер ONLYOFFICE Docs в Nextcloud.</p>
<div class="wp-block-image is-style-default">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" class="alignnone  wp-image-486" src="https://blog.sefdar.ru/wp-content/uploads/2025/11/screenshot_45-300x126.png" alt="" width="550" height="231" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/11/screenshot_45-300x126.png 300w, https://blog.sefdar.ru/wp-content/uploads/2025/11/screenshot_45-1024x431.png 1024w, https://blog.sefdar.ru/wp-content/uploads/2025/11/screenshot_45-768x323.png 768w, https://blog.sefdar.ru/wp-content/uploads/2025/11/screenshot_45.png 1069w" sizes="auto, (max-width: 550px) 100vw, 550px" /></figure>
</div>
<p>Где:</p>
<ul class="wp-block-list">
<li><code>Адрес ONLYOFFICE Docs</code> — указываем DNS имя сервера которое задавали в файле <code>ds.conf</code> в директиве <code>server_name</code></li>
<li><code>Секретный ключ</code> — указываем secret полученный при выполнении <code>/usr/bin/documentserver-jwt-status.sh</code></li>
</ul>
<h2 class="wp-block-heading">Дополнительно (дополняемая)</h2>
<p>Ниже буду дописывать какие то моменты которые могут пригодится в обслуживании ONLYOFFICE Docs.</p>
<h4 class="wp-block-heading">Как изменить секретный ключ</h4>
<p>В файле /etc/onlyoffice/documentserver/local.json в секциях <code>secret</code> — {<code>inbox, outbox, session</code>} в полях <code>string</code> указываем желаемый секретный ключ (должен быть одинаковый во всех трех строках).</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<p>/etc/onlyoffice/documentserver/local.json</p>
<pre class="shiki dark-plus" tabindex="0"><code>  "secret": {
    "inbox": {
      "string": "DbNCGPIT9Vqv53hmuAMuMIhl9m8PsEAiey54u7zX"
    },
    "outbox": {
      "string": "DbNCGPIT9Vqv53hmuAMuMIhl9m8PsEAiey54u7zX"
    },
    "session": {
      "string": "DbNCGPIT9Vqv53hmuAMuMIhl9m8PsEAiey54u7zX"
    }</code></pre>
</div>
<p>После внесения изменений, необходимо перезапустить службу <code>ds-docservice</code></p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>systemctl restart ds-docservice</code></pre>
</div>
<h4 class="wp-block-heading">Корректное отключение пользователей ONLYOFFICE Docs</h4>
<p>Чтобы избежать потери данных, при необходимости остановить ONLYOFFICE Docs в случаях обновления приложения, перезагрузки сервера и т.п. необходимо принудительно отключить пользователей ONLYOFFICE Docs.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>bash /usr/bin/documentserver-prepare4shutdown.sh</code></pre>
</div>
<p>Чтобы все заработало обратно, в случае если не было перезагрузки системы, то просто перезапускаем службы ONLYOFFICE Docs.</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<pre class="shiki light-plus" tabindex="0"><code>systemctl restart ds-docservice
systemctl restart ds-converter</code></pre>
</div>
<h4 class="wp-block-heading">Отключение страницы приветствия</h4>
<p>Если необходимо отключить страницу приветствия, то нужно в файле — <code>/etc/onlyoffice/documentserver/nginx/includes/ds-docservice.conf</code> закоментировать отмеченную строку и добавить ниже следующие:</p>
<div class="wp-block-kevinbatdorf-code-block-pro cbp-hl-loaded cbp-ff-loaded" data-code-block-pro-font-family="">
<p>/etc/onlyoffice/documentserver/nginx/includes/ds-docservice.conf</p>
<pre class="shiki dark-plus" tabindex="0"><code>#welcome page
#rewrite ^/$ $the_scheme://$the_host$the_prefix/welcome/ redirect;
rewrite ^/welcome $the_scheme://$the_host redirect;

location = / {
  return 404;
}</code></pre>
</div>
<p>После внесения изменений, перезапускаем nginx — <code>systemctl reload nginx</code></p>
<p>&nbsp;</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[web-server]]></category><category><![CDATA[cloud]]></category><category><![CDATA[nextcloud]]></category><category><![CDATA[web]]></category><category><![CDATA[onlyoffice]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/11/687.avif" type="image/avif" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/nginx-%d0%b2%d1%8b%d0%b4%d0%b0%d0%b5%d1%82-%d0%be%d1%88%d0%b8%d0%b1%d0%ba%d1%83-http-500-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-60-%d1%81%d0%b5%d0%ba%d1%83%d0%bd%d0%b4-%d0%bd%d0%b5%d1%81%d0%bc%d0%be%d1%82/</link>
					<title><![CDATA[NginX выдает ошибку HTTP 500 через 60 секунд, несмотря на конфигурацию.]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Mon, 29 Sep 2025 04:46:38 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="504" src="https://blog.sefdar.ru/wp-content/uploads/2025/09/i.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>NginX выдает ошибку HTTP 500 через 60 секунд, несмотря на конфигурацию.</h1>
													</header>
													<div class="card border-0">
<p>В конце прошлой недели я заметил проблему на одном из моих серверов, где Nginx всегда возвращает ответ HTTP 500, если запрос занимает более 60 секунд. Запрошенная страница представляет собой скрипт PHP</p>
<p>Я провел несколько дней, пытаясь найти ответы, и попробовал все, что я могу найти в Интернете, включая несколько записей здесь, в Stack Overflow, ничего не работает.</p>
<ul>
<li><a class="text-dark" title="$ _SERVER  не дает значения" href="https://ruphp.com/_server-7.html" rel="bookmark">$ _SERVER не дает значения</a></li>
<li><a class="text-dark" title="Nginx переписать не работает с расширением .php" href="https://ruphp.com/nginx-10.html" rel="bookmark">Nginx переписать не работает с расширением .php</a></li>
<li><a class="text-dark" title="Ошибка nginx подключиться к php5-fpm.sock не удалось (13: отказ от прав)" href="https://ruphp.com/nginx-php5-fpm-sock.html" rel="bookmark">Ошибка nginx подключиться к php5-fpm.sock не удалось (13: отказ от прав)</a></li>
<li><a class="text-dark" title="php-fpm разбился, когда curl или file_get_contents запросили https-url" href="https://ruphp.com/php-fpm-curl-file_get_contents-x4.html" rel="bookmark">php-fpm разбился, когда curl или file_get_contents запросили https-url</a></li>
<li><a class="text-dark" title="Сложность Ioncube с PHP 5.5" href="https://ruphp.com/ioncube-php-5-5.html" rel="bookmark">Сложность Ioncube с PHP 5.5</a></li>
</ul>
<p>Я пробовал изменять настройки PHP, настройки PHP-FPM и настройки Nginx. Увеличивал время ожидания и выполнение скриптов, но все сводилось к тому что где-то сидит конфиг который завершает выполнение через 60с. Это <strong>не</strong> та же проблема, что и ошибки HTTP 500 в других записях.</p>
<p>Чтобы помочь любому, кто хочет увидеть проблему в действии, я собираюсь провести вас через настройку, которую я запускал для последнего тестового сервера Micro.</p>
<p>Сделал образец файла PHP, который я тестирую, с которым</p>
<pre><code>&lt;?php sleep(70); die( 'Hello World' ); ?&gt;</code></pre>
<p>Сохраните это в webroot, а затем проверьте. Если вы запустите скрипт из командной строки, используя php или php-cgi, он будет работать. Если вы получите доступ к скрипту через веб-страницу и <em>закроете</em> журнал доступа <em>/var/log/nginx/example.access.log</em> , вы заметите, что получите ответ HTTP 1.1 499 через 60 секунд.</p>
<p>Теперь, когда вы можете увидеть таймаут, я рассмотрю некоторые изменения конфигурации, которые я сделал как для PHP, так и для NginX, чтобы попытаться обойти это. Для PHP я создам несколько файлов конфигурации, чтобы их можно было легко отключить</p>
<p><strong>Обновите PHP FPM Config, чтобы включить внешние файлы конфигурации</strong></p>
<pre><code>sudo echo ' include=/usr/local/php/php-fpm.d/*.conf ' &gt;&gt; /usr/local/php/etc/php-fpm.conf</code> в <code>sudo echo ' include=/usr/local/php/php-fpm.d/*.conf ' &gt;&gt; /usr/local/php/etc/php-fpm.conf</code></pre>
<p><strong>Создайте новую конфигурацию PHP-FPM для переопределения таймаута запроса</strong></p>
<pre><code>sudo echo '[www] request_terminate_timeout = 120s request_slowlog_timeout = 60s slowlog = /var/log/php-fpm-slow.log ' &gt; /usr/local/php/php-fpm.d/timeouts.conf</code></pre>
<p><strong>Измените некоторые глобальные настройки, чтобы обеспечить интервал аварийного перезапуска 2 минуты</strong></p>
<pre><code># Create a global tweaks sudo echo '[global] error_log = /var/log/php-fpm.log emergency_restart_threshold = 10 emergency_restart_interval = 2m process_control_timeout = 10s ' &gt; /usr/local/php/php-fpm.d/global-tweaks.conf</code></pre>
<p>Затем мы изменим некоторые параметры PHP.INI, снова используя отдельные файлы</p>
<pre><code># Log PHP Errors sudo echo '[PHP] log_errors = on error_log = /var/log/php.log ' &gt; /usr/local/php/conf.d/errors.ini sudo echo '[PHP] post_max_size=32M upload_max_filesize=32M max_execution_time = 360 default_socket_timeout = 360 mysql.connect_timeout = 360 max_input_time = 360 ' &gt; /usr/local/php/conf.d/filesize.ini</code></pre>
<p>Как вы можете видеть, это увеличивает тайм-аут сокета до 3 минут и помогает регистрировать ошибки.</p>
<p>Наконец, я отредактирую некоторые параметры NginX, чтобы увеличить тайм-аут той стороны</p>
<p>Сначала я редактирую файл <em>/etc/nginx/nginx.conf</em> и добавляю его в директиву http fastcgi_read_timeout 300;</p>
<p>Затем я редактирую файл <em>/ etc / nginx / sites-enabled / example,</em> который мы создали ранее, и добавьте следующие параметры в директиву <strong>сервера</strong></p>
<pre><code>client_max_body_size 200; client_header_timeout 360; client_body_timeout 360; fastcgi_read_timeout 360; keepalive_timeout 360; proxy_ignore_client_abort on; send_timeout 360; lingering_timeout 360;</code></pre>
<p>Наконец, я добавляю следующее в раздел <em>~ .php $</em> сервера dir</p>
<pre><code>fastcgi_read_timeout 360; fastcgi_send_timeout 360; fastcgi_connect_timeout 1200;</code></pre>
<p>Прежде чем повторять сценарий, запустите nginx и php-fpm, чтобы убедиться, что новые настройки были подняты. Затем я пытаюсь получить доступ к странице и все еще получаю запись HTTP / 1.1 499 в файле NginX example.error.log.</p>
<p>Итак, где я иду не так? Это просто работает на apache, когда я устанавливаю максимальное время выполнения PHP до 2 минут.</p>
<p>Я вижу, что настройки PHP были подобраны, запустив <strong>phpinfo ()</strong> с веб-страницы. Я просто не понимаю, я действительно думаю, что слишком много было увеличено, так как это должно было просто потребовать изменения <em>max_execution_time</em> PHP, <em>default_socket_timeout,</em> а также fastcgi_read_timeout от <em>NginX</em> только в директиве location-&gt; <em>server</em> .</p>
<h2>Обновление 1</h2>
<p>Проведя еще один тест, чтобы показать, что проблема заключается не в том, что клиент умирает, я модифицировал тестовый файл</p>
<pre><code>&lt;?php file_put_contents('/www/log.log', 'My first data'); sleep(70); file_put_contents('/www/log.log','The sleep has passed'); die('Hello World after sleep'); ?&gt;</code></pre>
<p>Если я запустил скрипт с веб-страницы, я увижу, что содержимое файла будет установлено в первую строку. Через 60 секунд в журнале NginX появляется ошибка. Через 10 секунд содержимое файла изменяется на вторую строку, доказывая, что PHP завершает процесс.</p>
<h2>Обновление 2</h2>
<p>Установка <strong>fastcgi_ignore_client_abort;</strong> изменяет ответ от HTTP 499 на HTTP 200, хотя ничего не возвращается конечному клиенту.</p>
<h2>Обновление 3</h2>
<p>Установив Apache и PHP (5.3.10) на поле прямо (используя apt), а затем увеличивая время выполнения, проблема также возникает и на Apache. Симптомы такие же, как и у NginX, ответ HTTP200, но фактическое время соединения с клиентом перед раздачей.</p>
<p>Я также начал замечать в журналах NginX, что если я тестирую с помощью Firefox, он делает двойной запрос (например, этот PHP-скрипт выполняется дважды, когда он длится более 60 секунд ). Хотя, похоже, это клиент, запрашивающий при неудачном сценарии.</p>
<div class="list-group list-group-flush">
<div class="list-group-item list-group-item-action flex-column align-items-start">
<p>Я думал, что оставлю свои два цента. Сначала проблема не связана с php (все еще может быть связано с php, php всегда меня удивляет: P). Это уж точно. в основном это вызвано сервером, проксированным для себя, в частности, имена имен хостов / псевдонимов, в вашем случае это может быть балансировка нагрузки, запрашивающая nginx, и nginx обращается к балансировщику нагрузки и продолжает идти таким образом.</p>
<p>Я столкнулся с <strong>аналогичной</strong> проблемой с nginx в качестве балансировки нагрузки и apache в качестве веб-сервера / прокси-сервера</p>
</div>
<div class="list-group-item list-group-item-action flex-column align-items-start">
<p>Вам нужно найти, в каком месте проблемы жить. Я не знаю точного ответа, но просто попробуем его найти.</p>
<p>У нас есть 3 элемента: nginx, php-fpm, php. Как вы сказали, одинаковые настройки php под apache в порядке. Разве это не такая же настройка? Вы пытались apache вместо nginx на той же ОС / хосте / и т. Д.?</p>
<p>Если мы увидим, что php не подозревает, у нас есть два подозреваемых: nginx &amp; php-fpm.</p>
<p>Чтобы исключить nginx: попробуйте настроить ту же «систему» ​​на рубине. См. <a href="https://github.com/garex/puppet-module-nginx" rel="nofollow">https://github.com/garex/puppet-module-nginx</a>, чтобы получить представление об установке простейшей рубиновой установки. Или используйте google (возможно, это будет еще лучше).</p>
<p>Мой главный подозреваемый здесь – php-fpm.</p>
<p>Попробуйте сыграть с этими настройками:</p>
<ul>
<li>php-fpm `request_terminate_timeout</li>
<li>nginx`s fastcgi_ignore_client_abort</li>
</ul>
</div>
<div class="list-group-item list-group-item-action flex-column align-items-start">
<p>На самом деле я столкнулся с той же проблемой на одном сервере, и я понял, что после изменений конфигурации nginx я не перезапустил сервер nginx, поэтому с каждым ударом nginx-url я получал ответ 499 http. После перезапуска nginx он начал нормально работать с ответами HTTP 200.</p>
</div>
</div>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[WEB]]></category><category><![CDATA[web-server]]></category><category><![CDATA[NGINX]]></category><category><![CDATA[web]]></category><category><![CDATA[php]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/09/i.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0-%d1%81-mdadm-%d0%b2-linux-%d0%b4%d0%bb%d1%8f-%d0%be%d1%80%d0%b3%d0%b0%d0%bd%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d0%b8-raid/</link>
					<title><![CDATA[Работа с mdadm в Linux для организации RAID]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jun 2025 12:42:12 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="784" height="392" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/543d745cvmLAq4MFLaKZHjek.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Работа с mdadm в Linux для организации RAID</h1>
													</header>
													<p>mdadm — утилита для работы с программными RAID-массивами различных уровней. В данной инструкции рассмотрим примеры ее использования.</p>
<h2 id="install">Установка mdadm</h2>
<p>Утилита mdadm может быть установлена одной командой.</p>
<p>Если используем <strong>CentOS / Red Hat</strong>:</p>
<div class="console">
<pre>yum install mdadm
</pre>
</div>
<p>Если используем <strong>Ubuntu / Debian</strong>:</p>
<div class="console">
<pre>apt-get install mdadm
</pre>
</div>
<h2 id="create">Сборка RAID</h2>
<p>Перед сборкой, стоит подготовить наши носители. Затем можно приступать к созданию рейд-массива.</p>
<h3 id="create-prepare">Подготовка носителей</h3>
<p>Сначала необходимо занулить суперблоки на дисках, которые мы будем использовать для построения RAID (если диски ранее использовались, их суперблоки могут содержать служебную информацию о других RAID):</p>
<div class="console">
<pre>mdadm --zero-superblock --force /dev/sd{b,c}
</pre>
</div>
<p><em>* в данном примере мы зануляем суперблоки для дисков <strong>sdb</strong> и <strong>sdc</strong>.</em></p>
<blockquote><p>Посмотреть, какие в вашей системе есть устройства можно командой:</p>
<div class="console">
<pre>lsblk
</pre>
</div>
</blockquote>
<p>Если мы получили ответ:</p>
<div class="console-like">
<pre>mdadm: Unrecognised md component device - /dev/sdb
mdadm: Unrecognised md component device - /dev/sdc
</pre>
</div>
<p>&#8230; то значит, что диски не использовались ранее для RAID. Просто продолжаем настройку.</p>
<p>Далее нужно удалить старые метаданные и подпись на дисках:</p>
<div class="console">
<pre>wipefs --all --force /dev/sd{b,c}
</pre>
</div>
<h3 id="create-raid">Создание рейда</h3>
<p>Для сборки избыточного массива применяем следующую команду:</p>
<div class="console">
<pre>mdadm --create --verbose /dev/md0 -l 1 -n 2 /dev/sd{b,c}
</pre>
</div>
<p><em>* где:</em></p>
<ul>
<li><em><strong>/dev/md0</strong> — устройство RAID, которое появится после сборки; </em></li>
<li><em><strong>-l 1</strong> — уровень RAID; </em></li>
<li><em><strong>-n 2</strong> — количество дисков, из которых собирается массив; </em></li>
<li><em><strong>/dev/sd{b,c}</strong> — сборка выполняется из дисков sdb и sdc.</em></li>
</ul>
<p>Мы должны увидеть что-то на подобие:</p>
<div class="console-like">
<pre>mdadm: Note: this array has metadata at the start and
may not be suitable as a boot device.  If you plan to
store '/boot' on this device please ensure that
your boot-loader understands md/v1.x metadata, or use
--metadata=0.90
mdadm: size set to 1046528K
</pre>
</div>
<p>Также система задаст контрольный вопрос, хотим ли мы продолжить и создать RAID — нужно ответить <strong>y</strong>:</p>
<div class="console-like">
<pre>Continue creating array? y
</pre>
</div>
<p>Мы увидим что-то на подобие:</p>
<div class="console-like">
<pre>mdadm: Defaulting to version 1.2 metadata
mdadm: array /dev/md0 started.
</pre>
</div>
<p>Вводим команду:</p>
<div class="console">
<pre>lsblk
</pre>
</div>
<p>&#8230; и находим информацию о том, что у наших дисков sdb и sdc появился раздел md0, например:</p>
<div class="console-like">
<pre>...
sdb                     8:16   0    2G  0 disk
??md0                   9:0    0    2G  0 raid1
sdc                     8:32   0    2G  0 disk
??md0                   9:0    0    2G  0 raid1
...
</pre>
</div>
<p><em>* в примере мы видим собранный raid1 из дисков sdb и sdc.</em></p>
<h2 id="conf">Создание файла mdadm.conf</h2>
<p>В файле mdadm.conf находится информация о RAID-массивах и компонентах, которые в них входят. Для его создания выполняем следующие команды:</p>
<div class="console">
<pre>mkdir /etc/mdadm
</pre>
</div>
<div class="console">
<pre>echo "DEVICE partitions" &gt; /etc/mdadm/mdadm.conf
</pre>
</div>
<div class="console">
<pre>mdadm --detail --scan --verbose | awk '/ARRAY/ {print}' &gt;&gt; /etc/mdadm/mdadm.conf
</pre>
</div>
<p>Пример содержимого:</p>
<div class="console-like">
<pre>DEVICE partitions
ARRAY /dev/md0 level=raid1 num-devices=2 metadata=1.2 name=proxy.dmosk.local:0 UUID=411f9848:0fae25f9:85736344:ff18e41d
</pre>
</div>
<p><em>* в данном примере хранится информация о массиве <strong>/dev/md0</strong> — его уровень 1, он собирается из 2-х дисков.</em></p>
<h2 id="fs-mount">Создание файловой системы и монтирование массива</h2>
<p>Создание файловой системы для массива выполняется также, как для раздела, например:</p>
<div class="console">
<pre>mkfs.ext4 /dev/md0
</pre>
</div>
<p><em>* данной командой мы создаем на <strong>md0</strong> файловую систему <strong>ext4</strong>.</em></p>
<p>или:</p>
<div class="console">
<pre>mkfs.xfs /dev/md0
</pre>
</div>
<p><em>* для файловой системы <strong>xfs</strong>.</em></p>
<p>Примонтировать раздел можно командой:</p>
<div class="console">
<pre>mount /dev/md0 /mnt
</pre>
</div>
<p><em>* в данном случае мы примонтировали наш массив в каталог <strong>/mnt</strong>.</em></p>
<p>Чтобы данный раздел также монтировался при загрузке системы, добавляем в fstab.</p>
<p>Сначала смотрим идентификатор раздела:</p>
<div class="console">
<pre>blkid
</pre>
</div>
<p>Мы увидим что-то на подобие:</p>
<div class="console-like">
<pre>/dev/md0: UUID="ffa7c082-7613-4dbc-ae62-3f5508652cf6" TYPE="ext4"
</pre>
</div>
<p><em>* в моем примере мы будем использовать идентификатор <strong>ffa7c082-7613-4dbc-ae62-3f5508652cf6</strong>.</em></p>
<p>Открываем теперь fstab и добавляем строку:</p>
<div class="console">
<pre>vi /etc/fstab
</pre>
</div>
<div class="editor">
<pre>UUID="ffa7c082-7613-4dbc-ae62-3f5508652cf6"    /mnt    ext4    defaults    0 0
</pre>
</div>
<p>Если ранее мы монтировали раздел в каталог /mnt, вводим:</p>
<div class="console">
<pre>umount /mnt
</pre>
</div>
<p>И после:</p>
<div class="console">
<pre>mount -a
</pre>
</div>
<p>Мы должны увидеть примонтированный раздел md, например:</p>
<div class="console">
<pre>df -h
</pre>
</div>
<div class="console-like">
<pre>/dev/md0               990M         2,6M  921M            1% /mnt
</pre>
</div>
<h2 id="info">Информация о RAID</h2>
<p>Посмотреть состояние всех RAID можно командой:</p>
<div class="console">
<pre>cat /proc/mdstat
</pre>
</div>
<p>В ответ мы получим что-то на подобие:</p>
<div class="console-like">
<pre>md0 : active raid1 sdc[1] sdb[0]
1046528 blocks super 1.2 [2/2] [UU]
</pre>
</div>
<p><em>* где <strong>md0</strong> — имя RAID устройства; <strong>raid1 sdc[1] sdb[0]</strong> — уровень избыточности и из каких дисков собран; <strong>1046528 blocks</strong> — размер массива; <strong>[2/2] [UU]</strong> — количество юнитов, которые на данный момент используются.<br />
** мы можем увидеть строку <strong>md0 : active(auto-read-only)</strong> — это означает, что после монтирования массива, он не использовался для записи.</em></p>
<p>Подробную информацию о конкретном массиве можно посмотреть командой:</p>
<div class="console">
<pre>mdadm -D /dev/md0
</pre>
</div>
<p><em>* где <strong>/dev/md0</strong> — имя RAID устройства.</em></p>
<p>Пример ответа:</p>
<div class="console-like">
<pre>           Version : 1.2
Creation Time : Wed Mar  6 09:41:06 2019
Raid Level : raid1
Array Size : 1046528 (1022.00 MiB 1071.64 MB)
Used Dev Size : 1046528 (1022.00 MiB 1071.64 MB)
Raid Devices : 2
Total Devices : 2
Persistence : Superblock is persistent

Update Time : Wed Mar  6 09:41:26 2019
State : clean
Active Devices : 2
Working Devices : 2
Failed Devices : 0
Spare Devices : 0

Consistency Policy : resync

Name : proxy.dmosk.local:0  (local to host proxy.dmosk.local)
UUID : 304ad447:a04cda4a:90457d04:d9a4e884
Events : 17

Number   Major   Minor   RaidDevice State
0       8       16        0      active sync   /dev/sdb
1       8       32        1      active sync   /dev/sdc
</pre>
</div>
<p><em>* где:</em></p>
<ul>
<li><em><strong>Version — </strong>версия метаданных.</em></li>
<li><em><strong>Creation Time — </strong>дата в время создания массива.</em></li>
<li><em><strong>Raid Level — </strong>уровень RAID.</em></li>
<li><em><strong>Array Size —</strong> объем дискового пространства для RAID.</em></li>
<li><em><strong>Used Dev Size — </strong>используемый объем для устройств. Для каждого уровня будет индивидуальный расчет: RAID1 — равен половине общего размера дисков, RAID5 — равен размеру, используемому для контроля четности.</em></li>
<li><em><strong>Raid Devices — </strong>количество используемых устройств для RAID.</em></li>
<li><em><strong>Total Devices — </strong>количество добавленных в RAID устройств.</em></li>
<li><em><strong>Update Time — </strong>дата и время последнего изменения массива.</em></li>
<li><em><strong>State —</strong> текущее состояние. clean — все в порядке.</em></li>
<li><em><strong>Active Devices — </strong>количество работающих в массиве устройств.</em></li>
<li><em><strong>Working Devices — </strong>количество добавленных в массив устройств в рабочем состоянии.</em></li>
<li><em><strong>Failed Devices — </strong>количество сбойных устройств.</em></li>
<li><em><strong>Spare Devices — </strong>количество запасных устройств.</em></li>
<li><em><strong>Consistency Policy — </strong>политика согласованности активного массива (при неожиданном сбое). По умолчанию используется <strong>resync</strong> — полная ресинхронизация после восстановления. Также могут быть bitmap, journal, ppl.</em></li>
<li><em><strong>Name — </strong>имя компьютера.</em></li>
<li><em><strong>UUID — </strong>идентификатор для массива.</em></li>
<li><em><strong>Events — </strong>количество событий обновления.</em></li>
<li><strong>Chunk Size</strong> (для RAID5) — размер блока в килобайтах, который пишется на разные диски.</li>
</ul>
<p>Подробнее про каждый параметр можно прочитать в мануале для mdadm:</p>
<div class="console">
<pre>man mdadm
</pre>
</div>
<p>Также, информацию о разделах и дисковом пространстве массива можно посмотреть командой fdisk:</p>
<div class="console">
<pre>fdisk -l /dev/md0
</pre>
</div>
<h2 id="check">Проверка целостности</h2>
<p>Для проверки целостности вводим:</p>
<div class="console">
<pre>echo 'check' &gt; /sys/block/md0/md/sync_action
</pre>
</div>
<p>Результат проверки смотрим командой:</p>
<div class="console">
<pre>cat /sys/block/md0/md/mismatch_cnt
</pre>
</div>
<p><em>* если команда возвращает <strong>0</strong>, то с массивом все в порядке.</em></p>
<p>Остановка проверки:</p>
<div class="console">
<pre>echo 'idle' &gt; /sys/block/md0/md/sync_action
</pre>
</div>
<h2 id="restore">Восстановление RAID</h2>
<p>Рассмотрим два варианта восстановлении массива.</p>
<h3 id="restore-disk">Замена диска</h3>
<p>В случае выхода из строя одного из дисков массива, команда cat /proc/mdstat покажет следующее:</p>
<div class="console">
<pre>cat /proc/mdstat
</pre>
</div>
<div class="console-like">
<pre>Personalities : [raid1]
md0 : active raid1 sdb[0]
1046528 blocks super 1.2 [2/1] [U_]
</pre>
</div>
<p><em>* о наличии проблемы нам говорит нижнее подчеркивание вместо U — <strong>[U_]</strong> вместо <strong>[UU]</strong>.</em></p>
<p>Или:</p>
<div class="console">
<pre>mdadm -D /dev/md0
</pre>
</div>
<div class="console-like">
<pre>...
Update Time : Thu Mar  7 20:20:40 2019
State : clean, degraded
...
</pre>
</div>
<p><em>* статус <strong>degraded</strong> говорит о проблемах с RAID.</em></p>
<p>Для восстановления, сначала удалим сбойный диск, например:</p>
<div class="console">
<pre>mdadm /dev/md0 --remove /dev/sdc
</pre>
</div>
<blockquote><p>Если нам нужно заменить диск, но при этом он в mdadm имеет рабочее состояние, мы получим ошибку:</p>
<div class="console-like">
<pre>... device or resource busy
</pre>
</div>
<p>Сначала, нам нужно пометить диск как сбойный:</p>
<div class="console">
<pre>mdadm /dev/md0 --manage --fail /dev/sdc
</pre>
</div>
<p><em>* в данном примере диск <strong>sdb</strong> массива <strong>md0</strong> будет помечен сбойным.</em></p>
<p>Теперь удаляем:</p>
<div class="console">
<pre>mdadm /dev/md0 --remove /dev/sdc
</pre>
</div>
</blockquote>
<p>Теперь добавим новый:</p>
<div class="console">
<pre>mdadm /dev/md0 --add /dev/sde
</pre>
</div>
<p>Смотрим состояние массива:</p>
<div class="console">
<pre>mdadm -D /dev/md0
</pre>
</div>
<div class="console-like">
<pre>...
Update Time : Thu Mar  7 20:57:13 2019
State : clean, degraded, recovering
...
Rebuild Status : 40% complete
...
</pre>
</div>
<p><em>* <strong>recovering</strong> говорит, что RAID восстанавливается; <strong>Rebuild Status</strong> — текущее состояние восстановления массива (в данном примере он восстановлен на <strong>40%</strong>).</em></p>
<p>Если синхронизация выполняется слишком медленно, можно увеличить ее скорость. Для изменения скорости синхронизации вводим:</p>
<div class="console">
<pre>echo '10000' &gt; /proc/sys/dev/raid/speed_limit_min
</pre>
</div>
<p><em>* по умолчанию скорость <strong>speed_limit_min</strong> = 1000 Кб, <strong>speed_limit_max</strong> — 200000 Кб. Для изменения скорости, можно поменять только минимальную.</em></p>
<h3 id="restore-assemble">Пересборка массива</h3>
<p>Если нам нужно вернуть ранее разобранный или развалившийся массив из дисков, которые уже входили в состав RAID, вводим:</p>
<div class="console">
<pre>mdadm --assemble --scan
</pre>
</div>
<p><em>* данная команда сама найдет необходимую конфигурацию и восстановит RAID.</em></p>
<p>Также, мы можем указать, из каких дисков пересобрать массив:</p>
<div class="console">
<pre>mdadm --assemble /dev/md0 /dev/sdb /dev/sdc
</pre>
</div>
<h2 id="spare">Запасной диск (Hot Spare)</h2>
<p>Если в массиве будет запасной диск для горячей замены, при выходе из строя одного из основных дисков, его место займет запасной.</p>
<p>Диском Hot Spare станет тот, который просто будет добавлен к массиву:</p>
<div class="console">
<pre>mdadm /dev/md0 --add /dev/sdd
</pre>
</div>
<p>Информация о массиве изменится, например:</p>
<div class="console">
<pre>mdadm -D /dev/md0
</pre>
</div>
<div class="console-like">
<pre>...
Number   Major   Minor   RaidDevice State
0       8       16        0      active sync   /dev/sdb
2       8       48        1      active sync   /dev/sdc

3       8       32        -      spare   /dev/sdd
</pre>
</div>
<p>Проверить работоспособность резерва можно вручную, симулировав выход из строя одного из дисков:</p>
<div class="console">
<pre>mdadm /dev/md0 --fail /dev/sdb
</pre>
</div>
<p>И смотрим состояние:</p>
<div class="console">
<pre>mdadm -D /dev/md0
</pre>
</div>
<div class="console">
<pre>...
Rebuild Status : 37% complete
...
Number   Major   Minor   RaidDevice State
3       8       32        0      spare rebuilding   /dev/sdd
2       8       48        1      active sync   /dev/sdc

0       8       16        -      faulty   /dev/sdb
...
</pre>
</div>
<p><em>* как видим, начинается ребилд. На замену вышедшему из строя <strong>sdb</strong> встал hot-spare <strong>sdd</strong>.</em></p>
<h2 id="add-to-raid">Добавить диск к массиву</h2>
<p>В данном примере рассмотрим вариант добавления активного диска к RAID, который будет использоваться для работы, а не в качестве запасного.</p>
<p>Добавляем диск к массиву:</p>
<div class="console">
<pre>mdadm /dev/md0 --add /dev/sde
</pre>
</div>
<p>Новый диск мы увидим в качестве spare:</p>
<div class="console">
<pre>4       8       16        -      spare   /dev/sde
</pre>
</div>
<p>Теперь расширяем RAID:</p>
<div class="console">
<pre>mdadm -G /dev/md0 --raid-devices=3
</pre>
</div>
<p><em>* в данном примере подразумевается, что у нас RAID 1 и мы добавили к нему 3-й диск.</em></p>
<h2 id="remove">Удаление массива</h2>
<div class="note">
<p>При удалении массива внимателнее смотрите на имена массива и дисков и подставляйте свои значения.</p>
</div>
<p>Если нам нужно полностью разобрать RAID, сначала размонтируем и остановим его:</p>
<div class="console">
<pre>umount /mnt
</pre>
</div>
<p><em>* где <strong>/mnt </strong>— каталог монтирования нашего RAID.</em></p>
<blockquote><p>Если мы получим ошибку <strong>umount: /mnt: target is busy</strong>, то смотрим пользовательские процессы, которые мешают отмонтировать раздел:</p>
<div class="console">
<pre>fuser -vm /mnt
</pre>
</div>
<p>И останавливаем их.</p></blockquote>
<div class="console">
<pre>mdadm -S /dev/md0
</pre>
</div>
<p><em>* где <strong>/dev/md0</strong> — массив, который мы хотим разобрать.</em></p>
<blockquote><p>Если мы получим ошибку <strong>mdadm: fail to stop array /dev/md0: Device or resource busy</strong>, с помощью команды</p>
<div class="console">
<pre>lsof -f -- /dev/md0
</pre>
</div>
<p>&#8230; смотрим процессы, которые используют раздел и останавливаем их.</p></blockquote>
<p>Затем очищаем суперблоки на всех дисках, из которых он был собран:</p>
<div class="console">
<pre>mdadm --zero-superblock /dev/sdb
</pre>
</div>
<div class="console">
<pre>mdadm --zero-superblock /dev/sdc
</pre>
</div>
<div class="console">
<pre>mdadm --zero-superblock /dev/sdd
</pre>
</div>
<p><em>* где диски <strong>/dev/sdb</strong>, <strong>/dev/sdc</strong>, <strong>/dev/sdd</strong> были частью массива md0.</em></p>
<p>А также удаляем метаданные и подпись:</p>
<div class="console">
<pre>wipefs --all --force /dev/sd{b,c,d}
</pre>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[RAID]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/06/543d745cvmLAq4MFLaKZHjek.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%ba%d0%b0%d0%ba-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%b0%d1%82%d1%8c-%d1%81-lvm/</link>
					<title><![CDATA[Как работать с LVM]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jun 2025 12:14:49 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="481" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/scale_1200.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Как работать с LVM</h1>
													</header>
													<p>В статье описаны основные моменты использования LVM для организации дисковой системы в Linux. Она поможет как чайникам разобраться с принципами ее работы, так и уже знающим LVM в качестве шпаргалки.</p>
<p>Используемые команды одинаково подойдут как для систем Red Hat / CentOS, так и Debian / Ubuntu.</p>
<h2 id="level">Уровни абстракции</h2>
<p>Работа с томами с помощью LVM происходит на 3-х уровнях абстракции:</p>
<ol>
<li>Физический уровень (<strong>PV</strong>). Сначала диск инициализируется командой <strong>pvcreate</strong> — в начале диска создается дескриптор группы томов. При этом важно заметить, что диск не обязательно должен быть физическим — мы можно отметить на использование обычный раздел диска.</li>
<li>Группа томов (<strong>VG</strong>). С помощью команды <strong>vgcreate</strong> создается группа томов из инициализированных на предыдущем этапе дисков.</li>
<li>Логический том (<strong>LV</strong>). Группы томов нарезаются на логические тома командой <strong>lvcreate</strong>.</li>
</ol>
<p>Схематично, уровни можно представить так:</p>
<p><img decoding="async" title="Схематичное представление уровней абстракции LVM" src="https://www.dmosk.ru/img/miniinstruktions/lvm-01.jpg" alt="Схематичное представление уровней абстракции LVM" /></p>
<h2 id="install">Установка</h2>
<p>Для работы с LVM необходима установка одноименной утилиты. В системе Linux  она может быть установлена по умолчанию. Но если ее нет, выполняем инструкцию ниже.</p>
<p>Если используем системы на безе deb (Ubuntu, Debian, Mint):</p>
<div class="console">
<pre>apt-get install lvm2
</pre>
</div>
<p>Если используем системы на безе RPM (Red Hat, CentOS, Fedora):</p>
<div class="console">
<pre>yum install lvm2
</pre>
</div>
<h2 id="create">Создание разделов</h2>
<p>Рассмотрим пример создания томов из дисков sdb и sdc с помощью LVM.</p>
<h3 id="create-pv">1. Инициализация</h3>
<p>Помечаем диски, что они будут использоваться для LVM:</p>
<div class="console">
<pre>pvcreate /dev/sdb /dev/sdc
</pre>
</div>
<p><em>* напомним, что в качестве примера нами используются диски <strong>sdb</strong> и <strong>sdc</strong>.</em></p>
<p>Посмотреть, что диск может использоваться LMV можно командой:</p>
<div class="console">
<pre>pvdisplay
</pre>
</div>
<p>В нашем случае мы должны увидеть что-то на подобие:</p>
<div class="console-like">
<pre>"/dev/sdb" is a new physical volume of "1,00 GiB"
--- NEW Physical volume ---
PV Name               /dev/sdb
VG Name
PV Size               1,00 GiB
Allocatable           NO
PE Size               0
Total PE              0
Free PE               0
Allocated PE          0
PV UUID               rR8qya-eJes-7AC5-wuxv-CT7a-o30m-bnUrWa

"/dev/sdc" is a new physical volume of "1,00 GiB"
--- NEW Physical volume ---
PV Name               /dev/sdc
VG Name
PV Size               1,00 GiB
Allocatable           NO
PE Size               0
Total PE              0
Free PE               0
Allocated PE          0
PV UUID               2jIgFd-gQvH-cYkf-9K7N-M7cB-WWGE-9dzHIY
</pre>
</div>
<p><em>* где </em></p>
<ul>
<li><em><strong>PV Name</strong> — имя диска. </em></li>
<li><em><strong>VG Name</strong> — группа томов, в которую входит данный диск (в нашем случае пусто, так как мы еще не добавили его в группу).</em></li>
<li><em><strong>PV Size</strong> — размер диска.</em></li>
<li><em><strong>Allocatable</strong> — распределение по группам. Если NO, то диск еще не задействован и его необходимо для использования включить в группу.</em></li>
<li><em><strong>PE Size</strong> — размер физического фрагмента (экстента). Пока диск не добавлен в группу, значение будет 0.</em></li>
<li><em><strong>Total PE</strong> — количество физических экстентов.</em></li>
<li><em><strong>Free PE</strong> — количество свободных физических экстентов.</em></li>
<li><em><strong>Allocated PE</strong> — распределенные экстенты.</em></li>
<li><em><strong>PV UUID</strong> — идентификатор физического раздела.</em></li>
</ul>
<h3 id="create-vg">2. Создание групп томов</h3>
<p>Инициализированные на первом этапе диски должны быть объединены в группы.</p>
<p>Группа может быть создана:</p>
<div class="console">
<pre>vgcreate vg01 /dev/sdb /dev/sdc
</pre>
</div>
<p><em>* где <strong>vg01</strong> — произвольное имя создаваемой группы; <strong>/dev/sdb, /dev/sdc</strong> — наши диски.</em></p>
<p>Просмотреть информацию о созданных группах можно командой:</p>
<div class="console">
<pre>vgdisplay
</pre>
</div>
<p>На что мы получим, примерно, следующее:</p>
<div class="console">
<pre>--- Volume group ---
VG Name               vg01
System ID
Format                lvm2
Metadata Areas        2
Metadata Sequence No  1
VG Access             read/write
VG Status             resizable
MAX LV                0
Cur LV                0
Open LV               0
Max PV                0
Cur PV                2
Act PV                2
VG Size               1,99 GiB
PE Size               4,00 MiB
Total PE              510
Alloc PE / Size       0 / 0
Free  PE / Size       510 / 1,99 GiB
VG UUID               b0FAUz-wlXt-Hzqz-Sxs4-oEgZ-aquZ-jLzfKz
</pre>
</div>
<p><em>* где:</em></p>
<ul>
<li><em><strong>VG Name</strong> — имя группы.</em></li>
<li><em><strong>Format</strong> — версия подсистемы, используемая для создания группы.</em></li>
<li><em><strong>Metadata Areas</strong> — область размещения метаданных. Увеличивается на единицу с созданием каждой группы.</em></li>
<li><em><strong>VG Access</strong> — уровень доступа к группе томов.</em></li>
<li><em><strong>VG Size</strong> — суммарный объем всех дисков, которые входят в группу.</em></li>
<li><em><strong>PE Size</strong> — размер физического фрагмента (экстента).</em></li>
<li><em><strong>Total PE</strong> — количество физических экстентов.</em></li>
<li><em><strong>Alloc PE / Size</strong> — распределенное пространство: колическтво экстентов / объем.</em></li>
<li><em><strong>Free  PE / Size</strong> — свободное пространство: колическтво экстентов / объем.</em></li>
<li><em><strong>VG UUID</strong> — идентификатор группы.</em></li>
</ul>
<h3 id="create-lv">3. Создание логических томов</h3>
<p>Последний этап — создание логического раздела из группы томов командой lvcreate. Ее синтаксис:</p>
<div class="console">
<pre>lvcreate [опции] &lt;имя группы томов&gt;
</pre>
</div>
<p>Примеры создания логических томов:</p>
<pre>lvcreate -L 1G vg01</pre>
<p><em>* создание тома на <strong>1 Гб</strong> из группы <strong>vg01</strong>.</em></p>
<pre>lvcreate -L50 -n lv01 vg01</pre>
<p><em>* создание тома с именем <strong>lv01</strong> на <strong>50 Мб</strong> из группы <strong>vg01</strong>.</em></p>
<div class="console">
<pre>lvcreate -l 40%VG vg01
</pre>
</div>
<p><em>* при создании тома используется <strong>40%</strong> от дискового пространства группы <strong>vg01</strong>.</em></p>
<div class="console">
<pre>lvcreate -l 100%FREE -n lv01 vg01
</pre>
</div>
<p><em>* использовать все свободное пространство группы <strong>vg01</strong> при создании логического тома.<br />
* также можно использовать <strong>%PVS</strong> — процент места от физического тома (PV); <strong>%ORIGIN</strong> — размер оригинального тома (применяется для снапшотов).</em></p>
<p>Посмотрим информацию о созданном томе:</p>
<div class="console">
<pre>lvdisplay</pre>
</div>
<div class="console-like">
<pre><code>  --- Logical volume ---
LV Path                /dev/vg01/lv01
LV Name                lv01
VG Name                vg01
LV UUID                4nQ2rp-7AcZ-ePEQ-AdUr-qcR7-i4rq-vDISfD
LV Write Access        read/write
LV Creation host, time vln.dmosk.local, 2019-03-18 20:01:14 +0300
LV Status              available
# open                 0
LV Size                52,00 MiB
Current LE             13
Segments               1
Allocation             inherit
Read ahead sectors     auto
- currently set to     8192
Block device           253:2
</code></pre>
</div>
<p><em>* где:</em></p>
<ul>
<li><em><strong>LV Path</strong> — путь к устройству логического тома.</em></li>
<li><em><strong>LV Name</strong> — имя логического тома.</em></li>
<li><em><strong>VG Name</strong> — имя группы томов.</em></li>
<li><em><strong>LV UUID</strong> — идентификатор.</em></li>
<li><em><strong>LV Write Access</strong> — уровень доступа.</em></li>
<li><em><strong>LV Creation host, time</strong> — имя компьютера и дата, когда был создан том.</em></li>
<li><em><strong>LV Size</strong> — объем дискового пространства, доступный для использования.</em></li>
<li><em><strong>Current LE</strong> — количество логических экстентов.</em></li>
</ul>
<h2 id="fs">Создание файловой системы и монтирование тома</h2>
<p>Чтобы начать использовать созданный том, необходимо его отформатировать, создав файловую систему и примонтировать раздел в каталог.</p>
<h3 id="fs-format">Файловая система</h3>
<p>Процесс создания файловой системы на томах LVM ничем не отличается от работы с любыми другими разделами.</p>
<p>Например, для создания файловой системы ext4 вводим:</p>
<div class="console">
<pre>mkfs.ext4 /dev/vg01/lv01
</pre>
</div>
<p><em>* <strong>vg01</strong> — наша группа томов; <strong>lv01</strong> — логический том.</em></p>
<p>Для создания, например, файловой системы xfs вводим:</p>
<div class="console">
<pre>mkfs.xfs /dev/vg01/lv01
</pre>
</div>
<h3 id="fs-mount">Монтирование</h3>
<p>Как и в случае с файловой системой, процесс монтирования не сильно отличается от разделов, созданных другими методами.</p>
<p>Для разового монтирования пользуемся командой:</p>
<div class="console">
<pre>mount /dev/vg01/lv01 /mnt
</pre>
</div>
<p><em>* где <strong>/dev/vg01/lv01</strong> — созданный нами логический том, <strong>/mnt</strong> — раздел, в который мы хотим примонтировать раздел.</em></p>
<p>Для постоянного монтирования раздела добавляем строку в fstab:</p>
<div class="console">
<pre>vi /etc/fstab
/dev/vg01/lv01  /mnt    ext4    defaults        1 2</pre>
</div>
<p><em>* в данном примере мы монтируем при загрузке системы том <strong>/dev/vg01/lv01</strong> в каталог <strong>/mnt</strong>; используется файловая система <strong>ext4</strong>.</em></p>
<p>Проверяем настройку fstab, смонтировав раздел:</p>
<div class="console">
<pre>mount -a
</pre>
</div>
<p>Проверяем, что диск примонтирован:</p>
<div class="console">
<pre>df -hT
</pre>
</div>
<h2 id="show">Просмотр информации</h2>
<p>Разберемся, как получить информацию о дисковых накопителях в системе.</p>
<p>1. Для общего представления дисков, разделов и томов вводим:</p>
<div class="console">
<pre>lsblk
</pre>
</div>
<p>Мы получим что-то на подобие:</p>
<div class="console-like">
<pre>NAME             MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
sda                8:0    0   30G  0 disk
sda1             8:1    0    1G  0 part /boot
sda2             8:2    0   29G  0 part
sys-root     253:0    0   27G  0 lvm  /
sys-swap     253:1    0    2G  0 lvm  [SWAP]
sdb                8:16   0    1G  0 disk
vg01-lv01-real 253:3    0    1G  0 lvm
vg01-lv01    253:2    0    1G  0 lvm  /mnt
vg01-sn01    253:5    0    1G  0 lvm
sdc                8:32   0    1G  0 disk
vg01-lv01-real 253:3    0    1G  0 lvm
vg01-lv01    253:2    0    1G  0 lvm  /mnt
vg01-sn01    253:5    0    1G  0 lvm
vg01-sn01-cow  253:4    0  500M  0 lvm
vg01-sn01    253:5    0    1G  0 lvm
sdd                8:48   0    1G  0 disk
</pre>
</div>
<p><em>* как видим, команда отображает корневое блочное устройство, какие разделы из него сделаны и в какие логические тома организованы из некоторых из разделов.</em></p>
<p>2. Получить информацию о проинициализированных для LVM дисков:</p>
<p>Кратко:</p>
<div class="console">
<pre>pvs
</pre>
</div>
<p>Подробно:</p>
<div class="console">
<pre>pvdisplay</pre>
</div>
<div class="console">
<pre>pvdisplay /dev/sdb
</pre>
</div>
<p>3. Посмотреть информацию о группах LVM.</p>
<p>Кратко:</p>
<div class="console">
<pre>vgs
</pre>
</div>
<p>Подробно:</p>
<div class="console">
<pre>vgdisplay</pre>
</div>
<div class="console">
<pre>vgdisplay vg01
</pre>
</div>
<p>4. Посмотреть информацию о логических томах можно также двумя способами — краткая информация:</p>
<div class="console">
<pre>lvs
</pre>
</div>
<p><em>* команда покажет все логические разделы.</em></p>
<p>Для более подробной информации о логических томах вводим:</p>
<div class="console">
<pre>lvdisplay</pre>
</div>
<div class="console">
<pre>lvdisplay /dev/vg01/lv01
</pre>
</div>
<p>5. Для поиска всех устройств, имеющих отношение к LVM, вводим:</p>
<div class="console">
<pre>lvmdiskscan
</pre>
</div>
<h2 id="resizeup">Увеличение томов</h2>
<p>Увеличение размера тома может выполняться с помощью добавления еще одного диска или при увеличении имеющихся дисков (например, увеличение диска виртуальной машины). Итак, процедура выполняется в 4 этапа:</p>
<h3 id="resizeup-pvextend">1. Расширение физического тома</h3>
<p>Расширение физического раздела можно сделать за счет добавление нового диска или увеличение дискового пространства имеющегося (например, если диск виртуальный).</p>
<p>а) Если добавляем еще один диск.</p>
<p>Инициализируем новый диск:</p>
<div class="console">
<pre>pvcreate /dev/sdd
</pre>
</div>
<p><em>* в данном примере мы инициализировали диск <strong>sdd</strong>.</em></p>
<p>Проверяем объем физического тома:</p>
<div class="console">
<pre>pvdisplay
</pre>
</div>
<p>б) Если увеличиваем дисковое пространство имеющегося диска.</p>
<p>Увеличиваем размер физического диска командой:</p>
<div class="console">
<pre>pvresize /dev/sda
</pre>
</div>
<p><em>* где <strong>/dev/sda</strong> — диск, который был увеличен.</em></p>
<p>Проверяем объем физического тома:</p>
<div class="console">
<pre>pvdisplay
</pre>
</div>
<h3 id="resizeup-vgextend">2. Добавление нового диска к группе томов</h3>
<p>Независимо от способа увеличения физического тома, расширяем группу томов командой:</p>
<div class="console">
<pre>vgextend vg01 /dev/sdd
</pre>
</div>
<p><em>* данная команда расширит группу <strong>vg01</strong> за счет добавленого или расширенного диска <strong>sdd</strong>.</em></p>
<p>Результат можно увидеть командой:</p>
<div class="console">
<pre>vgdisplay
</pre>
</div>
<h3 id="resizeup-lvextend">3. Увеличение логического раздела</h3>
<p>Выполняется одной командой.</p>
<p><strong>а) все свободное пространство:</strong></p>
<div class="console">
<pre>lvextend -l +100%FREE /dev/vg01/lv01
</pre>
</div>
<p><em>* данной командой мы выделяем все свободное пространство группы томов <strong>vg01</strong> разделу <strong>lv01</strong>.</em></p>
<blockquote><p>Также можно использовать опцию -r, которая укажет программе сразу расширить файловую систему:</p>
<div class="console">
<pre>lvextend -r -l +100%FREE /dev/vg01/lv01
</pre>
</div>
</blockquote>
<p><strong>б) определенный объем:</strong></p>
<div class="console">
<pre>lvextend -L+30G /dev/vg01/lv01
</pre>
</div>
<p><em>* данной командой мы добавляем 30 Гб от группы томов <strong>vg01</strong> разделу <strong>lv01</strong>.</em></p>
<p><strong>в) до нужного объема:</strong></p>
<div class="console">
<pre>lvextend -L500G /dev/vg01/lv01
</pre>
</div>
<p><em>* данной командой мы доводим наш раздел до объема в 500 Гб.</em></p>
<p>Результат можно увидеть командой:</p>
<div class="console">
<pre>lvdisplay
</pre>
</div>
<p>Обратить внимание нужно на опцию <strong>LV Size</strong>:</p>
<div class="console-like">
<pre>...
LV Status              available
# open                 1
LV Size                &lt;2,99 GiB
Current LE             765
...
</pre>
</div>
<h3 id="resizeup-fs">4. Увеличение размера файловой системы</h3>
<p>Чтобы сама система увидела больший объем дискового пространства, необходимо увеличить размер файловой системы.</p>
<p>Посмотреть используемую файловую систему:</p>
<div class="console">
<pre>df -T
</pre>
</div>
<p>Для каждой файловой системы существуют свои инструменты.</p>
<p><strong>ext2/ext3/ext4:</strong></p>
<div class="console">
<pre>resize2fs /dev/vg01/lv01
</pre>
</div>
<p><strong>XFS:</strong></p>
<div class="console">
<pre>xfs_growfs /dev/vg01/lv01
</pre>
</div>
<p><strong>Reiserfs:</strong></p>
<div class="console">
<pre>resize_reiserfs /dev/vg01/lv01
</pre>
</div>
<h2 id="resizedown">Уменьшение томов</h2>
<div class="note">
<p>Размер некоторый файловых систем, например, XFS уменьшить нельзя. Из положения можно выйти, создав новый уменьшенный том с переносом на него данных и последующим удалением.</p>
</div>
<p>LVM также позволяет уменьшить размер тома. Для этого необходимо выполнить его отмонтирование, поэтому для уменьшения системного раздела безопаснее всего загрузиться с Linux LiveCD. Далее выполняем инструкцию ниже.</p>
<p>Отмонтируем раздел, который нужно уменьшить:</p>
<div class="console">
<pre>umount /mnt
</pre>
</div>
<p>Выполняем проверку диска:</p>
<div class="console">
<pre>e2fsck -fy /dev/vg01/lv01
</pre>
</div>
<p>Уменьшаем размер файловой системы:</p>
<div class="console">
<pre>resize2fs /dev/vg01/lv01 500M
</pre>
</div>
<p>Уменьшаем размер тома:</p>
<div class="console">
<pre>lvreduce -L-500 /dev/vg01/lv01
</pre>
</div>
<p>На предупреждение системы отвечаем y:</p>
<div class="console-like">
<pre>  WARNING: Reducing active logical volume to 524,00 MiB.
THIS MAY DESTROY YOUR DATA (filesystem etc.)
Do you really want to reduce vg01/lv01? [y/n]: y
</pre>
</div>
<p>Готово.</p>
<div class="note">
<p>Очень важно, чтобы сначала был уменьшен размер файловой системы, затем тома. Также важно не уменьшить размер тома больше, чем файловой системы. В противном случае данные могут быть уничтожены. Перед выполнением операции, обязательно создаем копию важных данных.</p>
</div>
<h2 id="delete">Удаление томов</h2>
<p>Если необходимо полностью разобрать LVM тома, выполняем следующие действия.</p>
<p>Отмонтируем разделы:</p>
<div class="console">
<pre>umount /mnt
</pre>
</div>
<p><em>* где <strong>/mnt</strong> — точка монтирования для раздела.</em></p>
<p>Удаляем соответствующую запись из fstab (в противном случае наша система может не загрузиться после перезагрузки):</p>
<div class="console">
<pre>vi /etc/fstab</pre>
</div>
<div class="editor">
<pre>#/dev/vg01/lv01  /mnt    ext4    defaults        1 2
</pre>
</div>
<p><em>* в данном примере мы не удалили, а закомментировали строку монтирования диска.</em></p>
<p>Смотрим информацию о логичеких томах:</p>
<div class="console">
<pre>lvdisplay
</pre>
</div>
<p>Теперь удаляем логический том:</p>
<div class="console">
<pre>lvremove /dev/vg01/lv01
</pre>
</div>
<p>На вопрос системы, действительно ли мы хотим удалить логических том, отвечаем да (<strong>y</strong>):</p>
<div class="console-like">
<pre>Do you really want to remove active logical volume vg01/lv01? [y/n]: <strong>y</strong>
</pre>
</div>
<p><em>* если система вернет ошибку <strong>Logical volume contains a filesystem in use</strong>, необходимо убедиться, что мы отмонтировали том.</em></p>
<p>Смотрим информацию о группах томов:</p>
<div class="console">
<pre>vgdisplay
</pre>
</div>
<p>Удаляем группу томов:</p>
<div class="console">
<pre>vgremove vg01
</pre>
</div>
<p>Убираем пометку с дисков на использование их для LVM:</p>
<div class="console">
<pre>pvremove /dev/sd{b,c,d}
</pre>
</div>
<p><em>* в данном примере мы деинициализируем диски <strong>/dev/sdb, /dev/sdc, /dev/sdd</strong>.</em></p>
<p>В итоге мы получим:</p>
<div class="console-like">
<pre>Labels on physical volume "/dev/sdb" successfully wiped.
Labels on physical volume "/dev/sdc" successfully wiped.
Labels on physical volume "/dev/sdd" successfully wiped.
</pre>
</div>
<h2 id="mirror">Создание зеркала</h2>
<p>С помощью LVM мы может создать зеркальный том — данные, которые мы будем на нем сохранять, будут отправляться на 2 диска. Таким образом, если один из дисков выходит из строя, мы не потеряем свои данные.</p>
<p>Зеркалирование томов выполняется из группы, где есть, минимум, 2 диска.</p>
<p>1. Сначала инициализируем диски:</p>
<div class="console">
<pre>pvcreate /dev/sd{d,e}
</pre>
</div>
<p><em>* в данном примере <strong>sdd</strong> и <strong>sde</strong>.</em></p>
<p>2. Создаем группу:</p>
<div class="console">
<pre>vgcreate vg02 /dev/sd{d,e}
</pre>
</div>
<p>3. Создаем зеркальный том:</p>
<div class="console">
<pre>lvcreate -L200 -m1 -n lv-mir vg02
</pre>
</div>
<p><em>* мы создали том <strong>lv-mir</strong> на 200 Мб из группы <strong>vg02</strong>.</em></p>
<p>В итоге:</p>
<div class="console">
<pre>lsblk
</pre>
</div>
<p>&#8230; мы увидим что-то на подобие:</p>
<div class="console-like">
<pre>sdd                       8:16   0    1G  0 disk
vg02-lv--mir_rmeta_0  253:2    0    4M  0 lvm
vg02-lv--mir        253:6    0  200M  0 lvm
vg02-lv--mir_rimage_0 253:3    0  200M  0 lvm
vg02-lv--mir        253:6    0  200M  0 lvm
sde                       8:32   0    1G  0 disk
vg02-lv--mir_rmeta_1  253:4    0    4M  0 lvm
vg02-lv--mir        253:6    0  200M  0 lvm
vg02-lv--mir_rimage_1 253:5    0  200M  0 lvm
vg02-lv--mir        253:6    0  200M  0 lvm
</pre>
</div>
<p><em>* как видим, на двух дисках у нас появились разделы по 200 Мб.</em></p>
<h2 id="snapshot">Работа со снапшотами</h2>
<p>Снимки диска позволят нам откатить состояние на определенный момент. Это может послужить быстрым вариантом резервного копирования. Однако нужно понимать, что данные хранятся на одном и том же физическом носителе, а значит, данный способ не является полноценным резервным копированием.</p>
<p>Создание снапшотов для тома, где уже используется файловая система XFS, имеет некоторые нюансы, поэтому разберем разные примеры.</p>
<p>Создание для <strong>не</strong> XFS:</p>
<div class="console">
<pre>lvcreate -L500 -s -n sn01 /dev/vg01/lv01
</pre>
</div>
<p><em>* данная команда помечает, что <strong>500 </strong>Мб дискового пространства устройства <strong>/dev/vg01/lv01</strong> (тома lv01 группы vg01) будет использоваться для snapshot (опция <strong>-s</strong>).</em></p>
<p>Создание для XFS:</p>
<div class="console">
<pre>xfs_freeze -f /mnt; lvcreate -L500 -s -n sn01 /dev/vg01/lv01; xfs_freeze -u /mnt
</pre>
</div>
<p><em>* команда xfs_freeze замораживает операции в файловой системе XFS.</em></p>
<p>Посмотрим список логических томов:</p>
<div class="console">
<pre>lvs
</pre>
</div>
<p>Получим что-то на подобие:</p>
<div class="console-like">
<pre>LV   VG   Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
lv01 vg01 owi-aos---   1,00g
sn01 vg01 swi-a-s--- 500,00m      lv01   2,07
</pre>
</div>
<p><em>* поле <strong>Origin</strong> показывает, к какому оригинальному логическому тому относится LV, например, в данной ситуации наш раздел для снапшотов относится к <strong>lv01</strong>.</em></p>
<p>Также можно посмотреть изменения в томах командой:</p>
<div class="console">
<pre>lsblk
</pre>
</div>
<p>Мы должны увидеть что-то подобное:</p>
<div class="console-like">
<pre>sdc                8:32   0    1G  0 disk
vg01-lv01-real 253:3    0    1G  0 lvm
vg01-lv01    253:2    0    1G  0 lvm  /mnt
vg01-sn01    253:5    0    1G  0 lvm
vg01-sn01-cow  253:4    0  500M  0 lvm
vg01-sn01    253:5    0    1G  0 lvm
</pre>
</div>
<p>С этого момента все изменения пишутся в vg01-sn01-cow, а vg01-lv01-real фиксируется только для чтения и мы может откатиться к данному состоянию диска в любой момент.</p>
<p>Содержимое снапшота можно смонтировать и посмотреть, как обычный раздел:</p>
<div class="console">
<pre>mkdir /tmp/snp
</pre>
</div>
<p>Монтирование <strong>не</strong> XFS:</p>
<div class="console">
<pre>mount /dev/vg01/sn01 /tmp/snp
</pre>
</div>
<p>Монтирование XFS:</p>
<div class="console">
<pre>mount -o nouuid,ro /dev/vg01/sn01 /tmp/snp
</pre>
</div>
<p>Для выполнения отката до снапшота, выполняем команду:</p>
<div class="console">
<pre>lvconvert --merge /dev/vg01/sn01
</pre>
</div>
<h2 id="import">Импорт диска из другой системы</h2>
<p>Если мы перенесли LVM-диск с другого компьютера или виртуальной машины и хотим подключить его без потери данных, то нужно импортировать том.</p>
<p>Если есть возможность, сначала нужно на старом компьютере отмонтировать том и сделать его экспорт:</p>
<div class="console">
<pre>umount /mnt
</pre>
</div>
<p><em>* предположим, что диск примонтирован в <strong>/mnt</strong>.</em></p>
<p>Деактивируем группу томов:</p>
<div class="console">
<pre>vgchange -an vg_test
</pre>
</div>
<p><em>* в данном примере наша группа называется <strong>vg_test</strong>.</em></p>
<p>Делаем экспорт:</p>
<div class="console">
<pre>vgexport vg_test
</pre>
</div>
<p>После переносим диск на новый компьютер.</p>
<p>На новой системе сканируем группы LVM следующей командой:</p>
<div class="console">
<pre>pvscan
</pre>
</div>
<p>&#8230; система отобразит все LVM-тома (подключенные и нет), например:</p>
<div class="console-like">
<pre>  PV /dev/sdb    VG vg_test         lvm2 [1020,00 MiB / 0    free]
PV /dev/sda5   VG ubuntu-vg       lvm2 [11,52 GiB / 0    free]
Total: 2 [12,52 GiB] / in use: 2 [12,52 GiB] / in no VG: 0 [0   ]
</pre>
</div>
<p><em>* в данном примере найдено два диска с томами LVM — <strong>/dev/sdb</strong> (группа <strong>vg_test</strong>) и <strong>/dev/sda5</strong> (группа <strong>ubuntu-vg</strong>).</em></p>
<p>В моем примере новый диск с группой vg_test — будум импортировать его. Вводим команду:</p>
<div class="console">
<pre>vgimport vg_test
</pre>
</div>
<p>Возможны два варианта ответа:</p>
<p>1) если мы экспортировали том:</p>
<div class="console-like">
<pre>Volume group "vg_test" successfully imported
</pre>
</div>
<p>2) если не экспортировали:</p>
<div class="console-like">
<pre>Volume group "vg_test" is not exported
</pre>
</div>
<p>Так или иначе, группа томов должна появиться в нашей системе — проверяем командой:</p>
<div class="console">
<pre>vgdisplay
</pre>
</div>
<p>&#8230; мы должны увидеть что-то на подобие:</p>
<div class="console-like">
<pre>--- Volume group ---
VG Name               vg_test
System ID
Format                lvm2
...
</pre>
</div>
<p>Активируем его:</p>
<div class="console">
<pre>vgchange -ay vg_test
</pre>
</div>
<p>Готово. Для монтирования раздела, смотрим его командой:</p>
<div class="console">
<pre>lvdisplay
</pre>
</div>
<p>&#8230; и монтируем в нужный каталог, например:</p>
<div class="console">
<pre>mount /dev/vg_test/lvol0 /mnt
</pre>
</div>
<p><em>* в данном примере мы примонтируем раздел <strong>lvol0</strong> в группе томов <strong>vg_test</strong> к каталогу <strong>/mnt</strong>.</em></p>
<h2 id="windows">Работа с LVM из под Windows</h2>
<p>По умолчанию, система Windows не умеет работать с томами LVM. Для реализации такой возможности, необходимо установить утилиту <a href="http://www.chrysocome.net/virtualvolumes" target="_blank" rel="noopener">Virtual Volumes</a>.</p>
<div class="note">
<p>На данный момент на сайте разработчика имеется предупреждение, что программное обеспечение на тестировании и его не следует применять для разделов, где есть важные данные без резервных копий. В противном случае, данные можно потерять.</p>
</div>
<h2 id="errors">Возможные ошибки</h2>
<p>Рассмотрим ошибки, с которыми можно столкнуться при работе с LVM.</p>
<h3>Device /dev/sdX excluded by a filter</h3>
<p>Данную ошибку можно встретить при попытке инициализировать диск командой <strong>pvcreate</strong>.</p>
<p><strong>Причина:</strong> либо диск не полностью чист, либо раздел не имеет нужный тип.</p>
<p><strong>Решение:</strong> в зависимости от типа проблемы, рассмотрим 2 варианта.</p>
<p><strong>а) если добавляем целый диск.</strong></p>
<p>Удаляем все метаданные с диска командой:</p>
<div class="console">
<pre>wipefs -a /dev/sdX
</pre>
</div>
<p><em>* где вместо X (или sdX) подсталвляем имя диска.</em></p>
<p><strong>б) если добавляем раздел.</strong></p>
<p>Открываем диск с помощью команды fdisk:</p>
<div class="console">
<pre>fdisk /dev/sdX
</pre>
</div>
<p><em>* где вместо X (или sdX) подсталвляем имя диска.</em></p>
<p>Смотрим список созданных на диске разделов:</p>
<div class="console">
<pre>: p
</pre>
</div>
<p>Задаем тип раздела:</p>
<div class="console">
<pre>: t
</pre>
</div>
<p>Выбираем номер раздела (например, раздел номер 3):</p>
<div class="console">
<pre>: 3
</pre>
</div>
<p>Командой L можно посмотреть список всех типов, но нас интересует конкретный — LVM (8e):</p>
<div class="console">
<pre>: 8e
</pre>
</div>
<p>Сохраняем настройки:</p>
<div class="console">
<pre>: w
</pre>
<p>Источник: <a href="https://www.dmosk.ru/instruktions.php?object=lvm#create">dmosk.ru</a></p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[LVM]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/06/scale_1200.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b0-%d1%84%d0%b0%d0%b9%d0%bb%d0%be%d0%b2-%d0%bd%d0%b0-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-php/</link>
					<title><![CDATA[Загрузка файлов на сервер PHP]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jun 2025 11:31:27 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="500" height="300" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/4a8bbfe6ef3a935e4e92fe068ffd630d.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Загрузка файлов на сервер PHP</h1>
													</header>
													<div class="clearfix">
<p>В статье приведен пример формы и php-скрипта для безопасной загрузки файлов на сервер, возможные ошибки и рекомендации при работе с данной темой.</p>
<p>HTML-форма отправит файл только методом POST и с атрибутом <code class="code-attr">enctype="multipart/form-data"</code>.</p>
</div>
<div class="block_code">
<pre><code class="html hljs language-xml">    
    &lt;form action="/upload.php" enctype="multipart/form-data" method="post"&gt;
        &lt;input name="file" type="file" /&gt; &lt;input type="submit" value="Отправить" /&gt;
    &lt;/form&gt;
</code></pre>
</div>
<p id="title-6239">Форма для загрузки сразу нескольких файлов</p>
<pre><code class="html hljs language-xml">    
    &lt;form action="/upload.php" enctype="multipart/form-data" method="post"&gt;
        &lt;input type="file" name="file[]" multiple /&gt; &lt;input type="submit" value="Отправить" /&gt;
    &lt;/form&gt;
</code></pre>
<h4 id="title-6245">Файл upload.php</h4>
<ul>
<li>Поддерживает как одиночную загрузку файла так и множественную (multiple) без изменения кода.</li>
<li>Проверка на все возможные ошибки которые могут возникнуть при загрузке файлов.</li>
<li>Имена файлов переводятся в транслит и удаляются символы которые будут в дальнейшем мешать вывести их на сайте.</li>
<li>Есть возможность указать разрешенные и запрещенные для загрузки расширения файлов.</li>
</ul>
<div class="block_code">
<pre><code class="php hljs language-php">
// Название 
$input_name = 'file';
 
// Разрешенные расширения файлов.
$allow = array();
 
// Запрещенные расширения файлов.
$deny = array(
	'phtml', 'php', 'php3', 'php4', 'php5', 'php6', 'php7', 'phps', 'cgi', 'pl', 'asp', 
	'aspx', 'shtml', 'shtm', 'htaccess', 'htpasswd', 'ini', 'log', 'sh', 'js', 'html', 
	'htm', 'css', 'sql', 'spl', 'scgi', 'fcgi'
);
 
// Директория куда будут загружаться файлы.
$path = __DIR__ . '/uploads/';
 
if (isset($_FILES[$input_name])) {
	// Проверим директорию для загрузки.
	if (!is_dir($path)) {
		mkdir($path, 0777, true);
	}
 
	// Преобразуем массив $_FILES в удобный вид для перебора в foreach.
	$files = array();
	$diff = count($_FILES[$input_name]) - count($_FILES[$input_name], COUNT_RECURSIVE);
	if ($diff == 0) {
		$files = array($_FILES[$input_name]);
	} else {
		foreach($_FILES[$input_name] as $k =&gt; $l) {
			foreach($l as $i =&gt; $v) {
				$files[$i][$k] = $v;
			}
		}		
	}	
	
	foreach ($files as $file) {
		$error = $success = '';
 
		// Проверим на ошибки загрузки.
		if (!empty($file['error']) || empty($file['tmp_name'])) {
			switch (@$file['error']) {
				case 1:
				case 2: $error = 'Превышен размер загружаемого файла.'; break;
				case 3: $error = 'Файл был получен только частично.'; break;
				case 4: $error = 'Файл не был загружен.'; break;
				case 6: $error = 'Файл не загружен - отсутствует временная директория.'; break;
				case 7: $error = 'Не удалось записать файл на диск.'; break;
				case 8: $error = 'PHP-расширение остановило загрузку файла.'; break;
				case 9: $error = 'Файл не был загружен - директория не существует.'; break;
				case 10: $error = 'Превышен максимально допустимый размер файла.'; break;
				case 11: $error = 'Данный тип файла запрещен.'; break;
				case 12: $error = 'Ошибка при копировании файла.'; break;
				default: $error = 'Файл не был загружен - неизвестная ошибка.'; break;
			}
		} elseif ($file['tmp_name'] == 'none' || !is_uploaded_file($file['tmp_name'])) {
			$error = 'Не удалось загрузить файл.';
		} else {
			// Оставляем в имени файла только буквы, цифры и некоторые символы.
			$pattern = "[^a-zа-яё0-9,~!@#%^-_\$\?\(\)\{\}\[\]\.]";
			$name = mb_eregi_replace($pattern, '-', $file['name']);
			$name = mb_ereg_replace('[-]+', '-', $name);
			
			// Т.к. есть проблема с кириллицей в названиях файлов (файлы становятся недоступны).
			// Сделаем их транслит:
			$converter = array(
				'а' =&gt; 'a',   'б' =&gt; 'b',   'в' =&gt; 'v',    'г' =&gt; 'g',   'д' =&gt; 'd',   'е' =&gt; 'e',
				'ё' =&gt; 'e',   'ж' =&gt; 'zh',  'з' =&gt; 'z',    'и' =&gt; 'i',   'й' =&gt; 'y',   'к' =&gt; 'k',
				'л' =&gt; 'l',   'м' =&gt; 'm',   'н' =&gt; 'n',    'о' =&gt; 'o',   'п' =&gt; 'p',   'р' =&gt; 'r',
				'с' =&gt; 's',   'т' =&gt; 't',   'у' =&gt; 'u',    'ф' =&gt; 'f',   'х' =&gt; 'h',   'ц' =&gt; 'c',
				'ч' =&gt; 'ch',  'ш' =&gt; 'sh',  'щ' =&gt; 'sch',  'ь' =&gt; '',    'ы' =&gt; 'y',   'ъ' =&gt; '',
				'э' =&gt; 'e',   'ю' =&gt; 'yu',  'я' =&gt; 'ya', 
			
				'А' =&gt; 'A',   'Б' =&gt; 'B',   'В' =&gt; 'V',    'Г' =&gt; 'G',   'Д' =&gt; 'D',   'Е' =&gt; 'E',
				'Ё' =&gt; 'E',   'Ж' =&gt; 'Zh',  'З' =&gt; 'Z',    'И' =&gt; 'I',   'Й' =&gt; 'Y',   'К' =&gt; 'K',
				'Л' =&gt; 'L',   'М' =&gt; 'M',   'Н' =&gt; 'N',    'О' =&gt; 'O',   'П' =&gt; 'P',   'Р' =&gt; 'R',
				'С' =&gt; 'S',   'Т' =&gt; 'T',   'У' =&gt; 'U',    'Ф' =&gt; 'F',   'Х' =&gt; 'H',   'Ц' =&gt; 'C',
				'Ч' =&gt; 'Ch',  'Ш' =&gt; 'Sh',  'Щ' =&gt; 'Sch',  'Ь' =&gt; '',    'Ы' =&gt; 'Y',   'Ъ' =&gt; '',
				'Э' =&gt; 'E',   'Ю' =&gt; 'Yu',  'Я' =&gt; 'Ya',
			);
 
			$name = strtr($name, $converter);
			$parts = pathinfo($name);
 
			if (empty($name) || empty($parts['extension'])) {
				$error = 'Недопустимое тип файла';
			} elseif (!empty($allow) &amp;&amp; !in_array(strtolower($parts['extension']), $allow)) {
				$error = 'Недопустимый тип файла';
			} elseif (!empty($deny) &amp;&amp; in_array(strtolower($parts['extension']), $deny)) {
				$error = 'Недопустимый тип файла';
			} else {
				// Чтобы не затереть файл с таким же названием, добавим префикс.
				$i = 0;
				$prefix = '';
				while (is_file($path . $parts['filename'] . $prefix . '.' . $parts['extension'])) {
		  			$prefix = '(' . ++$i . ')';
				}
				$name = $parts['filename'] . $prefix . '.' . $parts['extension'];
 
				// Перемещаем файл в директорию.
				if (move_uploaded_file($file['tmp_name'], $path . $name)) {
					// Далее можно сохранить название файла в БД и т.п.
					$success = 'Файл «' . $name . '» успешно загружен.';
				} else {
					$error = 'Не удалось загрузить файл.';
				}
			}
		}
		
		// Выводим сообщение о результате загрузки.
		if (!empty($success)) {
			echo $success; 
                } else { echo $error; } } }</code></pre>
</div>
<h2>Возможные проблемы</h2>
<ul>
<li>На unix хостингах php функция <code class="code-attr">move_uploaded_file()</code> не будут перемещать файлы в директорию если у нее права меньше 777.</li>
<li>Загрузка файлов может быть отключена в настройках PHP директивой <code class="code-attr">file_uploads</code>.</li>
<li>Не загружаются файлы большого размера, причина в ограничениях хостинга.<br />
Посмотрите в <code class="code-attr">phpinfo()</code> значения директив:</p>
<ul>
<li><code class="code-attr">upload_max_filesize</code> – максимальный размер закачиваемого файла.</li>
<li><code class="code-attr">max_file_uploads</code> – максимальное количество одновременно закачиваемых файлов.</li>
<li><code class="code-attr">post_max_size</code> – максимально допустимый размер данных, отправляемых методом POST, его значение должно быть больше <code class="code-attr">upload_max_filesize</code>.</li>
<li><code class="code-attr">memory_limit</code> – значение должно быть больше чем <code class="code-attr">post_max_size</code>.</li>
</ul>
</li>
</ul>
<div class="snp_alert-warning">
<p>Не забудьте в директории куда помещаются загруженные файлы <a href="https://snipp.ru/htaccess/no-php">запретить выполнение PHP</a>.</p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[PHP]]></category><category><![CDATA[web-server]]></category><category><![CDATA[php]]></category><category><![CDATA[uploads]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/06/4a8bbfe6ef3a935e4e92fe068ffd630d.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/qemu-guest-agent/</link>
					<title><![CDATA[Qemu-guest-agent]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jun 2025 11:11:22 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="527" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/proxmox-qemu-guest-a.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Qemu-guest-agent</h1>
													</header>
													<h2>Введение — что такое qemu-guest-agent</h2>
<p>Qemu-guest-agent — это вспомогательный демон, который устанавливается в гостевой системе. Он используется для обмена информацией между хостом и гостевой системой, а также для выполнения команд в гостевой системе.</p>
<p>В Proxmox VE qemu-guest-agent используется в основном для трёх целей:</p>
<ol>
<li>Чтобы правильно завершить работу гостевой системы, не полагаясь на команды ACPI или политики Windows</li>
<li>Чтобы заморозить гостевую файловую систему при создании резервной копии/снимка (в Windows используйте службу теневого копирования томов VSS). Если гостевой агент включен и работает, он вызывает <i>guest-fsfreeze-freeze</i> и <i>guest-fsfreeze-thaw</i> для повышения согласованности.</li>
<li>На этапе возобновления работы гостевой (виртуальной) машины после паузы (например, после создания снимка состояния) она немедленно синхронизирует своё время с гипервизором с помощью qemu-guest-agent (в качестве первого шага).</li>
</ol>
<h2>Установка</h2>
<h3>Ведущий</h3>
<p>Вам нужно установить гостевой агент на каждую виртуальную машину, а затем включить его. Это можно сделать в веб-интерфейсе Proxmox VE (графический интерфейс)</p>
<p><a class="image" title="Опция гостевого агента QEMU" href="https://pve.proxmox.com/wiki/File:Proxmox_VE_-_QEMU_Guest_Agent_Option.png"><img loading="lazy" decoding="async" src="https://pve.proxmox.com/mediawiki/images/6/6d/Proxmox_VE_-_QEMU_Guest_Agent_Option.png" alt="Опция гостевого агента QEMU" width="700" height="500" /></a></p>
<p>или через CLI: <code>qm set VMID --agent 1</code></p>
<h3>Гость</h3>
<h4>Linux</h4>
<p>В Linux вам нужно просто установить qemu-guest-agent, пожалуйста, обратитесь к документации по вашей системе.</p>
<p>Здесь мы приводим команды для систем на базе Debian/Ubuntu и Redhat:</p>
<p>в системах на базе Debian/Ubuntu (с apt-get) выполните:</p>
<pre>apt-get установить qemu-guest-agent
</pre>
<p>а также в системах на базе Redhat (с yum):</p>
<pre>yum установить qemu-guest-agent
</pre>
<p>В зависимости от дистрибутива гостевой агент может не запуститься автоматически после установки.</p>
<p>Начните его либо непосредственно с</p>
<pre>systemctl запустить qemu-guest-agent
</pre>
<p>Затем включите автозапуск службы (на постоянной основе), если она не запускается автоматически.</p>
<pre>включить системный сервис qemu-guest-agent
</pre>
<p>(должно работать в большинстве дистрибутивов) или перезагрузите гостевую систему.</p>
<h4>Windows</h4>
<div class="thumb tright">
<div class="thumbinner">
<p><a class="image" href="https://pve.proxmox.com/wiki/File:Screen-vioserial-device-manager.png"><img loading="lazy" decoding="async" class="thumbimage" src="https://pve.proxmox.com/mediawiki/images/thumb/3/3f/Screen-vioserial-device-manager.png/300px-Screen-vioserial-device-manager.png" srcset="/mediawiki/images/thumb/3/3f/Screen-vioserial-device-manager.png/450px-Screen-vioserial-device-manager.png 1.5x, /mediawiki/images/thumb/3/3f/Screen-vioserial-device-manager.png/600px-Screen-vioserial-device-manager.png 2x" alt="Экран-менеджер устройств.png" width="300" height="218" /></a></p>
<div class="thumbcaption">
<div class="magnify"></div>
</div>
</div>
</div>
<div class="thumb tright">
<div class="thumbinner">
<p><a class="image" href="https://pve.proxmox.com/wiki/File:Screen-vioserial-driver.png"><img loading="lazy" decoding="async" class="thumbimage" src="https://pve.proxmox.com/mediawiki/images/thumb/f/f3/Screen-vioserial-driver.png/300px-Screen-vioserial-driver.png" srcset="/mediawiki/images/thumb/f/f3/Screen-vioserial-driver.png/450px-Screen-vioserial-driver.png 1.5x, /mediawiki/images/thumb/f/f3/Screen-vioserial-driver.png/600px-Screen-vioserial-driver.png 2x" alt="Экран-виртуальный-драйвер.png" width="300" height="239" /></a></p>
<div class="thumbcaption">
<div class="magnify"></div>
</div>
</div>
</div>
<p>Сначала вам нужно скачать образ драйвера virtio-win (см. <a title="Драйверы Windows VirtIO" href="https://pve.proxmox.com/wiki/Windows_VirtIO_Drivers">Драйверы Windows VirtIO</a>).</p>
<p>Затем установите драйвер virtio-serial:</p>
<ol>
<li>Подключите ISO-образ к виртуальной машине Windows (virtio-*.iso)</li>
<li>Перейдите в Диспетчер устройств Windows</li>
<li>Найдите «простой коммуникационный контроллер PCI»</li>
<li>Щелкните правой кнопкой мыши -&gt; «Обновить драйвер» и выберите подключенный ISO-образ в разделе «DRIVE:\vioserial\&lt;OSVERSION&gt;\», где &lt;OSVERSION&gt; — это ваша версия Windows (например, 2k12R2 для Windows 2012 R2)</li>
</ol>
<p>После этого вам нужно будет установить qemu-guest-agent:</p>
<ol>
<li>Перейдите в раздел «Подключённый ISO» в проводнике</li>
<li>Установщик гостевого агента находится в каталоге <b>guest-agent</b></li>
<li>Запустите установщик двойным щелчком (либо <b>qemu-ga-x86_64.msi</b> (64-разрядная версия), либо <b>qemu-ga-i386.msi</b> (32-разрядная версия)</li>
</ol>
<p>После этого qemu-guest-agent должен быть запущен. Вы можете проверить это в списке служб Windows или в PowerShell с помощью:</p>
<pre>PS C:\Users\Administrator&gt; Get-Service QEMU-GA

Состояние Имя Отображаемое имя
------ ---- -----------
Работает QEMU-GA Гостевой агент QEMU

</pre>
<p>Если он не запущен, вы можете использовать панель управления <b>«Службы»</b>, чтобы запустить его и убедиться, что он запустится автоматически при следующей загрузке.</p>
<h3>Проверка работоспособности связи с гостевым агентом</h3>
<p>Связь с гостевым агентом осуществляется через сокет unix, расположенный в /var/run/qemu-server/&lt;my_vmid&gt;.qga Вы можете протестировать коммуникационный qm-агент:</p>
<pre>запрос агента qm &lt;vmid&gt;
</pre>
<p>если qemu-guest-agent корректно работает на виртуальной машине, он вернет сообщение без ошибок.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[qemu]]></category><category><![CDATA[guest agent]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/06/proxmox-qemu-guest-a.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b9%d0%ba%d0%b0-%d0%ba%d0%bb%d0%b0%d1%81%d1%82%d0%b5%d1%80%d0%b0-proxmox-ve/</link>
					<title><![CDATA[Настройка кластера Proxmox VE]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jun 2025 11:08:48 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="537" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/cluster.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Настройка кластера Proxmox VE</h1>
													</header>
													<p>В данной инструкции мы сначала соберем кластер Proxmox для управления всеми хостами виртуализации из единой консоли, а затем — кластер высокой доступности (HA или отказоустойчивый). В нашем примере мы будем работать с 3 серверами — pve1, pve2 и pve3.</p>
<p>Мы не станем уделять внимание процессу установки Proxmox VE, а также настройки сети и других функций данного гипервизора — все это можно прочитать в пошаговой инструкции Установка и настройка Proxmox VE.</p>
<h2 id="prepare">Подготовка нод кластера</h2>
<p>Серверы должны иметь возможность обращения друг к другу по их серверным именам. В продуктивной среде лучше всего для этого создать соответствующие записи в DNS. В тестовой можно отредактировать файлы hosts. В Proxmox это можно сделать в консоли управления — устанавливаем курсор на сервере &#8212; переходим в <strong>Система</strong> &#8212; <strong>Hosts</strong> &#8212; добавляем все серверы, которые будут включены в состав кластера:</p>
<p><img decoding="async" title="Добавляем в hosts записи для всех нод proxmox" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/1.jpg" alt="Добавляем в hosts записи для всех нод proxmox" /></p>
<p><em>* в данном примере у нас в <strong>hosts</strong> занесены наши два сервера Proxmox, из которых мы будем собирать кластер.</em></p>
<h2 id="cluster">Настройка кластера</h2>
<p>Построение кластерной системы выполняется в 2 этапа — сначала мы создаем кластер на любой из нод, затем присоединяем к данному кластеру остальные узлы.</p>
<h3 id="cluster-create">Создание кластера</h3>
<p>Переходим в панель управления Proxmox на любой их нод кластера. Устанавливаем курсов на <strong>Датацентр</strong> &#8212; кликаем по <strong>Кластер</strong> &#8212; <strong>Создать кластер</strong>:</p>
<p><img decoding="async" title="Переходим к созданию кластера" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/2.jpg" alt="Переходим к созданию кластера" /></p>
<p>Для создания кластера нам нужно задать его имя и, желательно, выбрать IP-адрес интерфейса, на котором узел кластера будет работать:</p>
<p><img decoding="async" title="Настройки для кластера" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/3.jpg" alt="Настройки для кластера" /></p>
<p>&#8230; кликаем <strong>Создать</strong> — процесс не должен занять много времени. В итоге, мы должны увидеть «TASK OK»:</p>
<p><img decoding="async" title="Статус создания кластера Proxmox" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/4.jpg" alt="Статус создания кластера Proxmox" /></p>
<h3 id="cluster-addnode">Присоединение ноды к кластеру</h3>
<p>На первой ноде, где создали кластер, в том же окне станет активна кнопка <strong>Данные присоединения</strong> — кликаем по ней:</p>
<p><img decoding="async" title="Получаем данные для присоединения к кластеру Proxmox" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/5.jpg" alt="Получаем данные для присоединения к кластеру Proxmox" /></p>
<p>В открывшемся окне копируем данные присоединения:</p>
<p><img decoding="async" title="Копирование данных для присоединения к кластеру" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/6.jpg" alt="Копирование данных для присоединения к кластеру" /></p>
<p>Теперь переходим в панель управления нодой, которую хотим присоединить к кластеру. Переходим в <strong>Датацентр</strong> &#8212; <strong>Кластер</strong> &#8212; кликаем по <strong>Присоединить к кластеру</strong>:</p>
<p><img decoding="async" title="Переходим к присоединению ноды к кластеру" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/7.jpg" alt="Переходим к присоединению ноды к кластеру" /></p>
<p>В поле «Данные» вставляем данные присоединения, которые мы скопировали с первой ноды — поля «Адрес сервера» и «Отпечаток заполняться автоматически». Заполняем пароль пользователя root первой ноды и кликаем <strong>Присоединение</strong>:</p>
<p><img decoding="async" title="Заполняем данные для присоединения к кластеру" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/8.jpg" alt="Заполняем данные для присоединения к кластеру" /></p>
<p>Присоединение также не должно занять много времени. Ждем несколько минут для завершения репликации всех настроек. Кластер готов к работе — при подключении к любой из нод мы будем подключаться к кластеру:</p>
<p><img decoding="async" title="Панель управления с настроенным кластером Proxmox" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/9.jpg" alt="Панель управления с настроенным кластером Proxmox" /></p>
<p>Готово. Данный кластер можно использовать для централизованного управления хостами Proxmox.</p>
<p>Посмотреть статус работы кластера можно командой в SSH:</p>
<div class="console">
<p>pvecm status</p>
</div>
<h2 id="ha">Отказоустойчивый кластер</h2>
<p>Настроим автоматический перезапуск виртуальных машин на рабочих нодах, если выйдет из строя сервер.</p>
<p>Для настройки отказоустойчивости (High Availability или HA) нам нужно:</p>
<ul>
<li>Минимум 3 ноды в кластере. Сам кластер может состоять из двух нод и более, но для точного определения живых/не живых узлов нужно большинство голосов (кворумов), то есть на стороне рабочих нод должно быть больше одного голоса. Это необходимо для того, чтобы избежать ситуации 2-я активными узлами, когда связь между серверами прерывается и каждый из них считает себя единственным рабочим и начинает запускать у себя все виртуальные машины. Именно по этой причине HA требует 3 узла и выше.</li>
<li>Общее хранилище для виртуальных машин. Все ноды кластера должны быть подключены к общей системе хранения данных — это может быть СХД, подключенная по FC или iSCSI, NFS или распределенное хранилище Ceph или GlusterFS.</li>
</ul>
<h3 id="ha-prepare">1. Подготовка кластера</h3>
<p>Процесс добавления 3-о узла аналогичен процессу, <a class="self" href="https://www.dmosk.ru/miniinstruktions.php?mini=proxmoxve-cluster#cluster-addnode">описанному выше</a> — на одной из нод, уже работающей в кластере, мы копируем данные присоединения; в панели управления третьего сервера переходим к настройке кластера и присоединяем узел.</p>
<h3 id="ha-storage">2. Добавление хранилища</h3>
<p>Подробное описание процесса настройки самого хранилища выходит за рамки данной инструкции. В данном примере мы разберем пример и использованием СХД, подключенное по iSCSI.</p>
<p>Если наша СХД настроена на проверку инициаторов, на каждой ноде смотрим командой:</p>
<div class="console">
<p>cat /etc/iscsi/initiatorname.iscsi</p>
</div>
<p>&#8230; IQN инициаторов. Пример ответа:</p>
<div class="content-like">
<p>&#8230;<br />
InitiatorName=iqn.1993-08.org.debian:01:4640b8a1c6f</p>
</div>
<p><em>* где <strong>iqn.1993-08.org.debian:01:4640b8a1c6f</strong> — IQN, который нужно добавить в настройках СХД.</em></p>
<p>После настройки СХД, в панели управления Proxmox переходим в <strong>Датацентр</strong> &#8212; <strong>Хранилище</strong>. Кликаем <strong>Добавить</strong> и выбираем тип (в нашем случае, <strong>iSCSI</strong>):</p>
<p><img decoding="async" title="Переходим к добавлению iSCSI" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/10.jpg" alt="Переходим к добавлению iSCSI" /></p>
<p>В открывшемся окне указываем настройки для подключения к хранилке:</p>
<p><img decoding="async" title="Настройки для добавления iSCSI" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/11.jpg" alt="Настройки для добавления iSCSI" /></p>
<p><em>* где <strong>ID</strong> — произвольный идентификатор для удобства; <strong>Portal</strong> — адрес, по которому iSCSI отдает диски; <strong>Target</strong> — идентификатор таргета, по которому СХД отдает нужный нам LUN.</em></p>
<p>Нажимаем добавить, немного ждем — на всех хостах кластера должно появиться хранилище с указанным идентификатором. Чтобы использовать его для хранения виртуальных машин, еще раз добавляем хранилище, только выбираем <strong>LVM</strong>:</p>
<p><img decoding="async" title="Переходим к созданию тома LVM" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/12.jpg" alt="Переходим к созданию тома LVM" /></p>
<p>Задаем настройки для тома LVM:</p>
<p><img decoding="async" title="Настройка нового тома LVM на хранилище iSCSI" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/13.jpg" alt="Настройка нового тома LVM на хранилище iSCSI" /></p>
<p><em>* где было настроено:</em></p>
<ul>
<li><em><strong>ID</strong> — произвольный идентификатор. Будет служить как имя хранилища.</em></li>
<li><em><strong>Основное хранилище</strong> — выбираем добавленное устройство iSCSI.</em></li>
<li><em><strong>Основное том</strong> — выбираем LUN, который анонсируется таргетом.</em></li>
<li><em><strong>Группа томов</strong> — указываем название для группы томов. В данном примере указано таким же, как ID.</em></li>
<li><em><strong>Общедоступно</strong> — ставим галочку, чтобы устройство было доступно для всех нод нашего кластера.</em></li>
</ul>
<p>Нажимаем <strong>Добавить</strong> — мы должны увидеть новое устройство для хранения виртуальных машин.</p>
<p>Для продолжения настройки отказоустойчивого кластера создаем виртуальную машину на общем хранилище.</p>
<h3 id="ha-failover">3. Настройка отказоустойчивости</h3>
<h4>Создание группы</h4>
<p>Для начала, определяется с необходимостью групп. Они нужны в случае, если у нас в кластере много серверов, но мы хотим перемещать виртуальную машину между определенными нодами. Если нам нужны группы, переходим в <strong>Датацентр</strong> &#8212; <strong>HA</strong> &#8212; <strong>Группы</strong>. Кликаем по кнопке <strong>Создать</strong>:</p>
<p><img decoding="async" title="Переходим к созданию группы высокой доступности" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/14.jpg" alt="Переходим к созданию группы высокой доступности" /></p>
<p>Вносим настройки для группы и выбираем галочками участников группы:</p>
<p><img decoding="async" title="Настройки для создания HA-группы" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/15.jpg" alt="Настройки для создания HA-группы" /></p>
<p><em>* где:</em></p>
<ul>
<li><em><strong>ID</strong> — название для группы.</em></li>
<li><em><strong>restricted</strong> — определяет жесткое требование перемещения виртуальной машины внутри группы. Если в составе группы не окажется рабочих серверов, то виртуальная машина будет выключена.</em></li>
<li><em><strong>nofailback</strong> — в случае восстановления ноды, виртуальная машина не будет на нее возвращена, если галочка установлена.</em></li>
</ul>
<p>Также мы можем задать приоритеты для серверов, если отдаем каким-то из них предпочтение.</p>
<p>Нажимаем <strong>OK</strong> — группа должна появиться в общем списке.</p>
<h4>Настраиваем отказоустойчивость для виртуальной машины</h4>
<p>Переходим в <strong>Датацентр</strong> &#8212; <strong>HA</strong>. Кликаем по кнопке <strong>Добавить</strong>:</p>
<p><img decoding="async" title="Переходим к добавлению ресурса в группу HA" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/16.jpg" alt="Переходим к добавлению ресурса в группу HA" /></p>
<p>В открывшемся окне выбираем виртуальную машину и группу:</p>
<p><img decoding="async" title="Добавляем виртуальную машину в HA" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/17.jpg" alt="Добавляем виртуальную машину в HA" /></p>
<p>&#8230; и нажимаем <strong>Добавить</strong>.</p>
<h3 id="ha-check">4. Проверка отказоустойчивости</h3>
<p>После выполнения всех действий, необходимо проверить, что наша отказоустойчивость работает. Для чистоты эксперимента, можно выключиться сервер, на котором создана виртуальная машина, добавленная в HA.</p>
<div class="note">
<p>Важно учесть, что перезагрузка ноды не приведет к перемещению виртуальной машины. В данном случае кластер отправляет сигнал, что он скоро будет доступен, а ресурсы, добавленные в HA останутся на своих местах.</p>
</div>
<p>Для выключения ноды можно ввести команду:</p>
<div class="console">
<p>systemctl poweroff</p>
</div>
<p>Виртуальная машина должна переместиться в течение 1 &#8212; 2 минут.</p>
<h2 id="move">Ручное перемещение виртуальной машины</h2>
<p>Представим ситуацию, что у нас произошел сбой одного из узлов кластера, но при этом виртуальная машина не переехала на рабочую ноду. Например, если сервер был отправлен в перезагрузку, но не смог корректно загрузиться. В консоли управления нет возможности мигрировать виртуалку с неработающего сервера. Поэтому нам понадобиться командная строка.</p>
<p>И так, открываем SSH-консоль сервера, на любой работающем сервере Proxmox. Переходим в каталог <strong>qemu-server</strong> той ноды, которая не работает:</p>
<div class="console">
<p>cd /etc/pve/nodes/pve1/qemu-server</p>
</div>
<p><em>* мы предполагаем, что у нас вышел из строя сервер <strong>pve1</strong>.</em></p>
<p>Смотрим содержимое каталога:</p>
<div class="console">
<p>ls</p>
</div>
<p>Мы должны увидеть конфигурационные файлы запущенных виртуальных машин, например:</p>
<div class="console-like">
<p>100.conf</p>
</div>
<p><em>* в нашем примере у нас запущена только одна виртуальная машина с идентификатором 100.</em></p>
<p>Для удобства, создадим переменную с идентификатором:</p>
<div class="console">
<p>VM_ID=100</p>
</div>
<p>Переносим конфигурацию машины в каталог <strong>qemu-server</strong> текущего сервера:</p>
<div class="console">
<p>mv ${VM_ID}.conf ../../../qemu-server/</p>
</div>
<p>Командой:</p>
<div class="console">
<p>qm list</p>
</div>
<p>&#8230; проверяем, что виртуальная машина появилась в системе.</p>
<blockquote><p>В противном случае, перезапускаем службы:</p>
<div class="console">
<p>systemctl restart pvestatd pvedaemon pve-cluster</p>
</div>
</blockquote>
<p>Сбрасываем состояние для HA:</p>
<div class="console">
<p>ha-manager set ${VM_ID} &#8212;state disabled</p>
</div>
<div class="console">
<p>ha-manager set ${VM_ID} &#8212;state started</p>
</div>
<p><em>* в данном примере мы сбросили состояние для виртуальной машины с идентификатором <strong>100</strong>. Если это не сделать, то при запуске виртуалки ничего не будет происходить.</em></p>
<p>После виртуальную машину можно запустить:</p>
<div class="console">
<p>qm start ${VM_ID}</p>
</div>
<blockquote><p>Если виртуальная машина не запустится, а мы получим сообщение:</p>
<div class="console-like">
<p>Requesting HA start for VM 102</p>
</div>
<p>&#8230; значит HA не может восстановить свою работу. На момент восстановления нерабочей ноды, удаляем конфигурацию для HA:</p>
<div class="console">
<p>ha-manager remove ${VM_ID}</p>
</div>
<p>И снова запускаем машину:</p>
<div class="console">
<p>qm start ${VM_ID}</p>
</div>
</blockquote>
<h2 id="replication">Репликация виртуальных машин</h2>
<p>Если у нас нет общего дискового хранилища, мы можем настроить репликацию виртуальных машин между нодами. В таком случае мы получим, относительно, отказоустойчивую среду — в случае сбоя, у нас будет второй сервер, на котором есть аналогичный набор виртуальных машин.</p>
<h3 id="replication-zfs">Настройка ZFS</h3>
<p>Репликация может выполняться только на тома ZFS. Подробная работа с данной файловой системой выходит за рамки данной инструкции, однако, мы разберем основные команды, с помощью которых можно создать необходимый том.</p>
<p>Работа с пулами ZFS выполняется из командной строки. Чтобы увидеть уже существующие пулы вводим:</p>
<div class="console">
<p>zpool list -v</p>
</div>
<p>Для создания нового используем команду <strong>zpool create</strong>:</p>
<div class="console">
<p>zpool create -f zpool1 /dev/sdc</p>
</div>
<p><em>* в данном примере мы создадим пул с названием <strong>zpool1</strong> из диска <strong>/dev/sdc</strong>.</em></p>
<blockquote><p>Для создания пула из нескольких дисков (как RAID 0) перечисляем диски через пробел:</p>
<div class="console">
<p>zpool create -f zpool1 /dev/sdc /dev/sdd</p>
</div>
<p><em>* из дисков sdc и sdd.</em></p>
<p>Для создания отказоустойчивого тома (RAID 1) добавляем опцию <strong>mirror</strong>:</p>
<div class="console">
<p>zpool create -f zpool1 mirror /dev/sdc /dev/sdd</p>
</div>
</blockquote>
<p>Теперь открываем панель управления Proxmox. Переходим в <strong>Датацентр</strong> &#8212; <strong>Хранилище</strong> &#8212; <strong>ZFS</strong>:</p>
<p><img decoding="async" title="Переходим к добавлению ZFS" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/20.jpg" alt="Переходим к добавлению ZFS" /></p>
<p>Задаем настройки для создания хранилища из созданного ранее пула ZFS:</p>
<p><img decoding="async" title="Создание хранилища из пула zfs" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/21.jpg" alt="Создание хранилища из пула zfs" /></p>
<p><em>* в данном примере мы создаем хранилище из пула <strong>zpool1</strong>; название для хранилище задаем <strong>zfs-pool</strong>, также ставим галочку <strong>Дисковое резервирование</strong>. Остальные настройки оставляем по умолчанию.</em></p>
<p>После этого мы должны либо перенести виртуальную машину на хранилище ZFS, либо создать в нем новую машину.</p>
<h3 id="replication-setting">Настройка репликации</h3>
<p>Переходим к хосту, где находится виртуальная машина, для которой мы хотим настроить клонирование (она должна также находится на хранилище ZFS) &#8212; <strong>Репликация</strong>:</p>
<p><img decoding="async" title="Переходим к настройке репликации" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/18.jpg" alt="Переходим к настройке репликации" /></p>
<p>Задаем настройки для репликации виртуальной машины:</p>
<p><img decoding="async" title="Настраиваем репликацию для виртуальной машины" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/19.jpg" alt="Настраиваем репликацию для виртуальной машины" /></p>
<p><em>* в данном примере мы указываем системе проверять и реплицировать изменения каждые <strong>15</strong> минут для виртуальной машины с идентификатором <strong>100</strong>. Репликация должна проводиться на сервер <strong>pve2</strong>.</em></p>
<p>Нажимаем <strong>Создать</strong> — теперь ждем репликации по расписанию или форсируем событие, кликнув по <strong>Запустить сейчас</strong>:</p>
<p><img decoding="async" title="Форсируем запуск репликации виртуальной машины" src="https://www.dmosk.ru/img/miniinstruktions/proxmoxve-cluster/22.jpg" alt="Форсируем запуск репликации виртуальной машины" /></p>
<h2 id="delete-node">Удаление ноды из кластера</h2>
<p>Удаление узла из рабочего кластера выполняется из командной строки. Список всех нод можно увидеть командой:</p>
<div class="console">
<p>pvecm nodes</p>
</div>
<p>Мы увидим, примерно, следующее:</p>
<div class="console-like">
<p>Membership information<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-<br />
Nodeid      Votes Name<br />
1          1 pve1 (local)<br />
2          1 pve2<br />
3          1 pve3</p>
</div>
<p><em>* где <strong>pve1, pve2, pve3</strong> — узлы кластера; <strong>local</strong> указываем на ноду, с которой мы выполняем команду <strong>pvecm</strong>.</em></p>
<p>Для удаления узла, например, pve2 вводим:</p>
<div class="console">
<p>pvecm delnode pve2</p>
</div>
<p>Ждем немного времени, пока не пройдет репликация. В консоли управления Proxmox удаленный сервер должен пропасть. Однако, иногда, нода может продолжать висеть в Datacenter (списке серверов). Выполним команду:</p>
<div class="console">
<p>rm -rf /etc/pve/nodes/pve2</p>
</div>
<p><em>* где <strong>pve2 —</strong> нода, которую мы должны удалить.</em></p>
<h2 id="delete-cluster">Удаление кластера</h2>
<p>Рассмотрим процесс удаления нод из кластера и самого кластера. Данные действия не могут быть выполнены из веб-консоли — все операции делаем в командной строке.</p>
<p>Подключаемся по SSH к одной из нод кластера. Смотрим все узлы, которые присоединены к нему:</p>
<div class="console">
<p>pvecm nodes</p>
</div>
<p>Мы получим список нод — удалим все, кроме локальной, например:</p>
<div class="console">
<p>pvecm delnode pve2</p>
</div>
<div class="console">
<p>pvecm delnode pve3</p>
</div>
<p><em>* в данном примере мы удалили ноды pve2 и pve3.</em></p>
<p>Необходимо подождать, минут 5, чтобы прошла репликация между нодами. После останавливаем следующие службы:</p>
<div class="console">
<p>systemctl stop pvestatd pvedaemon pve-cluster corosync</p>
</div>
<p>Подключаемся к базе sqlite для кластера PVE:</p>
<div class="console">
<p>sqlite3 /var/lib/pve-cluster/config.db</p>
</div>
<p>Удаляем из таблицы tree все записи, поле name в которых равно corosync.conf:</p>
<div class="console">
<p>&gt; DELETE FROM tree WHERE name = &#8216;corosync.conf&#8217;;</p>
</div>
<p>Отключаемся от базы:</p>
<div class="console">
<p>&gt; .quit</p>
</div>
<p>Удаляем файл блокировки:</p>
<div class="console">
<p>rm -f /var/lib/pve-cluster/.pmxcfs.lockfile</p>
</div>
<p>Удаляем файлы, имеющие отношение к настройке кластера:</p>
<div class="console">
<p>rm -f /etc/pve/corosync.conf</p>
</div>
<div class="console">
<p>rm -rf /etc/corosync/*</p>
</div>
<div class="console">
<p>rm -rf /var/lib/corosync/*</p>
</div>
<p>Запускаем ранее погашенные службы:</p>
<div class="console">
<p>systemctl start pvestatd pvedaemon pve-cluster corosync</p>
</div>
<p>Кластер удален.</p>
<h2 id="errors">Решение проблем при работе с кластером Proxmox</h2>
<p>Рассмотрим в данном разделе ошибки, с которыми столкнулся я.</p>
<h3>No quorum</h3>
<p>Данная ошибка может появляться при попытке посмотреть некоторые разделы веб-интерфейса Proxmox или при попытке запустить виртуальную машину.</p>
<p><strong>Причина:</strong> нода кластера не видит достаточное количество участников для создания кворума. Если у нас 3 сервера, то это значит, что данная нода не видит оставльные две. А если у нас кластер из двух серверов, то падение любого из компьютеров приведет к данной ошибке.</p>
<p><strong>Решение:</strong> необходимо найти причину потери сетевой связи между всеми участниками кластера.</p>
<p>Если быстрого решения нет, мы можем временно поменять модель поведения, указал достоточное количество нод, чтобы кластер работал. Это делается командой:</p>
<div class="console">
<p>pvecm expect 1</p>
</div>
<p><em>* в данном примере мы указали, что кластер может полноценно работать, если у нас останется одна нода.</em></p>
<p>Источник: <a href="https://www.dmosk.ru/miniinstruktions.php?mini=proxmoxve-cluster#delete-cluster">dmosk.ru</a></p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="2">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/06/cluster.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%ba%d0%b0%d0%ba-%d0%b2%d1%8b%d0%bf%d1%83%d1%81%d1%82%d0%b8%d1%82%d1%8c-%d1%81%d0%b0%d0%bc%d0%be%d0%bf%d0%be%d0%b4%d0%bf%d0%b8%d1%81%d0%b0%d0%bd%d0%bd%d1%8b%d0%b9-ssl-%d1%81%d0%b5%d1%80%d1%82%d0%b8/</link>
					<title><![CDATA[Как выпустить самоподписанный SSL сертификат и заставить ваш браузер доверять ему]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jun 2025 10:08:03 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="614" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-1024x749.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Как выпустить самоподписанный SSL сертификат и заставить ваш браузер доверять ему</h1>
													</header>
													<p><img loading="lazy" decoding="async" class="aligncenter wp-image-435" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-300x220.png" alt="" width="747" height="548" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-300x220.png 300w, https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-768x562.png 768w, https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi.png 1074w" sizes="auto, (max-width: 747px) 100vw, 747px" /></p>
<p>Все крупные сайты давно перешли на протокол https. Тенденция продолжается, и многие наши клиенты хотят, чтобы их сайт работал по защищенному протоколу. А если разрабатывается backend для мобильного приложения, то https обязателен. Например, Apple требует, чтобы обмен данными сервера с приложением велся по безопасному протоколу. Это требование <a href="https://techcrunch.com/2016/06/14/apple-will-require-https-connections-for-ios-apps-by-the-end-of-2016/" target="_blank" rel="noopener">введено с конца 2016 года</a>.</p>
<p>На production нет проблем с сертификатами. Обычно хостинг провайдер предоставляет удобный интерфейс для подключения сертификата. Выпуск сертификата тоже дело не сложное. Но во время работы над проектом каждый разработчик должен позаботиться о сертификате сам.<br />
В этой статье я расскажу, как выпустить самоподписанный SSL сертификат и заставить браузер доверять ему.<br />
<a target="_blank" name="habracut"></a><br />
Чтобы выпустить сертификат для вашего локального домена, понадобится корневой сертификат. На его основе будут выпускаться все остальные сертификаты. Да, для каждого нового top level домена нужно выпускать свой сертификат. Получить корневой сертификат достаточно просто.<br />
Сначала сформируем закрытый ключ:</p>
<pre><code class="bash">openssl genrsa -out rootCA.key 2048</code></pre>
<p>Затем сам сертификат:</p>
<pre><code class="bash">openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.pem</code></pre>
<p>Нужно будет ввести <i>страну</i>, <i>город</i>, <i>компанию</i> и т.д. В результате получаем два файла: <u>rootCA.key</u> и <u>rootCA.pem</u></p>
<p><b>Переходим к главному, выпуск самоподписанного сертификата.</b> Так же как и в случае с корневым, это две команды. Но параметров у команд будет значительно больше. И нам понадобится вспомогательный конфигурационный файл. Поэтому оформим все это в виде bash скрипта <u>create_certificate_for_domain.sh</u></p>
<p>Первый параметр обязателен, выведем небольшую инструкцию для пользователя.</p>
<pre><code class="bash">if [ -z "$1" ]
then
  echo "Please supply a subdomain to create a certificate for";
  echo "e.g. mysite.localhost"
  exit;
fi</code></pre>
<p>Создадим новый приватный ключ, если он не существует или будем использовать существующий:</p>
<pre><code class="bash">if [ -f device.key ]; then
  KEY_OPT="-key"
else
  KEY_OPT="-keyout"
fi</code></pre>
<p>Запросим у пользователя название домена. Добавим возможность задания “общего имени” (оно используется при формировании сертификата):</p>
<pre><code class="bash">DOMAIN=$1
COMMON_NAME=${2:-$1}</code></pre>
<p>Чтобы не отвечать на вопросы в интерактивном режиме, сформируем строку с ответами. И зададим время действия сертификата:</p>
<pre><code class="bash">SUBJECT="/C=CA/ST=None/L=NB/O=None/CN=$COMMON_NAME"
NUM_OF_DAYS=999</code></pre>
<p>В переменной SUBJECT перечислены все те же вопросы, который задавались при создании корневого сертификата (<i>страна</i>, <i>город</i>, <i>компания</i> и т.д). Все значение, кроме CN можно поменять на свое усмотрение.</p>
<p>Сформируем <i>csr</i> файл (Certificate Signing Request) на основе ключа. Подробнее о файле запроса сертификата можно <a href="https://www.sslshopper.com/what-is-a-csr-certificate-signing-request.html" target="_blank" rel="noopener">почитать в этой статье</a>.</p>
<pre><code class="bash">openssl req -new -newkey rsa:2048 -sha256 -nodes $KEY_OPT device.key -subj "$SUBJECT" -out device.csr</code></pre>
<p><b>Формируем файл сертификата</b>. Для этого нам понадобится вспомогательный файл с настройками. В этот файл мы запишем домены, для которых будет валиден сертификат и некоторые другие настройки. Назовем его <u>v3.ext</u>. Обращаю ваше внимание, что это отдельный файл, а не часть bash скрипта.</p>
<pre><code class="bash">authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names

[alt_names]
DNS.1 = %%DOMAIN%%
DNS.2 = *.%%DOMAIN%%</code></pre>
<p>Да, верно, наш сертификат будет валидным для основного домена, а также для всех поддоменов. Сохраняем указанные выше строки в файл <u>v3.ext</u></p>
<p>Возвращаемся в наш bash скрипт. На основе вспомогательного файла <u>v3.ext</u> создаем временный файл с указанием нашего домена:</p>
<pre><code class="bash">cat v3.ext | sed s/%%DOMAIN%%/$COMMON_NAME/g &gt; /tmp/__v3.ext</code></pre>
<p>Выпускаем сертификат:</p>
<pre><code class="bash">openssl x509 -req -in device.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out device.crt -days $NUM_OF_DAYS -sha256 -extfile /tmp/__v3.ext</code></pre>
<p>Переименовываем сертификат и удаляем временный файл:</p>
<pre><code class="bash">mv device.csr $DOMAIN.csr
cp device.crt $DOMAIN.crt

# remove temp file
rm -f device.crt;</code></pre>
<p>Скрипт готов. Запускаем его:</p>
<pre><code class="bash">./create_certificate_for_domain.sh mysite.localhost</code></pre>
<p>Получаем два файла: <u>mysite.localhost.crt</u> и <u>device.key</u></p>
<p>Теперь нужно указать web серверу пути к этим файлам. На примере nginx это будет выглядеть так:</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-436" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/8mv4rkzcwxfnlr6uxkilnenonhs-300x211.png" alt="" width="793" height="558" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/06/8mv4rkzcwxfnlr6uxkilnenonhs-300x211.png 300w, https://blog.sefdar.ru/wp-content/uploads/2025/06/8mv4rkzcwxfnlr6uxkilnenonhs.png 579w" sizes="auto, (max-width: 793px) 100vw, 793px" /></p>
<p>Запускаем браузер, открываем <a href="https://mysite.localhost/" target="_blank" rel="noopener">https://mysite.localhost</a> и видим:</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-437" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/q8hiwzdowyfuus6a1qu75p6dtok-300x220.png" alt="" width="798" height="585" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/06/q8hiwzdowyfuus6a1qu75p6dtok-300x220.png 300w, https://blog.sefdar.ru/wp-content/uploads/2025/06/q8hiwzdowyfuus6a1qu75p6dtok-1024x749.png 1024w, https://blog.sefdar.ru/wp-content/uploads/2025/06/q8hiwzdowyfuus6a1qu75p6dtok-768x562.png 768w, https://blog.sefdar.ru/wp-content/uploads/2025/06/q8hiwzdowyfuus6a1qu75p6dtok.png 1074w" sizes="auto, (max-width: 798px) 100vw, 798px" /></p>
<p>Браузер не доверяет этому сертификату. Как быть?</p>
<p>Нужно отметить выпущенный нами сертификат как Trusted. На Linux (Ubuntu и, наверное, остальных Debian-based дистрибутивах) это можно сделать через сам браузер. В Mac OS X это можно сделать через приложение Keychain Access. Запускаем приложение и перетаскиваем в окно файл <u>mysite.localhost.crt</u>. Затем открываем добавленный файл и выбираем Always Trust:</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-438 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/qdn68hbbkgsi7dyzy7hzra8mvv4.png" alt="" width="713" height="711" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/06/qdn68hbbkgsi7dyzy7hzra8mvv4.png 713w, https://blog.sefdar.ru/wp-content/uploads/2025/06/qdn68hbbkgsi7dyzy7hzra8mvv4-300x300.png 300w, https://blog.sefdar.ru/wp-content/uploads/2025/06/qdn68hbbkgsi7dyzy7hzra8mvv4-150x150.png 150w" sizes="auto, (max-width: 713px) 100vw, 713px" /></p>
<p>Обновляем страницу в браузере и:</p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-435" src="https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-300x220.png" alt="" width="824" height="604" srcset="https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-300x220.png 300w, https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-1024x749.png 1024w, https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-768x562.png 768w, https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi.png 1074w" sizes="auto, (max-width: 824px) 100vw, 824px" /></p>
<p>Успех! Браузер доверяет нашему сертификату.</p>
<p>Сертификатом можно поделиться с другими разработчиками, чтобы они добавили его к себе. А если вы используете Docker, то сертификат можно сохранить там. Именно так это реализовано на всех наших проектах.</p>
<p>Источник: <a href="https://habr.com/ru/articles/352722/">https://habr.com/ru/articles/352722/</a></p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[WEB]]></category><category><![CDATA[SSL]]></category><category><![CDATA[bash-скрипт]]></category><category><![CDATA[сертификаты]]></category><category><![CDATA[https]]></category><category><![CDATA[протокол]]></category><category><![CDATA[google]]></category><category><![CDATA[chrome]]></category><category><![CDATA[openssl]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/06/vbx-fkfz0qk7mwt7y0dmc0bkjmi-1024x749.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b0%d0%b2%d1%82%d0%be%d1%80%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d0%be-ssh/</link>
					<title><![CDATA[авторизация по SSH]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 12 Mar 2025 11:51:52 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="367" src="https://blog.sefdar.ru/wp-content/uploads/2025/03/1aeeb161a1cefdec1044b25ea6ddf6c9-1024x447.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>авторизация по SSH</h1>
													</header>
													<div class="container">
<div class="article__header">
<div class="row">
<div class="col  col-11">
<h2 class="article__title">Как создать ключ для авторизации по SSH и добавить его на сервер?</h2>
</div>
</div>
</div>
</div>
<div class="container  container--narrowed">
<div class="article__body">
<div class="row">
<div class="col-7  col-sm-6  offset-sm-1  col-xs-2  offset-xs-0">
<div class="article__content  text-content-block">
<p><strong>SSH-ключи используются для идентификации клиента</strong> при подключении к серверу по <code class="code">SSH-протоколу</code>. Используйте этот способ вместо аутентификации по паролю.</p>
<p>SSH-ключи представляют собой пару — закрытый и открытый ключ. Закрытый должен храниться, соответственно, в закрытом доступе у клиента, а открытый отправляется на сервер и размещается в файле <code>authorized_keys</code>.</p>
<div id="table-of-contents" class="table-of-contents"></div>
<h2 id="sozdanie-ssh-klyuchei-v-linux"><i class="fa fa-link" aria-hidden="true"></i>Создание SSH-ключей в Linux</h2>
<p>На клиентской стороне должен быть установлен пакет ssh (openssh). На серверах FirstVDS с шаблонами по умолчанию необходимое ПО уже установлено.</p>
<p>Для ОС CentOS, AlmaLinux или RockyLinux выполните команду:</p>
<pre># yum -y install openssh-server openssh-clients</pre>
<p>Для ОС Debian или Ubuntu выполните команду:</p>
<pre># apt -y install openssh-server</pre>
<p>Дальнейшая инструкция будет одинаковая для всех ОС.</p>
<p>На клиентском компьютере в командной строке выполните команду генерации ключей:</p>
<pre># ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):</pre>
<p>Введите путь файла, в который будут помещены ключи. Каталог по умолчанию указан в скобках, в примере <code>/домашний_каталог/.ssh/id_rsa</code>. Если хотите оставить расположение по умолчанию, нажмите Enter.</p>
<p>Пароль (passphrase) используется для ограничения доступа к закрытому ключу. Пароль усложнит использование ключа третьими лицами в случае утраты. Если не хотите использовать секретную фразу, нажмите Enter без заполнения строки.</p>
<p>Успешно сгенерировав пару ключей, вы увидите уведомление:</p>
<pre>Your identification has been saved in /root/.ssh/id_rsa
Your public key has been saved in /root/.ssh/id_rsa.pub
The key fingerprint is:
SHA256:JPDzeSan06C9+osd+sKXWP0RmPk4UbSESaTvYn0aXVk root@test-server1.com
The key's randomart image is:
+---[RSA 3072]----+
|.    oo+o        |
|     o   .o...   |
|     + o  =.   E |
|      = o= .  o  |
|   S.=+ .o       |
|   o.@+.o.       |
| ..oB.=oo.       |
|  +=o= +.        |
|  +**..          |
+----[SHA256]-----+
</pre>
<p>В актуальных ОС генерация ключей происходит с такими настройками: тип аутентификации — RSA, число бит в ключе — 2048 или 3072.</p>
<p>Рекомендуем позаботится о безопасности ключей. В первую очередь обязательно необходимо задавать парольную фразу (passphrase), которая не должна быть простым.</p>
<p>Укажем также параметр <code class="code">-o</code>, что позволяет использовать формат OpenSSH, который более безопасен, чем старый PEM.</p>
<p>С помощью параметра <code class="code">-a</code> можно увеличить время проверки парольной фразы ключа, чтобы усложнить взлом методом грубого перебора (в случае, если ключ будет утерян, у вас будет больше времени на смену ключа на сервере).</p>
<p>Будьте внимательны, слишком большое значение приведет к тому, что вам придется ждать каждый раз при входе на сервер по ключу. Значение по умолчанию — 3 секунды, можно задать 100 секунд. С помощью параметра <code class="code">-b</code> можно задать число бит в ключе — 4096. Получаем такую команду:</p>
<div class="code-toolbar">
<pre class="language-plaintext" tabindex="0"><code class="language-plaintext"># ssh-keygen -t rsa -b 4096 -o -a 100 -C “ваш_email@example.com”</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy">Copy</button></div>
</div>
</div>
<p dir="ltr">Параметр <code class="code">-C</code> &#171;ваш_email@example.com&#187;  — комментарий, который помогает идентифицировать ключ. Можно указать любую информацию, чтобы пометить ключ. Это важно, когда ключей на сервере много, для единичного ключа комментарий можно не добавлять вовсе.</p>
<p dir="ltr">В последних ОС к 2024 году (Debian 12, Ubuntu 24) <strong>RSA</strong> больше не является оптимальным выбором для безопасности SSH, хотя он по-прежнему поддерживается. Более надёжными и устойчивыми к взлому считаются <strong>Ed25519</strong> и <strong>ECDSA</strong>.</p>
<p><strong>Ed25519</strong>: Этот алгоритм считается более безопасным, быстрым и устойчивым к атакам, чем RSA. Он также генерирует ключи меньшего размера, что улучшает производительность. Если ваш сервер поддерживает Ed25519, рекомендуется использовать его.</p>
<div class="code-toolbar">
<pre class="language-plaintext" tabindex="0"><code class="language-plaintext"> ssh-keygen -t ed25519 -C "ваш_email@example.com"</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy">Copy</button></div>
</div>
</div>
<ul>
<li>Команда сгенерирует ключ длиной 256 бит, который при этом обеспечивает высокую степень безопасности.</li>
</ul>
<p dir="ltr"><strong>ECDSA</strong>: Вторая альтернатива, к сожалению, уязвимая к квантовым атакам, но в основном используется в случаях, где Ed25519 не поддерживается, а RSA не подходит.</p>
<div class="code-toolbar">
<pre class="language-plaintext" tabindex="0"><code class="language-plaintext">ssh-keygen -t ecdsa -b 521 -C "ваш_email@example.com"</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy">Copy</button></div>
</div>
</div>
<ul>
<li dir="ltr">Ключ на 521 бит обеспечивает отличное соотношение безопасности и производительности.</li>
</ul>
<p>Выбираем директорию, вводим пароль и видим ключ RSA или выбранную вами альтернативу (<strong>Ed25519/ECDSA)</strong> .</p>
<p>Открытый ключ хранится в файле <code>/домашний_каталог/.ssh/id_rsa.pub</code>, закрытый — <code>/домашний_каталог/.ssh/id_rsa</code>.</p>
<div class="article-bg-text is-error">Никогда и никому не передавайте, не показывайте свой закрытый ключ и не выкладывайте его на публично доступные сервисы (в т.ч. GitLab, GitHub и пр.).</div>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-3.png" alt="Где хранятся открытый и закрытый ключи" width="701" height="532" /></figure>
</figure>
<p>Скопируйте открытый ключ на сервер в файл  <code>/домашний_каталог/.ssh/authorized_keys</code>. Одной строкой:</p>
<pre>cat ~/.ssh/id_rsa.pub | ssh root@ip-адрес-сервера 'cat &gt;&gt; ~/.ssh/authorized_keys'
</pre>
<p>Или откройте этот файл на сервере редактором vi и вставьте строку с открытым ключом после ssh-rsa.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-4.png" alt=" Копирование ключа в редакторе VI" width="702" height="71" /></figure>
</figure>
<p>Ещё один способ скопировать ключ в authorized_keys — команда echo, которая помещает строку в конец файла.</p>
<pre>echo <strong>ssh-rsa строка-публичного-ключа &gt;&gt;</strong> /root/.ssh/authorized_keys
</pre>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-5.png" alt=" Копирование ключа командой echo" width="816" height="52" /></figure>
</figure>
<p>Теперь можно отключить на сервере аутентификацию по паролю и использовать только SSH-ключи.</p>
<h2 id="sozdanie-ssh-klyuchei-na-windo"><i class="fa fa-link" aria-hidden="true"></i>Создание SSH-ключей на Windows</h2>
<p>Если вы используете ОС Windows, то подключиться по SSH к вашему (Linux) серверу можно через <code class="code">PuTTY</code>или <code class="code">OpenSSH</code>. Генерация ключей в этом случае выполняется также при помощи этих программ.</p>
<h3 id="openssh"><i class="fa fa-link" aria-hidden="true"></i>OpenSSH</h3>
<p dir="ltr">Рассмотрим создание ключа через утилиту OpenSSH (доступно для Windows 10/Windows Server 2019 и новее).</p>
<p><strong>Шаги для создания ключей:</strong></p>
<ol>
<li dir="ltr"><strong>Откройте PowerShell</strong> от имени администратора.</li>
</ol>
<p dir="ltr">Если у вас не установлен OpenSSH, выполните команду:</p>
<div class="code-toolbar">
<pre class="language-plaintext" tabindex="0"><code class="language-plaintext">Add-WindowsCapability -Online -Name OpenSSH.Client</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy">Copy</button></div>
</div>
</div>
<p dir="ltr">Проверить, установлен ли OpenSSH, можно командой:</p>
<div class="code-toolbar">
<pre class="language-plaintext" tabindex="0"><code class="language-plaintext">Get-WindowsCapability -Online | ? Name -like 'OpenSSH.Client*'</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy">Copy</button></div>
</div>
</div>
<p dir="ltr">Если статус installed, данное ПО доступно к работе на вашей Windows.</p>
<ol start="2">
<li dir="ltr">Выполним все в том же PowerShell команду генерации ключа, которая аналогична команде в Linux и выполняет те же функции:</li>
</ol>
<div class="code-toolbar">
<pre class="language-plaintext" tabindex="0"><code class="language-plaintext">ssh-keygen -t rsa -b 4096 -o -a 100 -C “ваш_email@example.com”</code></pre>
<div class="toolbar">
<div class="toolbar-item"><button class="copy-to-clipboard-button" type="button" data-copy-state="copy">Copy</button></div>
</div>
</div>
<ol start="3">
<li dir="ltr"><strong>Выберите путь для сохранения</strong>. Нажмите Enter, чтобы сохранить ключи в предложенном по умолчанию месте (обычно <code>С:\Users\Ваше имя\.ssh\id_rsa)</code>, или укажите другой путь.</li>
<li dir="ltr"><strong>Установите пароль для ключа</strong> (рекомендуется для большей безопасности).</li>
</ol>
<p dir="ltr">Теперь у вас есть пара ключей в каталоге <code class="code">.ssh</code>, которую можно использовать для авторизации на сервере.</p>
<h3 id="putty"><i class="fa fa-link" aria-hidden="true"></i>PuTTY</h3>
<p dir="ltr">Рассмотрим вариант генерации ключей через клиент <code class="code">PuTTY.</code></p>
<p>Запустите приложение <code>PuTTYgen</code>, которое устанавливается вместе с PuTTY.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-6.png" alt=" Запуск PuTTYgen" width="390" height="166" /></figure>
</figure>
<p>Выберите тип ключа SSH2-RSA и нажмите <code class="code"><strong>Generate</strong></code>.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-7.png" alt="Генерация ключа в PuTTY" width="470" height="458" /></figure>
</figure>
<p>В процессе генерации ключей несколько раз произвольно проведите мышкой по экрану приложения для создания случайных величин, используемых для ключей.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-8.png" alt=" Процесс генерации ssh ключей" width="476" height="462" /></figure>
</figure>
<p>После завершения создания ключей открытый ключ выводится на экран, закрытый хранится в памяти приложения. Чтобы сохранить эти ключи, нажмите <code>Save public key</code> и <code>Save private key</code>. Укажите расположение файлов с ключами.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-9.png" alt=" Сохранение ключей в PuTTY" width="475" height="462" /></figure>
</figure>
<p>При сохранении закрытого ключа, если не заполнено поле <code>Key passphrase</code>, появится запрос «Хотите ли вы сохранить ключ без секретной фразы?»</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-10.png" alt=" Запрос на сохранение ключа без секретной фразы" width="299" height="158" /></figure>
</figure>
<p>Теперь открытый ключ необходимо скопировать на сервер в файл authorized_keys. Используйте WinSCP или другой клиент для работы с файлами на удалённом Linux-сервере. Вы можете скопировать файл с открытым ключом целиком на сервер, чтоб его копия хранилась в папке .ssh</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-11.png" alt=" Копирование открытого ключа на сервер" width="700" height="428" /></figure>
</figure>
<p>Откройте файл authorized_keys через WinSCP и файл, в который вы сохранили открытый ключ (public), на локальном компьютере текстовым редактором. Скопируйте значение ключа, сохраните и закройте файл в WinSCP.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-12.png" alt="Сохранение ключа в файле в WinSCP" width="700" height="425" /></figure>
</figure>
<p>При запуске PuTTY укажите путь к закрытому ключу на локальном компьютере. Для этого во вкладке <code>Connections → Auth</code> выберите необходимый путь.</p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-15.png" alt=" Указание пути к закрытому ключу" width="452" height="437" /></figure>
</figure>
<p>Теперь можно отключить на сервере аутентификацию по паролю и использовать только SSH-ключи.</p>
<h2 id="otklyuchenie-autentifikatsii-p"><i class="fa fa-link" aria-hidden="true"></i>Отключение аутентификации по паролю</h2>
<p>Подключитесь к серверу по SSH, используя пароль, и откройте файл sshd_config для редактирования (например, с помощью текстового редактора Vi).</p>
<pre># vi /etc/ssh/sshd_config
</pre>
<p>Убедитесь, что указан правильный путь к открытым ключам SSH, поставьте значение параметра <code>PasswordAuthentication no.</code></p>
<figure>
<figure><img loading="lazy" decoding="async" class="img-responsive" src="https://firstvds.ru/sites/default/files/kcfinder/images/ssh-key-13.png" alt=" Проверка пути к открытым ключам" width="700" height="359" /></figure>
</figure>
<p>Перезапустите службу sshd:</p>
<pre># systemctl restart sshd
</pre>
<figure><a href="https://firstvds.ru/technology/how-to-connect-to-the-server-via-ssh">Подключитесь к серверу по SSH</a> без использования пароля. Например, запустите PuTTY, проверьте, что во вкладке Connections -&gt; Auth содержится путь к закрытому ключу и откройте подключение.</figure>
<pre>Login as: root
Authenticating with public key “rsa-key-20230205”
Last login: Sun Feb  5 13:11:24 2023 from 1.1.1.1</pre>
<p>В случае успешной аутентификации по SSH-ключу вы получите доступ к командной строке сервера и сообщение вида Authenticating with public key &#171;rsa-key-20230205&#187;, где rsa-key-20230205 — имя применённого закрытого ключа, указанное вами в файле authorized_keys.</p>
</div>
</div>
</div>
</div>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[ssh]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/03/1aeeb161a1cefdec1044b25ea6ddf6c9-1024x447.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/ssh-%d1%82%d1%83%d0%bd%d0%bd%d0%b5%d0%bb%d0%b8/</link>
					<title><![CDATA[SSH-туннели]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 12 Mar 2025 07:52:44 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="483" src="https://blog.sefdar.ru/wp-content/uploads/2025/03/5bbc2386288383607baa91dbf486efb6-1024x589.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>SSH-туннели</h1>
													</header>
													<div class="tm-article-presenter__header">
<div class="tm-article-snippet tm-article-snippet tm-article-presenter__snippet"></div>
</div>
<div class="tm-article-body" lang="ru" data-gallery-root="">
<div id="post-content-body">
<div class="article-formatted-body article-formatted-body article-formatted-body_version-2">
<p>Туннели SSH — это зашифрованные TCP-соединения между клиентами и серверами SSH. Трафик входит с одной стороны туннеля и прозрачно выходит с другой. Изначально этот термин относился к туннелям на виртуальных сетевых интерфейсах TUN/TAP, однако сейчас так обычно называют проброс портов SSH.</p>
<p>Например, вот так будет выглядеть схема обратного туннеля, в котором обращение к порту 80 SSH-клиента выполняется через SSH-сервер с определенного IP-адреса (<code>1.2.3.4</code>):</p>
<figure class="full-width "><img loading="lazy" decoding="async" title="Здесь и далее все схемы взяты из оригинала статьи" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/666/9ec/099/6669ec099fd3b71f94cb9bb6d2b27507.png" alt="Здесь и далее все схемы взяты из оригинала статьи" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/666/9ec/099/6669ec099fd3b71f94cb9bb6d2b27507.png" /></p>
<div>
<div></div>
</div><figcaption>Здесь и далее все схемы взяты из оригинала статьи</figcaption></figure>
<p>Сценарии использования туннелей*:</p>
<ul>
<li>Предоставление зашифрованных каналов для протоколов, передающих данные «открытым текстом».</li>
<li>Открытие бэкдоров в частные сети.</li>
<li>Обход межсетевых экранов.</li>
</ul>

*. Примечание
<div class="spoiler__content"></div>

<h2>Проброс портов</h2>
<p>Перенаправляет порт из одной системы (локальной или удаленной) в другую.</p>
<h3>Проброс локального порта</h3>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/543/846/f87/543846f87bf4140c318be4b0c8ff7c3f.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/543/846/f87/543846f87bf4140c318be4b0c8ff7c3f.png" /></figure>
<p>Проброс локальных портов позволяет перенаправить трафик с SSH-клиента на целевой хост через SSH-сервер. Другими словами, можно получить доступ к удаленным сервисам по зашифрованному соединению так, как будто они локальные. Примеры использования:</p>
<ul>
<li>доступ к удаленному сервису (Redis, Memcached и т. д.) по внутреннему IP-адресу;</li>
<li>локальный доступ к ресурсам, размещенным в частной сети;</li>
<li>прозрачное проксирование запроса к удаленному сервису.</li>
</ul>
<h3>Проброс удаленного порта</h3>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/c0a/f21/f08/c0af21f08bc3a36e6851a61e7eb3b122.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/c0a/f21/f08/c0af21f08bc3a36e6851a61e7eb3b122.png" /></figure>
<p>Проброс удаленного порта позволяет направить трафик с SSH-сервера в пункт назначения либо через SSH-клиент, либо через другой удаленный хост. Открывает пользователям в публичных сетях доступ к ресурсам в частных сетях. Примеры использования:</p>
<ul>
<li>открытие доступа к локальному серверу разработки через публичную сеть;</li>
<li>предоставление доступа с ограничением по IP-адресу к удаленному ресурсу в частной сети.</li>
</ul>
<h3>Динамический проброс портов</h3>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/95c/3d6/425/95c3d64257da5ebf081e5e4b865358eb.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/95c/3d6/425/95c3d64257da5ebf081e5e4b865358eb.png" /></figure>
<p>При динамической переадресации портов на SSH-клиенте поднимается SOCKS-прокси для перенаправления TCP-трафика через SSH-сервер на удаленный хост.</p>
<h2>Пересылка с системных (privileged) портов</h2>
<p>Для пересылки трафика с системных портов (1–1023) необходимо запустить SSH с правами суперпользователя в системе, на которой открывается порт.</p>
<pre><code class="bash">sudo ssh -L 80:example.com:80 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/616/8f1/239/6168f1239634e038387e6f1e2a661594.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/616/8f1/239/6168f1239634e038387e6f1e2a661594.png" /></figure>
<h3>Флаги командной строки SSH</h3>
<p>Ниже приведены несколько полезных флагов при создании туннелей:</p>
<pre><code>-f # переводит процесс ssh в фоновый режим;
-n # предотвращает чтение из STDIN;
-N # не выполнять удаленные команды. Полезно, если нужно только перенаправить порты;
-T # отменяет переназначение терминала.</code></pre>
<p>Вот пример команды для создания SSH-туннеля в фоновом режиме и проброса локального порта через SSH-сервер:</p>
<pre><code>ssh -fnNT -L 127.0.0.1:8080:example.org:80 ssh-server</code></pre>
<p>Для краткости примеры ниже приводятся без флагов командной строки.</p>
<h2>Проброс локального порта</h2>
<p>Перенаправление соединений с порта локальной системы на порт удаленного хоста:</p>
<pre><code class="bash">ssh -L 127.0.0.1:8080:example.org:80 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/3ca/80e/5d4/3ca80e5d46d252347cac20abdabaac1e.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/3ca/80e/5d4/3ca80e5d46d252347cac20abdabaac1e.png" /></figure>
<p>Перенаправляет локальные подключения к <em>127.0.0.1:8080</em> на 80-й порт <em>example.org </em>через SSH-сервер. Трафик между локальной системой и SSH-сервером идет по SSH-туннелю. Трафик между SSH-сервером и <em>example.org</em> — нет. С точки зрения <em>example.org</em> трафик идет от SSH-сервера.</p>
<pre><code class="bash">ssh -L 8080:example.org:80 ssh-server</code></pre>
<pre><code class="bash">ssh -L *:8080:example.org:80 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/f7f/a3d/fae/f7fa3dfae5ff89e85beef7f512e45613.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/f7f/a3d/fae/f7fa3dfae5ff89e85beef7f512e45613.png" /></figure>
<p>Команды выше открывают доступ к <em>example.org:80</em> через SSH-туннель для подключений на порт 8080 на всех интерфейсах локальной системы.</p>
<pre><code class="bash">ssh -L 192.168.0.1:5432:127.0.0.1:5432 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/c74/4b6/06b/c744b606b489b1f30db86ecd011d019d.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/c74/4b6/06b/c744b606b489b1f30db86ecd011d019d.png" /></figure>
<p>Переадресует соединения с <em>192.168.0.1:5432</em> в локальной системе на <em>127.0.0.1:5432</em> на SSH-сервере. Обратите внимание, что здесь <em>127.0.0.1</em> — localhost с точки зрения SSH-сервера.</p>
<h3>Конфигурации SSH</h3>
<p>Убедитесь, что на SSH-сервере включена переадресация TCP (по умолчанию так и должно быть). Проверьте запись в файле <code>/etc/ssh/sshd_config</code>:</p>
<pre><code class="bash">AllowTcpForwarding yes</code></pre>
<p>При переадресации портов на интерфейсы, отличные от <em>127.0.0.1</em>, в локальной системе необходимо включить <code>GatewayPorts</code> (в <code>/etc/ssh/ssh_config</code> или в командной строке):</p>
<pre><code class="bash">GatewayPorts yes</code></pre>
<h4>Сценарии использования</h4>
<p>Подходит для случаев, когда требуется защищенное соединение для доступа к удаленному сервису, который работает с незашифрованными данными. Например, Redis и Memcached используют протоколы на основе plaintext-данных.</p>
<p>В случае если защищенный доступ к одному из таких сервисов на удаленном сервере организован по общедоступным сетям, можно настроить туннель от локальной системы до этого сервера.</p>
<h2>Проброс удаленного порта</h2>
<p>Пробрасывает порт на удаленной системе в другую систему.</p>
<pre><code class="bash">ssh -R 8080:localhost:80 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/b6e/83c/f22/b6e83cf22687fb2f21fe4e036772ab4a.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/b6e/83c/f22/b6e83cf22687fb2f21fe4e036772ab4a.png" /></figure>
<p>Перенаправляет трафик с порта 8080 SSH-сервера для всех интерфейсов на порт <em>localhost:80</em> на локальном компьютере. Если один из интерфейсов смотрит в Интернет, трафик, адресуемый на порт 8080, будет перенаправляться на локальную систему.</p>
<pre><code class="bash">ssh -R 1.2.3.4:8080:localhost:80 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/c79/670/176/c79670176698bbb9c4c444042989b179.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/c79/670/176/c79670176698bbb9c4c444042989b179.png" /></figure>
<p>Переадресует трафик с порта 8080 SSH-сервера на <em>localhost:80</em> в локальной системе, при этом доступ ко входу в SSH-туннель со стороны сервера разрешен только с IP-адреса <em>1.2.3.4</em> (обратите внимание: директиву <code>GatewayPorts</code> необходимо установить в <code>clientspecified</code>).</p>
<p><strong><em>Прим. переводчика:</em></strong><em> здесь, возможно, ошибка. Флаг </em><code>-R</code><em> — это </em><code>binding_address</code><em>, выбор IP адреса на машине, на котором SSH-сервер будет слушать порт. Соответственно вместо одного человечка с IP должны быть человечки, а вместо </em><code>ssh_server:8080</code><em> должно быть </em><code>1.2.3.4:8080</code><em>.</em></p>
<pre><code class="bash">ssh -R 8080:example.org:80 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/a1d/ff8/c63/a1dff8c630aef3775b6ca2c0f705ecdf.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/a1d/ff8/c63/a1dff8c630aef3775b6ca2c0f705ecdf.png" /></figure>
<p>Переадресует трафик с порта 8080 SSH-сервера для всех интерфейсов на <em>localhost:80</em> в локальной системе. Далее трафик из локальной системы направляется на <em>example.org:80</em>. С точки зрения <em>example.org</em> источником трафика выступает локальная система.</p>
<h3>Конфигурация SSH-сервера</h3>
<p>SSH-сервер конфигурируется в файле <code>/etc/ssh/sshd_config</code>.</p>
<p>По умолчанию переадресуемые порты недоступны для доступа из Интернета. Для переадресации публичного интернет-трафика на локальный компьютер добавьте в <code>sshd_config</code> на удаленном сервере такую строку:</p>
<pre><code class="bash">GatewayPorts yes</code></pre>
<p>Также в <code>sshd_config</code> можно указать, каким клиентам разрешен доступ:</p>
<pre><code class="bash">GatewayPorts clientspecified</code></pre>
<h2>Динамический проброс портов</h2>
<p>Перенаправление трафика с нескольких портов на удаленный сервер.</p>
<pre><code class="bash">ssh -D 3000 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/d17/b4c/528/d17b4c528329f7abcf9d8ea45921eb04.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/d17/b4c/528/d17b4c528329f7abcf9d8ea45921eb04.png" /></figure>
<p>Команда выше поднимает SOCKS-прокси на порту 3000 для всех интерфейсов в локальной системе. Теперь трафик, отправленный через прокси-сервер на SSH-сервер, можно адресовать на любой порт или конечный хост. По умолчанию используется протокол SOCKS5, поддерживающий TCP и UDP.</p>
<pre><code class="bash">ssh -D 127.0.0.1:3000 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/2c3/82f/26f/2c382f26f04f0717776c8461aee9f75e.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/2c3/82f/26f/2c382f26f04f0717776c8461aee9f75e.png" /></figure>
<p>Поднимает SOCKS-прокси на <em>127.0.0.1:3000</em> в локальной системе.</p>
<p>При работающем SOCKS-прокси можно настроить браузер на его использование для доступа к ресурсам так, как будто соединения исходят от SSH-сервера. Например, если у SSH-сервера есть доступ к другим серверам в частной сети, с помощью SOCKS-прокси можно заходить на эти серверы локально (словно вы находитесь в той же сети), и не нужно настраивать VPN.</p>
<p>Работу SOCKS-прокси можно проверить командой:</p>
<pre><code class="bash">curl -x socks5://127.0.0.1:12345 https://example.org</code></pre>
<h3>Конфигурация SSH-клиента</h3>
<p>SSH-клиент настраивается в файле <code>/etc/ssh/ssh_config</code>.</p>
<p>Включите <code>GatewayPorts</code> в системе, чтобы открыть доступ другим интерфейсам к SOCKS-прокси:</p>
<pre><code>GatewayPorts yes</code></pre>
<p>Поскольку <code>GatewayPorts</code> конфигурируется на SSH-клиенте, вместо <code>ssh_config</code> для настройки можно использовать параметры командной строки:</p>
<pre><code class="bash">ssh -o GatewayPorts=yes -D 3000 ssh-server</code></pre>
<h2>Jump-хосты и команды прокси-сервера</h2>
<p>Прозрачное подключение к удаленному хосту через промежуточные.</p>
<pre><code class="bash">ssh -J user1@jump-host user2@remote-host</code></pre>
<pre><code class="bash">ssh -o "ProxyJump user1@jump-host" user2@remote-host</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/ba0/020/bfd/ba0020bfd39836666f0abcd163fc61f5.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/ba0/020/bfd/ba0020bfd39836666f0abcd163fc61f5.png" /></figure>
<p>Устанавливает SSH-соединение с jump-хостом и переадресуют трафик на удаленный хост.</p>
<p>Подключается к удаленному хосту через промежуточный jump-хост. Приведенная выше команда должна сработать сразу, если у jump-хоста уже есть SSH-доступ к удаленному хосту. Если нет, можно использовать <code>agent forwarding</code> для проброса SSH-ключа с локального компьютера на удаленный хост.</p>
<pre><code class="bash">ssh -J jump-host1,jump-host2 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/6ce/9c4/502/6ce9c45027c73f8e4e843e3354fedb14.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/6ce/9c4/502/6ce9c45027c73f8e4e843e3354fedb14.png" /></figure>
<p>Можно указать несколько jump-хостов через запятую.</p>
<pre><code class="bash">ssh -o ProxyCommand="nc -X 5 -x localhost:3000 %h %p" user@remote-host</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/7a6/a69/0a0/7a6a690a0597228d6e261b90025ed4f1.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/7a6/a69/0a0/7a6a690a0597228d6e261b90025ed4f1.png" /></figure>
<p>Подключение к удаленному серверу через SOCKS5 с использованием <code>netcat</code>. С точки зрения сервера, IP-адрес отправителя принадлежит прокси-хосту. При этом для SSH-соединения используется сквозное шифрование, так что прокси-хост видит только зашифрованный трафик между локальной системой и удаленным хостом.</p>
<h3>Конфигурация SSH-клиента</h3>
<p>SSH-клиент конфигурируется в файле <code>/etc/ssh/ssh_config</code>.</p>
<p>Для подключения <code>agent forwarding</code> можно добавить локальный SSH-ключ к локальному SSH-агенту с помощью <code>ssh-add</code>:</p>
<pre><code class="bash">ssh-add</code></pre>
<h2>Надежные SSH-туннели</h2>
<p>Перечисленные выше команды работают на разовой основе: вы сразу получаете конкретный результат, и на этом их работа заканчивается. Поэтому, чтобы обеспечить защиту SSH-туннелей от сбоев в сети или ненадежных соединений, придется выполнить дополнительную настройку.</p>
<p>По умолчанию TCP-соединение, используемое для создания SSH-туннеля, может разрываться после некоторого периода бездействия. Чтобы это предотвратить, нужно настроить сервер (<code>/etc/ssh/sshd_config</code>) на отправку heartbeat-сообщений:</p>
<pre><code>ClientAliveInterval 15
ClientAliveCountMax 4</code></pre>
<p>На отсылку таких сообщений также можно настроить клиент (<code>/etc/ssh/ssh_config</code>):</p>
<pre><code>ServerAliveInterval 15
ServerAliveCountMax 4</code></pre>
<h3>Использование AutoSSH</h3>
<p>Указанные выше настройки могут предотвратить разрывы из-за неактивности, но они не в состоянии восстановить прерванные соединения. Для автоматического перезапуска SSH-туннеля можно воспользоваться утилитой <code>autossh</code> — она создает SSH-туннель и отслеживает его работоспособность.</p>
<p>AutoSSH принимает те же аргументы для настройки переадресации портов, что и SSH:</p>
<pre><code class="bash">autossh -R 2222:localhost:22 ssh-server</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/090/238/e28/090238e289234f1d1d560e7c278b337e.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/090/238/e28/090238e289234f1d1d560e7c278b337e.png" /></figure>
<p>Эта команда создает туннель, способный восстанавливаться после сетевых сбоев. По умолчанию AutoSSH открывает дополнительные порты на SSH-клиенте/сервере для проверки работоспособности (healthcheck). Если трафик не проходит между healthcheck-портами, AutoSSH перезапускает туннель.</p>
<pre><code class="bash">autossh -R 2222:localhost:22 \
  -M 0 \
  -o "ServerAliveInterval 10" -o "ServerAliveCountMax 3" \
  remote-host</code></pre>
<p>Флаг <code>-M 0</code> отключает healthcheck-порты (за проверку работоспособности в этом случае отвечает SSH-клиент). В примере выше сервер должен посылать сигналы каждые 10 секунд. Если не проходят три подряд сигнала, SSH-клиент завершает работу, а AutoSSH поднимает новый туннель.</p>
<h2>Дополнительные примеры и сценарии использования</h2>
<p>Прозрачный доступ к удаленному ресурсу в частной сети.</p>
<p>Предположим, в частной сети есть Git-репозиторий, доступ к которому возможен только через выделенный сервер в этой сети. Сервер не подключен к Интернету. Есть прямой доступ к серверу, но нет VPN-доступа к частной сети.</p>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/071/96f/3af/07196f3af1adff303b439e5dd3616c5b.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/071/96f/3af/07196f3af1adff303b439e5dd3616c5b.png" /></figure>
<p>Требуется открыть доступ к Git-репозиторию, как если бы подключение к нему шло напрямую из локальной системы. Если есть SSH-доступ к другому серверу, который доступен как с локального компьютера, так и с выделенного сервера, можно создать SSH-туннель и воспользоваться директивами ProxyCommand.</p>
<pre><code class="bash">ssh -L 127.0.0.1:22:127.0.0.1:2222 intermediate-host</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/4c1/42f/496/4c142f4968eae4156941818e193032c2.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/4c1/42f/496/4c142f4968eae4156941818e193032c2.png" /></figure>
<p>Команда выше пробрасывает порт 2222 на промежуточном хосте на порт 22 выделенного сервера. Теперь можно подключиться к SSH-серверу на выделенном сервере, несмотря на то, что он недоступен из Интернета.</p>
<p><strong><em>Прим. переводчика:</em></strong><em> возможно, что здесь тоже ошибка: перепутаны местами 22 и 2222 порты в команде.</em></p>
<pre><code class="bash">ssh -p 2222 user@localhost</code></pre>
<p>Для большего удобства можно добавить несколько директив в локальный <code>~/.ssh/config</code>:</p>
<pre><code class="bash">Host git.private.network
  HostName git.private.network
  ForwardAgent yes
  ProxyCommand ssh private nc %h %p

Host private
  HostName localhost
  Port 2222
  User private-user
  ForwardAgent yes
  ProxyCommand ssh tunnel@intermediate-host nc %h %p</code></pre>
<figure class="full-width "><img loading="lazy" decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/upload_files/b17/511/e73/b17511e738701b686b17d8a1accd1238.png" width="780" height="50" data-src="https://habrastorage.org/getpro/habr/upload_files/b17/511/e73/b17511e738701b686b17d8a1accd1238.png" /></figure>
<p>В результате пользователь получает доступ к локальному Git-репозиторию, как если бы находился в частной сети.</p>
<div class="tm-article-presenter__header">
<div class="tm-article-snippet tm-article-snippet tm-article-presenter__snippet">
<div class="tm-article-snippet__stats" data-test-id="articleStats"><a class="tm-publication-hub__link" href="https://habr.com/ru/companies/flant/articles/">Блог компании Флант</a><a class="tm-publication-hub__link" href="https://habr.com/ru/hubs/linux/">Настройка Linux*</a><a class="tm-publication-hub__link" href="https://habr.com/ru/hubs/sys_admin/">Системное администрирование*</a><a class="tm-publication-hub__link" href="https://habr.com/ru/hubs/nix/">*nix*</a></div>
<div class="tm-article-labels" data-test-id="articleLabels">
<div class="tm-article-labels__container">
<div class="tm-publication-label tm-publication-label_variant-translation">Перевод</div>
</div>
</div>
</div>
</div>
<div class="tm-article-presenter__origin"><a class="tm-article-presenter__origin-link" href="https://robotmoon.com/ssh-tunnels/" target="_blank" rel="noopener">Автор оригинала: Linmiao Xu</a></div>
<div class="tm-article-body" lang="ru" data-gallery-root="">
<div></div>
<div id="post-content-body">
<div class="article-formatted-body article-formatted-body article-formatted-body_version-2">
<p><strong><em>Прим. переводчика:</em></strong><em> автор статьи рассматривает практические сценарии и примеры организации SSH-туннелей. А для более наглядного объяснения того, как это работает, графически показывает потоки трафика.</em></p>
</div>
</div>
</div>
</div>
</div>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[ssh]]></category><category><![CDATA[tunels]]></category><category><![CDATA[тунели]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2025/03/5bbc2386288383607baa91dbf486efb6-1024x589.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/windows-server-2019-%d1%82%d0%b5%d1%80%d0%bc%d0%b8%d0%bd%d0%b0%d0%bb%d1%8c%d0%bd%d1%8b%d0%b9-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80-%d0%b1%d0%b5%d0%b7-%d0%b4%d0%be%d0%bc%d0%b5%d0%bd%d0%b0/</link>
					<title><![CDATA[Windows Server 2019 &#8212; терминальный сервер без домена]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 29 Nov 2024 07:56:16 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="810" height="428" src="https://blog.sefdar.ru/wp-content/uploads/2024/11/Windows-Server-Logo.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Windows Server 2019 &#8212; терминальный сервер без домена</h1>
													</header>
													<p>Установим роли терминального сервера на Windows Server 2019 и лицензируем. Маленькая тонкость — сервер не в домене.</p>
<h3>Подготовка Windows Server 2019</h3>
<p>Для начала установим сам сервер. Всё необходимое вынесено в отдельную статью:</p>
<p><a href="https://internet-lab.ru/windows_server_2019_install_vmware" target="_blank" rel="noopener">Установка Windows Server 2019 на виртуальную машину VMware</a></p>
<p>Итак, операционная система установлена и настроена. Сервер в рабочей группе WORKGROUP.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_1.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_1.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="228b0744-8806-4237-a328-72452328eaf2" /></a></p>
<h3>Установка роли терминального сервера</h3>
<p>Нам понадобится установить две роли, можно выполнить установку одновременно, я предлагаю инструкцию с минимальным количеством перезагрузок.</p>
<h4>Роль Remote Desktop Licensing</h4>
<p>Входим в Server Manager. Справа вверху выбираем Manage &gt; Add Roles and Features.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_2.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_2.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="316157a1-dc7d-4c45-b666-680cabfd8a40" /></a></p>
<p>Попадаем в раздел Before You Begin.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_3.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_3.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="27c3f4b7-b27c-4a51-aa7c-47571797d925" /></a></p>
<p>Это начальная страница, пропускаем. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_4.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_4.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="8797fb42-1201-4cf4-b231-4993a8742a13" /></a></p>
<p>Попадаем в раздел Installation Type. Для установки сервиса удаленных рабочих столов предусмотрен специальный мастер <strong>Remote Desktop Services installation</strong>, но нам не удастся его использовать, поскольку сервер не в домене. Выбираем <strong>Role-based or feature-based installation</strong>. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_5.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_5.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="2e08963c-3138-436e-a63d-150deed72eed" /></a></p>
<p>Попадаем в раздел Server Selection. Выбираем текущий сервер. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_6.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_6.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="f94a37b5-8523-4480-b740-b927906d196d" /></a></p>
<p>Попадаем в раздел Server Roles. Выделяем галкой роль <strong>Remote Desktop Services</strong>. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_7.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_7.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="7a5a4138-d702-4c12-83f6-ab8a33301f1b" /></a></p>
<p>Попадаем в раздел Features. Здесь ничего дополнительно не выбираем. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_8.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_8.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="61d65567-98b2-4e62-a866-461dc2cc7a25" /></a></p>
<p>Попадаем в раздел Remote Desktop Services. Ненужное нам окошко. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_9.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_9.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="9b1defe4-d4e0-468a-9fee-287eba108725" /></a></p>
<p>Попадаем в раздел Role Services. Первая роль, которую нам нужно установить, это <strong>Remote Desktop Licensing</strong>. Выделяем галкой.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_10.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_10.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="55d0a748-58bd-4077-92fe-697a599f110c" /></a></p>
<p>Нам предлагают установить дополнительные фичи, которые требуются для данной роли. Соглашаемся, Add Features.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_11.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_11.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="1d37c6d1-6ee3-4052-9459-0d1124cdbe69" /></a></p>
<p><strong>Remote Desktop Licensing</strong> выделено галкой, Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_12.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_12.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="91caa002-c31e-4f85-9f05-2da28adeabd4" /></a></p>
<p>Попадаем в раздел Confirmation. Install.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_13.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_13.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="79e9721c-b258-41c2-a2fc-44f9509c5ef2" /></a></p>
<p>Начинается установка роли.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_14.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_14.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="4a05ba9f-d47d-4266-ac57-e3cac8754aaf" /></a></p>
<p>Роль <strong>Remote Desktop Licensing</strong> успешно установлена. Примечательно, что перезагрузка не требуется.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_15.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_15.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="5f4420ea-2fcf-4732-8a35-3ec72be5cc96" /></a></p>
<p>Открываем Windows Administrative Tools.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_16.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_16.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="3878b416-94c2-4b98-b917-12a9e6f959f3" /></a></p>
<p>Переходим в папку Remote Desktop Services.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_17.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_17.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="f0f03d7e-ce5d-43cd-b8a5-2640e936fe5e" /></a></p>
<p>Запускаем оснастку <strong>Remote Desktop Licensing Manager</strong>.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_18.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_18.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="79f6cf8d-3d68-48a4-933f-77365f23d98a" /></a></p>
<p>Выбираем наш сервер, правой кнопкой — активировать.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_19.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_19.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="01ff6de8-14a6-4a15-aa09-9870e93a1ba6" /></a></p>
<p>Открывается окно активации. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_20.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_20.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="2be702c6-72d5-44d1-9f42-624b70f539eb" /></a></p>
<p>Выбираем метод соединения Web Browser. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_21.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_21.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="9c162501-2719-43ea-aa1d-ddfe0d489ba7" /></a></p>
<p>Получаем код продукта который нам понадобится для активации (Product ID). Копируем.</p>
<p>В браузере открываем сайт <a href="https://activate.microsoft.com/" target="_blank" rel="noopener">https://activate.microsoft.com/</a></p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_22.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_22.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="e3fa636f-9fd9-4cdb-99ca-3d0b28afe89c" /></a></p>
<p>Выбираем &#171;Activate a license server&#187;. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_23.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_23.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="91a6274c-ed1d-48fd-b657-be5a90d02e1f" /></a></p>
<p>Вводим Product ID полученный ранее, организацию и любую страну или регион. Next. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_24.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_24.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="fc752bb5-961d-408a-acf1-57d8d3f90f28" /></a></p>
<p>Если все сделано правильно, то мы получим необходимый код сервера лицензирования. Копируем его. На вопрос &#171;Do you wish to install client access licenses now on the license server with this product ID?&#187; отвечаем &#171;Yes&#187; и пока возвращаемся к терминальному серверу, к текущему окну ещё вернёмся.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_25.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_25.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="ec42b57a-9d0e-4229-aec0-d821d03a03af" /></a></p>
<p>Вводим код в открытом мастере, жмём Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_26.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_26.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="11abcdf3-2ef5-47b5-8b59-8adcfc479774" /></a></p>
<p>Устанавливаем галку &#171;Start Install Licenses Wizard now&#187;. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_27.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_27.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="12a195ad-a9a1-44c7-bfac-fe0171885718" /></a></p>
<p>Открывается мастер установки лицензий. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_28.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_28.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="0f407ea9-f392-4df1-8d1f-71015bef5365" /></a></p>
<p>Нас просят ввести <strong>license key pack ID</strong>. Возвращаемся к браузеру.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_29.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_29.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="e75388d6-9281-4726-bb7a-cbfd78b4ed07" /></a></p>
<p>Вставляем License Server ID, в качестве программы лицензирования, по идее он уже должен сюда переместиться из предыдущего окна. License Program выбираем Enterprise agreement. Указываем компанию и страну. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_30.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_30.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="a76348ff-1441-4e91-bc73-92d504c62aab" /></a></p>
<p>Выбираем тип продукта: <strong>Windows Server 2019 Remote Desktop Services Per Device client access license</strong>. Указываем количество лицензий. Обязательно соглашение Enterprise agreement, или ищем в интернете который подойдет…</p>
<p><a href="https://internet-lab.ru/windows_server_2016_terminal" target="_blank" rel="noopener">Настройка и лицензирование терминального сервера Windows Server 2016</a></p>
<p>Не стоит выбирать лицензии <strong>Per User,</strong> иначе потом вы получите такую ошибку:</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/err_rds.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/err_rds.png" alt="win" width="754" height="264" data-entity-type="file" data-entity-uuid="c11a23f8-f116-4f4c-9aa2-e05f5aebc07a" /></a></p>
<p>Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_31.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_31.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="91d03103-4e3b-42da-aaf1-4c884fcf9e7a" /></a></p>
<p>Ну вот мы и получили нужные нам клиентские лицензии. Копируем.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_32.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_32.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="01975111-35a5-48c5-9ff0-e58b1c56a6dc" /></a></p>
<p>Вводим ключ в мастер. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_33.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_33.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="09651d5e-7e12-49bf-9017-a54cfbb07f81" /></a></p>
<p>Finish.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_34.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_34.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="33c4214c-6ca8-4452-a470-577aee3c78d9" /></a></p>
<p>Возвращаемся к Remote Desktop Licensing Manager. Сервер активирован. Лицензии получены. Кстати, они начнут тратиться после окончания триального периода.</p>
<h4>Роль Remote Desktop Session Host</h4>
<p>Входим в Server Manager. Справа вверху выбираем Manage &gt; Add Roles and Features.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_36.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_36.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="be63de75-5cb1-4348-9113-06754b39fa9b" /></a></p>
<p>Попадаем в раздел Before You Begin.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_37.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_37.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="aaa9378a-53c0-48e8-881b-c30a6e8536db" /></a></p>
<p>Это начальная страница, пропускаем. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_38.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_38.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="a996a9b5-b195-48dc-b07b-821f5d499f91" /></a></p>
<p>Попадаем в раздел Installation Type. Выбираем <strong>Role-based or feature-based installation</strong>. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_39.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_39.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="5752e0c1-086e-4a58-9639-4b6e6faa71e3" /></a></p>
<p>Попадаем в раздел Server Selection. Выбираем текущий сервер. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_40.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_40.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="d488b87d-03c0-4585-a630-f8db3b7d74e5" /></a></p>
<p>Попадаем в раздел Server Roles. Выделяем галкой роль <strong>Remote Desktop Session Host</strong>.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_41.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_41.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="0a298ee2-cef3-49df-9b5d-b639551d77cd" /></a></p>
<p>Нам предлагают установить дополнительные фичи, соглашаемся. Add Features.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_42.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_42.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="b174a543-9919-49ba-afde-d131d4ce26ec" /></a></p>
<p>Роль <strong>Remote Desktop Session Host</strong> выделена. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_43.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_43.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="aa087b77-9196-47af-859d-ec85c52c4e91" /></a></p>
<p>Попадаем в раздел Features, ничего не выделяем. Next.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_44.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_44.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="79e46ec4-9b56-47ac-8dae-276784f0a8d9" /></a></p>
<p>Попадаем в раздел Confirmation. Ставим галку <strong>Restart the destination server automatically if required</strong>. Отображается предупреждение, что сервер может быть перезагружен. Yes.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_45.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_45.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="9fd612d0-5df0-4df7-a3c8-6c1d3141c413" /></a></p>
<p>Install.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_46.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_46.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="ccb7749c-05b8-4f12-9388-2d835c64309a" /></a></p>
<p>Начинается процесс установки роли.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_47.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_47.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="a838f1f1-1f04-4939-b9a8-2115fd76e51a" /></a></p>
<p>Сервер перезагружается.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_48.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_48.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="fe0c10e6-ee16-4ba0-b79c-d0be3b6e6fa3" /></a></p>
<p>В процессе устанавливаются компоненты.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_49.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_49.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="a807f3e4-e1dd-4e21-a7f8-dabd7e0e6971" /></a></p>
<p>После перезагрузки автоматически продолжается установка роли. Триальный период работы терминального сервера — 119 дней.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_50.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_50.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="e028cfe3-c4e8-4037-8a23-db98254b1eb0" /></a></p>
<p>Роль <strong>Remote Desktop Session Host </strong>успешно установлена. Close.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_51.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_51.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="3c2cea3d-f3b7-4927-8adb-ca888492a2f8" /></a></p>
<p>Открываем Windows Administrative Tools.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_52.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_52.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="7fd711e2-4f7c-4a72-bd9b-4e69a06af97a" /></a></p>
<p>Переходим в папку Remote Desktop Services.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_53.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_53.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="db10022e-77a9-4c89-9a45-d48abde7a5ab" /></a></p>
<p>&nbsp;</p>
<p>Запускаем оснастку <strong>Remote Desktop Licensing Diagnoser</strong>.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_54.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_54.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="fc83775f-fdba-4f82-9de7-76429e4f956e" /></a></p>
<p>Видим ошибку.</p>
<blockquote><p>The licensing mode for Remote Desktop Session Host server is not configured.</p></blockquote>
<p>Выполняем gpedit.msc.</p>
<pre><code>gpedit.msc</code></pre>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_55.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_55.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="c685cb50-1445-480c-bbfd-c2d8de91422e" /></a></p>
<p>Откроется Local Group Policy Editor.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_56.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_56.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="3c7f4ff7-4613-4683-90b8-017b0e83c0d8" /></a></p>
<p>Раскрываем Computer Configuration &gt; Administrative Templates &gt; Windows Components &gt; Remote Desktop Services &gt; Remote Desktop Session Host &gt; Licensing.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_57.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_57.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="919ca38c-6f60-4538-abf0-18a7910186a1" /></a></p>
<p>Редактируем <strong>Use the specified Remote Desktop license servers</strong>.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_58.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_58.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="6827593c-c280-48be-b555-6d7dcbc72218" /></a></p>
<p>Включаем — Enabled. В поле &#171;License server to use&#187; прописываем сервер, с которого получать лицензии, в моём случае &#171;localhost&#187;. OK.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_59.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_59.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="b702945f-cf2c-480e-afed-3fd32cfe0e2c" /></a></p>
<p>Редактируем <strong>Set the Remote Desktop licensing mode</strong>.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_60.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_60.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="f477e94a-29d4-4d3f-ab8a-7c2042795d29" /></a></p>
<p>Включаем — Enabled. В поле &#171;Specify the licensing mode for the RD Session Host server&#187; устанавливаем значение <strong>Per Device</strong>. OK.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_61.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_61.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="fa0ad5bd-65db-4772-b684-c7e641084eba" /></a></p>
<p>Снова запускаем оснастку <strong>Remote Desktop Licensing Diagnoser</strong>. Теперь всё зелёное, ошибок нет.</p>
<h3>Практические испытания</h3>
<p>Поскольку мы с вами системные администраторы 99 уровня, то нам нужно провести практические испытания терминального сервера.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_62.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_62.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="83d94149-1ac6-47c1-8c56-90ac4ee6c780" /></a></p>
<p>На терминальном сервере создаём трёх локальных пользователей: user1, user2, user3.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_63.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_63.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="3e3fcd64-78e8-428b-90a0-4479c8190a46" /></a></p>
<p>Включаем их в группу <strong>Remote Desktop Users</strong>.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/users_term.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/users_term.png" alt="win" width="914" height="638" data-entity-type="file" data-entity-uuid="7ae1674f-687e-42a4-b0ab-094925c425a5" /></a></p>
<p>Коннектимся под этими пользователями к терминальному серверу по RDP.</p>
<p><a class="colorbox cboxElement" href="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_64.png" data-colorbox-gallery="ckeditor-colorbox-inline" data-once="init-colorbox"><img loading="lazy" decoding="async" src="https://internet-lab.ru/sites/internet-lab.ru/files/inline-images/terminal2019_workgroup_64.png" alt="win" width="1026" height="833" data-entity-type="file" data-entity-uuid="d1746a75-9b61-406e-8fe7-b6fc3d255ca1" /></a></p>
<p>Есть три активных сеанса.</p>
<h3>Заключение</h3>
<p>Мы с вами успешно создали терминальный сервер Windows Server 2019 в рабочей группе WORKGROUP без домена. 120 дней терминальный сервер будет работать в триальном режиме, затем начнёт использовать лицензии Per Device. Для подключения к терминальному серверу требуется создать локальную учётную запись и включить её в группу Remote Desktop Users.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[windows]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/11/Windows-Server-Logo.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-nextcloud/</link>
					<title><![CDATA[Установка Nextcloud]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Tue, 26 Nov 2024 07:49:39 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/11/47895a00-3aef-11ea-97c9-db1565d05c79-1024x576.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Установка Nextcloud</h1>
													</header>
													
<div class="sub-title-widget-area">Прежде чем ставить Nextcloud по этой инструкции, вначале установите LEMP-стек. </div>
<div class="entry-content">
<h2 class="wp-block-heading">Шаг 1: Скачиваем Nextcloud</h2>
<p>Зайдите на сервер и загрузите на него архив Nextcloud. Последняя стабильная версия 29.0.4 на момент публикации. Скачать её можно на <a href="https://nextcloud.com/install/" target="_blank" rel="noreferrer noopener" aria-label=" (откроется в новой вкладке)">https://nextcloud.com/install</a>, раздел «Download server» пункт COMMUNITY PROJECTS и выбрать кнопку «Download for server».</p>
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" class="wp-image-3373" src="https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-799x1024.png" sizes="auto, (max-width: 799px) 100vw, 799px" srcset="https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-799x1024.png 799w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-234x300.png 234w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-117x150.png 117w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-1198x1536.png 1198w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-1597x2048.png 1597w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_14-31-16-624x800.png 624w" alt="" width="799" height="1024" /></figure>
<p>Можно wget’ом скачать его на сервер сразу же. Так и сделаем. Скачаем последнюю версию.</p>
<pre class="wp-block-preformatted">wget https://download.nextcloud.com/server/releases/latest.tar.bz2</pre>
<p>Распакуем</p>
<pre class="wp-block-preformatted">sudo tar -xjf latest.tar.bz2 -C /usr/share/nginx/</pre>
<p>Опция -C указывает путь, куда распакуется Nextcloud.</p>
<p>Если в процессе распаковки появилась ошибка «<em>tar (child): bzip2: Cannot exec: No such file or directory</em>«, то установите пакет bzip2.</p>
<pre class="wp-block-preformatted">sudo apt install bzip2</pre>
<p>Изменим владельца файлов для корректной работы сервера</p>
<pre class="wp-block-preformatted">sudo chown www-data: /usr/share/nginx/nextcloud/ -R</pre>
<h2 class="wp-block-heading">Шаг 2. Создаём базу данных для Nextcloud</h2>
<p>Логинимся на сервер MariaDB нижеследующей командой. С тех пор как MariaDB стала использовать плагин unix_socket для аутентификации, необходимость вводить root пароль отпала. Просто запустим оболочку под sudo.</p>
<pre class="wp-block-preformatted">sudo mariadb</pre>
<p>Запуститься оболочка MySQL сервера MariaDB. Начнём процесс установки.</p>
<p>Создадим базу данных для Nextcloud</p>
<pre class="wp-block-preformatted">create database nextcloud;</pre>
<p>Создадим пользователя, у которого будут права на эту базу и который будет ей управлять. Имя можно выбрать любое, главное запомнить его. Вместо your-password подставьте свой придуманный пароль.</p>
<pre class="wp-block-preformatted">create user nextclouduser@localhost identified by 'your-password';</pre>
<p>Выдайте новому пользователю права на новую базу данных</p>
<pre class="wp-block-preformatted">grant all privileges on nextcloud.* to nextclouduser@localhost identified by 'your-password';</pre>
<p>Примените изменения</p>
<pre class="wp-block-preformatted">flush privileges;

exit;</pre>
<h2 class="wp-block-heading">Шаг 3. Создаём конфигурационный файл nginx для Nextcloud.</h2>
<p>Создайте файл nextcloud.conf в директории /etc/nginx/conf.d/</p>
<pre class="wp-block-preformatted">sudo nano /etc/nginx/conf.d/nextcloud.conf</pre>
<p>Файл описан в <a href="https://docs.nextcloud.com/server/latest/admin_manual/installation/nginx.html" target="_blank" rel="noreferrer noopener">инструкции на сайте</a> разработчиков</p>
<p>Вставьте нижеследующий текст в новый файл. Жирным начертанием выделены строки на замену</p>
<pre class="wp-block-preformatted">upstream php-handler {
    server unix:/run/php/php8.3-fpm.sock;
}

# Set the `immutable` cache control options only for assets with a cache busting `v` argument
map $arg_v $asset_immutable {
    "" "";
    default ", immutable";
}

server {
    listen 80;
    listen [::]:80;
    server_name <strong>cloud.example.com</strong>;

    # Prevent nginx HTTP Server Detection
    server_tokens off;

    # Enforce HTTPS
    return 301 https://$server_name$request_uri;
}

server {
    listen 443      ssl http2;
    listen [::]:443 ssl http2;
    server_name <strong>cloud.example.com</strong>;

    # Path to the root of your installation
    root /usr/share/nginx/nextcloud;

    # Use Mozilla's guidelines for SSL/TLS settings
    # https://mozilla.github.io/server-side-tls/ssl-config-generator/
    ssl_certificate     /etc/nginx/cert/<strong>server.crt</strong>;
    ssl_certificate_key /etc/nginx/cert/<strong>server.key</strong>;

    # Prevent nginx HTTP Server Detection
    server_tokens off;

    # HSTS settings
    # WARNING: Only add the preload option once you read about
    # the consequences in https://hstspreload.org/. This option
    # will add the domain to a hardcoded list that is shipped
    # in all major browsers and getting removed from this list
    # could take several months.
    #add_header Strict-Transport-Security "max-age=15768000; includeSubDomains; preload" always;

    # set max upload size and increase upload timeout:
    client_max_body_size 512M;
    client_body_timeout 300s;
    fastcgi_buffers 64 4K;

    # Enable gzip but do not remove ETag headers
    gzip on;
    gzip_vary on;
    gzip_comp_level 4;
    gzip_min_length 256;
    gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
    gzip_types application/atom+xml text/javascript application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;

    # Pagespeed is not supported by Nextcloud, so if your server is built
    # with the `ngx_pagespeed` module, uncomment this line to disable it.
    #pagespeed off;

    # The settings allows you to optimize the HTTP2 bandwidth.
    # See https://blog.cloudflare.com/delivering-http-2-upload-speed-improvements/
    # for tuning hints
    client_body_buffer_size 512k;

    # HTTP response headers borrowed from Nextcloud `.htaccess`
    add_header Referrer-Policy                   "no-referrer"       always;
    add_header X-Content-Type-Options            "nosniff"           always;
    add_header X-Frame-Options                   "SAMEORIGIN"        always;
    add_header X-Permitted-Cross-Domain-Policies "none"              always;
    add_header X-Robots-Tag                      "noindex, nofollow" always;
    add_header X-XSS-Protection                  "1; mode=block"     always;

    # Remove X-Powered-By, which is an information leak
    fastcgi_hide_header X-Powered-By;

    # Set .mjs and .wasm MIME types
    # Either include it in the default mime.types list
    # and include that list explicitly or add the file extension
    # only for Nextcloud like below:
    include mime.types;
    types {
        text/javascript mjs;
	application/wasm wasm;
    }

    # Specify how to handle directories -- specifying `/index.php$request_uri`
    # here as the fallback means that Nginx always exhibits the desired behaviour
    # when a client requests a path that corresponds to a directory that exists
    # on the server. In particular, if that directory contains an index.php file,
    # that file is correctly served; if it doesn't, then the request is passed to
    # the front-end controller. This consistent behaviour means that we don't need
    # to specify custom rules for certain paths (e.g. images and other assets,
    # `/updater`, `/ocs-provider`), and thus
    # `try_files $uri $uri/ /index.php$request_uri`
    # always provides the desired behaviour.
    index index.php index.html /index.php$request_uri;

    # Rule borrowed from `.htaccess` to handle Microsoft DAV clients
    location = / {
        if ( $http_user_agent ~ ^DavClnt ) {
            return 302 /remote.php/webdav/$is_args$args;
        }
    }

    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    # Make a regex exception for `/.well-known` so that clients can still
    # access it despite the existence of the regex rule
    # `location ~ /(\.|autotest|...)` which would otherwise handle requests
    # for `/.well-known`.
    location ^~ /.well-known {
        # The rules in this block are an adaptation of the rules
        # in `.htaccess` that concern `/.well-known`.

        location = /.well-known/carddav { return 301 /remote.php/dav/; }
        location = /.well-known/caldav  { return 301 /remote.php/dav/; }

        location /.well-known/acme-challenge    { try_files $uri $uri/ =404; }
        location /.well-known/pki-validation    { try_files $uri $uri/ =404; }

        # Let Nextcloud's API for `/.well-known` URIs handle all other
        # requests by passing them to the front-end controller.
        return 301 /index.php$request_uri;
    }

    # Rules borrowed from `.htaccess` to hide certain paths from clients
    location ~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)  { return 404; }
    location ~ ^/(?:\.|autotest|occ|issue|indie|db_|console)                { return 404; }

    # Ensure this block, which passes PHP files to the PHP process, is above the blocks
    # which handle static assets (as seen below). If this block is not declared first,
    # then Nginx will encounter an infinite rewriting loop when it prepends `/index.php`
    # to the URI, resulting in a HTTP 500 error response.
    location ~ \.php(?:$|/) {
        # Required for legacy support
        rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri;

        fastcgi_split_path_info ^(.+?\.php)(/.*)$;
        set $path_info $fastcgi_path_info;

        try_files $fastcgi_script_name =404;

        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $path_info;
        fastcgi_param HTTPS on;

        fastcgi_param modHeadersAvailable true;         # Avoid sending the security headers twice
        fastcgi_param front_controller_active true;     # Enable pretty urls
        fastcgi_pass php-handler;

        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;

        fastcgi_max_temp_file_size 0;
    }

    # Serve static files
    location ~ \.(?:css|js|mjs|svg|gif|ico|jpg|png|webp|wasm|tflite|map|ogg|flac)$ {
        try_files $uri /index.php$request_uri;
        # HTTP response headers borrowed from Nextcloud `.htaccess`
        add_header Cache-Control                     "public, max-age=15778463$asset_immutable";
        add_header Referrer-Policy                   "no-referrer"       always;
        add_header X-Content-Type-Options            "nosniff"           always;
        add_header X-Frame-Options                   "SAMEORIGIN"        always;
        add_header X-Permitted-Cross-Domain-Policies "none"              always;
        add_header X-Robots-Tag                      "noindex, nofollow" always;
        add_header X-XSS-Protection                  "1; mode=block"     always;
        access_log off;     # Optional: Don't log access to assets
    }

    location ~ \.woff2?$ {
        try_files $uri /index.php$request_uri;
        expires 7d;         # Cache-Control policy borrowed from `.htaccess`
        access_log off;     # Optional: Don't log access to assets
    }

    # Rule borrowed from `.htaccess`
    location /remote {
        return 301 /remote.php$request_uri;
    }

    location / {
        try_files $uri $uri/ /index.php$request_uri;
    }
}</pre>
<h3 class="wp-block-heading">Включение HTTPS</h3>
<p class="has-very-light-gray-background-color has-background">[…]Здесь в оригинале были шаги по включению https, но я считаю это темой отдельной статьи, так как там используется получение сертификатов через LetsEncrypt. Можете глянуть в оригинале. […]</p>
<p>Но если кратко, то рекомендую создать в папке nginx самоподписные сертификаты</p>
<pre class="wp-block-preformatted">sudo mkdir /etc/nginx/cert
cd /etc/nginx/cert</pre>
<pre class="wp-block-preformatted">sudo openssl req -x509 -newkey rsa:4096 -keyout server.key -out server.crt -nodes -days 3650 -subj '/CN=localhost'</pre>
<p>Не забудьте перезапустить nginx</p>
<pre class="wp-block-preformatted">sudo systemctl reload nginx</pre>
<p>После всего на обратном прокси (если он у вас есть конечно) можете указать путь до этого сервера по https протоколу.</p>
<h2 class="wp-block-heading">Шаг 4. Установка php-модулей.</h2>
<p>Выполните нижеприведённую команду, чтобы установить требуемые или рекомендованные модули php для Nextcloud.</p>
<pre class="wp-block-preformatted">sudo apt install php-imagick php8.3-zip php8.3-bz2 php8.3-intl</pre>
<h2 class="wp-block-heading">Финиш. Заключительные штрихи</h2>
<p>Для большей безопасности поменяем папку с данными и не будем хранить их в корне веб-сервера. Расположим их, например, в<br />
<strong>/usr/share/nginx/nextcloud-data</strong>, используя следующую команду</p>
<pre class="wp-block-preformatted">sudo mkdir /usr/share/nginx/nextcloud-data</pre>
<p>Сделаем владельцем этого каталога пользователя www-data</p>
<pre class="wp-block-preformatted">sudo chown www-data: /usr/share/nginx/nextcloud-data -R</pre>
<p>P.S. Если вы следовали советам по установке LEMP, то удалите файл default.conf. Если его не удалить, то будет показываться окно приветственной страницы nginx.</p>
<pre class="wp-block-preformatted">sudo rm /etc/nginx/conf.d/default.conf</pre>
<p>Можно ещё удалить файл default в /etc/nginx/sites-enabled/, если вы хотите заходить на nextcloud по http и сделали необходимые изменения в файле конфига.</p>
<pre class="wp-block-preformatted">sudo rm /etc/nginx/sites-enabled/default.conf</pre>
<p>Теперь заходим на https://nextcloud_IP/ и видим окно установки. (Или заходим на http://nextcloud_ip/, если отключили в конфиге nginx https)</p>
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" class="wp-image-3374" src="https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55-1024x987.png" sizes="auto, (max-width: 1024px) 100vw, 1024px" srcset="https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55-1024x987.png 1024w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55-300x289.png 300w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55-150x145.png 150w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55-1536x1481.png 1536w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55-624x602.png 624w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-41-55.png 1956w" alt="" width="1024" height="987" /></figure>
<p>&nbsp;</p>
<p>Вводим имя администратора, придумываем пароль. Ниже указываем путь до каталога данных Nextcloud, вписываем учётную запись базы данных («nextclouduser»), пароль пользователя к базе данных (в данном случае это «your-password»), имя базы данных («nextcloud»). Жмём кнопку «Установить» и переходим к следующему шагу.</p>
<p>На этом шаге можете поставить рекомендуемые приложения, а можете пропустить установку.</p>
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" class="wp-image-3375" src="https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-43-50-916x1024.png" sizes="auto, (max-width: 916px) 100vw, 916px" srcset="https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-43-50-916x1024.png 916w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-43-50-268x300.png 268w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-43-50-134x150.png 134w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-43-50-624x698.png 624w, https://kurazhov.ru/wp-content/uploads/2024/08/2024-08-17_15-43-50.png 1218w" alt="" width="916" height="1024" /></figure>
<p>Установка завершена. Вас будет приветствовать стартовый экран Nextcloud с кратким описанием возможностей. Как видно, заметных отличий от установки в Ubuntu 20 нет. Но для быстрой установки, чтобы не путаться в версиях php-fpm я написал данную статью.</p>
<p>Впереди немного настроек и настройка резервного копирования. Ну и если хочется посмотреть видео установки, то оно ниже — основано на статье про установку Nextcloud на Ubuntu 18.</p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Cloud]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/11/47895a00-3aef-11ea-97c9-db1565d05c79-1024x576.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%82%d1%8e%d0%bd%d0%b8%d0%bd%d0%b3-nextcloud/</link>
					<title><![CDATA[Тюнинг Nextcloud]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Tue, 26 Nov 2024 07:33:25 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/11/47895a00-3aef-11ea-97c9-db1565d05c79-1024x576.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Тюнинг Nextcloud</h1>
													</header>
													<div class="sub-title-widget-area">UPD 2024.08.17. Скоро статья обновится на использование Ubuntu 24 и, соответственно, php версии 8.3. Разницы в настройке почти нет, просто на старых системах придётся вручную менять версии.</div>
<div class="entry-content">
<p>После <a href="https://kurazhov.ru/install-nextcloud-ubuntu-18-lemp/">установки Nextcloud</a> им можно сразу же пользоваться. (А если вы здесь по вопросу отключения техобслуживания Nextcloud, то вот команда — sudo -u www-data php /path/to/nextcloud/occ maintenance:mode —off (перед off ставьте два дефиса) )</p>
<p>Но, если вам хочется большей производительности, а также не хочется видеть предупреждение о текущей конфигурации, которое будет видно каждый раз при заходе в административную панель, то следующие советы для вас.</p>
<figure class="wp-block-image"><img loading="lazy" decoding="async" class="wp-image-1938" src="https://kurazhov.ru/wp-content/uploads/2019/02/2019-02-16_01-39-38-1024x219.png" sizes="auto, (max-width: 1024px) 100vw, 1024px" srcset="https://kurazhov.ru/wp-content/uploads/2019/02/2019-02-16_01-39-38-1024x219.png 1024w, https://kurazhov.ru/wp-content/uploads/2019/02/2019-02-16_01-39-38-150x32.png 150w, https://kurazhov.ru/wp-content/uploads/2019/02/2019-02-16_01-39-38-300x64.png 300w, https://kurazhov.ru/wp-content/uploads/2019/02/2019-02-16_01-39-38-624x134.png 624w, https://kurazhov.ru/wp-content/uploads/2019/02/2019-02-16_01-39-38.png 1588w" alt="" width="1024" height="219" /></figure>
<p>Как и ранее я писал, Nextcloud стоит на Ubuntu 18.04 и работает под связкой nginx + php-fpm (версии 7.4) + mysql. Язык интерфейса — русский. Nextcloud установлен в /usr/share/nginx/nextcloud/</p>
<p>После внесения изменений не забываем перезапускать php-fpm. Или можете после применения всех изменений перезапустить его один раз.</p>
<p id="0"><strong><em>Содержание:</em></strong></p>
<ol class="wp-block-list">
<li><a href="#1">PHP не настроен правильно для получения переменных системного окружения.</a></li>
<li><a href="#2">PHP OPcache не настроен правильно</a></li>
<li><a href="#3">Некоторые индексы базы данных не были преобразованы в тип big int</a></li>
<li><a href="#4">Разрешённое максимальное значение использования памяти PHP ниже рекомендуемого значения в 512 МБ</a></li>
<li><a href="#5">Не настроена система кеширования</a></li>
<li><a href="#6">В базе данных отсутствуют некоторые индексы</a></li>
<li><a href="#6">MySQL используется в качестве базы данных, но не поддерживает 4-байтовые символы</a></li>
<li><a href="#8">Задействован устаревший режим шифрования файлов на стороне сервера</a></li>
<li><a href="#9">Настройка обратного прокси для доступа</a></li>
<li><a href="#10">Заголовок HTTP «X-Frame-Options» не настроен на значение «SAMEORIGIN»</a></li>
<li><a href="#11">Новый dashboard</a></li>
<li><a href="#12">Модуль php-imagick и SVG</a></li>
<li><a href="#13">Регион размещения сервера</a></li>
<li><a href="#14">Файлы .mjs</a></li>
<li><a href="#15">Время обслуживания</a></li>
</ol>
<p><a name="1"></a></p>
<h2>Убираем первое предупреждение:</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>«PHP не настроен правильно для получения переменных системного окружения.</p>
<p>Запрос getenv(«PATH») возвращает пустые результаты.<br />
Обратитесь к разделу о конфигурации PHP и примечаниям к конфигурации<br />
PHP из <a href="https://docs.nextcloud.com/server/15/go.php?to=admin-php-fpm">руководства по установке</a>. Обратите внимание на настройку<br />
параметров PHP, особенно при использовании механизма php-fpm.»</p></blockquote>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Как сказано в документации</p>
<p>Когда вы используете php-fpm, системные переменные среды, такие как PATH, TMP или другие, не заполняются автоматически так же, как при использовании php-cli. Вызов функции PHP, такой как getenv(‘PATH’); может возвращать пустой результат. Поэтому вам может потребоваться вручную настроить переменные среды в файле конфигурации php-fpm.</p></blockquote>
<p>Редактируем файл /etc/php/7.4/fpm/pool.d/www.conf</p>
<p>Ищем такие строки:</p>
<pre class="wp-block-preformatted">;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin 
;env[TMP] = /tmp 
;env[TMPDIR] = /tmp 
;env[TEMP] = /tmp</pre>
<p>И раскомментируем их.</p>
<p>Или, если побыстрее</p>
<pre class="wp-block-preformatted">sed -i -e "s/\;env\[/env\[/g" \
/etc/php/7.4/fpm/pool.d/www.conf</pre>
<p>Не забываем перезапустить php-fpm</p>
<pre class="wp-block-preformatted">systemctl restart php7.4-fpm</pre>
<p>Готово. Идём дальше.</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="2"></a></p>
<h2>Убираем второе предупреждение</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>«PHP OPcache не настроен правильно»</p>
<p> <a href="https://docs.nextcloud.com/server/15/go.php?to=admin-php-opcache">Для обеспечения лучшей производительности рекомендуется </a>задать в файле <code>php.ini</code> следующие параметры настроек:</p>
<p><code>opcache.enable=1</code><br />
<code>opcache.enable_cli=1</code><br />
<code>opcache.interned_strings_buffer=8</code><br />
<code>opcache.max_accelerated_files=10000</code><br />
<code>opcache.memory_consumption=128</code><br />
<code>opcache.save_comments=1</code><br />
<code>opcache.revalidate_freq=1</code></p></blockquote>
<p>Заменим вручную вышеуказанные параметры в файле <strong>/etc/php/7.4/fpm/php.ini</strong> или сразу заменим значения sed’ом</p>
<pre class="wp-block-preformatted">sed -i -e "s/\;opcache.enable=1/opcache.enable=1/g" \
/etc/php/7.4/fpm/php.ini
sed -i -e "s/\;opcache.enable_cli=0/opcache.enable_cli=1/g" \
/etc/php/7.4/fpm/php.ini
sed -i -e "s/\;opcache.interned_strings_buffer=8/opcache.interned_strings_buffer=8/g" \
/etc/php/7.4/fpm/php.ini
 sed -i -e "s/\;opcache.max_accelerated_files=10000/opcache.max_accelerated_files=10000/g" \
/etc/php/7.4/fpm/php.ini
sed -i -e "s/\;opcache.memory_consumption=128/opcache.memory_consumption=128/g" \
/etc/php/7.4/fpm/php.ini
sed -i -e "s/\;opcache.save_comments=1/opcache.save_comments=1/g" \
/etc/php/7.4/fpm/php.ini
sed -i -e "s/\;opcache.revalidate_freq=2/opcache.revalidate_freq=1/g" \
/etc/php/7.4/fpm/php.ini</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="3"></a></p>
<h2>Убираем третье предупреждение</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Некоторые индексы базы данных не были преобразованы в тип big int</p>
<p><br />
Так как преобразование таких индексов может занять продолжительное время, оно должно быть запущенно вручную. Чтобы выполнить преобразование, необходимо включить режим обслуживания и запустить в терминале команду «occ db:convert-filecache-bigint». Дополнительные сведения приведены <a href="https://docs.nextcloud.com/server/15/go.php?to=admin-bigint-conversion">на соответствующей странице документации</a>.filecache.mtime<br />
filecache.storage_mtime</p></blockquote>
<p>Для того, чтобы не потерять данные, или чтобы не было ошибок на клиентах, или просто для спокойствия нервной системы введите Nextcloud в режим обслуживания.</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:mode --on</pre>
<p>В браузере вы можете увидеть, что система находится в режиме обслуживания. Теперь в консоли выполните следующее:</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ db:convert-filecache-bigint --no-interaction
</pre>
<p>Затем выключите режим обслуживания.</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:mode --off</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="4"></a></p>
<h2>Убираем предупреждение о php</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Разрешённое максимальное значение использования памяти PHP ниже рекомендуемого значения в 512 МБ.</p></blockquote>
<pre class="wp-block-preformatted">sudo nano /etc/php/7.4/fpm/php.ini</pre>
<p>Ищем memory_limit и вводим, например, 512M вместо 128M. И перезапускаем php-fpm</p>
<p>или если хотим побыстрее</p>
<pre class="wp-block-preformatted">sed -i -e "s/memory_limit = 128M/memory_limit = 512M/g" /etc/php/7.4/fpm/php.ini</pre>
<pre class="wp-block-preformatted">sudo systemctl restart php7.4-fpm</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="5"></a></p>
<h2>Убираем предупреждение о кешировании.</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Не настроена система кеширования</p>
<p>Для увеличения производительности сервера, по возможности, настройте memcache. Более подробная информация доступна в <a href="https://docs.nextcloud.com/server/15/go.php?to=admin-performance">документации</a></p></blockquote>
<p>Поэтому прикручиваем систему кэширования, состоящую из локальной системы кэширования на основе APCu и системы распределённого кеширования Redis.</p>
<h3 class="wp-block-heading">Ставим APCu</h3>
<pre class="wp-block-preformatted"> sudo apt install php-apcu -y</pre>
<p>В файле php.ini включаем <strong>apcu</strong></p>
<pre class="wp-block-preformatted">sudo nano /etc/php/7.4/cli/php.ini</pre>
<p>вставив в начало</p>
<pre class="wp-block-preformatted">apc.enable_cli=1</pre>
<p>Сохраняем файл и перезапускаем php-fpm.</p>
<pre class="wp-block-preformatted">sudo systemctl restart php7.4-fpm</pre>
<p>Редактируем файл config/config.php в директории установки Nextсloud</p>
<pre class="wp-block-preformatted">sudo nano /usr/share/nginx/nextcloud/config/config.php</pre>
<p>и вставляем следующую строку перед закрывающем скобкой «);»</p>
<pre class="wp-block-preformatted">'memcache.local' =&gt; '\OC\Memcache\APCu',</pre>
<h3 class="wp-block-heading">Ставим Redis.</h3>
<pre class="wp-block-preformatted">sudo apt install redis-server php-redis -y</pre>
<p>Проверяем, что он запустился</p>
<pre class="wp-block-preformatted">ps ax | grep redis
 15758 ?        Ssl    0:00 /usr/bin/redis-server 127.0.0.1:6379</pre>
<p>В тот же файл config/config.php</p>
<pre class="wp-block-preformatted">sudo nano /usr/share/nginx/nextcloud/config/config.php</pre>
<p>вставьте следующее опять перед закрывающей скобкой «);»</p>
<pre class="wp-block-preformatted">  'memcache.distributed' =&gt; '\OC\Memcache\Redis',
  'redis' =&gt;
  array (
        'host' =&gt; '127.0.0.1',
        'port' =&gt; 6379,
  ),
  'memcache.locking' =&gt; '\OC\Memcache\Redis',</pre>
<p>Сохраняем файл. Перезапускаем php-fpm, если вы это ещё не сделали и наслаждаемся ускоренной работе Nextcloud.</p>
<p>P.S. Если при консольном выполнении команд вы получаете такое сообщение:</p>
<pre class="wp-block-preformatted">OC\HintException: [0]: Memcache \OC\Memcache\APCu not available for local cache (Is the matching PHP module installed and enabled?)</pre>
<p>то тогда пропишите в файл php.ini, который находится по пути /etc/php/7.4/cli следующий текст</p>
<pre class="wp-block-preformatted">apc.enable_cli=1</pre>
<p>Ошибка должна исчезнуть</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="6"></a></p>
<h2>Убираем ошибку отсутствия индексов</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>В базе данных отсутствуют некоторые индексы.</p>
<p>Так как создание таких индексов может занять достаточно продолжительное время, оно должно быть запущено вручную. Для создания индексов необходимо запустить команду «occ db:add-missing-indices» во время работы сервера Nextcloud. При созданных индексах, как правило, запросы к базе данных выполняются значительно быстрее.</p></blockquote>
<p>Выполняем</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ db:add-missing-indices</pre>
<p>При успешном индексировании будет следующий текст:</p>
<pre class="wp-block-preformatted">Check indices of the share table.
Check indices of the filecache table.
Check indices of the twofactor_providers table.
Check indices of the login_flow_v2 table.
Check indices of the whats_new table.
Check indices of the cards table.
Check indices of the cards_properties table.
Check indices of the calendarobjects_props table.
Adding calendarobject_calid_index index to the calendarobjects_props table, this can take some time…
calendarobjects_props table updated successfully.
Check indices of the schedulingobjects table.
Adding schedulobj_principuri_index index to the schedulingobjects table, this can take some time…
schedulingobjects table updated successfully.</pre>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Некоторые индексы базы данных не были преобразованы в тип big int.</p>
<p>Так как преобразование таких индексов может занять продолжительное время, оно должно быть запущенно вручную. Чтобы выполнить преобразование, необходимо включить режим обслуживания и запустить в терминале команду «occ db:convert-filecache-bigint». Дополнительные сведения приведены <a href="https://docs.nextcloud.com/server/18/go.php?to=admin-bigint-conversion">на соответствующей странице документации</a>.</p></blockquote>
<p>Вводим сервер в режим обслуживания и выполняем преобразование</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:mode --on</pre>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ db:convert-filecache-bigint</pre>
<p>Появится сообщение</p>
<pre class="wp-block-preformatted">Nextcloud is in maintenance mode - no apps have been loaded
Following columns will be updated:
mounts.storage_id
mounts.root_id
mounts.mount_id
This can take up to hours, depending on the number of files in your instance!
Continue with the conversion (y/n)? [n]</pre>
<p>Вводим «y»</p>
<p>И выводим из режима обслуживания</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:mode --off</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="7"></a></p>
<h2>Убираем предупреждение о 4-х байтовых символах</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>MySQL используется в качестве базы данных, но не поддерживает 4-байтовые символы.</p>
<p>Чтобы иметь возможность обрабатывать 4-байтовые символы (например, смайлики) без проблем в именах файлов или комментариях, рекомендуется включить 4-байтовую поддержку в MySQL. Для получения более подробной информации обратитесь к <a href="https://docs.nextcloud.com/server/18/go.php?to=admin-mysql-utf8mb4">документации</a>.</p></blockquote>
<p>Так как первоначально Nextcloud я ставил на базе MariaDB, то по ссылке выше для возможности обработки ошибки я не заметил продолжение про MariaDB, а сразу стал применять шаги для MySQL. Не надо так. Поэтому распишу по шагам, что и как надо делать.</p>
<p>P.S. Убедитесь, что MariaDB версии выше 10.2. У меня была версия 15.1</p>
<p>Убедитесь, что на вашем сервере MySQL установлены следующие параметры InnoDB в файле:</p>
<pre class="wp-block-preformatted">sudo nano /etc/mysql/mariadb.cnf</pre>
<pre class="wp-block-preformatted">[mysqld]
innodb_large_prefix=true
innodb_file_format=barracuda
innodb_file_per_table=1</pre>
<p>и если их нет, то вставьте в конец файла.</p>
<p>Перезапустите сервер MariaDB</p>
<pre class="wp-block-preformatted">sudo systemctl restart mariadb</pre>
<p>Выясните был ли изменён формат файла на Barracuda</p>
<pre class="wp-block-preformatted">sudo mariadb</pre>
<pre class="wp-block-preformatted">SELECT NAME, SPACE, FILE_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME like "nextcloud%";</pre>
<p>Если формат файла — «barracuda» для каждой отдельной таблицы, то ничего особенного не остается делать. Продолжайте с инструкциями для MySQL. Во время тестирования формат файла всех таблиц был “Antelope”.</p>
<p>Таблицы должны быть перенесены в “barracuda” вручную, одна за другой. Однако команды SQL можно легко создавать:</p>
<pre class="wp-block-preformatted">USE INFORMATION_SCHEMA;
SELECT CONCAT("ALTER TABLE `", TABLE_SCHEMA,"`.`", TABLE_NAME, "` ROW_FORMAT=DYNAMIC;") AS MySQLCMD FROM TABLES WHERE TABLE_SCHEMA = "nextcloud";</pre>
<p>Скопируйте появившийся ответ и уберите в нем символ «|». После этого вставляйте текст в консоль mariadb</p>
<p>После всего проделанного формат файла должен поменяться на Barracuda. Проверим.</p>
<pre class="wp-block-preformatted">SELECT NAME, SPACE, FILE_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME like "nextcloud%";
exit;</pre>
<h4 class="wp-block-heading">Инструкции для MySQL</h4>
<p>Вводим в режим обслуживания.</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:mode --on</pre>
<pre class="wp-block-preformatted">sudo mariadb</pre>
<pre class="wp-block-preformatted">ALTER DATABASE nextcloud CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
exit;</pre>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ config:system:set mysql.utf8mb4 --type boolean --value="true"</pre>
<p>Должен быть такой результат</p>
<pre class="wp-block-preformatted">Nextcloud is in maintenance mode - no apps have been loaded

System config value mysql.utf8mb4 set to boolean true</pre>
<p>Запускаем конвертацию</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:repair</pre>
<p>Отключаем режим обслуживания.</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ maintenance:mode --off</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="8"></a></p>
<h2>Режим шифрования</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Задействован устаревший режим шифрования файлов на стороне сервера.</p>
<p>Рекомендуется отключить такое шифрование. Более подробные сведения содержатся в <a href="https://docs.nextcloud.com/server/20/go.php?to=admin-sse-legacy-format">документации</a>.</p></blockquote>
<p>Как я понял, устаревший режим шифрования был введён в ранних версиях Nextcloud и впоследствии заменён на новый. Однако в хранилище могли остаться файлы со старым (legacy) типом шифрования.</p>
<p>В документации сказано, что найти эти файлы можно командой</p>
<pre class="wp-block-preformatted">occ encryption:scan:legacy-format</pre>
<p>или более полный вариант</p>
<pre class="wp-block-preformatted">sudo -u www-data php /usr/share/nginx/nextcloud/occ encryption:scan:legacy-format</pre>
<p>В процессе сканирования occ начнёт искать файлы со старым типом шифрования или если в базе такие файлы отсутствуют, выдаст предупреждение, «<em>does not have a proper header</em>«.</p>
<p>Такие файлы я просто заменил копиями тех, у кого есть нужные заголовки. Так как таких файлов у меня просто не было.</p>
<p>После этого в файле config.php можно отключить поддержку устаревшего формата шифрования, удалив строку</p>
<pre class="wp-block-preformatted">'encryption.legacy_format_support' =&gt; true,</pre>
<p>или, выставив значение <strong>false </strong>вместо <strong>true</strong></p>
<p>С самими файлами в хранилище ничего не произойдёт, они так же будут зашифрованы как и раньше. В данном случае, мы просто отключили поддержку старого режима шифрования.</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="9"></a></p>
<h2>Настройка обратного прокси для доступа</h2>
<p>Для доступа к файлам, используя обратный прокси, особых настроек делать не надо, достаточно в директиве proxy_pass указать IP сервера с Nextcloud. Однако, если вы используете клиент Nextcloud, то он при авторизации запустит окно браузера с IP сервера Nextcloud, а не его доменным именем. Чтобы это исправить, делаем следующее:</p>
<p>Для примера IP обратного прокси — 192.168.0.1, IP Nextcloud-сервера — 192.168.0.2</p>
<p>В файле nextcloud/config/config.php</p>
<pre class="wp-block-preformatted">'trusted_domains' =&gt;
array (
0 =&gt; '192.168.0.2',
1 =&gt; '192.168.0.1',
),</pre>
<pre class="wp-block-preformatted">'overwritehost' =&gt; 'domain.name.example.org',
'overwriteprotocol' =&gt; 'https',
'overwritewebroot' =&gt; '',
'overwritecondaddr' =&gt; '^192\.168\.0\.1$',
'overwrite.cli.url' =&gt; 'https://domain.name.example.org',</pre>
<pre class="wp-block-preformatted">'trusted_proxies' =&gt;
array (
    0 =&gt; '192.168.0.1',
),</pre>
<p>Таким образом, опция trusted_proxies исправляет проблему «<em>Заголовки обратного прокси настроены неправильно, либо вы подключены к серверу Nextcloud через доверенный прокси</em>«</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="10"></a></p>
<h2>Уведомление о HTTP «X-Frame-Options»</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Заголовок HTTP «X-Frame-Options» не настроен на значение «SAMEORIGIN».</p>
<p>Это потенциальная проблема безопасности для устранения которой рекомендуется задать этот параметр.</p></blockquote>
<p>Для этого добавьте в файл конфигурации nginx на стороне nextcloud следующее содержимое в секцию <strong><em>server</em></strong></p>
<pre class="wp-block-preformatted">add_header X-Frame-Options "SAMEORIGIN";</pre>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Веб-сервер не настроен должным образом для разрешения «/.well-known/caldav». .</p>
<p>Дополнительная информация может быть найдена в нашей документации</p></blockquote>
<p>В конфиге nextcloud в статье есть строки с настройкой доступа к этому пути. Для удобства повторю тут</p>
<pre class="wp-block-preformatted"> location = /.well-known/carddav {
         return 301 $scheme://$host/remote.php/dav;
     }

     location = /.well-known/caldav {
        return 301 $scheme://$host/remote.php/dav;
     }</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="11"></a></p>
<h2>Новый dashboard</h2>
<p>Следующая опция для тех, кто обновился до 20 версии и при заходе на главную облака видит новый dashboard вместо знакомого списка файлов.</p>
<p>Исправляется просто добавлением в файл config.php следующей строки</p>
<pre class="wp-block-preformatted">'defaultapp' =&gt; 'files',</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="12"></a></p>
<h2>Модуль php-imagick и SVG</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Модуль php-imagick в этом случае не поддерживает SVG.</p>
<p>Для лучшей совместимости рекомендуется установить его</p></blockquote>
<p>После установки или обновления Nextcloud до 21 версии появится сообщение об ошибке в модуле php-imagick. И хотя само расширение для php установлено, может статься, что в системе не установлен пакет приложения imagemagick. Поэтому ставим его через apt</p>
<pre class="wp-block-preformatted">apt install imagemagick</pre>
<p>В русском переводе на 2021.03.25 фраза переведена немного неправильно. В оригинале это выглядит как «Module php-imagick in this instance has no SVG support. For better compatibility it is recommended to install it.» — «У модуля php-imagick на этом сервере отсутствует поддержка формата SVG. Для лучшей совместимости рекомендуется установить его»</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="13"></a></p>
<h2>Регион размещения сервера</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Не указан регион размещения этого сервера Nextcloud, что требуется для возможности проверки номеров телефонов без указания кода страны.</p>
<p>Чтобы разрешить пользователям сервера указывать номера телефонов без указания кода страны, добавьте параметр «default_phone_region» с соответствующим кодом страны в соответствии с <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements" target="_blank" rel="noreferrer noopener">ISO 3166-1↗</a>.</p></blockquote>
<p>Опять же после обновления до 21 версии Nextcloud появляется такое предупреждение. Точную причину почему в Nextcloud понадобилось указывать номер телефона я не знаю, но как устранить это предупреждение — знаю.</p>
<p>Открывает файл config.php, расположенный в директории Nextcloud по пути config/config.php и внизу вставляем строку</p>
<pre class="wp-block-preformatted">  'default_phone_region' =&gt; 'RU',</pre>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="14"></a></p>
<h2>Файлы .mjs</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Your webserver does not serve `.mjs` files using the JavaScript MIME type. This will break some apps by preventing browsers from executing the JavaScript files. You should configure your webserver to serve `.mjs` files with either the `text/javascript` or `application/javascript` MIME type.</p></blockquote>
<p>С версии 28 в Nextcloud появился функционал использования файлов mjs</p>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Файл с расширением .mjs — это файл исходного кода JavaScript, который используется в качестве модуля ECMA (модуль ECMAScript) в приложениях Node.js.</p></blockquote>
<p>Из-за этого в панели администрирования можно увидеть предупреждение о том, что веб-сервер не поддерживает mjs файлы, необходимые для работы некоторых приложений или дополнений. Чтобы это исправить просто добавьте в конфигурационный файл mime-типов вашего веб-сервера следующую строку (для начала покажу на примере nginx)</p>
<pre class="wp-block-preformatted">nano /etc/nginx/mime.types</pre>
<pre class="wp-block-code"><code>image/jpeg                            jpeg jpg;
application/javascript                js;
application/javascript                mjs;
application/atom+xml                  atom;</code></pre>
<p>Затем перезапустите nginx</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p><a name="15"></a></p>
<h2>Время обслуживания</h2>
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Server has no maintenance window start time configured. This means resource intensive daily background jobs will also be executed during your main usage time. We recommend to set it to a time of low usage, so users are less impacted by the load caused from these heavy tasks</p></blockquote>
<p>С 28 версии появилось предупреждение о том, что не настроено окно для проведения работ по обслуживанию системы. Опция была и раньше, просто предупреждение не выводилось в админ-панель.</p>
<p>Этот параметр учитывается только в режиме <code>cron</code>.</p>
<p>Чтобы исправить предупреждение добавьте в config/config.php строку</p>
<pre class="wp-block-preformatted">'maintenance_window_start' =&gt; 5,</pre>
<p>Документация гласит, что указанное число используется как время старта задач по обслуживанию системы. Время старта задаётся числом с началом отсчёта по времени UTC. Тяжёлые задачи будут отложены, чтобы не нагружать сервер в рабочие часы. Они будут выполнены в течение 4 часов после наступления этого времени. То есть, указав 5 в параметре, тяжёлые задачи выполнятся с 2 ночи до 6 утра по Москве (UTC+3 — московское время, плюс 2 часа — в итоге получаем 2 часа ночи как точка старта)</p>
<p>Если ваша система не сильно нагружена, то можно указать в параметре 100.</p>
<p><a href=""><em>К оглавлению</em></a></p>
<p>На этом тюнинг закончен, но не завершён.</p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[PHP]]></category><category><![CDATA[WEB]]></category><category><![CDATA[cloud]]></category><category><![CDATA[nextcloud]]></category><category><![CDATA[web]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/11/47895a00-3aef-11ea-97c9-db1565d05c79-1024x576.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/php-%d1%87%d0%b0%d1%81%d1%82%d0%be-%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d0%bc%d1%8b%d0%b5-%d0%bc%d0%be%d0%b4%d1%83%d0%bb%d0%b8/</link>
					<title><![CDATA[PHP часто используемые модули]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Tue, 12 Nov 2024 18:11:55 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/11/34817752-66aa06af4967f-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>PHP часто используемые модули</h1>
													</header>
													<p>В PHP есть очень много разных модулей. И описание к ним разбросано по всему интернету. Поэтому решил собрать самые используемые в одной статье с описанием. И так приступим:</p>
<p><a href="http://www.ioncube.com/" target="_blank" rel="noopener">IonCube</a> — это набор утилит для командной строки, которые позволяют производить кодирование, <a href="http://ru.wikipedia.org/wiki/%CE%E1%F4%F3%F1%EA%E0%F6%E8%FF" target="_blank" rel="noopener">обфускацию</a> и лицензирование исходного кода, написанного на языке php.<br />
Функционал IonCube очень обширен что бы о нем можно было написать в одной статье. Под катом я опишу основной функционал IonCube, который необходим для защиты кода от не лицензионного использования.</p>
<p><strong>Fileinfo</strong> — расширение для PHP, которое позволяет получить тип контента и кодировку файла. С его помощью можно получить MIME-информацию о файле, например, определить тип изображения (PNG), текста (HTML) и т. д..</p>
<p><strong>Zend Opcache</strong> – это расширение PHP, предназначенное для повышения производительности PHP, сокращения времени загрузки веб-страниц и уменьшения нагрузки на сервере.</p>
<p><a href="https://ru.wikipedia.org/wiki/Memcached" target="_blank" rel="noreferrer noopener">Memcached</a> &#8212; программное обеспечение, реализующее сервис кэширования данных в оперативной памяти на основе хеш-таблицы. Проще говоря, когда страница сгенерирована, она через <strong>memcached</strong> помещается в оперативную память, и при последующем обращении к странице незачем её генерировать снова, затрачивая время и ресурсы сервера &#8212; она попросту берётся из <strong>memcached</strong>.</p>
<p><b>Redis (Remote Dictionary Server)</b>— это высокопроизводительное хранилище данных в оперативной памяти с открытым исходным кодом, используемое как база данных, кэш и брокер сообщений. Он поддерживает различные структуры данных, такие как строки, хэши, списки, множества и сортированные множества. Redis известен своей скоростью, производительностью и простотой использования.</p>
<p><strong>APCu</strong> — это расширение для PHP, которое добавляет функции кэширования объектов.  Оно сохраняет данные в оперативной памяти сервера, уменьшая необходимость в дорогих запросах к базе данных и операциях с файловой системой.</p>
<p><strong>IMagick</strong> — это расширение PHP для создания и модификации изображений с использованием библиотеки ImageMagick. Оно используется для чтения, записи и преобразования изображений в любых форматах, включая EXR, GIF, JPEG, PDF, PNG, PhotoCD, TIFF и т.д..</p>
<p class="FuturisMarkdown-Paragraph"><strong>Xdebug — средство профилирования и отладки PHP-скриптов. </strong>Поставляется как расширение для PHP и работает по протоколу DBGp.</p>
<p>IMAP в PHP предоставляет функциональность для работы с почтовыми ящиками по протоколу IMAP. Базовая библиотека C, от которой зависит расширение, не получала обновлений с 2018 года.</p>
<p><strong>PHP Exif</strong> — это <strong>расширение, которое позволяет работать с метаданными, хранящимися в файлах изображений</strong>, таких как JPEG и TIFF.</p>
<p><strong>PHP intl</strong> &#8212; Модуль интернационализации (далее Intl) &#8212; это обёртка для библиотеки <a class="link external" href="https://icu.unicode.org/">» ICU</a>, позволяющая программистам на PHP производить различные операции, которые зависят от локали, например, форматирование, транслитерация, преобразование кодировок, операции с календарём, совместимое с <a class="link external" href="https://www.unicode.org/reports/tr10/">» UCA</a> сравнение, определение границ текста и работать с идентификаторами локалей, часовыми поясами и графемами.</p>
<p><strong>PHP XSL расширение</strong> позволяет использовать библиотеку PHP XSLT для преобразования XML-документов в другие форматы, такие как HTML, XML или простой текст.</p>
<p><strong><a href="https://github.com/swoole/swoole-src" target="_blank" rel="noopener">Swoole</a></strong> ― высокопроизводительный асинхронный фреймворк для PHP. Используется такими интернет-гигантами как Alibaba и Baidu. С версии 4.1.0 появился волшебный метод <i>Swoole\Runtime::enableCoroutine()</i>, позволяющий «одной строкой кода преобразовать синхронные сетевые библиотеки PHP в асинхронные».</p>
<p><strong>PHP OCI8</strong> — это расширение, которое позволяет взаимодействовать с базами данных Oracle. Оно предоставляет функции для подключения к базе данных, выполнения SQL-заявлений, получения результатов и управления транзакциями.</p>
<p><strong>php-swow</strong> — <strong>расширение для PHP, которое предоставляет асинхронные возможности на базе libuv</strong>. В частности, с его помощью можно использовать асинхронный стрим, а также функции PDO, file_get_contents() и другие (когда они обёрнуты в корутину).</p>
<p><strong>Расширение PHP SQLSRV</strong> предоставляет функции для доступа к базам данных Microsoft SQL Server.</p>
<p><strong>PHP-rdkafka</strong> — это <strong>стабильный и быстрый клиент Kafka для PHP на основе librdkafka</strong>.</p>
<p><strong>Расширение PHP для MongoDB</strong> обеспечивает API для доступа к коллекциям MongoDB и позволяет выполнять большинство задач, относящихся к доступу и использованию базы данных MongoDB из приложений, написанных на языке PHP.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[PHP]]></category><category><![CDATA[WEB]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/11/34817752-66aa06af4967f-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%be%d1%82%d1%84%d0%be%d1%80%d0%bc%d0%b0%d1%82%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d1%84%d0%bb%d0%b5%d1%88%d0%ba%d1%83-%d0%ba%d0%be%d1%82%d0%be%d1%80%d0%b0%d1%8f-%d0%b1%d1%8b%d0%bb%d0%b0/</link>
					<title><![CDATA[Сетевые настройки на сервере Debian]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 25 Aug 2024 11:32:17 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/08/maxresdefault-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Сетевые настройки на сервере Debian</h1>
													</header>
													<p>Сейчас мы подробно разберем все наиболее значимые нюансы сетевых настроек, которые могут пригодиться в повседневной работе. Первоначальная настройка сети начинается во время установки сервера. Если у вас есть сетевой интерфейс и dhcp сервер в сети, то сеть сконфигурируется автоматически на основе полученных настроек и будет готова к работе. Впоследствии вы можете выполнить настройку сети в Debian через консоль с помощью программ <strong>ip</strong> или <strong>ifconfig</strong>. Наиболее популярным и современным средством на текущий момент является ip, поэтому в дальнейшем рассмотрим вопрос конфигурации сетевых интерфейсов с её помощью. Про ifconfig тоже не забудем. Рассмотрим её в конце. Отдельно стоит такой инструмент управления сетевыми подключениями как <strong>Network Manager</strong>. В базовой версии сервера Debian минимальной конфигурации он не установлен. Его удобно использовать в сочетании с графическими оболочками, которых на сервере обычно нет, поэтому вопрос его настройки я не буду рассматривать.</p>
<p>Есть 2 различные возможности изменить сеть в Debian:</p>
<ol>
<li>Настройка сети из консоли с помощью указанных ранее консольных программ.</li>
<li>С помощью редактирования конфигурационного файла сетевых интерфейсов <em>/etc/network/interfaces</em>.</li>
</ol>
<p>Мы рассмотрим оба этих варианта. Вводная теоретическая часть окончена, приступаем к практике.</p>
<h2>Настройка статического IP</h2>
<p>Вы установили сервер и во время установки указали какие-то сетевые параметры, или не указали, не важно. Но сейчас вы решили, что вам нужно назначить статический ip (static ip) адрес. Воспользуемся для этого утилитой <strong>ip</strong>. Сначала посмотрим список всех сетевых интерфейсов:</p>
<pre># ip a</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-01.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15934" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-01.png" sizes="auto, (max-width: 1141px) 100vw, 1141px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-01.png 1141w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-01-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-01-1024x453.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-01-768x340.png 768w" alt="Сетевые настройки в debian" width="1141" height="505" data-wp-pid="15934" /></a></p>
<p>У меня в системе 1 сетевой интерфейс <strong>ens18</strong> и он каким-то образом уже сконфигурирован. Назначим ему еще один статический адрес:</p>
<pre># ip addr add 192.168.1.35/24 dev ens18</pre>
<p>Этот адрес будет добавлен к уже существующему адресу. Проверим это:</p>
<pre># ip a</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-02.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15935" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-02.png" sizes="auto, (max-width: 1141px) 100vw, 1141px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-02.png 1141w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-02-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-02-1024x453.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-02-768x340.png 768w" alt="Настройка статического ip" width="1141" height="505" data-wp-pid="15935" /></a></p>
<p>Теперь сервер будет доступен по обоим адресам. Текущая настройка сохранится только до перезагрузки сервера. Чтобы она применялась во время загрузки, нужно либо каким-то образом добавить команду на изменение настроек в автозагрузку, например в <em>/etc/rc.local </em>или в <em>/etc/crontab</em>, но это будет костыль. Так сделать можно, но не нужно. Правильнее отредактировать файл, который отвечает за сетевые настройки в Debian &#8212; <em>/etc/network/interfaces</em>. Для того, чтобы назначить постоянный статический ip адрес, его нужно привести к следующему виду:</p>
<pre># mcedit /etc/network/interfaces</pre>
<pre>source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto ens18
iface ens18 inet static
address 10.20.1.36
gateway 10.20.1.1
netmask 255.255.255.0
</pre>
<table>

<tr>
<td>auto</td>
<td>указанный интерфейс необходимо запускать автоматически при загрузке системы</td>
</tr>
<tr>
<td>iface</td>
<td>интерфейс ens18 находится в диапазоне адресов IPv4 со статическим ip</td>
</tr>
<tr>
<td>address</td>
<td>статический ip адрес</td>
</tr>
<tr>
<td>gateway</td>
<td>шлюз по умолчанию</td>
</tr>
<tr>
<td>netmask</td>
<td>маска сети</td>
</tr>

</table>
<p>Отдельно задержусь на моменте с активацией интерфейса. Оно может выполняться двумя разными настройками:</p>
<ul>
<li><strong>auto</strong> &#8212; интерфейс активируется при загрузке системы. Это подходящая настройка для статичного сетевого адаптера.</li>
<li><strong>allow-hotplug</strong> &#8212; интерфейс поднимается, когда подсистема udev обнаружит его. Это произойдёт и при загрузке системы, как в случае с auto, если сетевая карта будет подключена, и в случае подключения, отключения устройства. Например, если это usb сетевая карта или VPN туннель. Настройка больше подходит для динамических сетевых интерфейсов.</li>
</ul>
<p>Для проверки перезагружаем сервер и смотрим, всё ли в порядке с настройкой статического ip адреса. Если вам нужно сменить ip адрес в Debian, то вы можете временно изменить его с помощью команды ip, либо постоянно, отредактировав параметр <strong>address </strong>в файле сетевых настроек <em>interfaces</em>.</p>
<h2>Получение сетевых настроек по DHCP</h2>
<p>Теперь рассмотрим вариант, когда вам необходимо получить динамический ip адрес в Debian. Здесь по аналогии с предыдущими настройками можно пойди двумя путями:</p>
<ol>
<li>Получить ip адрес по dhcp в консоли с помощью программы <strong>dhclient</strong>, который будет работать до перезагрузки.</li>
<li>Отредактировать файл конфигурации сетевых интерфейсов.</li>
</ol>
<p>Смотрим снова на текущую конфигурацию сети:</p>
<pre># ip a</pre>
<figure class="aligncenter"><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-03.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15936" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-03.png" sizes="auto, (max-width: 1142px) 100vw, 1142px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-03.png 1142w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-03-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-03-1024x454.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-03-768x340.png 768w" alt="Параметры сети в debian" width="1142" height="506" data-wp-pid="15936" /></a></figure>
<p>Выполним команду на получение ip адреса по dhcp и проверим сеть:</p>
<pre># dhclient
# ip a</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-04.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15937" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-04.png" sizes="auto, (max-width: 1140px) 100vw, 1140px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-04.png 1140w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-04-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-04-1024x453.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-04-768x340.png 768w" alt="Получение настроек по dhcp" width="1140" height="504" data-wp-pid="15937" /></a></p>
<p>В качестве второго ip мы получили адрес от dhcp сервера. Если у вас несколько сетевых интерфейсов, то необходимо добавлять название после команды, например вот так:</p>
<pre># dhclient eth0</pre>
<p>Для того, чтобы сбросить адрес, нужно воспользоваться следующим ключом:</p>
<pre># dhclient -r</pre>
<p>Обращаю внимание, что эта команда сбросит все ip адреса интерфейса, в том числе и статические. Выполнять её можно только будучи подключенным к консоли сервера напрямую, а не по сети. Чтобы снова запросить адрес, нужно выполнить предыдущую команду на получение ip. А чтобы вернуть статические настройки, надо перезапустить службу сети:</p>
<pre># systemctl restart networking</pre>
<p>Все изменения, сделанные в консоли сервера после перезагрузки, исчезнут. Чтобы их сохранить, приведем файл <em>/etc/network/interfaces</em> к следующему виду:</p>
<pre># mcedit /etc/network/interfaces</pre>
<pre>source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto ens18
iface ens18 inet dhcp</pre>
<h2>Установка шлюза по умолчанию (default gateway)</h2>
<p>Теперь разберемся со шлюзом по умолчанию. В предыдущих примерах со статическим ip адресом и настройками по dhcp у нас не было необходимости указывать отдельно default gateway. Мы его устанавливали вместе с остальными настройками. Чтобы посмотреть установленный по умолчанию шлюз в Debian, можно воспользоваться следующей командой в консоли:</p>
<pre># ip route</pre>
<p>или ещё короче:</p>
<pre>ip r</pre>
<pre><strong>default via 10.20.1.1 dev ens18 onlink</strong>
10.20.1.0/24 dev ens18 proto kernel scope link src 10.20.1.66</pre>
<p>Выделен шлюз по умолчанию (default gateway). Можно воспользоваться другими программами, которые на текущий момент признаны устаревшими, но от этого не переставшими выполнять свои функции:</p>
<pre># route
# netstat -nr</pre>
<p>Если получите ошибки:</p>
<pre>-bash: route: command not found
-bash: netstat: command not found</pre>
<p>Значит у вас не установлен пакет <strong>net-tools</strong>. Установить его можно следующей командой.</p>
<pre># apt install net-tools</pre>
<p>Сетевые инструменты из пакета net-tools объявлены устаревшими и не включены в состав базовой системы. Я иногда продолжаю пользоваться, потому что мне нравится их вывод больше, чем у команды ip. Netstat мне видится более информативным, хотя по сути, они все показывают одно и то же. Отказ в пользу утилиты ip идет по той причине, что она объединяет в себе все основные сетевые инструменты. Удобнее пользоваться только ей одной для настройки сети, нежели разными утилитами для разных целей. Если вы только изучаете Linux, то пользуйтесь сразу командой ip.</p>
<p>Если нам нужно сменить default gateway, то сначала надо удалить текущий шлюз, а потом назначить новый.</p>
<pre># ip route del default
# ip route add default via 10.20.1.100</pre>
<p>То же самое, только с помощью route:</p>
<pre># route del default gw 10.20.1.1
# route add default gw 10.20.1.100</pre>
<p>Проверяем, что получилось:</p>
<pre># ip r</pre>
<pre>default via 10.20.1.100 dev ens18
10.20.1.0/24 dev ens18 proto kernel scope link src 10.20.1.66</pre>
<p>Всё получилось. Эта настройка будет действовать до перезагрузки. Чтобы ее сохранить, либо меняйте конфигурационный файл /etc/<em>network</em>/<em>interfaces</em>, либо, при необходимости, придумывайте что-то ещё.<em> </em></p>
<h2>Как указать DNS сервер</h2>
<p>Остался последний из основных сетевых параметров &#8212; <strong>dns</strong> сервер. С ним в Debian и Ubuntu есть определенная путаница. Традиционно в ОС на базе ядра Linux для установки dns серверов используется файл <em>/etc/resolv.conf</em>. Но в какой-то момент в этих дистрибутивах появилась программа <strong>resolvconf</strong>, которая стала управлять настройками dns в системе. В итоге, файл <em>resolv.conf</em> постоянно перезаписывается этой программой. Нужна она в первую очередь для систем, где dns сервера постоянно меняются. Она следит за их изменением и корректно передает информацию об изменении программам, для которых это важно. Я лично не знаю таких программ и мне не приходилось сталкиваться с ситуацией, когда это было необходимо. Если я не ошибаюсь, то в минимальной конфигурации Debian программа resolvconf не устанавливается, а вот в Ubuntu она стоит. Проверить наличие программы очень просто:</p>
<pre># dpkg -l | grep resolvconf</pre>
<p>Если в выводе пусто, значит ее нет. Тогда все очень просто. Для того, чтобы указать dns сервер, достаточно его записать в файл <em>/etc/resolv.conf </em>в следующем виде:</p>
<pre># mcedit /etc/resolv.conf</pre>
<pre>nameserver 10.20.1.1
nameserver 77.88.8.1
nameserver 8.8.8.8
nameserver 1.1.1.1</pre>
<table>

<tr>
<td>10.20.1.1</td>
<td>локальный dns сервер</td>
</tr>
<tr>
<td>77.88.8.1</td>
<td>публичный сервер Яндекса</td>
</tr>
<tr>
<td>8.8.8.8</td>
<td>публичный сервер Google</td>
</tr>
<tr>
<td>1.1.1.1</td>
<td>публичный сервер Cloudflare</td>
</tr>

</table>
<p>Я на всякий случай указал локальный сервер и 3 внешних. Если у вас стоит resolvconf, то в случае ненадобности, удалите его командой:</p>
<pre># apt-get remove resolvconf</pre>
<p>После этого сервер надо перезагрузить и удалить сломавшуюся символьную ссылку <em>/etc/resolv.conf</em>, а вместо нее создать файл с нужным содержанием, которое я привел выше. Если же вам по какой-то причине необходима указанная выше программа, она у вас стоит и вы не хотите ее удалять, то адрес dns сервера необходимо указать в файле <em>/etc/network/interfaces</em>, добавив к параметрам интерфейса еще один:</p>
<pre>dns-nameservers 10.20.1.1 77.88.8.1 8.8.8.8 1.1.1.1</pre>
<p>Этот параметр нужно установить сразу после указания шлюза gateway. Несколько адресов разделяются пробелом.</p>
<h2>Изменить hostname (имя хоста)</h2>
<p>Во время установки Debian вы указывали имя хоста. Посмотреть его текущее значение можно в консоли:</p>
<pre># hostname
debian</pre>
<p>Это значение записано в файле <em>/etc/hostname</em>. Есть 2 способа изменить hostname в debian:</p>
<ol>
<li>Простой и быстрый с помощью консольной команды. Результат работает только до перезагрузки компьютера. Потом вернется старое имя.</li>
<li>С помощью изменения конфигурационного файла результат сохраняется и после перезагрузки. Чтобы сразу применить изменение, потребуется выполнить системный скрипт.</li>
</ol>
<p>Для первого способа достаточно в консоли ввести команду:</p>
<pre># hostname debian12</pre>
<p>Теперь проверим, что получилось:</p>
<pre># hostname
debian12</pre>
<p>Имя хоста изменилось, но в файле <em>/etc/hostname </em>по-прежнему указано прошлое значение. После перезагрузки hostname снова примет старое значение. Чтобы сделать постоянное изменение, необходимо ввести новое значение в файл вручную:</p>
<pre># mcedit /etc/hostname
debian12</pre>
<p>Изменение вступит в силу после перезагрузки. Если воспользоваться командой:</p>
<pre># hostnamectl set-hostname debian12</pre>
<p>то изменения применятся сразу же. Этот способ более правильный, рекомендую использовать именно его. Теперь проверьте текущее значение имени хоста. Оно изменится на то, что вы указали в команде.</p>
<h2>2 и более IP на одном интерфейсе</h2>
<p>Иногда возникают ситуации, когда необходимо назначить несколько ip на одном интерфейсе. Сделать это очень просто. В самом начале я показал, как быстро через консоль в Debian можно назначить несколько ip c помощью dhclient, когда уже указан статический адрес. Теперь сделаем так, чтобы эти настройки сохранялись после перезагрузки. Для этого редактируем наш любимый и ненаглядный <em>/etc/network/interfaces</em>:</p>
<pre># mcedit /etc/network/interfaces</pre>
<pre>source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto ens18
iface ens18 inet dhcp

auto ens18:1
iface ens18:1 inet static
address 10.20.1.66
netmask 255.255.255.0</pre>
<p>С такими настройками я получу 2 ip адреса на сетевом интерфейсе:</p>
<ol>
<li>Первый от dhcp сервера.</li>
<li>Второй адрес на этой же сетевой карте будет указан статически.</li>
</ol>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-05.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15938" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-05.png" sizes="auto, (max-width: 1145px) 100vw, 1145px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-05.png 1145w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-05-300x132.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-05-1024x450.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-05-768x337.png 768w" alt="2 IP адреса на одном сетевом интерфейсе" width="1145" height="503" data-wp-pid="15938" /></a></p>
<div class="box warning  ">
<div class="box-inner-block"><i class="fa tie-shortcode-boxicon"></i>Важное замечание. Если после указанного выше добавления к динамическому адресу статического, вы перезапустите сеть, то останется только статический адрес. Если же просто перезагрузите сервер, то все будет правильно &#8212; динамика и статика.</div>
</div>
<p>Вы таким образом можете добавить сколько вам необходимо адресов, используя различные параметры.</p>
<h2>Как быстро узнать ip адрес сервера в Debian</h2>
<p>Часто возникает вопрос, как в Debian быстро узнать или проверить ip адреса, назначенные серверу. Выше я уже приводил пример простой команды, которая показывает все сетевые параметры интерфейса. Сейчас рассмотрим несколько вариантов, которые наглядно покажут только ip адреса, без лишней информации. Для начала воспользуемся уже известной командой ip, немного подрезав ее вывод:</p>
<pre># ip a | grep inet | awk '{print $2}'</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-06.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15939" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-06.png" sizes="auto, (max-width: 1142px) 100vw, 1142px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-06.png 1142w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-06-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-06-1024x454.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-06-768x340.png 768w" alt="Узнать ip адрес" width="1142" height="506" data-wp-pid="15939" /></a></p>
<p>Вы узнаете все ip адреса сервера, в том числе и ipv6. То же самое, только без ipv6 можно увидеть другой командой:</p>
<pre># ifconfig | grep 'inet '</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-07.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15940" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-07.png" sizes="auto, (max-width: 1144px) 100vw, 1144px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-07.png 1144w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-07-300x132.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-07-1024x452.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-07-768x339.png 768w" alt="Список ip адресов" width="1144" height="505" data-wp-pid="15940" /></a></p>
<p>Если получите ошибку:</p>
<pre>-bash: ifconfig: command not found</pre>
<p>Значит у вас не установлен пакет <strong>net-tools</strong>. Установить его можно следующей командой:</p>
<pre># apt install net-tools</pre>
<p>Если совсем заморочиться и обрезать все лишнее в выводе команды ifconfig, то можно вывести только список ip адресов:</p>
<pre># ifconfig | grep 'inet ' | awk '{ print $2}'</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-08.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15941" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-08.png" sizes="auto, (max-width: 1140px) 100vw, 1140px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-08.png 1140w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-08-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-08-1024x453.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-08-768x340.png 768w" alt="Краткий список ip адресов" width="1140" height="504" data-wp-pid="15941" /></a></p>
<p>Можно убрать локальный интерфейс, чтобы глаза не мозолил, тогда вообще все наглядно:</p>
<pre># ifconfig | grep 'inet ' | awk '{ print $2}' | grep -v 127.0.0.1</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-09.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15942" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-09.png" sizes="auto, (max-width: 1140px) 100vw, 1140px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-09.png 1140w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-09-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-09-1024x453.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-09-768x340.png 768w" alt="ip адреса" width="1140" height="504" data-wp-pid="15942" /></a></p>
<p>То же самое для ip:</p>
<pre># ip a | grep 'inet ' | awk '{ print $2}' | grep -v 127.0.0.1</pre>
<p>Думаю, этих вариантов достаточно, чтобы проверить все ip адреса, отрезав лишнее.</p>
<h2>Static routes (статические маршруты)</h2>
<p>Следующим важным элементом настройки сети является управление статическими маршрутами (static routes): добавление (route add) и удаление (route del). Это часто бывает нужно, когда на шлюзе настроены VPN соединения. К примеру, запросы в одну подсеть отправляем через один VPN интерфейс, в другую подсесть &#8212; через другой. Какие-то VPN сервисы умеют сами управлять своими статическими маршрутами, какие-то нет. Тогда это нужно сделать вручную.</p>
<p>Вновь воспользуемся консольной командой ip. Для того, чтобы добавить маршрут в Debian, достаточно ввести в консоли:</p>
<pre># ip route add 192.168.13.0/24 via 10.20.1.100</pre>
<table>

<tr>
<td>192.168.13.0</td>
<td>адрес подсети, для которой создаём отдельный маршрут в обход шлюза по умолчанию</td>
</tr>
<tr>
<td>/24</td>
<td>маска подсети</td>
</tr>
<tr>
<td>10.20.1.100</td>
<td>адрес шлюза, который будет роутить трафик в указанную подсеть</td>
</tr>

</table>
<p>Проверяем таблицу маршрутов:</p>
<pre># ip r</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-10.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15943" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-10.png" sizes="auto, (max-width: 1138px) 100vw, 1138px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-10.png 1138w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-10-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-10-1024x454.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-10-768x341.png 768w" alt="static routes" width="1138" height="505" data-wp-pid="15943" /></a></p>
<p>Чтобы удалить маршрут, выполняем команду:</p>
<pre># ip route delete 192.168.13.0/24</pre>
<p>После перезагрузки все маршруты, добавленные таким способом, исчезнут. Чтобы статический маршрут в Debian сохранялся после перезагрузки, опять редактируем <em>interfaces</em>, добавляя в описание того интерфейса, к которому будут относиться маршруты, следующие строки:</p>
<pre>post-up route add -net 192.168.13.0 netmask 255.255.255.0 gw 10.20.1.100
post-up route add -net 192.168.15.0 netmask 255.255.255.0 gw 10.20.1.100
pre-down route del -net 192.168.13.0 netmask 255.255.255.0 gw 10.20.1.100
pre-down route del -net 192.168.15.0 netmask 255.255.255.0 gw 10.20.1.100</pre>
<p>Мы добавили 2 статических маршрута. Перезагружаемся и проверяем.</p>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-11.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15944" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-11.png" sizes="auto, (max-width: 1141px) 100vw, 1141px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-11.png 1141w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-11-300x133.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-11-1024x452.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-11-768x339.png 768w" alt="статические маршруты" width="1141" height="504" data-wp-pid="15944" /></a></p>
<p>Мой конфиг целиком стал выглядеть вот так:</p>
<pre>source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto ens18
iface ens18 inet dhcp
post-up route add -net 192.168.13.0 netmask 255.255.255.0 gw 10.20.1.100
post-up route add -net 192.168.15.0 netmask 255.255.255.0 gw 10.20.1.100
pre-down route del -net 192.168.13.0 netmask 255.255.255.0 gw 10.20.1.100
pre-down route del -net 192.168.15.0 netmask 255.255.255.0 gw 10.20.1.100

auto ens18:1
iface ens18:1 inet static
address 10.20.1.66
netmask 255.255.255.0</pre>
<p>С постоянными статическими маршрутами в Debian разобрались, ничего сложного. Идём дальше.</p>
<h2>Как выполнить перезапуск сети</h2>
<p>Если есть возможность перезагрузить сервер, чтобы проверить новые сетевые настройки, лучше это сделать. Это избавит вас от сюрпризов, которые могут возникнуть, если вы отложите перезагрузку и где-то ошибётесь. Не всегда это обязательно делать. Иногда достаточно просто перечитать сетевую конфигурацию. Для перезапуска сети в Debian можно воспользоваться командой:</p>
<pre># systemctl restart networking</pre>
<p>или</p>
<pre># service networking restart</pre>
<p>Они выполняются не мгновенно, обычно несколько секунд.</p>
<p>Несмотря на то, что в большинстве современных дистрибутивов на базе Linux внедрена система инициализации <strong>systemd</strong>, в директории <em>/etc/init.d/</em> для совместимости остались рудименты от старой системы <strong>SysVinit</strong>. Выполнить перезагрузку сети можно с их помощью:</p>
<pre># /etc/init.d/networking restart
[ ok ] Restarting networking (via systemctl): networking.service.</pre>
<p>Команда делает то же самое, но есть некая обратная связь о том, как всё прошло. Если у вас всё в порядке на сервере и нет сетевых ошибок, то рестарт сети можно спокойно делать удаленно по ssh. Вас даже не отключит от текущей сессии. Но на всякий случай я не рекомендую это делать, если у вас нет доступа к консоли сервера. Всякое может случиться, я бы не рисковал лишний раз. Настройку сети, как и файрвола, лучше не делать, не имея прямого доступа к консоли сервера.</p>
<h2>Настройка vlan в Debian</h2>
<p>Для настройки vlan в Debian первым делом необходимо установить пакет vlan:</p>
<pre># apt install vlan</pre>
<p>Теперь нужно разобраться с необходимым модулем ядра для vlan &#8212; <strong>8021q</strong>. Проверим, загружен ли он в системе:</p>
<pre># lsmod | grep 8021q</pre>
<p>Если в выводе пусто, а по умолчанию там будет пусто, модуль не загружен. Загрузим его и проверим:</p>
<pre># modprobe 8021q
# lsmod | grep 8021q
8021q                  40960  0
garp                   16384  1 8021q
mrp                    20480  1 8021q
</pre>
<p>Всё в порядке, vlan модуль загрузился. Добавим его в автозагрузку:</p>
<pre># echo 8021q &gt;&gt; /etc/modules</pre>
<p>Теперь этот модуль будет загружаться при старте сервера. Создадим виртуальный интерфейс с vlan с id 1500:</p>
<pre># ip link add link ens18 name ens18.1500 type vlan id 1500</pre>
<p>Назначим адрес новому интерфейсу и запустим его:</p>
<pre># ip addr add 10.20.1.150/24 dev ens18.1500
# ip link set ens18.1500 up</pre>
<p>Можно в одну команду, с помощью ifconfig:</p>
<pre># ifconfig ens18.1500 10.20.1.150 netmask 255.255.255.0 up</pre>
<p>Смотрим, что получилось:</p>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-12.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15945" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-12.png" sizes="auto, (max-width: 1145px) 100vw, 1145px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-12.png 1145w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-12-300x137.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-12-1024x468.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-12-768x351.png 768w" alt="Настройка vlan в debian" width="1145" height="523" data-wp-pid="15945" /></a></p>
<p>Мы выполнили настройку vlan интерфейса в Debian. Теперь сделаем так, чтобы после перезагрузки настройки сохранились. Для этого добавляем свойства vlan интерфейса в файл конфигурации сети, оставляя и не трогая то, что там уже есть:</p>
<pre># mcedit /etc/network/interfaces</pre>
<pre>auto ens18.1500
iface ens18.1500 inet static
address 10.20.1.150
netmask 255.255.255.0
vlan_raw_device ens18</pre>
<p>Перезагрузите сервер и проверьте, что получилось. Можно выполнить перезапуск сети, но если вы до этого все вручную через консоль сделали, то не поймете, сработали настройки из файла или нет. Таким образом очень просто и быстро настроить vlan на сервере с Debian.</p>
<h2>Как отключить ipv6 в Debian</h2>
<p>Пока еще эта версия протокола ip не получила широкого распространения в России. Если он вам специально не нужен, ipv6 можно отключить. Прежде чем отключать, необходимо узнать, какие сервисы в настоящее время его используют и перенастроить их, отключив у них ipv6. Если этого не сделать, то в работе этих программ могут возникнуть ошибки. Скорее всего некритичные, но всё равно, сделаем аккуратно и правильно. Сначала проверим, что у нас работает на ipv6:</p>
<pre># ss -tulnp | grep ::</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-13.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15946" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-13.png" sizes="auto, (max-width: 1341px) 100vw, 1341px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-13.png 1341w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-13-300x113.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-13-1024x386.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-13-768x290.png 768w" alt="Отключение IPV6 в Debian" width="1341" height="506" data-wp-pid="15946" /></a></p>
<p>На целевом сервере с Debian программы ssh, postfix и rpcbind используют ipv6. Отключим это. Начнем с ssh. Открываем файл <em>/etc/ssh/sshd_config</em> и раскомментируем параметр ListenAddress:</p>
<pre># mcedit /etc/ssh/sshd_config</pre>
<pre>ListenAddress 0.0.0.0</pre>
<p>Перезапускаем ssh:</p>
<pre># systemctl restart sshd</pre>
<p>Сделаем то же самое с postfix. Открываем файл конфигурации <em>/etc/postfix/main.cf</em> и меняем параметр:</p>
<pre># mcedit /etc/postfix/main.cf</pre>
<pre>inet_protocols = ipv4</pre>
<p>Перезапускаем postfix:</p>
<pre># systemctl restart postfix</pre>
<p>Отключаем ipv6 в rpcbind. Для этого нужно внести изменения в системный systemd unit:</p>
<pre># systemctl edit rpcbind.socket</pre>
<p>Добавляем между сегментами с комментариями:</p>
<pre>[Socket]
ListenStream=
ListenDatagram=
ListenStream=0.0.0.0:111
ListenDatagram=0.0.0.0:111
</pre>
<p>Перечитываем настройки юнита и перезапускаем службу rpcbind:</p>
<pre># systemctl daemon-reload
# systemctl restart rpcbind.socket</pre>
<p>Проверяем, что у нас получилось:</p>
<pre># ss -tulnp | grep ::</pre>
<p>В выводе пусто. Мы изменили настройки всех служб, которые использовали ipv6, отключив его.</p>
<p>Теперь полностью отключаем ipv6 в Debian на уровне системы:</p>
<pre># mcedit /etc/sysctl.conf</pre>
<pre>net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1</pre>
<p>Добавьте эти строки в любое место конфига, например, в самый конец. Отключим ipv6 на уровне GRUB. Открываем конфиг <em>/etc/default/grub</em> и в параметр GRUB_CMDLINE_LINUX нужно добавить значение <strong>ipv6.disable=1</strong>. Если там уже указаны другие значения, то перечислены они должны быть через пробел. Примерно так:</p>
<pre>GRUB_CMDLINE_LINUX="crashkernel=auto rhgb quiet ipv6.disable=1"</pre>
<p>После этого нужно обновить загрузчик:</p>
<pre># dpkg-reconfigure grub-pc</pre>
<p>После запуска команды все параметры, которые предложит оболочка, можно оставить по умолчанию, ничего не меняя. Когда обновление загрузчика закончится, надо перезагрузить систему.</p>
<p>Проверяем свойства сетевых интерфейсов командами ip или ifconfig. Адресов ipv6 в их настройках быть не должно, мы полностью отключили этот протокол. Более подробно об отключении ipv6 в различных приложениях читайте в отдельной статье &#8212; <a href="https://serveradmin.ru/disable-ipv6/" target="_blank" rel="noopener noreferrer">как отключить ipv6</a>.</p>
<h2>Работа с файлом hosts</h2>
<p>В папке <em>/etc</em> любого linux дистрибутива, в том числе Debian, есть файл <strong>hosts</strong>. Разберемся немного, что это за файл и для чего нужен. По умолчанию он выглядит следующим образом:</p>
<pre># cat /etc/hosts</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-14.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15947" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-14.png" sizes="auto, (max-width: 1170px) 100vw, 1170px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-14.png 1170w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-14-300x130.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-14-1024x443.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-14-768x332.png 768w" alt="содержимое hosts" width="1170" height="506" data-wp-pid="15947" /></a></p>
<p>Представим, что у нас в локальной сети есть некий сервер с именем server и ip 10.20.1.2. Мы хотим к нему обращаться по имени. Тогда добавляем запись в файл hosts в самый конец новой строкой:</p>
<pre>10.20.1.2 server</pre>
<p>Теперь мы можем обращаться к серверу просто по имени server.</p>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-15.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15948" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-15.png" sizes="auto, (max-width: 1169px) 100vw, 1169px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-15.png 1169w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-15-300x129.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-15-1024x441.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-15-768x331.png 768w" alt="файл hosts" width="1169" height="504" data-wp-pid="15948" /></a></p>
<p>Локальный сервер будет в первую очередь смотреть информацию в файле hosts, только потом в настроенном dns сервере. Например, если вы добавите в файл строку:</p>
<pre>127.0.0.1 ya.ru</pre>
<p>То обращаясь к адресу ya.ru будете попадать на localhost:</p>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-16.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15949" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-16.png" sizes="auto, (max-width: 1171px) 100vw, 1171px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-16.png 1171w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-16-300x129.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-16-1024x441.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-16-768x331.png 768w" alt="изменение hosts" width="1171" height="504" data-wp-pid="15949" /></a></p>
<p>Эта функциональность может быть полезна для публикации в локальной сети каких-то внутренних сервисов, к которым доступ будет только в рамках ваших серверов. Если их будет немного, вам нет необходимости использовать dns сервер, с файлом hosts настройка делается гораздо быстрее. Например, с его помощью можно связать именами 3 сервера небольшого локального кластера. Так же правка файла hosts актуальна, если вы используете локальную копию сервиса <a href="https://serveradmin.ru/webpagetest-lokalnaya-ustanovka-i-nastroyka/" target="_blank" rel="noopener noreferrer">webpagetest</a> для тестирования скорости работы сайта на разных хостингах. Вы просто меняете ip адреса для домена и делаете тесты. Так можно наглядно и однозначно сравнивать быстродействие разных хостингов. Подробно об этом можно почитать в статье &#8212; <a href="https://serveradmin.ru/optimizacziya-skorosti-sajta-audit-sajta/" target="_blank" rel="noopener noreferrer">ускорение сайта и аудит</a>.</p>
<h2>Настройка сетевой карты</h2>
<p>Иногда возникают ситуации, когда необходимо настроить или изменить настройки сетевой карты. Сразу отмечу, что настраивать сетевую карту можно только на реальном железе. На виртуальном, скорее всего, ни одна из предложенных дальше команд не приведет к какому-нибудь результату. У виртуальных сетевых адаптеров просто нет настроек. Для начала посмотрим, какие сетевые карты есть на сервере:</p>
<pre># lspci | grep Eth
05:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 06)</pre>
<p>В моем случае это единственная сетевая карта фирмы Realtek. Теперь установим утилиту <strong>ethtool</strong> для настройки сетевой карты:</p>
<pre># apt install ethtool</pre>
<p>Посмотрим информацию о сетевой карте:</p>
<pre># ethtool enp5s0</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15950" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17.png" sizes="auto, (max-width: 1172px) 100vw, 1172px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17.png 1172w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17-300x150.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17-1024x511.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17-768x383.png 768w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17-660x330.png 660w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-17-1050x525.png 1050w" alt="Параметры сетевой карты" width="1172" height="585" data-wp-pid="15950" /></a></p>
<p>Указана текущая скорость, на которой работает карточка. Ее можно сменить в случае необходимости:</p>
<pre># ethtool -s enp5s0 speed 100 duplex full</pre>
<p>Этой командой можно изменить скорость сетевой карточки до 100Mb/s в случае, если там стояла другая скорость. Смотрим, что получилось:</p>
<pre># ethtool enp5s0 | grep Speed
Speed: 100Mb/s</pre>
<figure class="aligncenter"></figure>
<p><a href="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18.png"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-15951" src="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18.png" sizes="auto, (max-width: 1171px) 100vw, 1171px" srcset="https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18.png 1171w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18-300x150.png 300w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18-1024x512.png 1024w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18-768x384.png 768w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18-660x330.png 660w, https://serveradmin.ru/wp-content/uploads/2024/10/debian-network-18-1050x525.png 1050w" alt="Изменение скорости сетевой карты" width="1171" height="586" data-wp-pid="15951" /></a></p>
<p>Показал просто для примера, вряд ли кому-то понадобится уменьшать скорость. Чаще нужно выполнить обратное преобразование. У меня была ситуация, когда сетевая карта упорно не хотела работать на скорость 1Gb/s, хотя поддерживала такую работу, и свитч был гигабитный. Долго бился и пробовал различные утилиты для изменения скорости. Оказалось, что патч корд был 4-х жильный из комплекта какого-то роутера. Им воспользовались для подключения и даже не обратили внимание на то, что он не поддерживает работу по гигабиту. У утилиты ethtool много параметров, с помощью которых можно настроить сетевую карту. Пример этих параметров можно посмотреть на сайте <a href="https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Deployment_Guide/s1-ethtool.html" target="_blank" rel="noopener noreferrer">redhat</a>.</p>
<h2>Работа с утилитой ifconfig</h2>
<p>В завершении сетевых настроек хотел немного поговорить об <strong>ifconfig</strong>. Ранее я упомянул, что более современным средством для настройки сети является утилита <strong>ip</strong>. В современных релизах Debian и CentOS ifconfig вообще исключили из базовой установки, ее приходится устанавливать отдельно. IP объединяет в себе две функциональности &#8212; настройка сетевых интерфейсов и маршрутизации. То есть по сути она заменяет ifconfig + route. В ней реализована функциональность обоих программ. Сам я начинал с ifconfig, так как она есть не только в Linux, но и в Freebsd и других системах Unix. Удобно использовать одно и то же средство во всех дистрибутивах. Но в последние несколько лет переучился на ip, так как надо идти в ногу со временем. Тенденция такова, что ip заменила ifconfig во всех современных дистрибутивах на базе Linux. Что касается удобства, лично я ничего не могу сказать, мне совершенно всё равно, какую команду использовать:</p>
<pre>ip addr add 192.168.1.35/24 dev eth0</pre>
<p>или</p>
<pre>ifconfig eth0 192.168.1.35 netmask 255.255.255.0</pre>
<p>Делают они одно и то же. Остальные команды по конфигурированию сетевых интерфейсов тоже не сильно отличаются, просто пишутся немного по-разному. Вот пример работы с маршрутами:</p>
<pre>ip route add 192.168.100.0/24 dev eth2</pre>
<p>или</p>
<pre>route add -net 192.168.100.0/24 dev eth2</pre>
<p>В случае с ip мы работаем с одной командой, а не двумя. Чем пользоваться вам, выбирайте сами. Если не привыкли к чему-то конкретному, рекомендую использовать ip. Мне было бы любопытно узнать, кто, что использует. Оставьте свой комментарий на эту тему. На этом я завершаю свой материал по теме настройки сети в Debian. Я рассмотрел все наиболее значимые и необходимые параметры, с которыми приходится сталкиваться во время конфигурирования сервера.</p>
<h6>Взято с сайта <a href="https://serveradmin.ru/nastroyka-seti-v-debian/">serveradmin.ru</a></h6>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[линукс]]></category><category><![CDATA[настройка сети]]></category><category><![CDATA[сети]]></category><category><![CDATA[интрасети]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/08/maxresdefault-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b0%d0%b2%d1%82%d0%be%d1%80%d0%b8%d0%b7%d0%b0%d1%86%d0%b8%d1%8f-%d0%bf%d0%be-%d0%ba%d0%bb%d1%8e%d1%87%d1%83-ssh/</link>
					<title><![CDATA[Авторизация по ключу SSH]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Thu, 06 Jun 2024 10:00:53 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/06/maxresdefault-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="ssh-key" decoding="async" loading="lazy" />								</figure>
														<h1>Авторизация по ключу SSH</h1>
													</header>
													<p>SSH или Secure Shell &#8212; это зашифрованный протокол, который часто используется для взаимодействия и удаленного управления серверами. Если вы захотите что-либо сделать на удаленном сервере, скорее всего, вам придется воспользоваться SSH и работать через терминал.</p>
<p>В SSH существует несколько способов авторизации. Вы можете каждый раз вводить пароль пользователя или использовать более безопасный и надежный способ &#8212; ключи SSH. Что самое интересное, он более удобен для применения, вам даже не нужно будет вводить пароль. В этой статье мы рассмотрим как настраивается авторизация по ключу SSH.</p>
<h2 id="kak-rabotayut-klyuchi-ssh" data-toc-heading="true">Как работают ключи SSH?</h2>
<p>SSH сервер может выполнять аутентификацию пользователей с помощью различных алгоритмов. Самый популярный &#8212; это аутентификация по паролю. Он достаточно прост, но не очень безопасный. Пароли передаются по безопасному каналу, но они недостаточно сложны для противостояния попыткам перебора. Вычислительная мощность современных систем в сочетании со специальными скриптами делают перебор очень простым. Конечно, существуют другие способы дополнительной безопасности, например, fail2ban, но аутентификация по ключу SSH более надежна.</p>
<p>Каждая пара ключей состоит из открытого и закрытого ключа. Секретный ключ сохраняется на стороне клиента и не должен быть доступен кому-либо еще. Утечка ключа позволит злоумышленнику войти на сервер, если не была настроена дополнительная аутентификация по паролю.</p>
<p>Открытый ключ используется для шифрования сообщений, которые можно расшифровать только закрытым ключом. Это свойство и используется для аутентификации с помощью пары ключей. Открытый ключ загружается на удаленный сервер, к которому необходимо получить доступ. Его нужно добавить в специальный файл ~/.ssh/authorized_keys.</p>
<p>Когда клиент попытается выполнить проверку подлинности через этот ключ, сервер отправит случайное сообщение для проверки, клиент шифрует его с помощью закрытого ключа и отправляет обратно. Дальше сервер проверяет получится ли его расшифровать с помощью открытого ключа и если да &#8212; аутентификация пройдена.</p>
<p><a href="https://losst.pro/wp-content/uploads/2017/02/ssh-key-auth-flow.png"><img loading="lazy" decoding="async" class="size-full wp-image-14036 aligncenter" src="https://losst.pro/wp-content/uploads/2017/02/ssh-key-auth-flow.png" sizes="auto, (max-width: 745px) 100vw, 745px" srcset="https://losst.pro/wp-content/uploads/2017/02/ssh-key-auth-flow.png 745w, https://losst.pro/wp-content/uploads/2017/02/ssh-key-auth-flow-300x72.png 300w" alt="" width="745" height="179" /></a></p>
<h2 id="kak-sozdat-klyuchi-ssh" data-toc-heading="true">Как создать ключи SSH?</h2>
<p>Сначала необходимо создать ключи ssh для аутентификации на локальном сервере. Для этого существует специальная утилита ssh-keygen, которая входит в набор утилит OpenSSH. По умолчанию она создает пару 2048 битных RSA ключей, которая подойдет не только для SSH, но и для большинства других ситуаций.</p>
<p>Итак, генерация ключей ssh выполняется командой:</p>
<p><code class="user"> ssh-keygen</code></p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-14043 aligncenter" src="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-17-59-21-1024x576.png" sizes="auto, (max-width: 750px) 100vw, 750px" srcset="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-17-59-21-1024x576.png 1024w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-17-59-21-300x169.png 300w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-17-59-21-768x432.png 768w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-17-59-21.png 1366w" alt="" width="750" height="422" /></p>
<p>Утилита предложит вам выбрать расположение ключей. По умолчанию ключи располагаются в папке ~/.ssh/. Лучше ничего не менять, чтобы все работало по умолчанию и ключи автоматически подхватывались. Секретный ключ будет называться id_rsa, а публичный id_rsa.pub.</p>
<p>Затем утилита предложит ввести пароль для дополнительного шифрования ключа на диске. Его можно не указывать, если не хотите. Использование дополнительного шифрования имеет только один минус &#8212; необходимость вводить пароль, и несколько преимуществ:</p>
<ul>
<li>Пароль никогда не попадет в сеть, он используется только на локальной машине для расшифровки ключа. Это значит что перебор по паролю больше невозможен.</li>
<li>Секретный ключ хранится в закрытом каталоге и у клиента ssh нет к нему доступа пока вы не введете пароль;</li>
<li>Если злоумышленник хочет взломать аутентификацию по ключу SSH, ему понадобится доступ к вашей системе. И даже тогда ключевая фраза может стать серьезной помехой на его пути.</li>
</ul>
<div class="rath2aiD rath2aiD-2">
<div class="ai-dynamic" data-code=""></div>
</div>
<p>Но все же, это необязательное дополнение и если не хотите, то вы можете просто нажать Enter. Тогда доступ по ключу ssh будет выполняться автоматически и вам не нужно будет что-либо вводить.</p>
<p>Теперь у вас есть открытый и закрытый ключи SSH и вы можете использовать их для проверки подлинности. Дальше нам осталось разместить открытый ключ на удаленном сервере.</p>
<h2 id="zagruzka-klyucha-na-server" data-toc-heading="true">Загрузка ключа на сервер</h2>
<p>Когда генерация ключей завершена, нам осталось только загрузить ключ на сервер. Для загрузки ключа можно использовать несколько способов. В некоторых случаях вы можете указать ключ в панели управления сервером, например, сPanel или любой другой. Но мы такой способ рассматривать не будем. Мы рассмотрим ручные способы.</p>
<p>Самый простой способ скопировать ключ на удаленный сервер &#8212; это использовать утилиту ssh-copy-id. Она тоже входит в пакет программ OpenSSH. Но для работы этого метода вам нужно иметь пароль доступа к серверу по SSH. Синтаксис команды:</p>
<p><code class="user"> ssh-copy-id username@remote_host</code></p>
<p><a href="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-00-14.png"><img loading="lazy" decoding="async" class="size-large wp-image-14044 aligncenter" src="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-00-14-1024x576.png" sizes="auto, (max-width: 750px) 100vw, 750px" srcset="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-00-14-1024x576.png 1024w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-00-14-300x169.png 300w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-00-14-768x432.png 768w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-00-14.png 1366w" alt="" width="750" height="422" /></a></p>
<p>При первом подключении к серверу система может его не распознать, поэтому вам нужно ввести yes. Затем введите ваш пароль пользователя на удаленном сервере. Утилита подключится к удаленному серверу, а затем использует содержимое ключа id.rsa.pub для загрузки его на сервер в файл ~/.ssh/authorized_keys. Дальше вы можете выполнять аутентификацию с помощью этого ключа.</p>
<p>Если такой способ по какой-либо причине для вас не работает, вы можете скопировать ключ по ssh вручную. Мы создадим каталог ~/.ssh, а затем поместим наш ключ в файл authorized_keys с помощью символа &gt;&gt;, это позволит не перезаписывать существующие ключи:</p>
<p><code class="user"> cat ~/.ssh/id_rsa.pub | ssh username@remote_host "mkdir -p ~/.ssh &amp;&amp; cat &gt;&gt; ~/.ssh/authorized_keys"</code></p>
<p>Здесь вам тоже нужно набрать yes, если вы подключаетесь к новому серверу, а затем ввести пароль. Теперь вы можете использовать созданный ключ для аутентификации на сервере:</p>
<p><code class="user"> ssh username@remote_host</code></p>
<p>Если вы не захотели создать ssh ключ с доступом по паролю, то вы сразу же будете авторизованы, что очень удобно. Иначе, сначала вам придется ввести фразу-пароль для расшифровки ключа.</p>
<h2 id="otklyuchenie-proverki-parolya" data-toc-heading="true">Отключение проверки пароля</h2>
<p>Если пароль больше не будет использоваться, то для увеличения безопасности системы лучше его вовсе отключить. Но убедитесь, что ключ надежно сохранен и вы его не потеряете, потому что по паролю вы больше не войдете. Авторизуйтесь на сервере, затем откройте конфигурационный файл /etc/ssh/sshd_config и найдите там директиву PasswordAuthenticatin. Нужно установить ее значение в No:</p>
<p><code class="user"> sudo vi /etc/ssh/sshd_config</code></p>
<p><code class="message">PasswordAuthentication no</code></p>
<p><a href="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-02-59.png"><img loading="lazy" decoding="async" class="size-large wp-image-14046 aligncenter" src="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-02-59-1024x576.png" sizes="auto, (max-width: 750px) 100vw, 750px" srcset="https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-02-59-1024x576.png 1024w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-02-59-300x169.png 300w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-02-59-768x432.png 768w, https://losst.pro/wp-content/uploads/2017/02/Snimok-ekrana-iz-2017-02-06-18-02-59.png 1366w" alt="" width="750" height="422" /></a></p>
<p>Теперь сохраните файл и перезапустите службу ssh:</p>
<p><code class="user"> sudo service ssh restart</code></p>
<p>Дальше будет возможно только подключение по ключу ssh, пароль не будет приниматься.</p>
<div class="rath2aiD rath2aiD-4"></div>
<h2 id="vyvody" data-toc-heading="true">Выводы</h2>
<p>В этой статье мы рассмотрели как выполняется авторизация по ключу ssh, настройка ключей ssh и добавить ssh ключ. Теперь вы можете войти на сервер без ввода пароля. Если у вас остались вопросы, спрашивайте в комментариях!</p>
<p>материал взят с сайта <a href="https://losst.pro/avtorizatsiya-po-klyuchu-ssh">losst.pro</a></p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
		        <turbo:extendedHtml>true</turbo:extendedHtml>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[линукс]]></category><category><![CDATA[ssh]]></category><category><![CDATA[ключи]]></category><category><![CDATA[безопастность]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/06/maxresdefault-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b0%d0%ba%d1%82%d0%b8%d0%b2%d0%b0%d1%86%d0%b8%d1%8f-%d0%b2%d1%81%d0%b5%d1%85-%d0%b2%d0%b5%d1%80%d1%81%d0%b8%d0%b9-windows-server-%d0%b1%d0%b5%d0%b7-%d0%ba%d0%bb%d1%8e%d1%87%d0%b0-%d0%bf%d1%80%d0%be/</link>
					<title><![CDATA[Активация всех версий Windows Server без ключа продукта]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Thu, 04 Apr 2024 03:13:54 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/winserver-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Активация всех версий Windows Server без ключа продукта</h1>
													</header>
													<div class="markdown-heading" dir="auto" data-vivaldi-translated="">
<p data-vivaldi-translated="">Как вы знаете, Windows Server &#8212; это специализированная операционная система, предназначенная только для сервера. В сегодняшнем посте я покажу вам, как бесплатно активировать Windows на вашем VPS или выделенном сервере с помощью ключей клиентского продукта KMS. Хотя лицензия KMS действительна только в течение 180 дней, но количество активаций не ограничено. Таким образом, вы можете обновить его, когда захотите. На самом деле, лицензия будет обновляться автоматически каждые 7 дней по умолчанию (почти аналогично <a href="https://letsencrypt.org/" target="_blank" rel="noreferrer noopener nofollow">Let’s Encrypt certificate</a>). Таким образом, просто сделайте это один раз и полностью забудьте об этом.</p>
<div class="alert alert-info" role="alert">
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Запись:</strong></p>
<ul>
<li data-vivaldi-translated="">Если вы студент, офисный работник или любой стандартный пользователь, использующий настольную версию Windows, просто пропустите этот пост и, пожалуйста, не следуйте инструкциям. Я не буду нести ответственность за любой ущерб, причиненный вами.</li>
<li data-vivaldi-translated="">Все выпуски Windows Server на домашней странице Microsoft являются оценочными и не поддерживаются KMS. Так что, если вы используете ознакомительную версию, просто конвертировать его в розничную прежде чем следовать инструкциям ниже.</li>
</ul>
</div>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Поддерживаемые продукты:</strong></p>
<ul>
<li data-vivaldi-translated="">Windows Server 2022/2019/2016.</li>
<li data-vivaldi-translated="">Windows Server, версия 1809, 1803, 1709.</li>
<li data-vivaldi-translated="">Windows Server 2008/2012 (R2).</li>
</ul>
<figure class="wp-block-image"><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-352 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-1.png" alt="проверка на активацию" width="730" height="580" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-1.png 730w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-1-300x238.png 300w" sizes="auto, (max-width: 730px) 100vw, 730px" /><figcaption data-vivaldi-translated="">Вот статус Windows Server, когда он не активирован</figcaption></figure>
<p data-vivaldi-translated="">Как вы можете видеть на изображении выше, я использую копию стандарта Windows Server 2016, и она не активирована.</p>
<div class="code-block code-block-7" data-vivaldi-translated=""></div>
<div class="lwptoc lwptoc-autoWidth lwptoc-baseItems lwptoc-transparent lwptoc-notInherit" data-smooth-scroll="1" data-smooth-scroll-offset="24" data-lwptoc-initialized="1" data-vivaldi-translated="">
<div class="lwptoc_i" data-vivaldi-translated="">
<div class="lwptoc_header" data-vivaldi-translated=""><b class="lwptoc_title" data-vivaldi-translated="">содержание</b></div>
<div class="lwptoc_items lwptoc_items-visible" data-vivaldi-translated="">
<div class="lwptoc_itemWrap" data-vivaldi-translated="">
<div class="lwptoc_item" data-vivaldi-translated="">Метод 1: Ручная установка клиентского ключа KMS и его активация.</div>
<div class="lwptoc_item" data-vivaldi-translated="">Метод 2: Использование предварительно написанного пакетного файла.</div>
</div>
</div>
</div>
</div>
<h2 data-vivaldi-translated="">Метод 1: Ручная установка клиентского ключа KMS и его активация.</h2>
<figure class="wp-block-embed is-type-video is-provider-vimeo wp-block-embed-vimeo wp-embed-aspect-16-9 wp-has-aspect-ratio"><figcaption data-vivaldi-translated=""></figcaption></figure>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 1.1:</strong> Получите правильный ключ продукта от <a href="https://docs.microsoft.com/en-us/windows-server/get-started/kmsclientkeys" target="_blank" rel="noreferrer noopener nofollow" data-type="URL" data-id="https://docs.microsoft.com/en-us/windows-server/get-started/kmsclientkeys" data-vivaldi-translated="">официальная статья Microsoft</a>.<br data-vivaldi-translated="" />Ключ настройки клиента KMS стандарта Win Server 2016: “ WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY ”. Я буду использовать это на следующем шаге.</p>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 1.2:</strong> Установите ключ на вашем сервере.<br data-vivaldi-translated="" />Чтобы открыть командную строку, нажмите кнопку Windows, найдите “ cmd ” и запустите командную строку в качестве администратора. Затем введите “ slmgr /ipk CLIENTKEY ” в командном окне.<br data-vivaldi-translated="" />Примечание: за каждой командой следует нажатие Enter.</p>
<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-360 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/open-cmd-with-admin-rights.png" alt="Открыть cmd с правами администратора" width="690" height="573" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/open-cmd-with-admin-rights.png 690w, https://blog.sefdar.ru/wp-content/uploads/2024/04/open-cmd-with-admin-rights-300x249.png 300w" sizes="auto, (max-width: 690px) 100vw, 690px" /><figcaption data-vivaldi-translated="">Открыть cmd с правами администратора</figcaption></figure>
<figure class="wp-block-image size-full"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-353 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-2.png" alt="запустить команду slmgr ipk" width="584" height="298" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-2.png 584w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-2-300x153.png 300w" sizes="auto, (max-width: 584px) 100vw, 584px" />запустить команду slmgr ipk</figcaption></figure>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 1.3:</strong> Установите сервер KMS.<br data-vivaldi-translated="" />Введите “ slmgr /skms km8.msguides.com ” в окне.</p>
<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-361 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/run-command-slmgr-skms.png" alt="запустить команду slmgr skms" width="590" height="87" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/run-command-slmgr-skms.png 590w, https://blog.sefdar.ru/wp-content/uploads/2024/04/run-command-slmgr-skms-300x44.png 300w" sizes="auto, (max-width: 590px) 100vw, 590px" /><figcaption data-vivaldi-translated="">запустить команду slmgr skms</figcaption></figure>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 1.4:</strong> Активируйте клиентский ключ KMS.<br data-vivaldi-translated="" />Наконец, используйте команду “slmgr /ato ”, чтобы активировать Windows.</p>
<figure class="wp-block-image size-full"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-354 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-4.png" alt="запустить команду slmgr ato" width="583" height="318" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-4.png 583w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-4-300x164.png 300w" sizes="auto, (max-width: 583px) 100vw, 583px" />запустить команду slmgr ato</figcaption></figure>
<p data-vivaldi-translated="">Если вы видите ошибку 0xC004F074, это означает, что ваше интернет-соединение нестабильно или сервер занят. Пожалуйста, убедитесь, что ваше устройство подключено к сети, и повторите команду “ ato ”, пока не добьетесь успеха.</p>
<h2 data-vivaldi-translated="">Метод 2: Использование предварительно написанного пакетного файла.</h2>
<p data-vivaldi-translated="">Этот больше не рекомендуется из-за <a href="https://msguides.com/detected-hacktool" target="_blank" rel="noreferrer noopener" data-vivaldi-translated="">новое обновление Microsoft</a>.</p>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 2.1:</strong> Скопируйте весь текст ниже в текстовый файл.</p>
<pre class="wp-block-code" data-vivaldi-translated=""><code>@echo off
title Activate Windows Server (ALL versions) for FREE - MSGuides.com&amp;cls&amp;echo =====================================================================================&amp;echo #Project: Activating Microsoft software products for FREE without additional software&amp;echo =====================================================================================&amp;echo.&amp;echo #Supported products:&amp;echo http://bit.ly/kmsclientkeys&amp;echo.&amp;echo.&amp;echo ============================================================================&amp;echo Activating your Windows...&amp;set i=1
cscript //nologo slmgr.vbs /ipk 4DWFP-JF3DJ-B7DTH-78FJB-PDRHK &gt;nul||cscript //nologo slmgr.vbs /ipk 22XQ2-VRXRG-P8D42-K34TD-G3QQC &gt;nul||cscript //nologo slmgr.vbs /ipk 7M67G-PC374-GR742-YH8V4-TCBY3 &gt;nul||cscript //nologo slmgr.vbs /ipk RCTX3-KWVHP-BR6TB-RB6DM-6X7HP &gt;nul||cscript //nologo slmgr.vbs /ipk 39BXF-X8Q23-P2WWT-38T2F-G3FPG &gt;nul||cscript //nologo slmgr.vbs /ipk YQGMW-MPWTJ-34KDK-48M3W-X4Q6V &gt;nul||cscript //nologo slmgr.vbs /ipk W7VD6-7JFBR-RX26B-YKQ3Y-6FFFJ &gt;nul||cscript //nologo slmgr.vbs /ipk TM24T-X9RMF-VWXK6-X8JC9-BFGM2 &gt;nul||cscript //nologo slmgr.vbs /ipk WYR28-R7TFJ-3X2YQ-YCY4H-M249D &gt;nul||cscript //nologo slmgr.vbs /ipk GT63C-RJFQ3-4GMB6-BRFB9-CB83V &gt;nul||cscript //nologo slmgr.vbs /ipk 74YFP-3QFB3-KQT8W-PMXWJ-7M648 &gt;nul||cscript //nologo slmgr.vbs /ipk 489J6-VHDMP-X63PK-3K798-CPX3Y &gt;nul||cscript //nologo slmgr.vbs /ipk YC6KT-GKW9T-YTKYR-T4X34-R7VHC &gt;nul||cscript //nologo slmgr.vbs /ipk TT8MH-CG224-D3D7Q-498W2-9QCTX &gt;nul||cscript //nologo slmgr.vbs /ipk 6TPJF-RBVHG-WBW2R-86QPH-6RTM4 &gt;nul||cscript //nologo slmgr.vbs /ipk 48HP8-DN98B-MYWDG-T2DCC-8W83P &gt;nul||cscript //nologo slmgr.vbs /ipk XNH6W-2V9GX-RGJ4K-Y8X6F-QGJ2G &gt;nul||cscript //nologo slmgr.vbs /ipk HM7DN-YVMH3-46JC3-XYTG7-CYQJJ &gt;nul||cscript //nologo slmgr.vbs /ipk XC9B7-NBPP2-83J2H-RHMBY-92BT4 &gt;nul||cscript //nologo slmgr.vbs /ipk 4K36P-JN4VD-GDC6V-KDT89-DYFKP &gt;nul||cscript //nologo slmgr.vbs /ipk 2WN2H-YGCQR-KFX6K-CD6TF-84YXQ &gt;nul||cscript //nologo slmgr.vbs /ipk 8N2M2-HWPGY-7PGT9-HGDD8-GVGGY &gt;nul||cscript //nologo slmgr.vbs /ipk BN3D2-R7TKB-3YPBD-8DRP2-27GG4 &gt;nul||cscript //nologo slmgr.vbs /ipk KNC87-3J2TX-XB4WP-VCPJV-M4FWM &gt;nul||cscript //nologo slmgr.vbs /ipk W3GGN-FT8W3-Y4M27-J84CP-Q3VJ9 &gt;nul||cscript //nologo slmgr.vbs /ipk D2N9P-3P6X9-2R39C-7RTCD-MDVJX &gt;nul||cscript //nologo slmgr.vbs /ipk JCKRF-N37P4-C2D82-9YXRT-4M63B &gt;nul||cscript //nologo slmgr.vbs /ipk WC2BQ-8NRM3-FDDYY-2BFGV-KHKQY &gt;nul||cscript //nologo slmgr.vbs /ipk CB7KF-BWN84-R7R2Y-793K2-8XDDG &gt;nul||cscript //nologo slmgr.vbs /ipk WVDHN-86M7X-466P6-VHXV7-YY726 &gt;nul||cscript //nologo slmgr.vbs /ipk N69G4-B89J2-4G8F4-WWYCC-J464C &gt;nul||cscript //nologo slmgr.vbs /ipk WMDGN-G9PQG-XVVXX-R3X43-63DFG &gt;nul||cscript //nologo slmgr.vbs /ipk DPCNP-XQFKJ-BJF7R-FRC8D-GF6G4 &gt;nul||cscript //nologo slmgr.vbs /ipk 6Y6KB-N82V8-D8CQV-23MJW-BWTG6 &gt;nul||cscript //nologo slmgr.vbs /ipk PTXN8-JFHJM-4WC78-MPCBR-9W4KR &gt;nul||cscript //nologo slmgr.vbs /ipk 2HXDN-KRXHB-GPYC7-YCKFJ-7FVDG &gt;nul||cscript //nologo slmgr.vbs /ipk N2KJX-J94YW-TQVFB-DG9YT-724CC &gt;nul||cscript //nologo slmgr.vbs /ipk 6NMRW-2C8FM-D24W7-TQWMY-CWH2D &gt;nul||cscript //nologo slmgr.vbs /ipk WX4NM-KYWYW-QJJR4-XV3QB-6VM33 &gt;nul||cscript //nologo slmgr.vbs /ipk VDYBN-27WPP-V4HQT-9VMD4-VMK7H &gt;nul||goto notsupported
:skms
if %i% GTR 10 goto busy
if %i% EQU 1 set KMS=kms7.MSGuides.com
if %i% EQU 2 set KMS=kms8.MSGuides.com
if %i% EQU 3 set KMS=kms9.MSGuides.com
if %i% GTR 3 goto ato
cscript //nologo slmgr.vbs /skms %KMS%:1688 &gt;nul
:ato
echo ============================================================================&amp;echo.&amp;echo.&amp;cscript //nologo slmgr.vbs /ato | find /i "successfully" &amp;&amp; (echo.&amp;echo ============================================================================&amp;echo.&amp;echo #My official blog: MSGuides.com&amp;echo.&amp;echo #How it works: bit.ly/kms-server&amp;echo.&amp;echo #Please feel free to contact me at msguides.com@gmail.com if you have any questions or concerns.&amp;echo.&amp;echo #Please consider supporting this project: donate.msguides.com&amp;echo #Your support is helping me keep my servers running 24/7!&amp;echo.&amp;echo ============================================================================&amp;choice /n /c YN /m "Would you like to visit my blog [Y,N]?" &amp; if errorlevel 2 exit) || (echo The connection to my KMS server failed! Trying to connect to another one... &amp; echo Please wait... &amp; echo. &amp; echo. &amp; set /a i+=1 &amp; goto skms)
explorer "http://MSGuides.com"&amp;goto halt
:notsupported
echo ============================================================================&amp;echo.&amp;echo Sorry, your version is not supported.&amp;echo.&amp;goto halt
:busy
echo ============================================================================&amp;echo.&amp;echo Sorry, the server is busy and can't respond to your request. Please try again.&amp;echo.
:halt
pause &gt;nul</code></pre>
<figure class="wp-block-image"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-362 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/windows-10-for-free-11.png" alt="Создать новый текстовый документ" width="574" height="400" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/windows-10-for-free-11.png 574w, https://blog.sefdar.ru/wp-content/uploads/2024/04/windows-10-for-free-11-300x209.png 300w" sizes="auto, (max-width: 574px) 100vw, 574px" />Создать новый текстовый документ</figcaption></figure>
<figure class="wp-block-image"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-355 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-5.png" alt="Сохранить пакетный скрипт" width="618" height="387" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-5.png 618w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-5-300x188.png 300w" sizes="auto, (max-width: 618px) 100vw, 618px" />Сохранить пакетный скрипт</figcaption></figure>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 2.2:</strong> Сохраните текстовый файл в виде пакетного файла с расширением .cmd. (Eg run.cmd)</p>
<div class="code-block code-block-7" data-vivaldi-translated=""></div>
<figure class="wp-block-image"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-356 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-6.png" alt="Установить имя пакетного скрипта" width="611" height="473" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-6.png 611w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-6-300x232.png 300w" sizes="auto, (max-width: 611px) 100vw, 611px" />Установить имя пакетного скрипта</figcaption></figure>
<p data-vivaldi-translated=""><strong data-vivaldi-translated="">Шаг 2.3:</strong> Запустите пакетный файл с правами администратора.</p>
<figure class="wp-block-image"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-357 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-7.png" alt="" width="359" height="413" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-7.png 359w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-7-261x300.png 261w" sizes="auto, (max-width: 359px) 100vw, 359px" />Выполнить пакетный скрипт в качестве администратора</figcaption></figure>
<figure class="wp-block-image"><figcaption data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-358 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-8.png" alt="Windows Server успешно активирован" width="633" height="303" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-8.png 633w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-8-300x144.png 300w" sizes="auto, (max-width: 633px) 100vw, 633px" />Windows Server успешно активирован</figcaption></figure>
<p data-vivaldi-translated=""><img loading="lazy" decoding="async" class="lazyloaded aligncenter wp-image-359 size-full" src="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-9.png" alt="" width="730" height="580" srcset="https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-9.png 730w, https://blog.sefdar.ru/wp-content/uploads/2024/04/instructions-how-to-activate-windows-server-without-product-key-9-300x238.png 300w" sizes="auto, (max-width: 730px) 100vw, 730px" />Наконец, проверьте статус активации вашего сервера еще раз.</p>
<figure class="wp-block-image"><figcaption data-vivaldi-translated="">Проверьте статус активации Windows Server</figcaption></figure>
<p data-vivaldi-translated="">На этом активация завершена. Спасибо за прочтение.</p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[windows]]></category><category><![CDATA[Windows]]></category><category><![CDATA[Windows Server]]></category><category><![CDATA[2016]]></category><category><![CDATA[2019]]></category><category><![CDATA[2022]]></category><category><![CDATA[2008]]></category><category><![CDATA[2012]]></category><category><![CDATA[активация]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/04/winserver-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%ba%d0%b0%d0%ba-%d1%83%d0%b2%d0%b8%d0%b4%d0%b5%d1%82%d1%8c-%d1%81%d0%bf%d0%b8%d1%81%d0%be%d0%ba-%d0%b2%d1%8b%d0%b4%d0%b0%d0%bd%d0%bd%d1%8b%d1%85-%d0%b0%d0%b4%d1%80%d0%b5%d1%81%d0%be%d0%b2-%d0%b2-dh/</link>
					<title><![CDATA[Как увидеть список выданных адресов в DHCP на Debian или CentOS.]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 13 Mar 2024 04:52:05 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/03/maxresdefault-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Как увидеть список выданных адресов в DHCP на Debian или CentOS.</h1>
													</header>
													<div class="post-outer">
<div class="post">
<div class="post-header">
<div class="post-header-line-1"></div>
</div>
<div id="post-body-1072081102211468742" class="post-body entry-content float-container">
<div dir="ltr"><u><b>В Debian:</b></u><br />
Информация о выданных адресах хранится в:<br />
dhcpd.leases внутри каталога /var/lib/dhcp/dhcpd.leases<br />
Открываем файл с помощью &#171;cat&#187; и смотрим, кто что получил.</p>
<p><u><b>В CentOS:</b></u><br />
cd /var/lib/dhcpd<br />
cat dhcpd.leases<br />
OR TO EDIT<br />
nano dhcpd.leases</div>
</div>
<div class="post-bottom">
<div class="post-footer float-container">
<div class="post-footer-line post-footer-line-1"></div>
<div class="post-footer-line post-footer-line-2"></div>
<div class="post-footer-line post-footer-line-3"></div>
</div>
<div class="post-share-buttons post-share-buttons-bottom invisible">
<div class="byline post-share-buttons goog-inline-block">
<div class="sharing" aria-owns="sharing-popup-Blog1-byline-1072081102211468742" data-title="Как увидеть список выданных адресов в DHCP на Debian или CentOS.">
<div class="flat-icon-button ripple"></div>
<div class="share-buttons-container"></div>
</div>
</div>
</div>
</div>
</div>
</div>
<a name="comments"></a>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/03/maxresdefault-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b2%d0%be%d1%81%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d0%bf%d0%b0%d1%80%d0%be%d0%bb%d1%8f-%d0%be%d1%82-root-%d0%b2-linux/</link>
					<title><![CDATA[Восстановление пароля от root в Linux]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 12 Jan 2024 08:47:32 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2024/01/2d90a7bc055ade9fb41cb6cce9561e64-1024x576.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Восстановление пароля от root в Linux</h1>
													</header>
													<p>Иногда так случается что теряешь, забываешь или передают машину без root-пароля. Тогда задаешься вопросом: Как восстановить (изменить, сбросить, нужное подставить) пароль рута для установки программ и управления системой. И я отвечаю на этот вопрос на примере CentOS 7:</p>
<p>Итак, добежав до серверной комнаты и подключив монитор с мышкой или подключившись к KVM виртуальной машины приступаем сбросу пароля. Перегружаем сервер и в меню загрузки нажимаем «<b>e</b>», как показано ниже:</p>
<p><a class="image featured" href="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/1.png" data-fslightbox=""><img decoding="async" class="article" title=" Как восстановить пароль от root в CentOS 7" src="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/1.png" alt="Как восстановить пароль от root в CentOS 7" /></a></p>
<p>Листаем вниз стрелками на клавиатуре и находим обозначение <b>ro</b>, как указано на скриншоте ниже:</p>
<p><a class="image featured" href="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/2.png" data-fslightbox=""><img decoding="async" class="article" title="CentOS 7 root reset пароля" src="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/2.png" alt="CentOS 7 root reset пароля" /></a></p>
<p>В <b>ro</b> заменяем <code>o → w</code> и добавляем <code>init=/sysroot/bin/sh</code> после <code>rw</code>. То есть вот так:</p>
<pre class="prettyprint hljs language-javascript">rw init=/sysroot/bin/sh</pre>
<p><a class="image featured" href="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/3.png" data-fslightbox=""><img decoding="async" class="article" title="CentOS 7 init=/sysroot/bin/sh" src="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/3.png" alt="CentOS 7 init=/sysroot/bin/sh" /></a></p>
<p>Теперь нажимаем <code>Ctrl + X</code> и входим в аварийный (emergency) режим. Запускаем следующую команду:</p>
<pre class="prettyprint hljs language-bash">chroot /sysroot</pre>
<p><a class="image featured" href="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/4.png" data-fslightbox=""><img decoding="async" class="article" title="CentOS 7 chroot /sysroot" src="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/4.png" alt="CentOS 7 chroot /sysroot" /></a></p>
<p>Меняем пароль от <b>root</b>. Для этого, даем в консоль команду <code>passwd root</code>. После этого вводим дважды новый пароль:</p>
<p><a class="image featured" href="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/5.png" data-fslightbox=""><img decoding="async" class="article" title=" Смена пароля от рута в СентОС 7" src="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/5.png" alt="Смена пароля от рута в СентОС 7" /></a></p>
<p>После этого, обновляем параметры <b>SELinux</b> командой <code>touch /.autorelabel</code>:</p>
<p><a class="image featured" href="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/6.png" data-fslightbox=""><img decoding="async" class="article" title="Обновить параметры SELinux после смены root пароля " src="https://wiki.merionet.ru/images/kak-vosstanovit-parol-ot-root-v-centos-7/6.png" alt="Обновить параметры SELinux после смены root пароля" /></a></p>
<p>Готово! Дайте в консоль команду <code>reboot</code> и загрузитесь в штатном режиме. Пароль от root будем изменен.</p>
<p>&nbsp;</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Uncategorized]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2024/01/2d90a7bc055ade9fb41cb6cce9561e64-1024x576.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%be%d1%82%d1%80%d0%b8%d1%81%d0%be%d0%b2%d0%ba%d0%b0-%d0%bf%d0%be-%d1%83%d1%81%d0%bb%d0%be%d0%b2%d0%b8%d1%8e/</link>
					<title><![CDATA[Отрисовка по условию]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 18 Oct 2023 04:52:47 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="400" height="153" src="https://blog.sefdar.ru/wp-content/uploads/2023/10/ifelsecodelogo.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Отрисовка по условию</h1>
													</header>
													<p>В React вы можете создавать отдельные компоненты, которые инкапсулируют нужное вам поведение. Затем вы можете отрисовать только некоторые из них, в зависимости от состояния вашего приложения.</p>
<p>Условная отрисовка в React работает так же, как условия работы в JavaScript. Используйте JavaScript-операторы, например if или тернарный оператор, чтобы создать элементы, представляющие текущее состояние, и пусть React обновит пользовательский интерфейс для соответствия им.</p>
<p>Рассмотрим эти два компонента:</p>
<pre>function UserGreeting(props) {
  return &lt;h1&gt;С возвращением!&lt;/h1&gt;;
}

function GuestGreeting(props) {
  return &lt;h1&gt;Пожалуйста, зарегистрируйтесь.&lt;/h1&gt;;
}</pre>
<p>Мы создадим компонент Greeting, который отрисовывает любой из этих компонентов в зависимости от того, вошел ли пользователь в систему:</p>
<pre>function Greeting(props) {
const isLoggedIn = props.isLoggedIn;
if (isLoggedIn) {
return ;
}
return ;
}

ReactDOM.render(
// Попробуйте изменить на isLoggedIn={true}:
,
document.getElementById('root')
);</pre>
<p>Этот пример отрисовывает другое приветствие в зависимости от значения свойства isLoggedIn.</p>
<h3>Переменные элементы</h3>
<p>Вы можете использовать переменные для хранения элементов. Это может помочь вам по условию отрисовать часть компонента, в то время как остальная часть вывода не изменится.</p>
<p>Рассмотрим эти два новых компонента, представляющих кнопки для выхода и авторизации:</p>
<pre>function LoginButton(props) {
  return (
    &lt; onClick={props.onClick}&gt;
      Авторизация
    &lt;/button&gt;
  );
}

function LogoutButton(props) {
  return (
    &lt; onClick={props.onClick}&gt;
      Выход
    &lt;/button&gt;
  );
}</pre>
<p>В приведённом ниже примере мы создадим компонент с состоянием с именем LoginControl.</p>
<p>Он будет отрисовывать либо или в зависимости от текущего состояния. Он также отрисует из предыдущего примера:</p>
<pre>class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    let button;

    if (isLoggedIn) {
      button = &lt;LogoutButton onClick={this.handleLogoutClick} /&gt;;
    } else {
      button = &lt;LoginButton onClick={this.handleLoginClick} /&gt;;
    }

    return (
      &lt;div&gt;
        &lt; isLoggedIn={isLoggedIn} /&gt;
        {button}
      &lt;/div&gt;
    );
  }
}

ReactDOM.render(
  &lt;LoginControl /&gt;,
  document.getElementById('root')
);</pre>
<p>Хотя объявление переменной и использование оператора if — прекрасный способ по условию отрисовать компонент, иногда возможно вы захотите использовать более короткий синтаксис. В JSX существует несколько способов встроенных условий, описанных ниже.</p>
<h3>Встроенный оператор if с логическим оператором &amp;&amp;</h3>
<p>Вы можете вставлять любые выражения в JSX, обертывая их фигурными фигурными скобками. Это включает в себя логический JavaScript-оператор &amp;&amp;. Это может быть удобно для условного включения элемента:</p>
<p>Вы можете вставлять любые выражения в JSX, обёртывания их фигурными скобками. Это включает логический JavaScript-оператор &amp;&amp;. Это может быть удобно для условной отрисовки элемента:</p>
<pre>function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    &lt;div&gt;
      &lt;h1&gt;Привет!&lt;/h1&gt;
      {unreadMessages.length &gt; 0 &amp;&amp;
        &lt;h2&gt;
          У вас {unreadMessages.length} непрочитанных сообщений.
        &lt;/h2&gt;
      }
    &lt;/div&gt;
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  &lt;Mailbox unreadMessages={messages} /&gt;,
  document.getElementById('root')
);</pre>
<p>Это работает, потому что в JavaScript <code class="gatsby-code-text">true &amp;&amp; expression</code> всегда вычисляется в <code class="gatsby-code-text">expression</code>, а <code class="gatsby-code-text">false &amp;&amp; expression</code> всегда вычисляется в <code class="gatsby-code-text">false</code>.</p>
<p>Поэтому, если условие равно true, элемент справа после &amp;&amp; появится в выводе. Если оно false, React игнорирует и пропускает его.</p>
<p>Встроенный оператор if-else с тернарным оператором<br />
Другой метод встроенной условной отрисовки элементов — использование условного оператора в JavaScript <code class="gatsby-code-text">условие ? true : false</code>.</p>
<p>В приведённом ниже примере мы используем его для условной отрисовки небольшого блока текста.</p>
<pre>render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    &lt;div&gt;
      Пользователь &lt;b&gt;{isLoggedIn ? 'в данный момент' : 'не'}&lt;/&gt; авторизован.
    &lt;/div&gt;
  );
}/pre&gt;
Он также может использоваться для больших выражений, хотя из-за этого менее очевидно, что происходит:</pre>
<pre>render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    &lt;div&gt;
      {isLoggedIn ? (
        &lt;LogoutButton onClick={this.handleLogoutClick} /&gt;
      ) : (
        &lt;LoginButton onClick={this.handleLoginClick} /&gt;
      )}
    &lt;/div&gt;
  );
}</pre>
<p>Как и в JavaScript, вы можете выбрать подходящий стиль, основанный на том, что вы и ваша команда считаете более читабельным. Также помните, что всякий раз, когда условия становятся слишком сложными, возможно, самое время извлечь компонент.</p>
<h3>Предотвращение отрисовки компонента</h3>
<p>В редких случаях, возможно, вам потребуется скрыть компонент, даже если он был отрисован другим компонентом. Для этого возвращаем null вместо вывода отрисовки.</p>
<p>В приведённом ниже примере отрисовывается в зависимости от значения свойства с названием warn. Если значение этого свойства равно false, то компонент не отрисовывается:</p>
<pre>function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    &lt;div className="warning"&gt;
      Предупреждение!
    &lt;/div&gt;
  );
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.= {showWarning: true};
    this.handleToggleClick = this.handleToggleClick.bind(this);
  }

  handleToggleClick(){
    this.setState(state =&gt; ({
      showWarning: !state.showWarning
    }));
  }

  render(){
    return(
      &lt;div&gt;
        &lt;WarningBanner warn={this.state.showWarning} /&gt;
        &lt;button onClick={this.handleToggleClick}&gt;
          {this.state.showWarning ? 'Скрыть' : 'Показать'}
        &lt;/button&gt;
      &lt;/div&gt;
    );
  }
}

ReactDOM.render(
  &lt;Page /&gt;,
  document.getElementById('root')
);</pre>
<p>Возврат null из метода компонента render не влияет на запуск методов жизненного цикла компонента. Например, componentDidUpdate по-прежнему будет вызываться.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[JavaScript]]></category><category><![CDATA[FrameWork]]></category><category><![CDATA[React]]></category><category><![CDATA[отрисовка]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/10/ifelsecodelogo.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%84%d0%b0%d0%b9%d0%bb-%d0%bf%d0%be%d0%b4%d0%ba%d0%b0%d1%87%d0%ba%d0%b8-linux-%d0%ba%d0%b0%d0%ba-%d0%b4%d0%be%d0%b1%d0%b0%d0%b2%d0%b8%d1%82%d1%8c-%d0%be%d0%b7%d1%83-%d0%b7%d0%b0-%d1%81%d1%87%d0%b5/</link>
					<title><![CDATA[Файл подкачки Linux. Как добавить ОЗУ за счет диска]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 14 Oct 2023 04:36:31 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="505" src="https://blog.sefdar.ru/wp-content/uploads/2023/10/swap-ubuntu-logo-1024x616.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Файл подкачки Linux. Как добавить ОЗУ за счет диска</h1>
													</header>
													<p>В операционной системе Linux, как и в других ОС, файл подкачки нужен для страховки оперативной памяти. Когда установленный объем ОЗУ заканчивается, используется именно выделенная область из файла подкачки. Это может понадобиться в двух случаях:</p>
<ul>
<li>Для того чтобы при полной занятости и, как следствие, отсутствия свободной оперативной памяти, компьютер не зависал.</li>
<li>Для распределения приоритетов (важным процессам отдается физическая оперативная память, а второстепенным файл подкачки Linux).</li>
</ul>
<p>Сам по себе swap &#8212; это отдельный логический раздел вашего диска либо просто файл на системном разделе. Чаще всего он создается именно при установке операционной системы. Но создать swap linux можно и после завершения инсталляции ОС.</p>
<p><i>В последних версиях операционной системы Ubuntu</i><i> Linux</i><i> файл подкачки создается автоматически вне зависимости от того, хотите вы этого или нет. При этом его размер составляет около 1 Гб.</i></p>
<h3>Как посмотреть swap в Linux</h3>
<p>Прежде чем приступить к процессу добавления, настройки или удаление файла подкачки, необходимо проверить его наличие. Для этого проще всего использовать приведенную ниже команду. В нашем случае она выглядит так:</p>
<pre>free -h</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28247" src="https://losst.pro/wp-content/uploads/2019/10/image2-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image2-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image2-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Используемая команда отображает размер файла подкачки вашей операционной системы. Однако, по ее результатам мы не можем определить – это файл подкачки или раздел подкачки. Поэтому будем использовать дополнительный другую команду, чтобы посмотреть swap linux. Вводим в терминал следующее:</p>
<pre>swapon --show</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28248" src="https://losst.pro/wp-content/uploads/2019/10/image3-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image3-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image3-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Как видите, в нашем случае под swap выделено 1.4 Гб и это файл. То есть, он находится не на отдельном разделе, а на том же диске, на котором установлена операционная система.</p>
<p><i>Если это будет отдельный логический том, то под надписью «</i><i>TYPE</i><i>» мы увидим слово «partition».</i></p>
<p>Если бы файл подкачки в вашей операционной системе отсутствовал, результат работы команды <strong>free &#8212;h </strong>выглядел бы примерно так:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28249" src="https://losst.pro/wp-content/uploads/2019/10/image4-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image4-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image4-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>То есть, вместо каких-либо данных о файле подкачки вы увидите нули.</p>
<h3>Создание файла подкачки Linux</h3>
<p>Если вы удостоверились в том, что файл подкачки отсутствует, можно переходить к его созданию. Пример, приведенный ниже, будет показан с использованием операционной системы Ubuntu 18.04, но работать это должно и на других дистрибутивах Linux.</p>
<h3>Шаг 1: Создаем swap файл</h3>
<p>Давайте создадим файл подкачки для нашей Ubuntu. Для примера его размер составит 1 Гб. Запустите терминал и введите команду, приведенную ниже:</p>
<pre>sudo fallocate -l 1G /swapfile</pre>
<p>Для обеспечения безопасности файла обязательно устанавливаем на него нужные права.</p>
<pre>sudo chmod 600 /swapfile</pre>
<p><i>При этом вместо «swapfile» мы можем указать любое другое название.</i></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28250" src="https://losst.pro/wp-content/uploads/2019/10/image5-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image5-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image5-1.jpg 1440w" alt="" width="806" height="504" /></p>
<h4>Шаг 2: Создание файловой системы</h4>
<p>Создание swap linux ещё не завершено. Теперь необходимо указать нашей операционной системе, что созданный объект должен использоваться как файл подкачки. Для этого мы будем использовать команду, приведенную ниже:</p>
<pre>sudo mkswap /swapfile</pre>
<p>Если все сделано верно, результат будет выглядеть так:</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28251" src="https://losst.pro/wp-content/uploads/2019/10/image6-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image6-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image6-1.jpg 1440w" alt="" width="806" height="504" /></p>
<h4>Шаг 3: Активируем файл подкачки</h4>
<p>Хорошо, теперь наш Linux понимает, что это файл подкачки, но этого недостаточно. Нам также необходимо включить SWAP:</p>
<pre>sudo swapon /swapfile</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28252" src="https://losst.pro/wp-content/uploads/2019/10/image7-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image7-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image7-1.jpg 1440w" alt="" width="806" height="504" /></p>
<div class="rath2aiD rath2aiD-2">
<div class="ai-dynamic" data-code=""></div>
</div>
<p>Давайте проверим, все ли мы сделали правильно:</p>
<pre>swapon --show</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28253" src="https://losst.pro/wp-content/uploads/2019/10/image8-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image8-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image8.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Отлично, операционная система распознала наш файл подкачки и начала его использовать. Мы видим тип в поле <strong>TYPE</strong> и размер в поле <strong>SIZE</strong>.</p>
<h4>Шаг 4. Сохранение изменений после перезагрузки</h4>
<p>Все операции, которые мы предприняли выше, временны. Как только компьютер будет перезагружен, они отменятся. Для того чтобы сделать изменения постоянными, нам необходимо дописать кое-какую информацию в <strong>/etc/fstab</strong>. Для этого поступаем так:</p>
<p>Прежде чем начать работать с файлом, о котором мы говорим, необходимо обязательно создать его резервную копию:</p>
<pre>sudo cp /etc/fstab /etc/fstab.back</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28254" src="https://losst.pro/wp-content/uploads/2019/10/image9-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image9-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image9-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>После этого можно переходить непосредственно к добавлению нужных нам данных. Нам надо добавить в файл такую строчку:</p>
<pre>/swapfile none swap sw 0 0</pre>
<p>Это реализуется через текстовый редактор, запущенный с правами суперпользователя, либо при помощи введенной в терминал команды:</p>
<pre>echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28255" src="https://losst.pro/wp-content/uploads/2019/10/image10-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image10-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image10-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Готово. Изменения сохранены и файл подкачки не сбросится после перезагрузки операционной системы.</p>
<h4>Настройка swappiness</h4>
<p>Дальше будет рассмотрена настройка swap linux. У файла подкачки существуют параметры, которые сообщают ОС, как часто его нужно использовать. Это явление называется «свопингом» и может иметь значение в пределах 0 &#8212; 100. Если это значение ближе к 100, ядро будет перемещать в раздел подкачки больше информации чтобы освободить память. При значениях ближе к нулю, система будет использовать подкачку только при крайней необходимости.</p>
<p>К примеру, в версии Ubuntu Linux для рабочего стола устанавливается параметр 60, а в серверных редакциях операционной системы &#8212; 1. Для того чтобы проверить, какой параметр используется в нашей ОС, вводим в терминал такую команду:</p>
<pre>cat /proc/sys/vm/swappiness</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28256" src="https://losst.pro/wp-content/uploads/2019/10/image11-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image11-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image11-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Как видите, в нашем случае «свопинг» установлен как 60. Если же вы хотите поменять swappiness, можете воспользоваться оператором, цифра в конце которого и будет новым значением:</p>
<pre>sudo sysctl vm.swappiness=25</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28257" src="https://losst.pro/wp-content/uploads/2019/10/image12-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image12-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image12-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Как и в случае с конфигурацией файла подкачки, данный параметр изначально будет временным и обнулится при следующей перезагрузке. Для того чтобы сделать его постоянным, в самом конце файла <strong>/etc/sysctl.conf</strong> записываем значение <strong>vm.swappiness=25</strong>.</p>
<pre>nano/etc/sysctl.conf
vm.swappiness=25</pre>
<p>Для этого можно воспользоваться, например, текстовым редактором, запущенным с администраторскими полномочиями.</p>
<h3>Размер swap файла в Linux</h3>
<p>Существует сразу несколько вариантов, позволяющих увеличить файл подкачки linux или уменьшить его. Однако, прежде чем их рассмотреть, необходимо напомнить об одном очень важном моменте:</p>
<p><i>Когда вы полностью отключаете файл подкачки, ваша операционная система использует только ОЗУ и в случае ее нехватки это может привести к полной остановке работы компьютера. Система просто зависнет.</i></p>
<p>Для того чтобы этого не произошло, в тот момент, когда мы удаляем или изменяем основной файл подкачки, необходимо создать второй, временный swap. Если вы это сделали или уверены в том, что имеющейся оперативной памяти хватит, можно переходить непосредственно к процессу изменения размера файла подкачки. Для этого давайте сначала отключим его:</p>
<pre>sudo swapoff /swapfile</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28258" src="https://losst.pro/wp-content/uploads/2019/10/image14-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image14-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image14-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>Вторым этапом меняем размер файла подкачки, воспользовавшись командой, приведенной ниже. При этом размер вашего swap файла нужно указать вместо параметра <strong>2G </strong>(2 гигабайта):</p>
<pre>sudo fallocate -l 2G /swapfile</pre>
<p>Теперь форматируем полученный файл в файловую систему swap:</p>
<pre>sudo mkswap /swapfile</pre>
<p>А затем включаем его обратно:</p>
<pre>sudo swapon /swapfile</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28259" src="https://losst.pro/wp-content/uploads/2019/10/image15-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image15-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image15-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p><i>При этом операционная система Linux позволяет использовать сразу несколько swap</i><i>.</i></p>
<h3>Как удалить файл подкачки в Linux</h3>
<p>Если по каким-то причинам файл подкачки вам не нужен, можете удалить его. Для этого сначала надо отключить swap linux:</p>
<pre>sudo swapoff /swapfile</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28260" src="https://losst.pro/wp-content/uploads/2019/10/image16-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image16-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image16-1.jpg 1440w" alt="" width="806" height="504" /></p>
<p>А потом удаляем:</p>
<pre>sudo rm /swapfile</pre>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28261" src="https://losst.pro/wp-content/uploads/2019/10/image17-1-922x576.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.pro/wp-content/uploads/2019/10/image17-1-922x576.jpg 922w, https://losst.pro/wp-content/uploads/2019/10/image17-1.jpg 1440w" alt="" width="806" height="504" /><br />
Не забудьте установить права на вновь созданный файл подкачки так, как мы описывали это выше.</p>
<h3>В заключение</h3>
<p>Надеемся теперь концепция файла подкачки в Linux ясна вам на 100%. Можете переходить к практике и проверять наличие swap на вашем компьютере или ноутбуке, его настройке, созданию или даже удалению. Если в результате у вас останутся какие-то вопросы, предложения или замечания, можете задать их нам, воспользовавшись формой комментирования ниже.</p>
<p>Источник <a href="https://losst.pro/fajl-podkachki-linux">lost.pro</a> очень хороший сайт, советую добавить его в закладки.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[RAM]]></category><category><![CDATA[линукс]]></category><category><![CDATA[swap]]></category><category><![CDATA[free]]></category><category><![CDATA[свап]]></category><category><![CDATA[своп]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/10/swap-ubuntu-logo-1024x616.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%80%d0%b0%d0%b7%d1%80%d0%b0%d0%b1%d0%be%d1%82%d0%ba%d0%b0-progressive-web-app-c-react/</link>
					<title><![CDATA[Разработка Progressive Web App c React]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 13 Sep 2023 12:10:10 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2023/09/2395488_bd78_2-1024x576-1.jpeg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Разработка Progressive Web App c React</h1>
													</header>
													<p>Progressive Web Apps это разрекламированное будущее интернета. Давайте разработаем такое приложение!</p>
<p>Google продвигает PWA как решение многих проблем современного веба &#8212; в частности вопросов связанных с мобильными пользователями: <a href="https://developers.google.com/web/progressive-web-apps/" target="_blank" rel="noopener noreferrer">https://developers.google.com/web/progressive-web-apps/</a>.</p>
<p>Progressive Web App &#8212; это по сути быстрые, ориентированные на производительность веб-приложения, которые специальным образом подготовлены для мобильных устройств. Также их можно сохранить на домашнем экране вашего смартфона, а оттуда они будут выглядеть и чувствовать себя как нативные приложения (включая оффлайн особенности и Push уведомления).</p>
<p>Крупные игроки, такие как Х(Twitter) или Flipboard недавно запустили свои PWA, которые можно попробовать посетив с мобильного устройства страницы <a class="markup--anchor markup--p-anchor" href="http://flipboard.com/" target="_blank" rel="noopener noreferrer" data-href="http://flipboard.com">http://flipboard.com</a> или <a class="markup--anchor markup--p-anchor" href="https://lite.twitter.com/" target="_blank" rel="nofollow noopener noreferrer" data-href="https://lite.twitter.com/">https://lite.twitter.com/</a>.</p>
<p>В этой статье, мы будем разрабатывать простое PWA с помощью React, которое даст нам шаблон для разработки более сложных приложений.</p>
<h2>Настройка</h2>
<p>Для начала, давайте создадим базовое React приложение с помощью <a class="markup--anchor markup--p-anchor" href="https://github.com/facebookincubator/create-react-app" target="_blank" rel="noopener noreferrer" data-href="https://github.com/facebookincubator/create-react-app">create-react-app</a>.</p>
<p>Перейдите в каталог в котором вы будете хранить ваше приложение и запустите следующие команды:</p>
<pre>npm install -g create-react-app
create-react-app pwa-experiment --template cra-template-pwa</pre>
<p>Теперь давайте установим React Router:</p>
<pre>pwa-experiment
npm install --save react-router@3.0.5</pre>
<p>Наконец, скопируйте этот код в файл App.js. Он даст нам простой макет страницы с навигацией:</p>
<pre>import React, { Component } from 'react';
import { Router, browserHistory, Route, Link } from 'react-router';
import logo from './logo.svg';
import './App.css';

const Page = ({ title }) =&gt; (
  &lt;div className="App"&gt;
    &lt;div className="App-header"&gt;
      &lt;img src={logo} className="App-logo" alt="logo" /&gt;
      &lt;h2&gt;{title}&lt;/h2&gt;
    &lt;/div&gt;
    &lt;p className="App-intro"&gt;
      This is the {title} page.
    &lt;/p&gt;
    &lt;p&gt;
      &lt;Link to="/"&gt;Home&lt;/Link&gt;
    &lt;/p&gt;
   &lt;p&gt;
      &lt;Link to="/about"&gt;About&lt;/Link&gt;
    &lt;/p&gt;
    &lt;p&gt;
      &lt;Link to="/settings"&gt;Settings&lt;/Link&gt;
    &lt;/p&gt;
  &lt;/div&gt;
);

const Home = (props) =&gt; (
  &lt;Page title="Home"/&gt;
);

const About = (props) =&gt; (
  &lt;Page title="About"/&gt;
);

const Settings = (props) =&gt; (
  &lt;Page title="Settings"/&gt;
);

class App extends Component {
  render() {
    return (
      &lt;Router history={browserHistory}&gt;
        &lt;Route path="/" component={Home}/&gt;
        &lt;Route path="/about" component={About}/&gt;
        &lt;Route path="/settings" component={Settings}/&gt;
      &lt;/Router&gt;
    );
  }
}

export default App;</pre>
<p>Запустите <em>npm start</em> чтобы протестировать ваше приложение. Смотреть ещё нечего, но для наших целей это хорошее начало. Давайте начнём конвертировать всё это в Progressive Web App.</p>
<h2>1. Установка Lighthouse</h2>
<p>Lighthouse &#8212; это бесплатный инструмент от Google, который оценивает ваше приложение на основе чек листа PWA. <a href="https://developers.google.com/web/tools/lighthouse/" target="_blank" rel="noopener noreferrer">https://developers.google.com/web/tools/lighthouse/</a>.</p>
<p>Давайте <a href="https://chrome.google.com/webstore/detail/lighthouse/blipmdconlkpinefehnmjammfjpmpbjk" target="_blank" rel="noopener noreferrer">установим его в Chrome</a>, а после этого оценим нашем приложение. Вы можете запустить аудит Lighthouse кликнув по иконке в правом верхнем углу браузера, а затем нажав на кнопку &#171;Generate Report&#187;.</p>
<p><img decoding="async" class="align-center" src="https://tuhub.ru/sites/default/files/inline-images/1-V6PeCwLINQCTumMaKGlIpg.png" alt="Lighthouse" data-entity-type="file" data-entity-uuid="ccedb8eb-e667-4b9c-93f9-4b54be6ab558" /></p>
<p>Упс.</p>
<p>Пока что наше приложение быстрое (так как у нас очень мало контента), но оно проваливается в большинстве ключевых областей.</p>
<p>Вы можете увидеть чек лист, который используется в Lighthouse здесь: <a href="https://developers.google.com/web/progressive-web-apps/checklist" target="_blank" rel="noopener noreferrer">https://developers.google.com/web/progressive-web-apps/checklist</a>.</p>
<p>Давайте работать с проблемами по порядку.</p>
<h2 id="section-3.0.0">2. Настройка Service Worker</h2>
<p><a class="markup--anchor markup--p-anchor" href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API" target="_blank" rel="noopener noreferrer" data-href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">Service worker</a> &#8212; это JavaScript код, который находится между нашим приложением и сетью. Мы будем использовать его для перехвата сетевых запросов и обслуживания закэшированных файлов &#8212; это позволит нашему приложению работать оффлайн.</p>
<p>Чтобы начать работу с Service Worker&#8217;ом, нам необходимо сделать 3 вещи:</p>
<ul>
<li>Создать файл service-worker.js в папке public;</li>
<li>Зарегистрировать worker через наш index.js;</li>
<li>Настроить кэширование;</li>
</ul>
<p>Давайте сделаем это.</p>
<p>Первый шаг довольно понятен. В папке pwa-experiment/public, создаём пустой JavaScript файл названный service-worker.js.</p>
<p>Второй шаг немного запутаннее. Мы хотим проверить если браузер поддерживает service worker&#8217;ы, и тогда регистрировать его с помощью service-worker.js.</p>
<p>Чтобы сделать это, давайте добавим тег script в файл public/index.html.</p>
<pre>&lt;!doctype html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    &lt;link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"&gt;
    &lt;title&gt;React App&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id="root"&gt;&lt;/div&gt;
    &lt;script&gt;
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', function() {
          navigator.serviceWorker.register('service-worker.js').then(function(registration) {
            // Registration was successful
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
          }, function(err) {
            // registration failed :(
            console.log('ServiceWorker registration failed: ', err);
          }).catch(function(err) {
            console.log(err)
          });
        });
      } else {
        console.log('service worker is not supported');
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>Этот код очень простой &#8212; если браузер поддерживает его, то мы ждём пока страница загрузится, а после этого регистрируем наш Service Worker загружая файл service-worker.js.</p>
<p>Завершающий шаг: Настройка кэширования!</p>
<p>Мы собираемся скопировать настройки Service Worker&#8217;а <a href="https://medium.com/@addyosmani/progressive-web-apps-with-react-js-part-3-offline-support-and-network-resilience-c84db889162c" target="_blank" rel="noopener noreferrer">отсюда</a> написанные Addy Osmani, а также отключим кэширование в целях разработки (и предпримем меры удаления всего кэша, когда Service Worker инициализируется).</p>
<p>В public/service-worker.js:</p>
<pre>// Set this to true for production
var doCache = false;

// Name our cache
var CACHE_NAME = 'my-pwa-cache-v1';

// Delete old caches that are not our current one!
self.addEventListener("activate", event =&gt; {
  const cacheWhitelist = [CACHE_NAME];
  event.waitUntil(
    caches.keys()
      .then(keyList =&gt;
        Promise.all(keyList.map(key =&gt; {
          if (!cacheWhitelist.includes(key)) {
            console.log('Deleting cache: ' + key)
            return caches.delete(key);
          }
        }))
      )
  );
});

// The first time the user starts up the PWA, 'install' is triggered.
self.addEventListener('install', function(event) {
  if (doCache) {
    event.waitUntil(
      caches.open(CACHE_NAME)
        .then(function(cache) {
          // Get the assets manifest so we can see what our js file is named
          // This is because webpack hashes it
          fetch("asset-manifest.json")
            .then(response =&gt; {
              response.json()
            })
            .then(assets =&gt; {
              // Open a cache and cache our files
              // We want to cache the page and the main.js generated by webpack
              // We could also cache any static assets like CSS or images
              const urlsToCache = [
                "/",
                assets["main.js"]
              ]
              cache.addAll(urlsToCache)
              console.log('cached');
            })
        })
    );
  }
});

// When the webpage goes to fetch files, we intercept that request and serve up the matching files
// if we have them
self.addEventListener('fetch', function(event) {
    if (doCache) {
      event.respondWith(
          caches.match(event.request).then(function(response) {
              return response || fetch(event.request);
          })
      );
    }
});</pre>
<p>Перезапустите ваш приложение с помощью <em>npm run start</em> и вы должны увидеть следующее в консоле:</p>
<p><img decoding="async" class="align-center" src="https://tuhub.ru/sites/default/files/inline-images/1-jdfnTvtUSvaohYy-PZWXQw.png" alt="Progressive Web App React Debug" data-entity-type="file" data-entity-uuid="3a09f773-3d21-4a8a-9649-bd16c0d1054c" /></p>
<p>Для более подробной дискуссии на тему Service Worker&#8217;ов, посмотрите это <a href="https://medium.com/@addyosmani/progressive-web-apps-with-react-js-part-3-offline-support-and-network-resilience-c84db889162c" target="_blank" rel="noopener noreferrer">https://medium.com/@addyosmani/progressive-web-apps-with-react-js-part-3-offline-support-and-network-resilience-c84db889162c</a>.</p>
<p>Давайте закроем консоль и запустим аудит Lighthouse снова:</p>
<p><img decoding="async" class="align-center" src="https://tuhub.ru/sites/default/files/inline-images/1-nZInBhvGwAP-oort56NHWw.png" alt="Lighthouse audit result" data-entity-type="file" data-entity-uuid="26f4da11-845e-4b4c-9d38-91f41a2c32ad" /></p>
<p>Мы делаем успехи! Теперь у нас есть зарегистрированный Service Worker. Так как у нас отключено кэширование, вторая галочка ещё не отмечена, но как только мы включим кэширование она будет работать!</p>
<h2>3. Добавление прогрессивных улучшений</h2>
<p>Прогрессивные улучшения в основном означают, что сайт будет работать без загрузки любого JavaScript кода.</p>
<p>Прямо сейчас, файл index.html отображает пустой div (#root), который подхватывает наше React приложение.</p>
<p>Вместо этого, мы хотим отображать какой-то базовый HTML и CSS, ещё до того как React приложение будет инициализировано.</p>
<p>Самый простой способ сделать это &#8212; переместить некоторые из наших основных HTML структур в этот самый div#root. Этот HTML будет перезаписан как только ReactDOM отобразит компонент App, но покажет пользователю что-то вместо пустой страницы на которую пришлось бы глазеть пока загружается bundle.js.</p>
<p>Вот наш новый index.html. Обратите внимание, что стили находятся в head, а HTML в div#root.</p>
<pre>&lt;!doctype html&gt;
&lt;html lang="en"&gt;
  &lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    &lt;link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"&gt;
    &lt;title&gt;React App&lt;/title&gt;
    &lt;!-- Add in some basic styles for our HTML --&gt;
    &lt;style type="text/css"&gt;
      body {
        margin: 0;
        padding: 0;
        font-family: sans-serif;
      }
      .App {
        text-align: center;
      }
      .App-header {
        background-color: #222;
        height: 150px;
        padding: 20px;
        color: white;
      }
      .App-intro {
        font-size: large;
      }
    &lt;/style&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;!-- Filler HTML as our app starts up --&gt;
    &lt;div id="root"&gt;
      &lt;div class="App"&gt;
      &lt;div class="App-header"&gt;
        &lt;h2&gt;Home&lt;/h2&gt;
      &lt;/div&gt;
      &lt;p class="App-intro"&gt;
        Loading site...
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;script&gt;
      if ('serviceWorker' in navigator) {
        window.addEventListener('load', function() {
          navigator.serviceWorker.register('service-worker.js').then(function(registration) {
            // Registration was successful
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
          }, function(err) {
            // registration failed :(
            console.log('ServiceWorker registration failed: ', err);
          }).catch(function(err) {
            console.log(err)
          });
        });
      } else {
        console.log('service worker is not supported');
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</pre>
<p>(Кстати, теперь мы можем удалить дубликаты стилей в App.css и index.css &#8212; просто чтобы сделать код чище.)</p>
<p>Одобрит ли это Lighthouse?<br />
<img decoding="async" src="https://tuhub.ru/sites/default/files/inline-images/1-znpXu5xiIU_AAfBaPWColQ.png" alt="Lighthouse audit result" data-entity-type="file" data-entity-uuid="fa07bf45-1b0e-4f2b-baa9-6b3294f82b1d" />Ага!</p>
<h2 id="section-5.0.0">4. Возможность добавления на домашний экран</h2>
<p>Мы можем пропустить требования касающиеся HTTPS &#8212; которые будут учтены после деплоя.</p>
<p>Ну а сейчас о том, что делает Progressive Web App действительно особенными: возможность пользователя сохранить его на свой домашний экран и открывать его как приложение.</p>
<p>Чтобы это сделать, нам нужно добавить файл manifest.json в папку public.</p>
<pre>{
  "hort_name": "My First PWA",
  "name": "My First Progressive Web App",
  "icons: [
    {
      "src":"icon.png",
      "sizes": "192x192",
      "type": "image/png"
    }
  ],
  "start_url": "/?utm_source=homescreen",
  "background_color": "#222",
  "theme_color": "#222",
  "display": "standalone"
}</pre>
<p>Если у вас нету значка, то можете использовать этот (любезность моей компании <a class="markup--anchor markup--p-anchor" href="http://musefind.com/" target="_blank" rel="noopener noreferrer" data-href="http://musefind.com">MuseFind</a>), или создайте свой собственный (должен быть 192 на 192 пикселя):</p>
<p><img decoding="async" class="align-center" src="https://tuhub.ru/sites/default/files/inline-images/1-W9RHL8akNvH-FUGwQgCUNw.png" alt="MuseFind" data-entity-type="file" data-entity-uuid="464d3ef4-6672-4c9d-ae27-a571c34eda7c" /></p>
<p>Добавьте icon.png и manifest.json в папку public, а также добавьте следующие строки в ваш index.html файл:</p>
<pre>&lt;head&gt;
    &lt;meta charset="utf-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1"&gt;
    &lt;link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"&gt;
    &lt;!-- Add manifest --&gt;
    &lt;link rel="manifest" href="%PUBLIC_URL%/manifest.json"&gt;
    &lt;!-- Tell the browser it's a PWA --&gt;
    &lt;meta name="mobile-web-app-capable" content="yes"&gt;
    &lt;!-- Tell iOS it's a PWA --&gt;
    &lt;meta name="apple-mobile-web-app-capable" content="yes"&gt;
    &lt;!-- Make sure theme-color is defined --&gt;
    &lt;meta name="theme-color" content="#536878"&gt;
    &lt;title&gt;React App&lt;/title&gt;
  &lt;/head&gt;</pre>
<p>Хорошо, что теперь мы делаем?</p>
<p><img decoding="async" class="align-center" src="https://tuhub.ru/sites/default/files/inline-images/1-3yE_WUW8kxL0OZEe3fKTsQ.png" alt="Lighthouse audit result" data-entity-type="file" data-entity-uuid="b315b85e-d6cf-4538-9fc7-a3f5f1104f44" /></p>
<p>Всё что нам не хватает, это кэширование и HTTPS.</p>
<h2>5. Деплой через Firebase</h2>
<p>Во-первых, включите кэширование. Измените <em>doCache</em> на true в файле service-worker.js.</p>
<p>После этого, в <a href="https://console.firebase.google.com/" target="_blank" rel="noopener noreferrer">консоле Firebase</a> создайте новый проект и назовите его pwa-experiment.</p>
<p>Вернитесь в папку с проектом и запустите следующее:</p>
<pre>npm install -g firebase-tools
firebase login
firebase init</pre>
<p>После того как вы пройдёте авторизацию и начнётся инициализация: ответьте на следующие вопросы:</p>
<p>Когда он спросит <em>What Firebase CLI features do you want to setup for this directory?</em>, с помощью пробела снимете галочки везде кроме &#171;Hosting&#187;.</p>
<p>Нажмите Enter, а после этого выберите pwa-experiment в качестве проекта.</p>
<p>Когда он спросит <em>What do you want to use as your public directory?</em>, наберите на клавитуре &#171;<em>build</em>&#187; и нажмите Enter.</p>
<p>На вопрос про одностраничное приложение, выберите &#171;No&#187;.</p>
<p>После этого процесс должен завершиться. Теперь можно запустить команду:</p>
<pre><code class="code language-bash hljs ">npm run build &amp;&amp; firebase deploy</code></pre>
<p>Это соберёт наш проект в папку build, которую Firebase будет деплоить.</p>
<p>Firebase вернёт нам URL. Давайте откроем его в Chrome и запустим аудит Lighthouse в заключительный раз.</p>
<p>&nbsp;</p>
<p><img decoding="async" class="align-center" src="https://tuhub.ru/sites/default/files/inline-images/1-je-cDo1IJOQ_aqSXLM9-JA.png" alt="Lighthouse audit result" data-entity-type="file" data-entity-uuid="1ae34f05-58e0-4871-92db-b71c9f2a38fb" /></p>
<p>Мы сделали это!</p>
<p>Ну и в качестве завершающего теста, откройте этот URL на вашем телефоне и попробуйте сохранить его на домашний экран. После открытия его с домашнего экрана, он должен выглядеть как нативное приложение.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[JavaScript]]></category><category><![CDATA[WEB]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/09/2395488_bd78_2-1024x576-1.jpeg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-%d0%bc%d0%b5%d1%81%d1%81%d0%b5%d0%bd%d0%b4%d0%b5%d1%80%d0%b0-icq-%d0%b2-linux-%d0%bc%d0%b8%d0%bd%d1%83%d1%8f-snap/</link>
					<title><![CDATA[Установка мессендера ICQ в Linux минуя snap]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Tue, 29 Aug 2023 08:46:57 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2023/08/icq-1024x576.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Установка мессендера ICQ в Linux минуя snap</h1>
													</header>
													<p><b><i>ICQ</i></b> (от англ. <b>I seek yo</b>u — «я ищу тебя») — стремительно набирающая популярность бесплатная, кроссплатформенная система <b>мгновенного обмена сообщениями</b>, для мобильных и иных платформ с поддержкой голосовой и видеосвязи.<br />
Позволяет пересылать текстовые сообщения, изображения, видео и аудио через <b>Интернет</b>.<br />
В этой статье мы с <b>Вами</b> рассмотрим все доступные способы установки данного <b>мессенджера</b>.<br />
Этот <b>мессенджер</b> доступен, как для <b>х64</b>-bit версий, так и для <b>х32</b>-bit версий <b><i>Ubuntu</i></b>/<b><i>Linux Mint</i></b> в том числе.<br />
В статье будет описана <b>консольно</b>&#8212;<b>терминальная</b> установка, но в магазине <b><i>Ubuntu</i></b> он тоже есть из <b>SNAP</b>.</p>
<p>Итак, приступим к <b>Установке</b>.<br />
Есть только <b>2 (два) способа</b> установки данного мессенджера.<br />
<b>1.</b> <b>Теперь уже, с версии <i>Ubuntu 22.04</i> Стандартный, из официальных SNAP-репозиториев <i>Ubuntu</i> и <i>Linux Mint</i></b> &#8212; самый простой, но, учитывая некий скептицизм пользователей к <b>SNAP</b> и существующими проблемами со скоростью работы приложений из <b>SNAP</b>, не самый, на мой взгляд, лучший <b>способ</b></p>
<p>Для <b>Установки</b> мессенджера открываем <b>Терминал</b> (<b>Ctrl+Alt+T</b>), копируем или прописываем следующую команду/код и жмём на <b>Enter</b>:</p>
<pre>sudo snap install icq-im</pre>
<p>Для <b>Удаления</b> мессенджера, поочерёдно выполняем следующие команды:</p>
<pre>sudo snap disable icq-im
sudo snap remove --purge icq-im
rm -Rf snap/ icq-im</pre>
<p><b>2.</b> <b>Из тарболла (tarball &#8212; архив tar)</b> &#8212; посложней, но, опять же на мой взгляд, наиболее приемлемый <b>способ</b><br />
Для <b>Установки</b> мессенджера открываем <b>Терминал</b> (<b>Ctrl+Alt+T</b>), копируем или прописываем поочерёдно следующие команды/коды, каждый раз нажимая на <b>Enter</b>:<br />
&#8212; создаём папку <b>icq</b> в каталоге <b>/opt</b> (полный путь <b>/opt/icq</b>)</p>
<pre>sudo mkdir /opt/icq</pre>
<p>&#8212; скачиваем <b>тарболл</b> в папку <b>/tmp</b><br />
<b>a.)</b> &#8212; для <b>x64</b>-bit</p>
<pre>wget https://icq-www.hb.bizmrg.com/linux/x64/icq.tar.xz -P /tmp</pre>
<p><b>b.)</b> &#8212; для <b>x32</b>-bit</p>
<pre>https://icq-www.hb.bizmrg.com/deprecated-versions/linux/x32/icq.tar.xz</pre>
<p>&#8212; распаковываем скачанный <b>тарболл</b> в папку <b>icq</b> в каталоге <b>/opt</b> (полный путь <b>/opt/icq</b>)</p>
<pre>sudo tar -xvf /tmp/icq.tar.xz -C /opt/icq</pre>
<p>&#8212; создаём символьную ссылку (ярлык) на <b><i>ICQ</i></b></p>
<pre>sudo ln -s /opt/icq/icq /usr/local/bin/icq-desktop</pre>
<p>&#8212; запускаем мессенджер <b><i>ICQ</i></b> с одновременным выходом из <b>Терминала</b>, за его ненадобностью далее</p>
<pre>icq-desktop</pre>
<p>После чего осуществится первый запуск <b>мессенджера</b> с приветственным окном <b><i>ICQ</i></b>, где нужно нажать на Принять и продолжить:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxNdmq9YwsTMXrJcdeovBaZEVtU32RKPqxngO9L7lNo3tOGPXg4W6ZpRJf5EwhDmTL_UOvuT8zKmjOo1qCXjG1Z7SBmqnegD4NKyRAHCDj_3ZNLlMOmDjkhRRJCNpVsk8B7uqWBPIWHSo_fzDDWJv5CMsYnoNaT7RdAvAARPKMx6jV7kR6dWWFQA/s1020/icq1.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxNdmq9YwsTMXrJcdeovBaZEVtU32RKPqxngO9L7lNo3tOGPXg4W6ZpRJf5EwhDmTL_UOvuT8zKmjOo1qCXjG1Z7SBmqnegD4NKyRAHCDj_3ZNLlMOmDjkhRRJCNpVsk8B7uqWBPIWHSo_fzDDWJv5CMsYnoNaT7RdAvAARPKMx6jV7kR6dWWFQA/s600/icq1.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>И в результате, мы попадаем в окно <b>Телефон</b>, где можно ввести его (<b>номер</b> вашего мобильного телефона) для <b>Регистрации</b>, или нажать в верхнем левом углу на <b>Вход по паролю</b>, если вы уже имеет Учётную записа в <b><i>ICQ</i></b>:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJaDBNmTat1EOWcQzSxw5ip19Obh58DeuNHnqrrtS7VwLZlzb-L_ExuoaG8EJZ28ycPGX_m0SFlee43eSvoI4kfSSP3vjKP5X_FU7eDGr8PueQ2uVeOGqYApXOTlFZew8g4uTeoZ3k3KR149lQcBY2SJB37e6OGFOf6lBRQ7F_Uv8JXZQlE5exNg/s1020/icq_0.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhJaDBNmTat1EOWcQzSxw5ip19Obh58DeuNHnqrrtS7VwLZlzb-L_ExuoaG8EJZ28ycPGX_m0SFlee43eSvoI4kfSSP3vjKP5X_FU7eDGr8PueQ2uVeOGqYApXOTlFZew8g4uTeoZ3k3KR149lQcBY2SJB37e6OGFOf6lBRQ7F_Uv8JXZQlE5exNg/s600/icq_0.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>Если вы нажали на <b>Вход по паролю</b>, то в следующем окне <b>Вход по паролю</b> вводите соответственно <b>Ваши логин и пароль</b> и жмёте на <b>Войти</b> и сразу попадаете в <b>Интерфейс</b> вашего <b>мессенджера</b>:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBlrKFxuqgj_ZpigD06FuqDdZA7CQg2SKhywwIc2PR5Ju21HmkzoV0CTH4fY-KvVhFfZfxsdY9LD_nNETr271kwrh8PU8fbQoET9UJ_LSXbkzAAGbLaXi3vIoCjIUdOEUefZolYmoGvwAJgBPv2ImvLjdPik38kWvi7MjCJC0nhp36iNJAw4Ahvg/s1020/icq_1.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBlrKFxuqgj_ZpigD06FuqDdZA7CQg2SKhywwIc2PR5Ju21HmkzoV0CTH4fY-KvVhFfZfxsdY9LD_nNETr271kwrh8PU8fbQoET9UJ_LSXbkzAAGbLaXi3vIoCjIUdOEUefZolYmoGvwAJgBPv2ImvLjdPik38kWvi7MjCJC0nhp36iNJAw4Ahvg/s600/icq_1.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>Если вы ещё не <b>Регистрировались</b>, вам следует оставаться в первом окне <b>Телефон</b>, ввести его и нажать на <b>Войти</b>:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmvIIyWXG-8HBB80TgCK5qL9HxmgtBmezE5pTvjEegVY6dW7DwZ7I2CaQcXZpbuXDXmEs36P7UQOTOPuAbKj8r2A3cox8a96fU0kOc0ju93lm1s71SseNVm2EXTbOt3bC84-JhVkuRkNJRx1FixjZVz1i7oRY4MQYuIk4ncQO4br9o4pGo-ZQBuw/s1020/icq_2.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjmvIIyWXG-8HBB80TgCK5qL9HxmgtBmezE5pTvjEegVY6dW7DwZ7I2CaQcXZpbuXDXmEs36P7UQOTOPuAbKj8r2A3cox8a96fU0kOc0ju93lm1s71SseNVm2EXTbOt3bC84-JhVkuRkNJRx1FixjZVz1i7oRY4MQYuIk4ncQO4br9o4pGo-ZQBuw/s600/icq_2.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>После чего вы попадаете в окно <b>Код из SMS</b>, где вам необходимо ввести полученный вами на вашем мобильном телефоне <b>шестизначный</b>, <b>цифровой код</b>:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGZa4KYNoeM5Hv_FX0USzuJzoJzbxFcNFnSGSWyd48Mi8nkJAP9Vtk84rn2uQnrYeE-9EVPYuFWECjt71s9TNW9JUkwjUTZulMjrWF0IYriC-KkFaP6Ij1lhI3PA0V-GJvNEDxvkRZ-YizyJ38V6J4hREVdDWiCTYl6-8ElRe_lzXPaT9tMjUklg/s1020/icq_4.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGZa4KYNoeM5Hv_FX0USzuJzoJzbxFcNFnSGSWyd48Mi8nkJAP9Vtk84rn2uQnrYeE-9EVPYuFWECjt71s9TNW9JUkwjUTZulMjrWF0IYriC-KkFaP6Ij1lhI3PA0V-GJvNEDxvkRZ-YizyJ38V6J4hREVdDWiCTYl6-8ElRe_lzXPaT9tMjUklg/s600/icq_4.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>И, если вы его правильно ввели, вы автоматически попадаете в следующее окно <b>Добавьте имя и аватар</b>, что вам и нужно сделать и нажать на <b>Далее</b>:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0m8elPqgQrg-mVutBaBJo1uCM-5xydqms3fstb_4zuki64xI4A6y0tVZMCzvj41z9tqDvlgOKYGSDKdxPx6Sgx1PXzK6yzBabNceFqX9YhCtvJ-3mU4p8JgcmyUtDhuEpM9SM5PmCDWPG8tTfU2sisLJTdjLaLVVSi-TcZs4U5excvFVRGbC96Q/s1020/icq_5.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0m8elPqgQrg-mVutBaBJo1uCM-5xydqms3fstb_4zuki64xI4A6y0tVZMCzvj41z9tqDvlgOKYGSDKdxPx6Sgx1PXzK6yzBabNceFqX9YhCtvJ-3mU4p8JgcmyUtDhuEpM9SM5PmCDWPG8tTfU2sisLJTdjLaLVVSi-TcZs4U5excvFVRGbC96Q/s600/icq_5.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>И, вот, наконец, вы попадаете в сам мессенджер <b><i>ICQ</i></b>, где можно нажать на кнопку-<b>шестерёнку</b> и настроить всё на свой вкус и цвет:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5mR9OCDngjyxud_2p-mCxnn1SczPqo1GPfrY34mvJy2UOnFiDadzNiqgjliEpFCqGgHi3Pzxq64OHJQWWtcwKNLZg-WOPACbGQo9YO_t_7v3KGv-fb9wQL5DeFWS3mKfs6d6aRBOKNgO_vrSoRniIQfHU6e47_v9yeG19K9lmdt_RdrOpLtFuGA/s1020/icq_6.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh5mR9OCDngjyxud_2p-mCxnn1SczPqo1GPfrY34mvJy2UOnFiDadzNiqgjliEpFCqGgHi3Pzxq64OHJQWWtcwKNLZg-WOPACbGQo9YO_t_7v3KGv-fb9wQL5DeFWS3mKfs6d6aRBOKNgO_vrSoRniIQfHU6e47_v9yeG19K9lmdt_RdrOpLtFuGA/s600/icq_6.png" alt="" width="600" border="0" data-original-height="655" data-original-width="1020" /></a></div>
<p>Теперь <b>закройте</b> мессенджер, но это ещё не всё, т.к. он просто свернулся в <b>трей</b> и поэтому надо ещё нажать <b>ЛКМ</b> на его иконку в верхней панели и в выпавшем контекстном меню нажать <b>ЛКМ</b> на <b>Закрыть</b>.</p>
<p>А теперь, для дальнейшего удобства, дабы в будущем не искать наш мессенджер в <b>Программах</b> и иметь быстрый доступ к нему, нажмите на <b>Обзор</b> или на <b>Показать приложения</b> и в <b>Введите для поиска</b> напишите <b>icq</b> и нажмите ЛКМ или на Enter на появившийся ярлык/иконку <b><i>ICQ</i></b>, чтобы вновь запусть его:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgscIxCtvRdK8y5R-qZ9RWP7CEDckiyJjqWwTSwUXQCGIL4puy7TX3DBDSXizel5Otmy-jzmJOTe-WKDPC_nx6shiGZpgcouBAnm-O7WoeHzWo0k2Q9NDHD6LbpNxvysZoOggPdsjlRLO6F3M3k9cAss3WLPMS0P8FEXEHhS87g2fDaxzZ0nUu-5Q/s529/icq_l.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgscIxCtvRdK8y5R-qZ9RWP7CEDckiyJjqWwTSwUXQCGIL4puy7TX3DBDSXizel5Otmy-jzmJOTe-WKDPC_nx6shiGZpgcouBAnm-O7WoeHzWo0k2Q9NDHD6LbpNxvysZoOggPdsjlRLO6F3M3k9cAss3WLPMS0P8FEXEHhS87g2fDaxzZ0nUu-5Q/s400/icq_l.png" alt="" width="400" border="0" data-original-height="279" data-original-width="529" /></a></div>
<p>После запуска, в <b>боковой панели</b> появится его ярлык/иконка.<br />
Жмём на этот ярлык/иконку <b>ПКМ</b> и в выпавшем контекстном меню жмём <b>ЛКМ</b> на <b>Добавить в избранное</b>, тем самым у нас всегда будет быстрый доступ к мессенджеру в боковой панели:</p>
<div class="separator"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheKkvUmO6kO54r1oCLjvUxjPaEt7YYGhtwDZ4bKQA7Lf5lXbKG7OPGsXl9U4iX0KFs1dzBrl3a1xcAodi8PvbZFoOR8lyWdvWXMaX6h_MbyRZ_KZmIXWl9311FqPX47OE-pC81oPVEDMdmVMcgSLKlYURwNdp1ezzwTyizF9u8t_ooxwaH57rHRA/s457/icq_6_0.png"><img decoding="async" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEheKkvUmO6kO54r1oCLjvUxjPaEt7YYGhtwDZ4bKQA7Lf5lXbKG7OPGsXl9U4iX0KFs1dzBrl3a1xcAodi8PvbZFoOR8lyWdvWXMaX6h_MbyRZ_KZmIXWl9311FqPX47OE-pC81oPVEDMdmVMcgSLKlYURwNdp1ezzwTyizF9u8t_ooxwaH57rHRA/s400/icq_6_0.png" alt="" width="400" border="0" data-original-height="353" data-original-width="457" /></a></div>
<p>Для <b>ленивых</b> &#8212; <b>установка</b> <b>однострочником</b>:</p>
<pre>sudo mkdir /opt/icq; wget https://icq-www.hb.bizmrg.com/linux/x64/icq.tar.xz -P /tmp; sudo tar -xvf /tmp/icq.tar.xz -C /opt/icq; sudo ln -s /opt/icq/icq /usr/local/bin/icq-desktop; icq-desktop</pre>
<p><b>Удалить</b> <b><i>ICQ</i></b> из системы можно, выполнив следющую команду/код:</p>
<pre>sudo rm -Rf /opt/icq /usr/local/bin/icq-desktop .config/ICQ .local/share/applications/icqdesktop.desktop .local/share/icons/icq.png</pre>
<p>На этом, <b>установка</b> мессенджера <b><i>ICQ</i></b> завершена.</p>
<p><b>Всем приятного пользования и удачи!</b></p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/08/icq-1024x576.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b8%d1%81%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d1%83%d0%b5%d0%bc-%d1%80%d0%b5%d0%bf%d0%be%d0%b7%d0%b8%d1%82%d0%be%d1%80%d0%b8%d0%b8-%d1%8f%d0%bd%d0%b4%d0%b5%d0%ba%d1%81%d0%b0-%d0%b4%d0%bb%d1%8f-apt-%d0%b2/</link>
					<title><![CDATA[Используем репозитории Яндекса для apt в Debian и Ubuntu.]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 22 Mar 2023 10:54:50 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2023/03/n_6207743a498d6.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Используем репозитории Яндекса для apt в Debian и Ubuntu.</h1>
													</header>
													<p>Сегодня мы рассмотрим настройку серверов и ПК под управлением операционной системы Debian и Ubuntu на использование зеркал репозиториев на https://mirror.yandex.ru/</p>
<p>Использовании зеркал Яндекса в Debian<br />
Для начала определимся с версиями Debian. У каждой версии Debian есть номер версии и кодовое имя выпуска. Ниже в таблице приведено соответствие номерной версии и кодового имени:</p>
<table>

<tr>
<th>Номер</th>
<th>Кодовое имя</th>
</tr>
<tr>
<td>2</td>
<td>Hamm</td>
</tr>
<tr>
<td>2.1</td>
<td>Slink</td>
</tr>
<tr>
<td>2.2</td>
<td>Potato</td>
</tr>
<tr>
<td>3.0</td>
<td>Woody</td>
</tr>
<tr>
<td>3.1</td>
<td>Sarge</td>
</tr>
<tr>
<td>4.0</td>
<td>Etch</td>
</tr>
<tr>
<td>5.0</td>
<td>Lenny</td>
</tr>
<tr>
<td>6</td>
<td>Squeeze</td>
</tr>
<tr>
<td>7</td>
<td>Wheezy</td>
</tr>
<tr>
<td>8</td>
<td>Jessie</td>
</tr>
<tr>
<td>9</td>
<td>Stretch</td>
</tr>
<tr>
<td>10</td>
<td>Buster</td>
</tr>
<tr>
<td>11</td>
<td>Bullseye</td>
</tr>

</table>
<p>В репозитории Яндекса мы можем найти зеркала репозиториев для всех версий начиная с 8 – Jessie.</p>
<p>Нам нужно исправить содержимое файла /etc/apt/sources.list</p>
<p>Сперва сделаем резервную копию файла:</p>
<p>cp /etc/apt/sources.list ~/<br />
Изменим файл:</p>
<p>mcedit /etc/apt/sources.list<br />
Заменим содержимое файла строками:</p>
<p>deb http://mirror.yandex.ru/debian/ bullseye main<br />
deb-src http://mirror.yandex.ru/debian/ bullseye main</p>
<p>deb http://mirror.yandex.ru/debian-security bullseye-security main contrib<br />
deb-src http://mirror.yandex.ru/debian-security bullseye-security main contri</p>
<p>deb http://mirror.yandex.ru/debian/ bullseye-updates main contrib<br />
deb-src http://mirror.yandex.ru/debian/ bullseye-updates main contrib<br />
По сути нам достаточно изменить во всех строчках:</p>
<p>deb http://xxx.xxxxx.xxx/debian/<br />
на</p>
<p>deb http://mirror.yandex.ru/debian/<br />
Запустим:</p>
<p>sudo apt update</p>
<p>…<br />
Reading package lists&#8230; Done<br />
Building dependency tree&#8230; Done<br />
Reading state information&#8230; Done<br />
All packages are up to date.<br />
База данных пакетов будет загружена с зеркала Яндекса.</p>
<p>Использовании зеркал Яндекса в Ubuntu<br />
Для начала определимся с версиями Ubuntu. У каждой версии Ubuntu есть номер версии и кодовое имя выпуска. Ниже в таблице приведено соответствие номерной версии и кодового имени:</p>
<table>

<tr>
<th>Номер</th>
<th>Кодовое имя</th>
</tr>
<tr>
<td>14.04</td>
<td>Trusty</td>
</tr>
<tr>
<td>16.04</td>
<td>Xenial</td>
</tr>
<tr>
<td>18.04</td>
<td>Bionic</td>
</tr>
<tr>
<td>20.04</td>
<td>Focal</td>
</tr>
<tr>
<td>21.04</td>
<td>Hirsute</td>
</tr>
<tr>
<td>21.10</td>
<td>Impish</td>
</tr>
<tr>
<td>22.04</td>
<td>Bionic</td>
</tr>

</table>
<p>В репозитории Яндекса мы можем найти зеркала репозиториев для всех версий начиная с 14.04 – Trusty.</p>
<p>Нам нужно исправить содержимое файла /etc/apt/sources.list</p>
<p>Сперва сделаем резервную копию файла:</p>
<p>cp /etc/apt/sources.list ~/<br />
Изменим файл:</p>
<p>mcedit /etc/apt/sources.list<br />
Заменим содержимое файла строками:</p>
<p>deb http://mirror.yandex.ru/ubuntu impish main restricted<br />
deb http://mirror.yandex.ru/ubuntu impish-updates main restricted<br />
deb http://mirror.yandex.ru/ubuntu impish universe<br />
deb http://mirror.yandex.ru/ubuntu impish-updates universe<br />
deb http://mirror.yandex.ru/ubuntu impish multiverse<br />
deb http://mirror.yandex.ru/ubuntu impish-updates multiverse<br />
deb http://mirror.yandex.ru/ubuntu impish-backports main restricted universe multiverse<br />
deb http://mirror.yandex.ru/ubuntu impish-security main restricted<br />
deb http://mirror.yandex.ru/ubuntu impish-security universe<br />
deb http://mirror.yandex.ru/ubuntu impish-security multiverse<br />
По сути нам достаточно изменить во всех строчках:</p>
<p>deb http://xxx.xxxxx.xxx/ubuntu/<br />
на</p>
<p>deb http://mirror.yandex.ru/ubuntu/<br />
Запустим</p>
<p>sudo apt update</p>
<p>…<br />
Reading package lists&#8230; Done<br />
Building dependency tree&#8230; Done<br />
Reading state information&#8230; Done<br />
57 packages can be upgraded. Run &#8216;apt list &#8212;upgradable&#8217; to see them.<br />
База данных пакетов будет загружена с зеркала Яндекса.</p>
<p>Заключение<br />
Сегодня мы рассмотрели настройку серверов и ПК под управлением операционной системы Debian и Ubuntu на использование зеркал Яндекса.</p>
<p>Внесли изменения в файл sources.list изменив имена доменов таким образом, чтобы они указывали на зеркало Яндекса.</p>
<p>Обновили базу данных пакетов.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/03/n_6207743a498d6.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/ip-%d1%82%d0%b5%d0%bb%d0%b5%d1%84%d0%be%d0%bd%d0%b8%d1%8f-%d0%ba%d0%b0%d0%ba-%d0%b5%d0%b5-%d0%b3%d0%be%d1%82%d0%be%d0%b2%d0%b8%d1%82%d1%8c-%d0%bd%d0%b0-centos7/</link>
					<title><![CDATA[IP-Телефония. Как ее готовить на CentOS7]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 Jan 2023 07:45:52 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2023/01/maxresdefault-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>IP-Телефония. Как ее готовить на CentOS7</h1>
													</header>
													<p>Всем Добра!</p>
<p>Сегодня телефония сама по себе можно сказать что умерла, но мы же пользуемся мобильной сетью и телефонами. Вопрос, а как они Собственно работают? На чем? и что находится за кулисами мобильных сетей и как сделать свою сеть.</p>
<p>На все эти вопросы один ответ <a href="https://www.asterisk.org/">ASTERISK </a>&#8212; это собственно программа которая превращает обычный компьютер в СЕРВЕР ip-телефонии. Именно с помощью нее мобильные и обычные операторы достовляют нам голоса и картинки наших близких.</p>
<p>И так задача опишем воображаемый офис:</p>
<ul>
<li>Работает 50 сотрудников. Номера будут 4-х значными, от 1000 до 4000.</li>
<li>У нас будут 4 отдела &#8212; менеджеры, топ-менеджеры,  технический отдел, руководство и все остальные.</li>
<li>Номер секретаря 4000, менеджеры 1000-1999, топ-менеджеры 2000-2999, техподдержка 3000-3999, руководство 4001-4999.</li>
<li>Мы не будем использовать  ни одного SIP провайдера для звонков, только внутренняя связь.</li>
</ul>
<p>Все нововееденя бдем производить на CentOS 7. Для быстрой настройки использую скрипт <a href="https://github.com/blackmcs/AISS">AISS</a>, очень быстро и удобно. И приступаем к установке.</p>
<p>Все это работать будет на Asterisk+FreePBX.</p>
<p><strong>Asterisk</strong> &#8212; бесплатное решение для организации voip телефонии. Он обладает всеми возможностями обычных АТС, но предоставляет более богатый функционал по управлению звонками. За относительную простоту настройки, по сравнению с цифровыми АТС, бесплатность и широкие возможности он и снискал такую популярность.</p>
<p><strong>Freepbx</strong> &#8212; бесплатный веб интерфейс для управления астериском. Он существенно упрощает работу с конфигурациями, позволяет выполнять некоторые функции людям, вообще далеким от астериска. Например, с его помощью практически любого можно научить управлять учетными записями пользователей.</p>
<p>Прежде чем мы начнем устанавливать asterisk, нам надо выполнить целый ряд подготовительных действий. Первым делом отключаем selinux. Для этого открываем файл:</p>
<pre># nano /etc/sysconfig/selinux</pre>
<p>и устанавливаем значение <strong>SELINUX=disabled</strong>. После этого применяем настройку без перезагрузки сервера:</p>
<pre># setenforce 0</pre>
<p>Рекомендация по отключению selinux дается в официальной инструкции по установке freepbx, так как это может привести к нарушению процесса инсталляции.</p>
<p>Дальше  ставим пакеты Development Tools:</p>
<pre># yum groupinstall core base "Development Tools"</pre>
<p>В своей работе FreePBX использует базу данных Mysql. В качестве mysql сервера будем использовать mariadb. Подключаем репозиторий со свежей версией MariaDB. Для этого создаем файл <em>/etc/yum.repos.d/MariaDB.repo</em></p>
<pre># nano <em>/etc/yum.repos.d/MariaDB.repo</em></pre>
<p>Cледующего содержания:</p>
<pre># MariaDB 10.3 CentOS repository list - created 2019-04-01 09:11 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1</pre>
<p>Устанавливаем MariaDB.</p>
<pre># yum install MariaDB-server MariaDB-client MariaDB-shared</pre>
<p>Запускаем mariadb и добавляем в автозагрузку.</p>
<pre># systemctl start mariadb
# systemctl enable mariadb</pre>
<p>Для работы панели FreePBX нужен web сервер с php. Я буду использовать версию php 7.4. это минимальная версия для FreePBX 16</p>
<p>Подключаем репозиторий epel, если еще не сделали это ранее.</p>
<pre># yum install epel-release</pre>
<p>Добавляем remi репозиторий:</p>
<pre># rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-7.rpm</pre>
<p>Активируем репу remi-php74, для этого выполняем команду:</p>
<pre># yum-config-manager --enable remi-php74</pre>
<p>Устанавливаем необходимые пакеты для работы сервера voip:</p>
<pre># yum install wget php php-pear php-cgi php-common php-curl php-mbstring php-gd php-mysql php-gettext php-bcmath php-zip php-xml php-imap php-json php-process php-snmp</pre>
<pre>Далее установим httpd. Он, по идее, должен установиться в качестве зависимости на предыдущем шаге, но на всякий случай проверьте.</pre>
<pre># yum install httpd</pre>
<p>Теперь нам нужно изменить некоторые параметры httpd &#8212; запустить его от пользователя asterisk и включить опцию AllowOverride. В файле <em>/etc/httpd/conf/httpd.conf</em>,  с помощью sed.</p>
<pre># sed -i 's/^\(User\|Group\).*/\1 asterisk/' /etc/httpd/conf/httpd.conf
# sed -i 's/AllowOverride None/AllowOverride All/' /etc/httpd/conf/httpd.conf</pre>
<p>Httpd запускать пока не надо, так как пользователя asterisk мы еще не создали. Сделаем это после установки asterisk.</p>
<p>Изменим параметр php, который отвечает за максимальный размер загружаемого файла. Дефолтное значение слишком низкое для freepbx. Для этого в <em>/etc/php.ini</em> устанавливаем параметр.</p>
<pre># sed -i 's/\(^upload_max_filesize = \).*/\120M/' /etc/php.ini</pre>
<p>С веб сервером закончили. Продолжаем подготовку к установке FreePBX на CentOS.</p>
<p>Для работы Freepbx требуется сервер NodeJS. Установим его на Centos 7. Подключаем репозиторий NodeJS с помощью скрипта автоматизации от разработчика и произведем его установку.</p>
<pre># curl -sL https://rpm.nodesource.com/setup_14.x | bash -
# yum install -y nodejs</pre>
<p>Обновляем кэш yum.</p>
<pre># yum clean all &amp;&amp; sudo yum makecache fast</pre>
<p>Устанавливаем зависимости для следующих шагов, компитятор языка С++ и сборщик пакетов.</p>
<pre># yum install gcc-c++ make</pre>
<p>Установка Asterisk. Скачиваем архив последней версии Asterisk с официального сайта.</p>
<pre># cd ~ &amp;&amp; wget http://downloads.asterisk.org/pub/telephony/asterisk/asterisk-18-current.tar.gz</pre>
<p>Распаковываем исходники.</p>
<pre># tar zxvf asterisk-*.tar.gz</pre>
<p>Переходим в директорию с исходниками.</p>
<pre># cd asterisk*</pre>
<p>Выполняем скрипт для установки пакетов с зависимостями для asterisk.</p>
<pre># contrib/scripts/install_prereq install</pre>
<p>Запускаем скрипт для скачивания исходников для работы с mp3.</p>
<pre># contrib/scripts/get_mp3_source.sh</pre>
<p>Настраиваем конфигурацию:</p>
<pre># ./configure --with-pjproject-bundled --with-jansson-bundled --with-crypto --with-ssl=ssl --with-srtp</pre>
<p>Запускаем меню для выбора параметров:</p>
<pre>make menuselect</pre>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-155" src="https://blog.sefdar.ru/wp-content/uploads/2022/06/centos-freepbx-asterisk-04-300x160.webp" alt="" width="1046" height="558" srcset="https://blog.sefdar.ru/wp-content/uploads/2022/06/centos-freepbx-asterisk-04-300x160.webp 300w, https://blog.sefdar.ru/wp-content/uploads/2022/06/centos-freepbx-asterisk-04-1024x546.webp 1024w, https://blog.sefdar.ru/wp-content/uploads/2022/06/centos-freepbx-asterisk-04-768x410.webp 768w, https://blog.sefdar.ru/wp-content/uploads/2022/06/centos-freepbx-asterisk-04.webp 1263w" sizes="auto, (max-width: 1046px) 100vw, 1046px" /></p>
<p>В целом, можно оставить дефолтную настройку, если вы не очень разбираетесь, что тут выбирать. Можно запускать установку asterisk.</p>
<pre># make &amp;&amp; make install &amp;&amp; make config &amp;&amp; make samples &amp;&amp; ldconfig</pre>
<p>Настроим запуск астериск от системного пользователя asterisk. Для этого редактируем скрипт запуска <em>/usr/sbin/safe_asterisk</em>, установив параметр ASTARGS=&#187;-U asterisk&#187;.</p>
<pre># sed -i 's/ASTARGS=""/ASTARGS="-U asterisk"/g' /usr/sbin/safe_asterisk</pre>
<p>Создадим этого пользователя и назначим нужные права на каталоги.</p>
<pre># useradd -m asterisk
# chown asterisk.asterisk /var/run/asterisk
# chown -R asterisk.asterisk /etc/asterisk
# chown -R asterisk.asterisk /var/{lib,log,spool}/asterisk
# chown -R asterisk.asterisk /usr/lib/asterisk</pre>
<p>Запускаем Asterisk.</p>
<pre>systemctl start asterisk</pre>
<p>Проверьте сразу, что он запустился.</p>
<pre># systemctl status asterisk</pre>
<p>Консоль выдаст:</p>
<pre>● asterisk.service - LSB: Asterisk PBX
Loaded: loaded (/etc/rc.d/init.d/asterisk; bad; vendor preset: disabled)
Active: active (running) since Чт 2022-06-16 09:20:58 MSK; 3s ago
Docs: man:systemd-sysv-generator(8)
Process: 19269 ExecStop=/etc/rc.d/init.d/asterisk stop (code=exited, status=0/SUCCESS)
Process: 19296 ExecStart=/etc/rc.d/init.d/asterisk start (code=exited, status=0/SUCCESS)
Main PID: 19325 (asterisk)
CGroup: /system.slice/asterisk.service
├─19323 /bin/sh /usr/sbin/safe_asterisk
└─19325 /usr/sbin/asterisk -f -U asterisk -vvvg -c

июн 16 09:20:58 tel.sefdar.ru systemd[1]: Starting LSB: Asterisk PBX...
июн 16 09:20:58 tel.sefdar.ru asterisk[19296]: Starting asterisk:
июн 16 09:20:58 tel.sefdar.ru systemd[1]: Can't open PID file /var/run/asterisk/asterisk.pid (yet?) after start: No such file or directory
июн 16 09:20:58 tel.sefdar.ru systemd[1]: asterisk.service: Supervising process 19325 which is not our child. We'll most likely not notice when it exits.
июн 16 09:20:58 tel.sefdar.ru systemd[1]: Started LSB: Asterisk PBX.</pre>
<p>Если будет ошибка вроде:</p>
<pre>radcli: rc_read_config: rc_read_config: can't open /etc/radiusclient-ng/radiusclient.conf: No such file or directory</pre>
<p>Тогда нужно отредактировать конфигурационные файлы:</p>
<pre># sed -i 's";\[radius\]"\[radius\]"g' /etc/asterisk/cdr.conf
# sed -i 's";radiuscfg =&gt; /usr/local/etc/radiusclient-ng/radiusclient.conf"radiuscfg =&gt; /etc/radcli/radiusclient.conf"g' /etc/asterisk/cdr.conf
# sed -i 's";radiuscfg =&gt; /usr/local/etc/radiusclient-ng/radiusclient.conf"radiuscfg =&gt; /etc/radcli/radiusclient.conf"g' /etc/asterisk/cel.conf</pre>
<p>После этого перезапустите asterisk, ошибок быть не должно. Скачиваем последнюю версию Freepbx с сайта разработчика. на момент написания статьи v.16</p>
<pre># cd ~ &amp;&amp; wget http://mirror.freepbx.org/modules/packages/freepbx/freepbx-16.0-latest.tgz
</pre>
<p>Распаковываем исходники.</p>
<pre># tar xvfz freepbx-*.tgz</pre>
<p>Переходим в каталог freepbx и запускаем скрипт проверки запуска asterisk.</p>
<pre># cd freepbx &amp;&amp; ./start_asterisk start</pre>
<p>Если не получили ошибок, то запускаем установку непосредственно FreePBX.</p>
<pre># ./install -n</pre>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[телефон]]></category><category><![CDATA[телефония]]></category><category><![CDATA[IP-телефония]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2023/01/maxresdefault-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%87%d1%82%d0%be-%d0%bd%d1%83%d0%b6%d0%bd%d0%be-%d0%b4%d0%bb%d1%8f-%d1%80%d0%b0%d0%b1%d0%be%d1%82%d1%8b-%d1%81-npm/</link>
					<title><![CDATA[Что нужно для работы с NPM?]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 03 Sep 2022 06:37:46 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2022/09/2441554433-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Что нужно для работы с NPM?</h1>
													</header>
													<p>Чтобы создать NPM-пакет у вас должен быть установлен <a href="https://nodejs.org/en/" target="_blank" rel="noopener">Node.js</a>. После установки Node.js, нужно убедиться что установка прошла корректно и заодно проверить его версию, сделать это можно следующей командой:</p>
<pre class="language-plaintext"><code class="hljs">npm -v</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<h2>Инициализация NPM-пакета</h2>
<p>Перед тем как инициализировать NPM-пакет важно отметить, что для его грамотной и удобной разработки, лучше всего использовать какой-нибудь Git-репозиторий, например <a href="https://github.com/" target="_blank" rel="noopener">Github</a> или <a href="https://about.gitlab.com/" target="_blank" rel="noopener">Gitlab</a>. Теперь в терминале, находясь в директории вашего NPM-пакета, нужно провести его инициализацию выполнив следующую команду:</p>
<pre class="language-plaintext"><code class="hljs">npm init</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>Вам будут заданы вопросы про ваш NPM-пакет, вы можете ответить на них сразу или пропустить, нажав Enter. После ответов на вопросы, в директории пакета создаться файл <code>package.json</code>, в нем будет прописана основная информация о вашем пакете.</p>
<h3>package.json</h3>
<p>Вы можете редактировать файл <code>package.json</code> вручную. Вот основные и самые важные его настройки:</p>
<ul>
<li><strong>name</strong> — Имя, по которому пакет будет доступен в NPM.</li>
<li><strong>description </strong>— Описание пакета.</li>
<li><strong>author </strong>— Автор пакета.</li>
<li><strong>license </strong>— Лицензия распространения пакета.</li>
<li><strong>version </strong>— Версия пакет (будет сгенерирована автоматически).</li>
</ul>
<p>Перед тем как создавать пакет, убедитесь что такого названия в базе NPM еще нету. Для этого воспользуйтесь <a href="https://www.npmjs.com/" target="_blank" rel="noopener">поиском на сайте</a>, вбейте название которое придумали и проверье уникальность.</p>
<h3>README.md</h3>
<p>После инициализация проекта, правилом хорошего тона будет создание документации по установке и использованию вашего проекта. В корне создайте файл <code>README.md</code> и пропишите все что может быть полезно другим разработчикам (да и вам) по управлению вашим проектом.</p>
<div class="note-information">
<p>Пример README.md можете взять <a href="https://gist.github.com/PurpleBooth/109311bb0361f32d87a2" target="_blank" rel="noopener">отсюда</a>.</p>
</div>
<h2>Публикация NPM-пакета</h2>
<p>Для начала нужно пройти регистрацию на <a href="https://www.npmjs.com/" target="_blank" rel="noopener">npmjs.com</a>, сделать это можно из терминала командой:</p>
<pre class="language-plaintext"><code class="hljs">npm adduser</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>Если же учетная запись у вас уже есть, то нужно авторизироваться в терминале:</p>
<pre class="language-plaintext"><code class="hljs">npm login</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>Проверить под какой учетной записью вы находитесь можно с помощью команды:</p>
<pre class="language-plaintext"><code class="hljs">npm whoami</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>Теперь можно публиковать NPM-пакет:</p>
<pre class="language-plaintext"><code class="hljs">npm publish</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>После введения команды выше, ваш пакет отправиться на сервера NPM и будет доступен для подключения к проектам.</p>
<h2>Обновление NPM-пакета</h2>
<p>Без обновлений никуда. Для того чтобы правильно обновить пакет, вам нужно:</p>
<ol>
<li>Внести изменения в код.</li>
<li>Обновить версию пакета командой <code>npm version [ major | minor | patch ]</code>.</li>
<li>Опубликовать новую версию пакета командой <code>npm publish</code>.</li>
</ol>
<p>Правильное версионирование пакета поможет разработчикам, которые используют ваш пакет понять, насколько критические изменения были внесены.</p>
<h3>npm version patch</h3>
<p>Команда <code>npm version patch</code>, увеличит версию пакета например, с 1.0.0 до 1.0.1. Незначительные исправления мелких ошибок.</p>
<h3>npm version minor</h3>
<p>Команда <code>npm version minor</code>, увеличит версию пакета например, с 1.0.0 до 1.1.0. Добавления нового функционала, который не влияет на уже существующий функционал.</p>
<h3>npm version major</h3>
<p>Команда <code>npm version major</code>, увеличит версию пакета например, с 1.0.0 до 2.0.0. Модификация пакета без обратной совместимости с предыдущей версией. Разработчик поймет что простое обновление пакета может что-то сломать и изучит вопрос правильного обновления на новую мажорную версию.</p>
<h2>Удаление NPM-пакета</h2>
<p>Удаление NPM-пакетов является очень плохим тоном, т. к. от этих пакетов могут зависеть проекты других пользователей. Однако, если после публикации пакета командой <code>npm publish</code> прошло менее 24 часов, то публикацию можно отменить командой <code>npm unpublish</code>. Пакеты, которые были добавлены более 24 часов назад, удалить нельзя.</p>
<p>Если все-таки вам необходимо удалить пакета, то напишите в <a href="https://www.npmjs.com/support" target="_blank" rel="noopener">поддержку</a>, указав причину удаления пакета. Пакет будет помечен как @deprecated и исчезнет из вашего профиля.</p>
<h2>Установка NPM-пакета</h2>
<p>После того, как ваш NPM-пакет появился в вашем профиле, он будет доступен по ссылку:</p>
<pre class="language-plaintext"><code class="hljs">https://www.npmjs.com/package/название-вашего-пакета</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>И его можно будет подключить к любому вашему проекту, с помощью команды:</p>
<pre class="language-plaintext"><code class="hljs">npm i название-вашего-пакета</code><button class="copy__code-button" type="button">Копировать код</button></pre>
<p>Теперь, вы можете гибко обновлять код вашего компонента, без необходимости вручную вносить изменения на уже существующих проектах. Просто обновите пакет до актуальной версии и все изменения подтянуться автоматически.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[JavaScript]]></category><category><![CDATA[NPM]]></category><category><![CDATA[javascript]]></category><category><![CDATA[repositoy]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2022/09/2441554433-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/nginx-%d0%b1%d0%b0%d0%bb%d0%b0%d0%bd%d1%81%d0%b8%d1%80%d0%be%d0%b2%d0%ba%d0%b0-%d0%bd%d0%b0%d0%b3%d1%80%d1%83%d0%b7%d0%ba%d0%b8/</link>
					<title><![CDATA[NGINX балансировка нагрузки]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 May 2022 04:40:54 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="467" src="https://blog.sefdar.ru/wp-content/uploads/2022/05/Depositphotos_21743149_s.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>NGINX балансировка нагрузки</h1>
													</header>
													<p>В данной статье  описывается возможные настройки балансировки веб-сервера NGINX. По большей части, статья подойдет для любого дистрибутива Linux. Таким образом настроенный NGINX сможет обеспечить распределение нагрузки и отказоустойчивость сетевым сервисам.</p>
<div class="note">
<p>Обратите внимание, что NGINX умеет распределять не только http-запросы. Его можно использовать для балансировки запросов на 4-м уровне модели OSI (TCP и UDP), например, подключения к СУБД, DNS и так далее — по сути, любой сетевой запрос может быть обработан и распределен с помощью данного программного продукта.</p>
<h2>Основы</h2>
<p>Чтобы сервер мог распределять нагрузку, создадим группу веб-серверов, на которые будут переводиться запросы:</p>
<div class="console">
<p>vi /etc/nginx/conf.d/upstreams.conf</p>
</div>
<p><em>* в данном примере создается файл <strong>upstreams.conf</strong>, в котором можем хранить все апстримы. NGINX автоматически читает все конфигурационные файлы в каталоге <strong>conf.d</strong>.</em></p>
<p>Впишем:</p>
<div class="editor">
<p>upstream balansed {<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<p><em>* предполагается, что в  внутренней сети есть кластер из трех веб-серверов — <strong>192.168.0.10</strong>, <strong>192.168.0.11 </strong>и <strong>192.168.0.12</strong>. Апстрим с названием balansed. Далее, настроим веб-сервер, чтобы он умел обращаться к данному бэкенду.</em></p>
<p>В настройках сайта (виртуального домена) необходимо теперь проксировать запросы на созданный upstream. Данная настройка будет такой:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location / {<br />
proxy_pass http://<em>balansed</em>;<br />
}<br />
&#8230;<br />
}</p>
</div>
<p><em>* данная настройка для нашего сайта укажет, что все запросы мы должны переводить на апстрим </em><strong>balansed</strong><em> (который, в свою очередь, будет отправлять запросы на три сервера).</em></p>
<p>Проверяем корректность нашего конфигурационного файла:</p>
<div class="console">
<p>nginx -t</p>
</div>
<p>Если ошибок нет, перезапускаем сервис:</p>
<div class="console">
<p>systemctl restart nginx</p>
</div>
<h2><a id="weight"></a>Приоритеты</h2>
<p>При настройке бэкендов можно указать, кому наш веб-сервер будет отдавать больше предпочтение, а кому меньше.</p>
<p>Синтаксис при указании веса:</p>
<div class="editor">
<p>server &lt;имя сервера&gt; weight=&lt;числовой эквивалент веса&gt;;</p>
</div>
<p>По умолчанию приоритет равен 1.</p>
<p>Также можно указать опции:</p>
<ul>
<li><strong>backup</strong>, которая будет говорить о наличие резервного сервера, к которому будет выполняться подключение только при отсутствии связи с остальными.</li>
<li><strong>down</strong>, при указании которой, сервер будет считаться постоянно недоступным. Может оказаться полезной, чтобы остановить временно запросы для проведения обслуживания.</li>
</ul>
<p>Немного преобразуем настройку upstreams:</p>
<div class="console">
<p>vi /etc/nginx/conf.d/upstreams.conf</p>
</div>
<div class="editor">
<p>upstream balansed {<br />
server 192.168.0.10 weight=100;<br />
server 192.168.0.11 weight=10;<br />
server 192.168.0.12;<br />
server 192.168.0.13 backup;<br />
}</p>
</div>
<div class="post-console">
<p>* итак, указали нашему серверу:</p>
<ul>
<li>переводить на сервер <strong>192.168.0.10</strong> в 10 раз больше запросов, чем на <strong>192.168.0.11</strong> и в 100 раз больше — чем на <strong>192.168.0.12</strong>.</li>
<li>переводить на сервер <strong>192.168.0.11</strong> в 10 раз больше запросов, чем на <strong>192.168.0.12</strong>.</li>
<li>на сервер <strong>192.168.10.13</strong> запросы переводятся, только если не доступны все три сервера.</li>
</ul>
</div>
<h2><a id="timeouts"></a>Задержки, лимиты и таймауты</h2>
<p>По умолчанию, NGINX будет считать сервер недоступным после 1-й неудачной попытки отправить на него запрос и в течение 10 секунд не будут продолжаться попытки работы с ним. Также каждый сервер не имеет ограничений по количеству к нему подключений.</p>
<p>Изменить поведение лимитов и ограничений при балансировке можно с помощью опций:</p>
<ul>
<li><strong>max_fails —</strong> количество неудачных попыток, после которых будем считать сервер недоступным.</li>
<li><strong>fail_timeout —</strong> время, в течение которого сервер нужно считать недоступным и не отправлять на него запросы.</li>
<li><strong>max_conns —</strong> максимальное число подключений, при превышении которого запросы на бэкенд не будут поступать. По умолчанию равно 0 (безлимитно).</li>
</ul>
<p>Синтаксис:</p>
<div class="editor">
<p>server &lt;имя сервера&gt; max_fails=&lt;число попыток&gt; fail_timeout=&lt;числовой показатель времени&gt;&lt;еденица времени&gt;;</p>
</div>
<p>В примере преобразуем настройку так:</p>
<div class="console">
<p>vi /etc/nginx/conf.d/upstreams.conf</p>
</div>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
server 192.168.0.10 weight=100 max_conns=1000;<br />
server 192.168.0.11 weight=10 max_fails=2 fail_timeout=90s;<br />
server 192.168.0.12 max_fails=3 fail_timeout=2m;<br />
server 192.168.0.13 backup;<br />
}</p>
</div>
<div class="post-console">
<p>* в итоге:</p>
<ul>
<li>сервер <strong>192.168.0.10</strong> будет принимать на себя, максимум, 1000 запросов.</li>
<li>сервер <strong>192.168.0.10</strong> будет иметь настройки по умолчанию.</li>
<li>если на сервер <strong>192.168.0.11</strong> будет отправлено 2-е неудачные попытки отправки запроса, то в течение 90 секунд на него не будут отправлять новые запросы.</li>
<li>сервер <strong>192.168.0.12</strong> будет недоступен в течение 2-х минут, если на него будут отправлены 3 неудачных запроса.</li>
</ul>
</div>
<h2><a id="methods"></a>Метод балансировки</h2>
<p>Способы балансировки, которые можно использовать в NGINX:</p>
<ol>
<li>Round Robin.</li>
<li>Hash.</li>
<li>IP Hash.</li>
<li>Least Connections.</li>
<li>Random.</li>
<li>Least Time (только в платной версии NGINX).</li>
</ol>
<p>Настройка метода балансировки выполняется в директиве upstream. Синтаксис:</p>
<div class="editor">
<p>upstream &lt;название апстрима&gt; {<br />
&lt;метод балансировки&gt;<br />
&#8230;<br />
}</p>
</div>
<h3><a id="methods-round"></a>Round Robin</h3>
<p>Веб-сервер будет передавать запросы бэкендам по очереди с учетом их весов. Данный метод является методом по умолчанию и его указывать в конфигурационном файле не нужно.</p>
<h3><a id="methods-hash"></a>Hash</h3>
<p>Данный метод определяет контрольную сумму на основе переменных веб-сервера и ассоциирует каждый полученный результат с конкретным бэкендом. Пример настройки:</p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
hash $scheme$request_uri;<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<p><em>* это самый распространенный пример настройки hash — с использованием переменных <strong>$scheme</strong> (http или https) и <strong>$request_uri</strong>. При данной настройке каждый конкретный URL будет ассоциирован с конкретным сервером.</em></p>
<h3><a id="methods-iphash"></a>IP Hash</h3>
<p>Ассоциация выполняется исходя из IP-адреса клиента и только для HTTP-запросов. Таким образом, для каждого посетителя устанавливается связь с одним и тем же сервером. Это, так называемый, Sticky Session метод.</p>
<div class="note">
<p>Для адресов IPv4 учитываются только первые 3 октета — это позволяет поддерживать одинаковые соединения с клиентами, чьи адреса меняются (получение динамических адресов от DHCP провайдера). Для адресов IPv6 учитывается адрес целиком.</p>
</div>
<p>Пример настройки:</p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
ip_hash;<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<h3><a id="methods-least"></a>Least Connections</h3>
<p>NGINX определяет, с каким бэкендом меньше всего соединений в данный момент и перенаправляет запрос на него (с учетом весов).</p>
<p>Настройка выполняется с помощью опции least_conn:</p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
least_conn;<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<h3><a id="methods-random"></a>Random</h3>
<p>Запросы передаются случайным образом (но с учетом весов). Дополнительно можно указать опцию two — если она задана, то NGINX сначала выберет 2 сервера случайным образом, затем на основе дополнительных параметров отдаст предпочтение одному из них. Это следующие параметры:</p>
<ul>
<li><strong>least_conn —</strong> исходя из числа активных подключений.</li>
<li><strong>least_time=header</strong> (только в платной версии) — на основе времени ответа (расчет по заголовку).</li>
<li><strong>least_time=last_byte</strong> (только в платной версии) — на основе времени ответа (расчет по полной отдаче страницы).</li>
</ul>
<p>Пример настройки:</p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
random two least_conn;<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<h3><a id="methods-ltime"></a>Least Time</h3>
<p>Данная опция будет работать только в NGINX Plus. Балансировка выполняется исходя из времени ответа сервера. Предпочтение отдается тому, кто отвечает быстрее.</p>
<p>Опция для указания данного метода — least_time. Также необходимо указать, что мы считаем ответом — получение заголовка (header) или когда страница возвращается целиком (last_byte).</p>
<p>Пример 1:</p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
least_time header;<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<p><em>* в данном примере делаться расчет исходя из того, как быстро получаем в ответ заголовки.</em></p>
<p>Пример 2:</p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
least_time last_byte;<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
server 192.168.0.12;<br />
}</p>
</div>
<p><em>* в данном примере делаться расчет исходя из того, как быстро получаем в ответ целую страницу.</em></p>
<h2><a id="examples"></a>Сценарии настройки</h2>
<p>В реальной жизни настройки могут быть несколько сложнее, чем приведенные здесь или в официальной документации. Рассмотрим несколько примеров, что может понадобиться настроить при балансировке.</p>
<h3><a id="examples-ssl"></a>1. Backend на https</h3>
<p>Предположим, что внутренние серверы отвечают по SSL-каналу. Таким образом, нужно отправлять запрос по порту 443. Также схема проксирования должна быть https.</p>
<p><strong>Настройка сайта:</strong></p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location / {<br />
proxy_pass https://<em>balansed</em>;<br />
proxy_set_header   Host             $host;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}<br />
&#8230;<br />
}</p>
</div>
<div class="post-console">
<p>* обратите внимание на 2 момента:</p>
<ol>
<li>В схеме подключения <strong>proxy_pass</strong> указали <strong>https</strong>. В противном случае при подключении NGINX будет возвращать ошибку 400.</li>
<li>Задали дополнительные опции <strong>proxy_set_header</strong>, которых не было в примерах выше.</li>
</ol>
</div>
<p><strong>Настройка upstream:</strong></p>
<div class="editor">
<p>upstream <em>balansed</em> {<br />
server 192.168.0.10:443;<br />
server 192.168.0.11:443;<br />
server 192.168.0.12:443;<br />
}</p>
</div>
<p><em>* в данном примере указали конкретный порт, по которому должно выполняться соединение с бэкендом. Для упрощения конфига дополнительные опции упущены.</em></p>
<h3><a id="examples-pages"></a>2. Разные бэкенды для разных страниц</h3>
<p>Нам может понадобиться разные страницы сайта переводить на разные группы внутренних серверов.</p>
<p><strong>Настройка сайта:</strong></p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location /page1 {<br />
proxy_pass http://<em>balansed</em>1;<br />
}</p>
<p>location /page2 {<br />
proxy_pass http://<em>balansed</em>2;<br />
}<br />
&#8230;<br />
}</p>
</div>
<p><em>* при такой настройке будут передавать запросы к странице <strong>page1</strong> на группу <strong>balansed1</strong>, а к <strong>page2</strong> — <strong>balansed2</strong>.</em></p>
<p><strong>Настройка upstream:</strong></p>
<div class="editor">
<p>upstream <em>balansed</em>1 {<br />
server 192.168.0.10;<br />
server 192.168.0.11;<br />
}</p>
<p>upstream <em>balansed</em>2 {<br />
server 192.168.0.12;<br />
server 192.168.0.13;<br />
}</p>
</div>
<p><em>* в данном примере у есть 2 апстрима, каждый со своим набором серверов.</em></p>
<h3><a id="examples-host"></a>3. На другой хост</h3>
<p>Может быть необходимым делать обращение к внутреннему ресурсу по другому hostname, нежели чем будет обращение к внешнему. Для этого в заголовках проксирования мы должны указать опцию Host.</p>
<p><strong>Настройка сайта:</strong></p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location / {<br />
proxy_pass https://<em>balansed</em>;<br />
proxy_set_header   Host             internal.domain.com;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}<br />
&#8230;<br />
}</p>
</div>
<p><em>* в данном примере будут проксировать запросы на бэкенды, передавая им имя хоста <strong>internal.domain.com</strong>.</em></p>
<h3><a id="examples-tcp"></a>4. TCP-запрос</h3>
<p>Рассмотрим, в качестве исключения, TCP-запрос на порт 5432 — подключение к базе PostgreSQL.</p>
<p><strong>Настройка сайта:</strong></p>
<div class="editor">
<p>server {<br />
listen 5432;<br />
proxy_pass tcp_postgresql;<br />
}</p>
</div>
<p><em>* в данном примере мы слушаем TCP-порт <strong>5432</strong> и проксируем все запросы на апстрим <strong>tcp_postgresql</strong>.</em></p>
<p><strong>Настройка upstream:</strong></p>
<div class="editor">
<p>upstream tcp_postgresql {<br />
server 192.168.0.14:5432;<br />
server 192.168.0.15:5432;<br />
}</p>
</div>
<p><em>* запросы будут случайным образом передаваться на серверы </em><strong>192.168.0.14</strong> и <strong>192.168.0.15</strong>.</p>
<h3><a id="examples-udp"></a>5. UDP-запрос</h3>
<p>Рассмотрим также и возможность балансировки UDP-запросов — подключение к DNS по порту 53.</p>
<p><strong>Настройка сайта:</strong></p>
<div class="editor">
<p>server {<br />
listen 53 udp;<br />
proxy_pass udp_dns;<br />
proxy_responses 1;<br />
}</p>
</div>
<p><em>* в данном примере мы слушаем UDP-порт <strong>53</strong> и проксируем все запросы на апстрим <strong>udp_dns</strong>. Опция <strong>proxy_responses</strong> говорит о том, что на один запрос нужно давать один ответ.</em></p>
<p><strong>Настройка upstream:</strong></p>
<div class="editor">
<p>upstream udp_dns {<br />
server 192.168.0.16:53;<br />
server 192.168.0.17:53;<br />
}</p>
</div>
<p><em>* запросы будут случайным образом передаваться на серверы </em><strong>192.168.0.16</strong> и <strong>192.168.0.17</strong>.</p>
<p>взято из сайта www.dmosk.ru</p>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[web-server]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2022/05/Depositphotos_21743149_s.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/nginx-%d0%bf%d0%b5%d1%80%d0%b5%d0%bd%d0%b0%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d1%8f-proxy_redirect-%d0%b8-redirect/</link>
					<title><![CDATA[NGINX перенаправления proxy_redirect  и redirect]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sat, 21 May 2022 04:12:21 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="440" src="https://blog.sefdar.ru/wp-content/uploads/2022/05/Use-redirects.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>NGINX перенаправления proxy_redirect  и redirect</h1>
													</header>
													<p>В данной статье описываеюся возможные перенаправления и проксирования запросов к серверу на NGINX. Перенаправления запросов на другие страницы с помощью NGINX.</p>
<h2>Настройка перенаправлений</h2>
<p>Настройки необходимо вносить в файлах конфигураций виртуальных доменов. В Linux на основе RPM (CentOS, Red Hat), как правило, они расположены в директории /etc/nginx/conf.d/. В Linux на основе Deb (Ubuntu, Debian) — в директории /etc/nginx/sites-enabled/. В FreeBSD все в одном файле — /usr/local/etc/nginx/nginx.conf.</p>
<p>Саму настройку на перенаправление в NGINX можно прописать несколькими способами.</p>
<p>1. Первый:</p>
<div class="editor">
<p>rewrite ^ https://$host$request_uri? &lt;флаг&gt;;</p>
</div>
<p><em>* <strong>$host</strong> — имя хоста из запроса, если отсутствует — имя в поле «Host» заголовка, если тоже отсутствует — имя сервера; <strong>$request_uri</strong> — первоначальный запрос с аргументами (все, что идет после доменного имени).<br />
** где флаги могут быть следующие:</em></p>
<ul>
<li><em>permanent — перенаправление с кодом 301.</em></li>
<li><em>redirect — перенаправить с кодом 302.</em></li>
<li><em>last — закончить обработку с переходом в новый location.</em></li>
<li><em>break — закончить обработку и остаться в текущем location.</em></li>
</ul>
<p>2. Второй:</p>
<div class="editor">
<p>return &lt;код&gt; https://$host$request_uri;</p>
</div>
<p><em>* где коды могут использоваться любые, но чаще всего — 301, 302, 404.</em></p>
<p>Есть различные мнения, какой из методов лучше и безопаснее, поэтому каким воспользоваться — решать по ситуации. В данных примерах используются оба варианта.</p>
<p>После внесения изменений, необходимо проверить их корректность:</p>
<div class="console">
<p>nginx -t</p>
</div>
<p>И для их применения перезапустить веб-сервер:</p>
<div class="console">
<p>systemctl restart nginx</p>
</div>
<div class="console">
<p>service nginx restart</p>
</div>
<p><em>* в первом примере перезапуск выполняется на новых системах Linux. Второй пример — на устаревших или FreeBSD.</em></p>
<div class="note">
<p>Проверяя редиректы в браузере, следует учесть, что настройки могут кэшироваться. Для обновления кэша используйте комбинацию Ctrl + F5. Если и это не помогает, закрывайте вкладку и открывайте новую.</p>
</div>
<h2><a id="http-https"></a>С HTTP на HTTPS (другой порт)</h2>
<p>Пример конфигурации для перенаправления запросов на другой порт — с 80 (http) на 443 (https):</p>
<div class="editor">
<p>server {<br />
listen 80;<br />
server_name domain.ru www.domain.ru;<br />
return 301 https://$host$request_uri;<br />
}</p>
</div>
<p><em>* в данном примере для всех обращений к сайту domain.ru по 80 порту (http) будет работать редирект на 443 порт (https) с кодом 301 (для склеивания доменов).</em></p>
<p>Также можно добавить условие, чтобы не перенаправлять на https для определенных ссылок, например:</p>
<div class="editor">
<p>server {<br />
listen 80;<br />
server_name domain.ru www.domain.ru;<br />
if ($uri !~ /page.html){<br />
return 301 https://$host$request_uri;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере запрос на страницу <strong>/page.html</strong> будет открыт по http.</em></p>
<p>Есть еще способ настройки директивы <strong>server</strong> сразу для http и https. При этом, если зайти по 80 порты, нас перекинет на 443:</p>
<div class="editor">
<p>server {<br />
listen       80;<br />
listen       443 ssl;<br />
server_name  domain.ru www.domain.ru;</p>
<p>if ($scheme = &#8216;http&#8217;) {<br />
return 301 https://$host$request_uri;<br />
}</p>
<p>ssl_certificate     /etc/nginx/ssl/cert.pem;<br />
ssl_certificate_key /etc/nginx/ssl/cert.key;</p>
<p>&#8230;<br />
}</p>
</div>
<p><em>* данный способ удобен, чтобы не создавать несколько секций server со своими настройками.</em></p>
<h2><a id="domains"></a>С одного домена на другой</h2>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name domain1.ru;<br />
return 302 http://domain2.ru$request_uri;<br />
}</p>
</div>
<h2><a id="www"></a>C домена без www на домен с www</h2>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name domain.ru;<br />
return 301 http://www.$host$request_uri;<br />
}</p>
</div>
<h2><a id="without-www"></a>С www на без www</h2>
<p>Конкретный домен:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name www.domain.ru;<br />
return 301 $scheme://domain.ru$request_uri;<br />
}</p>
</div>
<p>Все домены, которые обслуживает nginx:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name &#171;~^www\.(.*)$&#187;;<br />
return 301 $scheme://$1$request_uri;<br />
}</p>
</div>
<p>Или с использованием if:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if ($host ~ &#171;^www\.(.*)$&#187;) {<br />
return 301 $scheme://$1$request_uri;<br />
}<br />
&#8230;<br />
}</p>
</div>
<h2><a id="index"></a>C index.php на / (корень)</h2>
<p>Данная настройка позволит перевести все запросы с /index.php на корневой адрес /:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if ($request_uri ~ &#171;^(.*)index\.(?:php|html)&#187;) {<br />
return 301 $1;<br />
}<br />
}</p>
</div>
<h2><a id="default"></a>Перенаправление запросов для отсутствующих доменов (перенаправление по умолчанию)</h2>
<p>Если обращение к веб-серверу идет по IP-адресу или домену, который не прописан в конфигурационном файле, можно перенаправить весь трафик на домен по умолчанию:</p>
<div class="editor">
<p>server {<br />
listen 80 default_server;<br />
return 302 https://welcome.domain.ru$request_uri;<br />
}</p>
</div>
<p>или независимо от протокола:</p>
<div class="editor">
<p>server {<br />
listen 80 default_server;<br />
return 302 $scheme://welcome.domain.ru$request_uri;<br />
}</p>
<p>server {<br />
listen 443 ssl default_server;<br />
return 302 $scheme://welcome.domain.ru$request_uri;</p>
<p>ssl_certificate /etc/nginx/ssl/cert.pem;<br />
ssl_certificate_key /etc/nginx/ssl/cert.key;<br />
}</p>
</div>
<p><em>* <strong>$scheme</strong> позволяет перевести запрос на тот же протокол (http или https), по которому он был инициирован.<br />
* если nginx должен слушать и обрабатывать запросы по https, необходимо указывать в настройках пути к сертификатам.</em></p>
<h2><a id="ip"></a>С IP-адреса на домен</h2>
<p>В данном случае мы переводим все запросы по IP-адресу на конкретный домен:</p>
<div class="editor">
<p>server {<br />
listen 80;<br />
server_name 192.168.1.15;<br />
return 301 http://site.ru$request_uri;<br />
}</p>
</div>
<p><em>* при отправке http-запроса на сервер <strong>192.168.1.15</strong> по IP-адресу, он будет переведен на домен <strong>site.ru</strong>.</em></p>
<h2><a id="subdomains"></a>Редирект домена и всех его поддоменов</h2>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name  domain domain.*;<br />
return 301 https://$host$request_uri;<br />
}</p>
</div>
<h2><a id="file"></a>На другой файл</h2>
<p>Это скорее не перенаправление, а алиас или rewrite. Позволяет по запросу одного из файлов, отдать другой:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location = /robots.txt {<br />
rewrite ^/robots.txt$ /robots2.txt;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере по запросу <strong>robots.txt</strong>, сервер отдаст содержимое <strong>robots2.txt</strong>.</em></p>
<h2><a id="url-other-server"></a>Часть url на другой сервер</h2>
<p>Перенаправить запрос на другой сервер при обращении по url page1:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name  domain1.ru;<br />
location  ~ ^/page1/(.*)$ {<br />
return 301 $scheme://domain2.ru/$1;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере для всех запросов, начинающихся на <strong>/page1/&#8230;</strong> будет работать перенаправление на другой домен <strong>domain2.ru</strong>.</em></p>
<h2><a id="slash"></a>Редирект со слешем</h2>
<p><strong>1. Убрать слеш в конце url</strong></p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if (!-f $request_filename ) {<br />
rewrite ^/(.*)/$ /$1 permanent;<br />
}<br />
}</p>
</div>
<p><strong>2. Добавить слеш в конце url</strong></p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if (!-f $request_filename ) {<br />
rewrite ^(.*[^/])$ $1/ permanent;<br />
}<br />
}</p>
</div>
<h2><a id="expansion"></a>Удаляем расширение</h2>
<p>Для перенаправления запроса, где в URL есть полное название файла скрипта (с расширением) используем конфигурацию:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if ($request_uri ~ &#171;^(.*)\.(?:php|html)&#187;) {<br />
return 301 $1;<br />
}<br />
}</p>
</div>
<p><em>* в данном случае все запросы, которые заканчиваются на <strong>.php</strong> или <strong>.html</strong>, будут перенаправляться на страницы без данных расширений.</em></p>
<p>Для примера, запрос http://site-example.ru/page.php будет переведен на http://site-example.ru/page.</p>
<h2><a id="other-page"></a>На другую страницу</h2>
<p>Нам может понадобиться перенаправлять запросы с одной страницы сайта на другую. Приведем примеры, как это сделать с помощью return и rewrite.</p>
<p>а) с помощью rewrite:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
rewrite ^/page1$ /page2 permanent;<br />
}</p>
</div>
<p>б) с помощью return:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location = /page1 {<br />
return 301 /page2;<br />
}<br />
}</p>
</div>
<h2><a id="delete-url"></a>Удалить часть URL</h2>
<p>Иногда нужно удалять часть url. Это можно сделать следующими способами:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
rewrite /deleted-url/(.*) /$1 permanent;<br />
}</p>
</div>
<p>или:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if ($request_uri ~ &#171;/deleted-url/(.*)&#187;) {<br />
return 301 $1;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере из url мы удалим <strong>deleted-url/</strong>.</em></p>
<h2><a id="request_filename"></a>Перенаправить запрос в случае обращения к несуществующим файлам</h2>
<p>Предположим, что нужно обратиться к скриптам на сервере, но без прописывания в URL .php на конце. Запрос будет выглядеть, примерно, http://url/. Чтобы nginx перекинул запрос на url.php вставляем следующее:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
if (!-e $request_filename){<br />
rewrite ^(.*)$ /$1.php;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере мы проверяем наличие файла, к которому идет обращение. И если его нет, то происходит замена адреса на такое же имя файла с .php на конце.</em></p>
<h2><a id="tryfiles"></a>Перевод запросов, если файла не существует</h2>
<p>Данное действие не является редиректом, но близко по смыслу — NGINX проверяет наличие файла скрипта, к которому идет обращение, и если его нет, переводит запрос на другой файл. Как правило, это используется для того, чтобы перевести все обращения на файл index.php.</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location / {<br />
try_files $uri $uri/ /index.php?$query_string;<br />
}<br />
&#8230;<br />
}</p>
</div>
<p><em>* в данном примере мы скажем веб-серверу все запросы обрабатывать с помощью файла <strong>index.php</strong> в корневой директории.</em></p>
<h2><a id="proxypass"></a>Проксирование</h2>
<p>Проксирование, в отличие от редиректа, не передает инструкции браузеру перейти на другой url — NGINX сам выполняет http-запрос по другому адресу и возвращает готовый ответ. Эта возможность может применяться для внутреннего распределения серверных ресурсов.</p>
<p>Хоть это и не совсем редирект, рассмотрим примеры его настройки, так как очень часто нужно не перенаправление, а, как раз, обратное проксирование.</p>
<h3><a id="proxypass-otherserver"></a>1. На другой сервер</h3>
<p>Пример внутреннего перенаправления http-запроса на другой веб-сервер:</p>
<div class="editor">
<p>&#8230;<br />
location / {<br />
proxy_pass $scheme://192.168.0.15:8080/;<br />
proxy_redirect     off;<br />
proxy_set_header   Host             $host;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}</p>
</div>
<p><em>* в данном случае, принимать запросы от браузера и отвечать на них будет NGINX, а сама обработка будет выполняться на сервере с IP-адресом 192.168.0.15 на порту 8080.</em></p>
<p>Использование NGINX в качестве http-прокси:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name site1.ru www.site1.ru;<br />
location / {<br />
proxy_pass http://192.168.1.21/;<br />
proxy_redirect     off;<br />
proxy_set_header   Host             $host;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}<br />
}</p>
<p>server {<br />
&#8230;<br />
server_name site2.ru www.site2.ru;<br />
location / {<br />
proxy_pass http://192.168.1.22/;<br />
proxy_redirect     off;<br />
proxy_set_header   Host             $host;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере запросы на <strong>site1.ru</strong> будут перекинуты на сервер <strong>192.168.1.21</strong>, а запросы на <strong>site2.ru</strong> — <strong>192.168.1.22</strong>.</em></p>
<p>HTTP proxy с авторизацией (если удаленный веб-сервер требует аутентификации):</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location / {<br />
proxy_pass http://10.10.10.10/page/;<br />
proxy_set_header Authorization &#171;Basic dGVzdDp0ZXN0&#187;;<br />
&#8230;<br />
}<br />
}</p>
</div>
<p><em>* где <strong>10.10.10.10/page</strong> — страница, на которую будут перекинуты запросы; <strong>dGVzdDp0ZXN0</strong> — логин:пароль test:test, закодированные в формате base64.</em></p>
<h3><a id="proxypass-url-other-server"></a>2. Часть url на другой сервер</h3>
<p>Выше мы рассмотрели пример перенаправления запроса по части веб-адреса. По схожему сценарию мы можем делать проксирование:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
location  ~ ^/page1/(.*)$ {<br />
proxy_pass   $scheme://10.10.10.10/$1;<br />
}<br />
}</p>
</div>
<p><em>* и так, в данном примере при обращении по адресу <strong>site.ru/page1/&lt;что-то еще&gt;</strong>, nginx сделает внутренний запрос на сервер <strong>10.10.10.10</strong> по адресу <strong>10.10.10.10/&lt;что-то еще&gt;</strong> и вернет готовый ответ.</em></p>
<h3><a id="proxypass-othersite"></a>3. На другой сайт</h3>
<p>Мы можем сделать так, что при переходе по одному адресу у нас будет открываться совершенно другой сайт:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name dmosk.local;<br />
location / {<br />
proxy_pass https://www.dmosk.ru;<br />
proxy_set_header   Host             www.dmosk.ru;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}<br />
}</p>
</div>
<p><em>* в данном случае мы при обращении к нашему серверу (до доменному имени <strong>dmosk.local</strong>) будем попадать на сайт <strong>https://www.dmosk.ru</strong>. Обратите внимание, что в <strong>proxy_set_header</strong> мы передаем хосту его имя — в противном случае, как правило, другой сервер вернет ошибку. Также мы не указываем <strong>proxy_redirect</strong>, иначе, nginx будет переводить запросы на реальный сайт (отправлять инструкции браузеру перейти на него), а не тот, что мы используем за http-прокси.</em></p>
<h3><a id="proxypass-parturl"></a>4. На другой сайт по части URL</h3>
<p>Если нам нужно настроить проксирование на другой сайт при обращении к определенной странице сайта, настраиваем NGINX так:</p>
<div class="editor">
<p>server {<br />
&#8230;<br />
server_name www.dmosk.ru;<br />
location /page {<br />
rewrite /page/(.*) /$1  break;<br />
proxy_pass https://www.site.ru;<br />
proxy_set_header   Host             www.site.ru;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;<br />
}<br />
}</p>
</div>
<p><em>* в данном примере, если мы перейдем на страницу <strong>www.dmosk.ru/page</strong>, то мы попадем на сайт <strong>www.site.ru</strong>.</em></p>
<h3><a id="proxypass-redirects"></a>5. Редиректы при проксировании</h3>
<p>Если при проксировании хост возвращает инструкцию браузеру для выполнения редиректа, обозреватель может сменить адрес сайта. Это особенно не удобно, когда проксирование мы выполняем на другой сайт. Чтобы отловить редиректы и заменить их своими значениями, мы должны воспользоваться опцией <strong>proxy_redirect</strong>. Рассмотрим ее применение для предыдущего примера, когда мы проксировали запрос на сайт www.dmosk.ru:</p>
<div class="editor">
<p>server {<br />
listen 80;<br />
server_name dmosk.local www.dmosk.local;<br />
location / {<br />
proxy_pass https://www.dmosk.ru;<br />
proxy_set_header   Host             www.dmosk.ru;<br />
proxy_set_header   X-Real-IP        $remote_addr;<br />
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;</p>
<p>proxy_redirect https://www.dmosk.ru/url1 http://dmosk.local/url2;<br />
proxy_redirect https://www.dmosk.ru/ http://dmosk.local/;<br />
}<br />
}</p>
</div>
<p><em>* в конкретном случае мы проксируем запросы <strong>http://dmosk.local</strong> на сайт <strong>www.dmosk.ru</strong>, но если он вернет инструкцию для редиректа <strong>https://www.dmosk.ru/url1</strong>, в браузере он должен быть заменен на <strong>http://dmosk.local/url2</strong>. А также любое перенаправление для <strong>https://www.dmosk.ru/</strong> будет заменено на <strong>http://dmosk.local/</strong>.</em></p>
<p>взято из сайта www.dmosk.ru</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="2">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[web-server]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2022/05/Use-redirects.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-wine-%d0%b2-linux-mint-20-x/</link>
					<title><![CDATA[Установка Wine в Linux Mint 21.x-20.x.]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 15 May 2022 11:44:23 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="420" src="https://blog.sefdar.ru/wp-content/uploads/2022/05/wine-linux-programas-windows-2.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Установка Wine в Linux Mint 21.x-20.x.</h1>
													</header>
													<div class="entry-content">
<p>После установки Linux Mint есть проблема связаная с установкой Wine из стандартных репозиториев, поэтому пришлось описать способ решения данной проблемы.</p>
<p>Нижеприведенный способ установки Wine в Linux Mint работает также и в предыдущих версиях Linux Mint.<br />
Если вы пытались установить Wine из стандартных репозиториев, то сначала удалите его, затем введите команду</p>
<pre>sudo rm -rf ~/.wine</pre>
<p>Перед установкой необходимо обновить систему, даже если она только что установлена</p>
<pre>sudo apt update &amp;&amp; sudo apt upgrade -y</pre>
<p>Доустанавливаем необходимые пакеты</p>
<pre>sudo apt install dirmngr ca-certificates software-properties-common gnupg gnupg2 apt-transport-https curl -y</pre>
<p>Теперь можно приступать к установке Wine.</p>
<pre>sudo dpkg --add-architecture i386</pre>
<p>для Linux Mint 21.x и выше используем следующее:</p>
<pre>curl -s https://dl.winehq.org/wine-builds/winehq.key | gpg --dearmor | sudo tee /usr/share/keyrings/winehq.gpg &gt; /dev/null</pre>
<pre>echo deb [signed-by=/usr/share/keyrings/winehq.gpg] http://dl.winehq.org/wine-builds/ubuntu/ jammy main | sudo tee /etc/apt/sources.list.d/winehq.list</pre>
<p>Для Linux Mint 20.x и ниже нужно использовать следующие строки:</p>
<pre>wget -qO - https://dl.winehq.org/wine-builds/winehq.key | sudo apt-key add -</pre>
<pre>sudo add-apt-repository 'deb https://dl.winehq.org/wine-builds/ubuntu/ focal main'</pre>
<p>Далее для всех одинаково</p>
<pre>sudo apt update</pre>
<pre>sudo apt-get install --install-recommends winehq-stable</pre>
<p>Если вы хотите установить самую свежую версию Wine, то в конце предыдущей команды поменяйте stable на devel или staging</p>
<p>В принципе, на этом можно и закончить, но я бы рекомендовал доустановить пакеты Gecko и Mono &#8212; для этого необходимо выполнить команду</p>
<pre>winecfg</pre>
<p>По желанию можно доустановить пакет WineTricks, для этого необходимо ввести команду</p>
<pre>sudo apt-get install winetricks</pre>
</div>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[дистрибутивы]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2022/05/wine-linux-programas-windows-2.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d0%bf%d1%80%d0%b0%d0%b2%d0%bb%d0%b5%d0%bd%d0%b8%d0%b5-%d1%81%d0%b5%d1%80%d0%b2%d0%b5%d1%80%d0%be%d0%bc-%d1%87%d0%b5%d1%80%d0%b5%d0%b7-%d0%b2%d0%b5%d0%b1-%d0%bf%d0%b0%d0%bd%d0%b5%d0%bb%d1%8c-aap/</link>
					<title><![CDATA[Управление сервером через веб-панель aaPanel Linux]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 13 May 2022 08:42:41 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="387" src="https://blog.sefdar.ru/wp-content/uploads/2022/05/Dashboard-web-control-panel-1024x472.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Управление сервером через веб-панель aaPanel Linux</h1>
													</header>
													<h2>Введение</h2>
<p>Перепробовав разные панели управления сервером от платных и бесплатных, у меня всегда было ощущение некой не завершенности при работе с ними. Это всегда были разные проблемы, то сертификат не поставит в крон, то настолько сложная установка панели что состоит из 20-30 разных компонентов что опускаются руки все это делать. То закончилась поддержка продукта, а последнее обновление сломала систему в целом. У всех есть недостатки, но из 2-х зол выбираем наименьшее. <a href="https://www.aapanel.com/reference.html">aaPanel Linux </a>&#8212; панель управления с блекджеком.</p>
<p><strong>aaPanel </strong>– это панель управления веб-хостингом с открытым исходным кодом для управления такими услугами хостинга, как базы данных, веб-сайты и т. д., как и Webmin. Здесь мы увидим, как установить и настроить его на сервере CentOS 6/7 / RHEL или Ubuntu 19.04 / 18.04 / 17.04 Linux. Бесплатная хостинг-панель под Linux с простым и удобным интерфейсом. aaPanel на VPS-хостинге позволяет легко управлять сайтами, SSL-сертификатами, настраивать FTP-хранилища и выполнять мониторинг всей системы.</p>
<p>Будучи веб-графической панелью управления хостингом, ею можно легко управлять с любого локального или удаленного компьютера, как и популярная Cpanel. Однако на самом деле в aaPanel, как WHM, функций не так много, но их достаточно для работы и управления всем, что требуется веб-серверу. После установки aaPanel настроить и запустить веб-сайт стало очень легко: одним щелчком мыши мы можем настроить LANMP / LAMP (Linux, Apache / Nginx, MySQL, PHP) для тестирования или разработки веб-приложений.</p>
<p>С помощью aaPanel больше не будет головной боли, связанной с запуском различных команд для создания баз данных, создания и управления Docker, веб-сайтом, FTP-сервером и проектом Python, и всеми ими можно управлять с помощью всего нескольких щелчков мыши. Давайте посмотрим пошаговое руководство, чтобы узнать процесс установки aaPanel в CentOS с помощью локального или удаленного командного терминала.</p>
<h2>Установите aaPanel Linux на CentOS, Debian или Ubuntu</h2>
<p>&nbsp;</p>
<p>Приведенные ниже шаги по установке этой бесплатной веб-панели управления с открытым исходным кодом в CentOS будут одинаковыми для серверной / настольной операционной системы Debian или Ubuntu Linux.</p>
<h3>1 Войдите на сервер CentOS.</h3>
<p>&nbsp;</p>
<p>Во-первых, у вас должен быть root или стандартный пользователь с доступом sudo, тогда только мы сможем установить что-либо на нашем сервере CentOS.</p>
<h3>2.Установите Wget</h3>
<p>&nbsp;</p>
<p>Хотя мы можем использовать curl, здесь мы используем команду wget, поэтому сначала установите ее.</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-1" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-1" class="hljs ">sudo yum install wget</code></pre>
</div>
<h4>CentOS – Error: Failed to download metadata for repo ‘appstream’: Cannot prepare internal mirrorlist: No URLs in mirrorlist</h4>
<p>Если видим данную ошибку (у меня она часто возникает на чистом сервере под CentOS 8) тогда выполняем команды:</p>
<p><strong>Шаг 1:</strong> Перейдите в /etc/yum.repos.d/каталог.</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-2" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-2" class="hljs ">cd /etc/yum.repos.d/</code></pre>
</div>
<p><strong>Шаг 2:</strong> Запустите следующие команды</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-3" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-3" class="hljs python">sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-*</code></pre>
</div>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-4" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-4" class="hljs python">sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-*</code></pre>
</div>
<p><strong>Шаг 3:</strong> Теперь запустите обновление yum</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-5" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-5" class="hljs perl">yum update -y</code></pre>
</div>
<p>Вот и все. Ошибка исправлена (<a class="external external_icon" href="https://techglimpse.com/failed-metadata-repo-appstream-centos-8/" target="_blank" rel="noopener nofollow">спасибо автору</a>)</p>
<h3>3 Загрузите установочный скрипт aaPanel.</h3>
<p>&nbsp;</p>
<p>Теперь используйте команду wget вместе с последним доступным сценарием для установки aaPanel.</p>
<p><strong>Для CentOS или Redhat 7 0 или 8 Linux</strong></p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-6" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-6" class="hljs php">wget -O install.sh http://www.aapanel.com/script/install_6.0_en.sh</code></pre>
</div>
<p><strong>Для Debian или Ubuntu Linux</strong></p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-7" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-7" class="hljs php">wget -O install.sh http://www.aapanel.com/script/install-ubuntu_6.0_en.sh</code></pre>
</div>
<h3>4 Запустите скрипт install.sh веб-панели управления aaPanel Linux.</h3>
<p>&nbsp;</p>
<p>Теперь у нас есть сценарий в нашей системе, пора его запустить. Тип:</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-8" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-8" class="hljs css">bash install.sh</code></pre>
</div>
<p>Когда он говорит, хотите ли вы сейчас установить aaPanel в каталог / www. Введите <strong>Y</strong> и нажмите кнопку <strong>Enter</strong>.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764ac92688.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764ac92688.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<h3>5 Страница входа в систему. Веб-панель управления aaPanel.</h3>
<p>&nbsp;</p>
<p>После завершения установки вы получите ссылку для входа: localhost: 8888 / some-numbers. Кроме того, имя пользователя и пароль будут использоваться для входа в панель управления.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764ad79b40.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764ad79b40.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<h3>6 Установите программные пакеты для aaPanel Linux.</h3>
<p>&nbsp;</p>
<p>На панели управления веб-хостинга aaPanel в первый раз вам будет предложено установить между LNMP или LAMP, нажмите кнопку и установите нужную среду веб-сервера. Однако мы можем установить их позже из раздела приложений на этой панели Linux.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764ae3fd08.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764ae3fd08.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<h3>7 Основные характеристики, функции и снимок экрана aaPanel CP</h3>
<p>&nbsp;</p>
<p><strong>Приборная панель:</strong></p>
<p>На панели инструментов мы получаем весь статус серверной системы, на которой установлена ​​веб-панель управления aaPanel, например, локальный статус, использование ЦП, использование памяти и хранилище. Также справа вверху находятся параметры обновления, исправления и перезапуска.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764af7846d.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764af7846d.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<hr />
<p><strong>Безопасность системы:</strong></p>
<p>Это брандмауэр панели управления, откуда мы можем блокировать или открывать порты для нашей серверной системы, чтобы разрешить трафик.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b0db352.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b0db352.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<hr />
<p><strong>Настройки:</strong></p>
<p>В этом разделе можно включить поддержку SSL, двухфакторную аутентификацию через аутентификацию Google, Listen IPv6, API, изменить имя пользователя и пароль панели управления и другие параметры.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b2468fc.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b2468fc.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<hr />
<p><strong>Магазин приложений:</strong></p>
<p>Включение основных приложений и плагинов, таких как почтовый сервер, Java, Google Drive, Python и др., Действительно упрощает весь процесс графически, нам не нужно использовать командную строку сервера для установки любого из них. Все будет работать в фоновом режиме, и все, что нам нужно сделать, – это всего лишь один щелчок.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b3b9b16.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b3b9b16.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<hr />
<p><strong>Установка Docker:</strong></p>
<p>Если вы хотите установить Docker с помощью панели управления aaPanel, просто перейдите в раздел «Развертывание» и нажмите кнопку установки. Как только он будет установлен, вы сможете создавать образы Docker и управлять ими. Кроме того, доступны MongoDB, Redis и Memcached.</p>
<p><a title="" href="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b5006b4.jpg" data-rel="lightbox-gallery-0" data-rl_title="" data-rl_caption="" data-lightbox-gallery="lightbox-gallery-0"><img decoding="async" class="SDStudio-light-box-enable SDStudio-editor-tools-md-imp b-loaded" src="https://techblog.sdstudio.top/wp-content/uploads/2021/07/post-78611-60e764b5006b4.jpg" alt="Как установить панель управления веб-хостингом aaPanel на CentOS 7 или Ubuntu" /></a></p>
<p>Кроме того, мы также можем включить удаленный сервер, установленный с aaPanel, и получить к нему доступ, чтобы иметь централизованное управление кластерами серверов.</p>
<h3>Остановить, запустить и перезапустить</h3>
<p>&nbsp;</p>
<p><strong>Стоп</strong> :</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-9" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-9" class="hljs ">service bt stop</code></pre>
</div>
<p><strong>Начало</strong> :</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-10" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-10" class="hljs ">service bt start</code></pre>
</div>
<p><strong>Запустить снова:</strong></p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-11" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-11" class="hljs ">service bt restart</code></pre>
</div>
<h3>Удалить веб-панель управления aaPanel</h3>
<p>&nbsp;</p>
<p>Если в будущем вы захотите удалить установку панели управления сервером, используйте следующую команду:</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-12" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-12" class="hljs python">sudo service bt stop &amp;&amp; chkconfig --del bt &amp;&amp; rm -f /etc/init.d/bt &amp;&amp; rm -rf /www/server/panel</code></pre>
</div>
<p>Если приведенная выше команда не сработала, используйте эту:</p>
<div class="sds-scrivo-highlighter">
<div class="btn-copy" data-clipboard-target="#sds-scrivo-13" data-tooltip-sds-scrivo-highlighter="Скопировать код"></div>
<pre><code id="sds-scrivo-13" class="hljs ">sudo bt stop &amp;&amp;sudo update-rc.d -f bt remove &amp;&amp;sudo rm -f /etc/init.d/bt &amp;&amp;sudo rm -rf /www/server/panel</code></pre>
</div>
<p>Другие команды aaPanel см. На его <a class="external external_icon" href="https://www.aapanel.com/reference.html" target="_blank" rel="noopener nofollow">официальной странице</a>.</p>
<p>Использование и интерфейс этой панели управления Linux довольно просты и удобны. Но не ожидайте, что аналогичные услуги, подобные тем, которые мы получаем в платной панели WHM Cpanel, можно рассматривать как альтернативу платформам управления серверами, подобным Cockpit, но с множеством дополнительных опций. В нем не было приложения «Терминал», так что я мог отправлять команды прямо на сервер с помощью графического интерфейса этой панели веб-хостинга Linux. Тем не менее, необходимо признать, что они бесплатны, имеют открытый исходный код, не требуют затрат и упорный труд разработчиков, потому что то, что они сделали, действительно полезно. И, конечно, вы можете попробовать это вместо сервера командной строки.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[web-server]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2022/05/Dashboard-web-control-panel-1024x472.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b0-nodejs/</link>
					<title><![CDATA[Установка NODEJS]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 09 Jan 2022 05:20:16 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2022/09/2441554433-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Установка NODEJS</h1>
													</header>
													<h3 id="Введение">Введение</h3>
<p><a href="https://nodejs.org/">Node.js</a> — это среда выполнения JavaScript для программирования на стороне сервера. Она позволяет разработчикам создавать масштабируемый серверный функционал с помощью JavaScript, языка, который многим уже знаком по веб-разработке под браузер.</p>
<p>В этом обучающем модуле мы покажем вам три разных варианта установки Node.js на сервере Ubuntu 20.04:</p>
<ul>
<li>использование <code>apt</code> для установки пакета <code>nodejs</code> из репозитория ПО Ubuntu по умолчанию</li>
<li>использование <code>apt</code> с альтернативным репозиторием ПО PPA для установки определенных версий пакета <code>nodejs</code></li>
<li>установка диспетчера <code>nvm</code> (Node Version Manager) и его использование для установки нескольких версий node и управления ими</li>
</ul>
<p>Для многих пользователей будет достаточно использовать <code>apt</code> с репозиторием по умолчанию. Если вам требуется определенная более новая (или старая) версия Node, вам следует использовать репозиторий PPA. Если вы занимаетесь активной разработкой приложений Node, и вам нужно часто переключаться между версиями <code>node</code>, используйте метод <code>nvm</code>.</p>
<h2 id="Предварительные-требования">Предварительные требования</h2>
<p>Для целей этого обучающего модуля предполагается, что вы используете ОС Ubuntu 20.04. Для начала вам потребуется учетная запись пользователя без привилегий root с привилегиями sudo.</p>
<h2 id="Вариант-1-—-Установка-node-js-с-помощью-apt-из-репозиториев-по-умолчанию">Вариант 1 — Установка Node.js с помощью Apt из репозиториев по умолчанию</h2>
<p>В репозиториях Ubuntu 20.04 по умолчанию содержится версия Node.js, обеспечивающая согласованную работу в разных системах. На момент составления этого обучающего модуля в репозиториях хранится версия 10.19. Это не самая последняя версия, но она должна быть стабильной и подходить для небольших экспериментов с языком.</p>
<p>Для получения этой версии можно использовать диспетчер пакетов <code>apt</code>. Обновите указатель локальных пакетов с помощью следующей команды:</p>
<pre>sudo apt update</pre>
<p>Выполните установку Node.js:</p>
<pre>sudo apt install nodejs</pre>
<p>Проверьте, что установка выполнена успешно, запросив у <code>node</code> номер версии:</p>
<pre>nodejs -v</pre>
<div class="code-toolbar">
<div class="context">
<h2>Output</h2>
</div>
</div>
<pre class="code-pre "><code>v10.19.0
</code></pre>
<p>Если пакет из репозитория отвечает вашим потребностям, для начала работы с Node.js ничего больше не потребуется. В большинстве случаев также нужно установить <code>npm</code>, диспетчер пакетов Node.js. Для этого установите пакет <code>npm</code> с помощью <code>apt</code>:</p>
<pre>sudo apt install npm</pre>
<p>Это позволит вам устанавливать модули и пакеты для использования с Node.js.</p>
<p>Вы успешно установили Node.js и <code>npm</code>, используя <code>apt</code> и репозитории ПО Ubuntu по умолчанию. В следующем разделе мы покажем, как использовать альтернативный репозиторий для установки разных версий Node.js.</p>
<h2 id="Вариант-2-—-Установка-node-js-с-помощью-apt-через-архив-nodesource-ppa">Вариант 2 — Установка Node.js с помощью Apt через архив NodeSource PPA</h2>
<p>Для установки другой версии Node.js вы можете использовать архив <em>PPA</em> (архив персональных пакетов), обслуживаемый NodeSource. Через PPA можно установить другие версии Node.js, кроме доступных в официальных репозиториях Ubuntu. На момент составления этого обучающего модуля доступны версии Node.js v10, v12, v13 и v14.</p>
<p>Вначале установим PPA для получения доступа к его пакетам. Используйте в домашнем каталоге команду <code>curl</code> для получения скрипта установки предпочитаемой версии. Замените <code>14.x</code> предпочитаемым номером версии (если он отличается).</p>
<pre>cd ~
curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh</pre>
<p>Дополнительную информацию о доступных версиях можно найти в <a href="https://github.com/nodesource/distributions/blob/master/README.md">документации по NodeSource</a>.</p>
<p>Просмотрите содержимое загруженного скрипта в <code>nano</code> (или другом предпочитаемом текстовом редакторе):</p>
<pre>nano nodesource_setup.sh</pre>
<p>Убедившись в безопасности запуска скрипта, закройте редактор и запустите скрипт с привилегиями <code>sudo</code>:</p>
<pre>sudo bash nodesource_setup.sh</pre>
<p>Архив PPA будет добавлен в вашу конфигурацию, и кэш локальных пакетов автоматически обновится. Теперь вы можете установить пакет Node.js, как описывалось в предыдущем разделе:</p>
<pre>sudo apt install nodejs</pre>
<p>Убедитесь в установке новой версии, запустив <code>node</code> с флагом версии <code>-v</code>:</p>
<pre>node -v</pre>
<div class="code-toolbar">
<div class="context">
<p>Output</p>
</div>
</div>
<pre class="code-pre "><code>v14.2.0
</code></pre>
<p>Пакет NodeSource <code>nodejs</code> содержит двоичный код <code>node</code> и <code>npm</code>, так что не нужно устанавливать <code>npm</code> отдельно.</p>
<p>Вы успешно установили Node.js и <code>npm</code>, используя <code>apt</code> и архив NodeSource PPA. В следующем разделе мы покажем, как использовать диспетчер версий Node Version Manager для установки нескольких версий Node.js и управления ими.</p>
<h2 id="Вариант-3-—-Установка-node-с-помощью-node-version-manager">Вариант 3 — Установка Node с помощью Node Version Manager</h2>
<p>Еще одним способом установки Node.js, который является достаточно гибким, является использование nvm, или Node Version Manager. Это программное обеспечение позволяет устанавливать и поддерживать несколько разных независимых версий Node.js и связанных с ними пакетов Node.</p>
<p>Чтобы установить NVM на ваш сервер Ubuntu 20.04, откройте <a href="https://github.com/nvm-sh/nvm">страницу проекта на GitHub</a>. Скопируйте команду <code>curl</code> из файла README, отображаемого на главной странице. Она позволит получить самую последнюю версию скрипта установки.</p>
<p>Прежде чем передавать команду в <code>bash</code>, рекомендуется проверить скрипт, чтобы убедиться, что он не делает ничего, с чем вы не согласны. Вы можете сделать это, удалив сегмент <code>| bash</code> в конце команды <code>curl</code>:</p>
<pre>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh</pre>
<p>Проверьте и убедитесь, что вы не возражаете против изменений, которые вносит скрипт. Если вас удовлетворит результат, запустите команду еще раз с добавлением <code>| bash</code> в конце. URL-адрес, который вы используете, будет меняться в зависимости от последней версии NVM, но в настоящий момент скрипт можно загрузить и запустить с помощью следующей команды:</p>
<pre>curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash</pre>
<p>Она устанавливает скрипт <code>nvm</code> для вашей учетной записи. Для его использования необходимо сначала получить ваш файл <code>.bashrc</code>:</p>
<pre>source ~/.bashrc</pre>
<p>Теперь вы можете спросить у NVM, какие версии Node доступны:</p>
<pre>nvm list-remote</pre>
<p>Output</p>
<pre class="code-pre "><code></code></pre>
<pre class="code-pre "><code>. . .
       v12.13.0   (LTS: Erbium)
       v12.13.1   (LTS: Erbium)
       v12.14.0   (LTS: Erbium)
       v12.14.1   (LTS: Erbium)
       v12.15.0   (LTS: Erbium)
       v12.16.0   (LTS: Erbium)
       v12.16.1   (LTS: Erbium)
       v12.16.2   (LTS: Erbium)
       v12.16.3   (Latest LTS: Erbium)
        v13.0.0
        v13.0.1
        v13.1.0
        v13.2.0
        v13.3.0
        v13.4.0
        v13.5.0
        v13.6.0
        v13.7.0
        v13.8.0
        v13.9.0
       v13.10.0
       v13.10.1
       v13.11.0
       v13.12.0
       v13.13.0
       v13.14.0
        v14.0.0
        v14.1.0
        v14.2.0
</code></pre>
<p>Это очень длинный список! Вы можете установить версию Node, введя любую версию релиза, которую вы видите. Например, для получения версии 13.6.0 воспользуйтесь следующей командой:</p>
<pre>nvm install v13.6.0</pre>
<p>Вы можете увидеть установленные вами различные версии с помощью следующей команды:</p>
<p><code>nvm list<br />
</code></p>
<p><code></code>Output<br />
<code>-&gt;      v13.6.0<br />
default -&gt; v13.6.0<br />
node -&gt; stable (-&gt; v13.6.0) (default)<br />
stable -&gt; 13.6 (-&gt; v13.6.0) (default)<br />
. . .<br />
</code></p>
<pre class="code-pre "><code></code></pre>
<p>Она отображает текущую активную версию на первой строке (<code>-&gt; v13.6.0</code>), за которой следуют псевдонимы и версии, на которые указывают эти псевдонимы.</p>
<p><strong>Примечание.</strong> Если у вас также имеется версия Node.js, установленная с помощью <code>apt</code>, здесь вы сможете увидеть <code>системную</code> запись. Вы всегда можете активировать установленную системой версию Node с помощью команды <code>nvm use system</code>​​​.<br />
</p>
<p>Также вы увидите псевдонимы для различных <a href="https://nodejs.org/en/about/releases/">релизов Node с длительной поддержкой (LTS)</a>:</p>
<pre class="code-pre "><code></code></pre>
<div class="secondary-code-label " title="Output">Output</div>
<pre class="code-pre "><code>. . .
lts/* -&gt; lts/erbium (-&gt; N/A)
lts/argon -&gt; v4.9.1 (-&gt; N/A)
lts/boron -&gt; v6.17.1 (-&gt; N/A)
lts/carbon -&gt; v8.17.0 (-&gt; N/A)
lts/dubnium -&gt; v10.20.1 (-&gt; N/A)
lts/erbium -&gt; v12.16.3 (-&gt; N/A)
</code></pre>
<p>Мы можем установить релиз на основе этих псевдонимов. Например, для установки последней версии с долгосрочной поддержкой, <code>erbium</code>, запустите следующую команду:</p>
<pre>nvm install lts/erbium
Output
<code>Downloading and installing node v12.16.3...
. . .
Now using node v12.16.3 (npm v6.14.4)
</code></pre>
<pre class="code-pre "><code></code></pre>
<p>Вы можете переключаться между установленными версиями с помощью <code>nvm use</code>:</p>
<pre class="code-pre "><code>nvm use v13.6.0
</code></pre>
<pre class="code-pre "><code>Now using node v13.6.0 (npm v6.13.4)
</code></pre>
<p>Вы можете проверить, что установка выполнена успешно, с помощью того же метода, использованного в других разделах. Введите следующую команду:</p>
<pre>node -v
Output

<code>v13.6.0
</code></pre>
<p>Корректная версия Node установлена на нашем компьютере, как мы и ожидали. Совместимая версия <code>npm</code> также доступна.</p>
<h2 id="Заключение">Заключение</h2>
<p>Существует несколько способов запустить и начать использование Node.js на сервере Ubuntu 20.04. Наиболее подходящий метод из вышеперечисленных определяется в зависимости от обстоятельств. Хотя использование упакованной версии из репозитория Ubuntu — самый простой метод, использование <code>nvm</code> или архива NodeSource PPA дает дополнительную гибкость.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[JavaScript]]></category><category><![CDATA[javascript]]></category><category><![CDATA[NodeJS]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2022/09/2441554433-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/autokey-%d0%b0%d0%bd%d0%b0%d0%bb%d0%be%d0%b3-autohotkey-%d0%b4%d0%bb%d1%8f-linux/</link>
					<title><![CDATA[AutoKey аналог AutoHotKey для Linux]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 19 Dec 2021 04:36:37 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="468" src="https://blog.sefdar.ru/wp-content/uploads/2021/12/06931466-1024x571.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>AutoKey аналог AutoHotKey для Linux</h1>
													</header>
													<p><a href="http://zenway.ru/uploads/04_11/autokey_001.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_001.png" alt="" /></a></p>
<p><strong>AutoKey</strong> – удобный менеджер клавиатурных сочетаний (горячих клавиш / hotkeys), аббревиатур (сокращенных слов) и скриптов (сценариев), имеющий как GTK так и QT графический интерфейс (для более тесной интеграции в используемое окружение).</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_002.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_002.png" alt="" /></a></p>
<p>Многим пользователям, во время работы за компьютером, регулярно приходится выполнять одни и те же операции&#8230; Но не всегда встроенных функциональных возможностей системы, или конкретного приложения, хватает для настройки и удобного управления ими.</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_003.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_003.png" alt="" /></a></p>
<p>AutoKey многофункциональный инструмент, обладающий интуитивно понятным интерфейсом, предназначенный для того чтобы автоматизировав рутинные операции, упростить работу с компьютером сделав управление системой и приложениями более простым.</p>
<p>&nbsp;</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_004.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_004.png" alt="" /></a></p>
<p>Основное назначение AutoKey это предоставление возможности переназначения всех клавиатурных сочетаний (применяемых по умолчанию) и/или назначения новых сочетаний для любых действий пользователя, будь то запуск приложения, выполнения скрипта, открытия конкретного файла или каталога&#8230;</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_005.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_005.png" alt="" /></a></p>
<p>AutoKey так же даёт возможность осуществить &#171;подстановку текста&#187;, подразумевается замена аббревиатур их полным текстовым аналогом (подстановка текста вместо соответствующих аббревиатур). Реализована возможность настройки имитирования служебных клавиатурных сочетаний, позволяющих посылать команды приложениям.</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_007.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_007.png" alt="" /></a></p>
<p>У AutoKey есть возможность записи макросов (символьных имён) на основе полученных событий (от клавиатуры/мыши). Возможно использование скриптов, написанных на Python и API, позволяющих контролировать окна, буфер обмена, мышь и др&#8230; Имеется встроенный редактор кода (QScintilla для KDE и GtkSourceView2 для Gnome).</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_008.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_008.png" alt="" /></a></p>
<p>Установки сделанные в AutoKey работают в любом приложении, это позволяет с одинаковым удобством использовать её как с графическими так и с консольными интерфейсами пользователя. Приложение интегрируется в область уведомлений (системный трей) и имеет полную поддержку Юникода (Unicode).</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_006.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_006.png" alt="" /></a></p>
<p>Лицензия: GNU GPL v3</p>
<p><a href="http://zenway.ru/uploads/04_11/autokey_009.png"><img decoding="async" src="http://zenway.ru/uploads/04_11/mini/autokey_009.png" alt="" /></a></p>
<p><a href="https://code.google.com/archive/p/autokey/downloads">скачать</a></p>
<p>так же эту программу можно установить через стандартный установщик</p>
<p>$ sudo apt install autokey-gtk</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="2">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/12/06931466-1024x571.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%87%d0%b8%d0%bd%d0%b8%d0%bc-ping-%d0%b2-wine-%d0%bd%d0%b0-linux-mint-20-x/</link>
					<title><![CDATA[Чиним ping в wine на Linux Mint 20.x]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 19 Dec 2021 04:26:08 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="473" src="https://blog.sefdar.ru/wp-content/uploads/2021/12/maxresdefault-1024x576.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Чиним ping в wine на Linux Mint 20.x</h1>
													</header>
													<p>Иногда в wine не работает пингование ресурсов и для его починки в консоли нужно выполнить пару команд</p>
<pre class="no-highlight"><code>
$ sudo setcap cap_net_raw+epi /usr/bin/wine-preloader
$ sudo setcap cap_net_raw+epi /usr/bin/wine
$ sudo setcap 'cap_net_raw+epi' "$(readlink -f "/usr/bin/wine-preloader")"
</code></pre>
<p>вот и все теперь нужно проверить:</p>
<pre class="no-highlight"><code>
$ wine ping -n 5 linux.org.ru
</code></pre>
<p>вывод должен быть таким:</p>
<pre class="no-highlight"><code>
$ wine ping -n 5 linux.org.ru
03fc:fixme:font:get_name_record_codepage encoding 20 not handled, platform 1.
03fc:fixme:font:get_name_record_codepage encoding 20 not handled, platform 1.
Pinging linux.org.ru [178.248.233.6] with 32 bytes of data:
Reply from 178.248.233.6: bytes=32 time=51ms TTL=54
Reply from 178.248.233.6: bytes=32 time=49ms TTL=54
Reply from 178.248.233.6: bytes=32 time=50ms TTL=54
Reply from 178.248.233.6: bytes=32 time=50ms TTL=54
Reply from 178.248.233.6: bytes=32 time=58ms TTL=54

Ping statistics for 178.248.233.6
Packets: Sent = 5, Received = 5, Lost = 0 (0% loss)
Approximate round trip times in milli-seconds:
Minimum = 49ms, Maximum = 58ms, Average = 52ms
</code></pre>
<p>Взято отсюда <a href="https://wiki.winehq.org/FAQ#Failed_to_use_ICMP_.28network_ping.29.2C_this_requires_special_permissions">https://wiki.winehq.org/FAQ#Failed_to_use_ICMP_.28network_ping.29.2C_this_req&#8230;</a></p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/12/maxresdefault-1024x576.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b2%d0%b2%d0%b5%d1%81%d1%82%d0%b8-%d0%b2-%d0%b4%d0%be%d0%bc%d0%b5%d0%bd-active-directory-ad-%d0%bb%d0%b8%d0%bd%d1%83%d0%ba%d1%81-ubuntu-20-04-18-04-debian-10-linux-mint-20/</link>
					<title><![CDATA[Ввести в домен Active Directory (AD) Линукс]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 17 Dec 2021 10:45:30 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="559" src="https://blog.sefdar.ru/wp-content/uploads/2021/12/9d58f4c06a6a0a24b9ce8c12ca8d9b0f.jpeg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Ввести в домен Active Directory (AD) Линукс</h1>
													</header>
													<p>Как мне ввести в домен Linux машину. Не важно какой дистрибутив Mint, Ubuntu, Debian(они самые распространенные).</p>
<p>Для этого установим пакеты</p>
<p><code>sudo apt-get install sssd</code></p>
<p>Отредактируйте файл <code>sudo nano /etc/sssd/sssd.conf</code>, добавив следующую информацию:</p>
<pre>[sssd]
config_file_version = 2
services = nss, pam 
domains = ИМЯ_ДОМЕНА 
[pam]
[nss]
[domain/ИМЯ_ДОМЕНА]
ad_domain = ИМЯ_ДОМЕНА
krb5_realm = ИМЯ_ДОМЕНА
krb5_server = ИМЯ_КОНТРОЛЛЕРА_ДОМЕНА</pre>
<p>Добавьте Linux Mint в домен Windows командой: <code>sudo realm join ИМЯ_ДОМЕНА</code></p>
<p>Отредактируйте файл <code>sudo nano /etc/resolv.conf</code>, добавив следующую информацию:</p>
<pre>search your.domain.name
nameserver 1.2.3.4 #IP вашего сервера DNS(Контроллера домена)
nameserver 1.2.3.5</pre>
<p>После выполнения этих шагов, Linux Mint будет успешно подключен к домену Windows и пользователи смогут аутентифицироваться через домен.</p>
<p>Наконец выполнить вход под пользователем</p>
<pre>sudo realm join -U ПОЛЬЗОВАТЕЛЬ your.domain.name</pre>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Линух]]></category><category><![CDATA[линукс]]></category><category><![CDATA[Linux in AD]]></category><category><![CDATA[AD to Linux]]></category><category><![CDATA[AD]]></category><category><![CDATA[Active Directory]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/12/9d58f4c06a6a0a24b9ce8c12ca8d9b0f.jpeg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%be%d1%88%d0%b8%d0%b1%d0%ba%d0%b0-fatal-the-remote-end-hung-up-unexpectedly-%d0%bf%d1%80%d0%b8-%d0%b2%d1%8b%d0%bf%d0%be%d0%bb%d0%bd%d0%b5%d0%bd%d0%b8%d0%b8-git-push/</link>
					<title><![CDATA[Ошибка fatal: The remote end hung up unexpectedly при выполнении git push]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 14 Nov 2021 07:47:16 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="720" height="405" src="https://blog.sefdar.ru/wp-content/uploads/2021/11/fatal-error.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Ошибка fatal: The remote end hung up unexpectedly при выполнении git push</h1>
													</header>
													<p>Иногда при работе с git через http возникает ошибка <code>The remote end hung up unexpectedly</code>. Это может обозначать одну из нескольких проблем. Одна из проблем &#8212; размер репозитория больше максимально допустимого размера будефа POST. Рассмотрим решение данной проблемы.</p>
<p>Вывод о данной ошибке выглядит примерно следующим образом:</p>
<pre class="brash:ps">Counting objects: 7928, done.
Delta compression using up to 12 threads.
Compressing objects: 100% (7834/7834), done.
Writing objects: 100% (7928/7928), 204.43 MiB | 97.40 MiB/s, done.
Total 7928 (delta 968), reused 1 (delta 0)
error: RPC failed; result=22, HTTP code = 413
fatal: The remote end hung up unexpectedly
fatal: The remote end hung up unexpectedly
Everything up-to-date
</pre>
<p>Итак, первый вариант решения данной проблемы состоит в увеличении буфера данных POST запроса.</p>
<p>В первую очередь необхожимо узнать размер данных. В приведенном выше примере вывода размер равен 204.43 МБ. К этому числу добавим небольшой запас (например, до 250 МБ) и переведем все в байты. 250 МБ = 250 * 1024 * 1024 = 262144000 КБ. Задаем полученное значение в настройки git.</p>
<div>
<div id="highlighter_692202" class="syntaxhighlighter ps">
<div class="toolbar"><a class="toolbar_item command_help help" href="https://dev-tips.ru/blog/post/oshibka-the-remote-end-hung-up-unexpectedly#">?</a></div>
<table border="0" cellspacing="0" cellpadding="0">

<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="ps plain">git config http.postBuffer 262144000</code></div>
</div>
</td>
</tr>

</table>
</div>
</div>
<p>Этой командой мы выставили значение для конкретного репозитория, если необходимо применить данную настройку глобально, то необходимо добавить флаг &#8212;global:</p>
<div>
<div id="highlighter_894296" class="syntaxhighlighter ps">
<div class="toolbar"><a class="toolbar_item command_help help" href="https://dev-tips.ru/blog/post/oshibka-the-remote-end-hung-up-unexpectedly#">?</a></div>
<table border="0" cellspacing="0" cellpadding="0">

<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="ps plain">git config -</code><code class="ps keyword">-global</code> <code class="ps plain">http.postBuffer 262144000</code></div>
</div>
</td>
</tr>

</table>
</div>
</div>
<p>Если ваш сервер для хранения git репозиториев имеет максимальный размер тела запроса меньше заданного размера, то необходимо перенастроить web-сервер (если есть такая возможность). Для этого необходимо изменить значение <code>client_max_body_size</code> (для nginx) или <code>LimitRequestBody</code> (для apache) и перезагрузить сервис (<code>service nginx reload</code> или <code>service apache2 reload</code> соответственно). Если сервер не аш и нет возможности его сконфигурировать, то остается вариант номер 2.</p>
<p>Второй вариант заключается в переходе с протокола http на ssh. Вам будет необходимо изменить адрес удаленного репозитория с помощью команды <code>git remote set-url</code>:</p>
<div>
<div id="highlighter_233497" class="syntaxhighlighter ps">
<div class="toolbar"><a class="toolbar_item command_help help" href="https://dev-tips.ru/blog/post/oshibka-the-remote-end-hung-up-unexpectedly#">?</a></div>
<table border="0" cellspacing="0" cellpadding="0">

<tr>
<td class="gutter">
<div class="line number1 index0 alt2">1</div>
</td>
<td class="code">
<div class="container">
<div class="line number1 index0 alt2"><code class="ps plain">git remote </code><code class="ps keyword">set</code><code class="ps keyword">-url</code> <code class="ps plain">origin git@example.com:user/repository.git</code></div>
</div>
</td>
</tr>

</table>
</div>
</div>
<p>Вот мы рассмотрели два пути решения ошибки <code>The remote end hung up unexpectedly</code>. Вероятно есть другие причины возникновения данной ошибки и иные пути решения. Эта статья не охватывает все возможные варианты, но надеюсь, что она вам помогла.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[GIT]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/11/fatal-error.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%b2%d0%ba%d0%bb%d1%8e%d1%87%d0%b0%d0%b5%d0%bc-http-2-%d0%b8-ssl-%d0%b2-nginx-%d0%b4%d0%bb%d1%8f-%d1%81%d0%b0%d0%b9%d1%82%d0%b0/</link>
					<title><![CDATA[Включаем HTTP/2 и SSL в NGINX для сайта]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 15 Sep 2021 10:52:40 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="468" src="https://blog.sefdar.ru/wp-content/uploads/2021/09/http2-1024x570.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Включаем HTTP/2 и SSL в NGINX для сайта</h1>
													</header>
													<h4><b>Зачем нужен HTTP/2</b></h4>
<p>HTTP/2 – новая версия протокола HTTP, стандартизированная в начале 2015 года. Использование HTTP/1.1 из-за некоторых особенностей вносит негативный эффект на производительность веб-приложений.</p>
<p>В частности HTTP/1.0 позволяет выполнять только один запрос одновременно в TCP–соединении. В HTTP/1.1 были добавлены конвейерные запросы, но они только частично помогают параллельному исполнению запросов и по-прежнему приводят к блокировкам. Клиенты HTTP/1.0 и HTTP/1.1, которым необходимо делать много запросов сейчас используют множество соединений к серверу.</p>
<p>Кроме этого, поля заголовка HTTP многословны и часто повторяются, производя ненужный сетевой трафик. Также время тратится на заторы TCP. Это может привести к повышенным задержкам при множестве запросов сделанных с помощью новых TCP–соединений.</p>
<p>HTTP/2 решает эти проблемы, определяя оптимизированную семантику протокола HTTP. В частности это позволяет выполнять чередование запросов и ответов через то же подключение и предоставляет эффективное кодирование полей HTTP-заголовка. Также HTTP/2 позволяет приоритизировать запросы, позволяя более важным запросам выполняться быстрее.</p>
<p>В результате протокол становится более дружественным к сети, требуя установки меньшего количества TCP–соединений в сравнении с HTTP/1.x, что приводит к более эффективному использованию сети. Также HTTP/2 дает возможность эффективнее обрабатывать сообщения с помощью бинарного формата.</p>
<p>HTTP/2 тесно связан с SSL. Несмотря на то, что спецификация не требует обязательного использования SSL, все веб-браузеры выпущенные на текущий момент будут работать с HTTP/2 только если веб-сайт использует SSL.</p>
<h4><b>Генерируем сертификат</b></h4>
<p>Для работы HTTP/2 на текущий момент должна быть включенa поддержка соединения по HTTPS в NGINX.<br />
Обычно этот процесс состоит из четырех шагов:</p>
<ul>
<li>генерация приватного ключа (key)</li>
<li>создания запроса на подпись (CSR) и отправка запроса в сертифицирующий центр (CA)</li>
<li>установка сертификата от сертифицирующего центра</li>
<li>настройка конфигурации NGINX</li>
</ul>
<p>Такой процесс обеспечивает доверие браузеров пользователей к сайту.</p>
<p>Создайте папку, в которой будут храниться ключи шифрования и перейдите в нее:</p>
<pre><code class="bash hljs">mkdir /etc/nginx/ssl &amp;&amp; cd /etc/nginx/ssl
</code></pre>
<p>Для понимания способов генерации ключа необходимо знать следующие понятия:<br />
<strong>Алгоритм генерации ключа</strong>. OpenSSL поддерживает <a href="https://ru.wikipedia.org/wiki/RSA">RSA</a>, <a href="https://ru.wikipedia.org/wiki/DSA">DSA</a> и <a href="https://ru.wikipedia.org/wiki/ECDSA">ECDSA</a> ключи, но не все типы подходят для практического использования во всех сценариях. Например, для веб-серверов нужно использовать RSA, потому что DSA ключи ограничены 1024 битами (IE не поддерживает ничего сложнее) и ECDSA ключи еще не поддерживаются широко сертифицирующими центрами. Если бы мы генерировали ключ для SSH – подошли бы RSA и DSA, так как ECDSA еще может не поддерживаться частью клиентов.<br />
<strong>Размер ключа</strong>. Размер ключа по-умолчанию может быть небезопасен. Например ключ по-умолчанию для RSA – только 512 бит и его использование совершенно небезопасно. Сегодня рекомендуется использовать минимум 2048 бит для RSA, 2048 бит для DSA и 256 бит для ECDSA. Мы будем использовать RSA и 4086 бит.</p>
<p><strong>Для генерации приватного ключа и запроса на подписание сертификата</strong> выполните команду:</p>
<pre><code class="bash hljs">openssl req -out /etc/nginx/ssl/domain.csr -new -newkey rsa:4086 -nodes -keyout /etc/nginx/ssl/domain.key
</code></pre>
<p>В процессе обязательно укажите FQDN (Common name) – имя домена и email в домене, например webmaster@domain.tld. Не устанавливайте пароль на ключ.</p>
<p>После генерации вы увидите в папке <strong>/etc/nginx/ssl</strong> два файла с расширениями <strong>key</strong> (приватный ключ) и <strong>csr</strong> (запрос на подписание сертификата). Если вы хотите использовать доверенный сертификат — закажите его у центра сертификации (можно например заказать в <a href="https://store.pa.infobox.ru/">тут</a>). Для формирования сертификата потребуется содержимое <strong>csr</strong>, которое можно посмотреть так:</p>
<pre><code class="bash hljs">cat /etc/nginx/ssl/domain.csr
</code></pre>
<p>После заказа и формирования сертификата сохраните его содержимое в файле <strong>/etc/nginx/ssl/domain.crt</strong>. После самого содержимого сертификата в этот же файл с новой строки добавьте содержимое Intermediate сертификата, если он будет предоставлен вам сертифицирующим центром и сохраните файл.</p>
<p><strong>Если вы разворачиваете тестовое окружение — можно бесплатно сгенерировать самоподписанный сертификат</strong> так:</p>
<pre><code class="bash hljs">openssl req -x509 -nodes -days 365 -newkey rsa:4096 -keyout /etc/nginx/ssl/domain.key -out /etc/nginx/ssl/domain.crt
</code></pre>
<p><img decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/post_images/65f/2c0/685/65f2c068587254496b24befdbffbc8b9.jpg" width="800" data-src="https://habrastorage.org/getpro/habr/post_images/65f/2c0/685/65f2c068587254496b24befdbffbc8b9.jpg" /></p>
<p>Также необходимо сгенерировать DH параметры для того, чтобы в случае кражи приватного ключа нельзя было расшифровать последние сообщения.</p>
<pre><code class="bash hljs">openssl dhparam -out /etc/nginx/ssl/dhparam.pem 4096
</code></pre>
<p>&nbsp;</p>
<h4><b>Включаем доступ только по HTTPS в NGINX и активируем HTTP2</b></h4>
<p>Отредактируйте файл конфигурации NGINX <strong>/etc/nginx/conf.d/default.conf</strong>.<br />
В нем удалите секцию <strong>server</strong> и добавьте:</p>
<pre><code class="xml hljs">server {
        listen 80;
        server_name domain.tld  www.domain.tld;
        return 301 https://$host$request_uri;
    }

    server {
        listen 443 ssl http2;
        server_name domain.tld  www.domain.tld;
        ssl on;
        ssl_certificate /etc/nginx/ssl/domain.crt;
        ssl_certificate_key /etc/nginx/ssl/domain.key;
        ssl_dhparam /etc/nginx/ssl/dhparam.pem;
        ssl_prefer_server_ciphers On;
        ssl_protocols TLSv1.1 TLSv1.2;
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK;
        add_header Strict-Transport-Security max-age=15768000;
        ssl_stapling on;

        location / {
            root /usr/share/nginx/html;
	}
    }
}
</code></pre>
<p>, где <strong>domain.tld</strong> замените на имя вашего сайта, для которого включаете HTTP2.</p>
<p><img decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/post_images/0be/8e3/fee/0be8e3feeb76e83073eba84d1ca9c188.jpg" width="600" data-src="https://habrastorage.org/getpro/habr/post_images/0be/8e3/fee/0be8e3feeb76e83073eba84d1ca9c188.jpg" /></p>
<p>После изменений протестируйте конфигурацию nginx на отсутствие ошибок командой:</p>
<pre><code class="bash hljs">nginx -t
</code></pre>
<p><img decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/post_images/b90/a53/7ea/b90a537ea502b62019e5a3da7d312426.jpg" width="600" data-src="https://habrastorage.org/getpro/habr/post_images/b90/a53/7ea/b90a537ea502b62019e5a3da7d312426.jpg" /></p>
<p>Теперь перезапустите NGINX:</p>
<pre><code class="bash hljs">systemctl restart nginx
</code></pre>
<p>Откройте сайт по доменному имени в браузере. Если вы использовали самоподписанный сертификат и не заверяли его у сертифицирующего центра, вы увидите предупреждение.</p>
<p><img decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/post_images/83a/991/71d/83a99171d0218c4bc2f03692107e21f5.jpg" width="800" data-src="https://habrastorage.org/getpro/habr/post_images/83a/991/71d/83a99171d0218c4bc2f03692107e21f5.jpg" /></p>
<p>Добавьте сайт в исключения, браузер запомнит это и он корректно откроется.</p>
<p>Чтобы проверить, что сайт работает по HTTP2, установите HTTP2 indicator для <a href="https://addons.mozilla.org/en-us/firefox/addon/spdy-indicator/">Firefox</a> или <a href="https://chrome.google.com/webstore/detail/http2-and-spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin?hl=en">Chrome</a>.</p>
<p>Теперь при заходе на сайт, поддерживающий HTTP2 или SPDY вы увидите синюю молнию.</p>
<p><img decoding="async" src="https://habrastorage.org/r/w1560/getpro/habr/post_images/f52/f6f/4b3/f52f6f4b3493fe2432b08f5a88d2bbc1.jpg" width="800" data-src="https://habrastorage.org/getpro/habr/post_images/f52/f6f/4b3/f52f6f4b3493fe2432b08f5a88d2bbc1.jpg" /></p>
<p>Действительно, сайт работает по HTTP2.</p>
<p>Успешной работы!</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[WEB]]></category><category><![CDATA[HTTP]]></category><category><![CDATA[HTTP/2]]></category><category><![CDATA[SSL]]></category><category><![CDATA[NGINX]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/09/http2-1024x570.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%ba%d0%b0%d0%ba-%d0%be%d1%82%d0%ba%d1%80%d1%8b%d1%82%d1%8c-%d0%bf%d0%be%d1%80%d1%82-iptables/</link>
					<title><![CDATA[КАК ОТКРЫТЬ ПОРТ IPTABLES]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 15 Sep 2021 03:18:49 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="410" src="https://blog.sefdar.ru/wp-content/uploads/2021/09/unnamed.jpg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>КАК ОТКРЫТЬ ПОРТ IPTABLES</h1>
													</header>
													<p>Самой распространенной операцией при работе с межсетевым экраном, по моему мнению, является операция закрытия и открытия портов на сетевом интерфейсе. Порт открывается для того чтобы к нему можно было получить доступ из вне. Закрывают же порт чтобы запретить устанавливать соединение с программой на вашем устройстве, работающей по этому порту. В этой статье мы рассмотрим как открыть порт iptables на примере Debian Linux.</p>
<div class="code-block code-block-1"></div>
<p>Порт &#8212; это, грубо говоря, номер квартиры в многоквартирном доме, за которым проживают известные (или не очень) жильцы. IP адрес &#8212; это номер многоквартирного дома, в котором множество квартир. Жилец &#8212; это программа, использующая данный номер порта. Этот пример работает в том случае, когда целью является открытие и закрытие доступа программам на том же самом компьютере, который подключен к сети Интернет.</p>
<p>В iptables для создания нового правила или блока правил используется команда:</p>
<p><strong>sudo iptables [-t таблица] -A [цепочка] спецификации_правила</strong></p>
<p>Например:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp -s 8.8.8.8 --sport 53 -d 192.168.1.1 -j ACCEPT</code></p>
<p>Рассмотрим подробно случай открытия порта с помощью iptables. Следует заметить, что понятие <strong>порт</strong> используется в протоколах tcp и udp, поэтому для разных протоколов доступны одинаковые номера портов, но при этом эти номера, говоря на языке нашего примера, означают разные квартиры в разных домах в разных микрорайонах, где за микрорайон можно принять наименование протокола.</p>
<p><strong>Примечание:</strong> Существуют таблицы общепринятых номеров портов для распространённых программ и типов программ по функциональному назначению. Остальные порты являются свободно используемыми. Рассмотрение таблиц портов выходит за рамки данной статьи. Вернемся к простой задаче закрыть один порт.</p>
<p><strong>Примечание:</strong> Если вы собираетесь открыть порт, убедитесь, что политика iptables по умолчанию блокировать всё соединения к портам (DROP). Если же используется политика по умолчанию ACCEPT, то ничего открывать не надо, все порты уже открыты, а вам нужно только закрыть те, которые должны быть недоступны из вне.</p>
<h3><strong>1. ОДИН ПОРТ</strong></h3>
<p>Чтобы открыть порт iptables debian используется следующая команда:</p>
<p><strong>sudo iptables [-t таблица] -A [цепочка] -p протокол [&#8212;sport порт_отправителя] [&#8212;dport порт_назначения] -j [действие]</strong></p>
<p>Например:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp --dport 8081 -j ACCEPT</code></p>
<p><a href="https://losst.ru/wp-content/uploads/2020/01/Draw-3-1.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-29572" src="https://losst.ru/wp-content/uploads/2020/01/Draw-3-1-1024x558.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.ru/wp-content/uploads/2020/01/Draw-3-1-1024x558.jpg 1024w, https://losst.ru/wp-content/uploads/2020/01/Draw-3-1.jpg 1415w" alt="" width="806" height="439" /></a></p>
<p>В данном случае мы открыли в таблице filter в цепочке INPUT протокола tcp порт назначения 8081 с помощью действия ACCEPT (принять). Таким образом для всех внешних машин, пытающихся установить соединение по данному порту, данный порт будет теперь доступен. Если мы хотим открыть порт для конкретной машины следует использовать следующую команду:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp -s 10.0.0.1/32 --dport 8080 -j ACCEPT</code></p>
<p>Мы открыли порт 8080 на нашем компьютере для внешней машины с адресом 10.0.0.1.</p>
<p>&nbsp;</p>
<h3><strong>2. ДИАПАЗОН ПОРТОВ</strong></h3>
<p>Чтобы открыть диапазон портов iptables используется команда:</p>
<p><strong>sudo iptables [-t таблица] -A [цепочка] -p протокол [&#8212;sport начальный_порт_отправителя:конечный_порт_отправителя] [&#8212;dport начальный_порт_назначения:конечный_порт_назначения] -j [действие]</strong></p>
<p>Например:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp --dport 18070:18081 -j ACCEPT</code></p>
<p>Данной командой мы открыли порты <strong>18070-18081</strong> для входящих пакетов, адресованных именно этому компьютеру, передаваемых по протоколу TCP.</p>
<p><a href="https://losst.ru/wp-content/uploads/2020/01/Draw-3-2.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-29573" src="https://losst.ru/wp-content/uploads/2020/01/Draw-3-2-1024x559.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.ru/wp-content/uploads/2020/01/Draw-3-2-1024x559.jpg 1024w, https://losst.ru/wp-content/uploads/2020/01/Draw-3-2.jpg 1416w" alt="" width="806" height="440" /></a></p>
<p>&nbsp;</p>
<h3><strong>3. ВХОДЯЩЕЕ И ИСХОДЯЩЕЕ СОЕДИНЕНИЯ</strong></h3>
<div class="code-block code-block-2"></div>
<p>Все пакеты можно разделить на два типа: пакеты, приходящие на данный узел и пакеты, отправляемые данным узлом. В самом распространенном случае и для исходящих, и для входящих пакетов будет использоваться один и тот же сетевой интерфейс (физическое или логическое устройство, отвечающее за преобразование пакетов в сигналы и передачу сигналов в сеть).</p>
<p>Так вот, входящие пакеты будут создавать входящие соединения по определенным правилам для конкретных программ, и исходящие пакеты будут создавать исходящие соединения по определенным правилам для конкретных программ. При этом для каждой программы, нуждающейся в установлении связи с через сеть, чаще всего будут функционировать два соединения: входящее и исходящее, так как программе одновременно требуется в течении работы получать и отправлять данные.</p>
<p>Правила для входящих соединений будут в большинстве случаев расположены в цепочках <strong>PREROUTING</strong>, <strong>INPUT</strong>. Правила для исходящих соединений будут в большинстве случаев расположены в цепочках <strong>POSTROUTING</strong>, <strong>OUTPUT</strong>.</p>
<p>Чтобы разрешить порт iptables для входящего соединения:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp --dport 8080 -j ACCEPT</code></p>
<p>Пример для исходящего соединения:</p>
<p><code class="user">sudo iptables -t filter -A OUTPUT -p tcp --dport 8080 -j ACCEPT</code></p>
<p><strong>Примечание:</strong> В данном случае правила выглядят очень похоже, но смысловое значение у них будет абсолютно противоположное. В первом случае мы имеем дело с пакетом <strong>ВХОДЯЩИМ</strong>, который должен поступить на порт назначения 8080 <strong>НАШЕГО</strong> компьютера. Во втором случае мы имеем дело с пакетом <strong>ИСХОДЯЩИМ</strong>, который должен поступить на порт назначения 8080 <strong>УДАЛЕННОГО</strong> компьютера. Следует также заметить, что программа не использует на нашем компьютере и удаленном компьютере одинаковый номер порта для одной программы. Порты будут различаться.</p>
<p><a href="https://losst.ru/wp-content/uploads/2020/01/Draw-3-3.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-29574" src="https://losst.ru/wp-content/uploads/2020/01/Draw-3-3-1024x558.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.ru/wp-content/uploads/2020/01/Draw-3-3-1024x558.jpg 1024w, https://losst.ru/wp-content/uploads/2020/01/Draw-3-3.jpg 1417w" alt="" width="806" height="439" /></a></p>
<p>&nbsp;</p>
<h3><strong>4. СОСТОЯНИЕ СОЕДИНЕНИЯ</strong></h3>
<p>Существует возможность формировать правила фильтрации пакетов по совпадению с определенными шаблонами дополнительной спецификации правил Netfilter. За это отвечают параметры <strong>-m</strong> и <strong>-j</strong>. Мы рассмотрим использование параметра -m, который может использовать множество различных шаблонов, из которых мы рассмотрим один: <strong>&#8212;state</strong> состояние. Этот шаблон может принимать следующие значения:</p>
<ul>
<li><strong>NEW</strong> — пакет открыл новое соединение или иным образом связан с соединением, в рамках которого ещё не было пакетов в обоих направлениях (входящем и исходящем);</li>
<li><strong>ESTABLISHED</strong> — пакет связан с соединением, которое видело пакеты в обоих направлениях;</li>
<li><strong>RELATED</strong> — пакет открывает новое соединение, но связан с уже существующим соединением, например, передача данных FTP или ошибка протокола ICMP;</li>
<li><strong>INVALID</strong> — пакет, связанный с неизвестным соединением.</li>
</ul>
<p>Открытие портов iptables для новых соединений:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp -s 192.168.1.0/24 --dport 445 -m state --state NEW -j DROP</code></p>
<p>В этом примере в таблицу filter в цепочку INPUT для протокола tcp, от компьютера из подсети 192.168.1.0/24, на порт назначения 445 (так как цепочка входящая, то порт назначения находится на данном компьютере) для пакетов, открывающих новое соединение, применить действие ACCEPT (принять пакет).</p>
<p>А такая команда позволяет добавить порт iptables для уже установленных соединений:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp -s 192.168.2.0/24 --dport 445 -m state --state ESTABLISHED -j ACCEPT</code></p>
<p>В данном случае в таблицу filter в цепочку INPUT для протокола tcp, от компьютера из подсети 192.168.2.0/24, на порт назначения 445 (так как цепочка входящая, то порт назначения находится на данном компьютере) для пакетов, поступающих в рамках уже открытого соединения, применить действие ACCEPT (принять пакет).</p>
<p><a href="https://losst.ru/wp-content/uploads/2020/01/Draw-3-4.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-29575" src="https://losst.ru/wp-content/uploads/2020/01/Draw-3-4-1024x559.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.ru/wp-content/uploads/2020/01/Draw-3-4-1024x559.jpg 1024w, https://losst.ru/wp-content/uploads/2020/01/Draw-3-4.jpg 1417w" alt="" width="806" height="440" /></a></p>
<p>&nbsp;</p>
<h2><strong>КАК ЗАКРЫТЬ ПОРТ IPTABLES</strong></h2>
<p>Если вы открыли порт с помощью описанных выше правил и политика брандмауэра по умолчанию <strong>DROP</strong>, то достаточно это правило удалить. Если же у вас стоит политика по умолчанию <strong>ACCEPT,</strong> то чтобы закрыть порт надо использовать действие <strong>DROP</strong>.</p>
<p>Например:</p>
<p><code class="user">sudo iptables -t filter -A INPUT -p tcp -s 192.168.3.0/24 --dport 445 -m state --state ESTABLISHED -j DROP</code></p>
<p>Эта команда в таблицу filter в цепочку INPUT запишет правило для протокола TCP, от компьютера из подсети 192.168.3.0/24, на порт назначения 445 (так как цепочка входящая, то порт назначения находится на данном компьютере) для пакетов, поступающих в рамках уже открытого соединения, применять действие <strong>DROP</strong> (отбросить пакет).</p>
<p><a href="https://losst.ru/wp-content/uploads/2020/01/Draw-3-5.jpg"><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-29576" src="https://losst.ru/wp-content/uploads/2020/01/Draw-3-5-1024x558.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.ru/wp-content/uploads/2020/01/Draw-3-5-1024x558.jpg 1024w, https://losst.ru/wp-content/uploads/2020/01/Draw-3-5.jpg 1418w" alt="" width="806" height="439" /></a></p>
<p>&nbsp;</p>
<p>Для правил, запрещающих прием пакета, применимо всё сказанное выше для закрытия порта (одиночный порт, диапазон портов, входящие и исходящие соединения, действия для установленных соединений и новых соединений).</p>
<p><strong>ПРОВЕРКА ОТКРЫТ ЛИ ПОРТ</strong></p>
<p>Когда мы настроили все правила, закрывающие и открывающие порты, нам необходимо проверить корректность примененных настроек. Для этого можно использовать приложение telnet. Telnet &#8212; приложение, позволяющее установить двунаправленное соединение между двумя компьютерами с помощью протокола telnet. В рамках нашей задачи попытка установления соединения между двумя машинами в сети используется как тест правил Netfilter. Выполняем команду следующего вида:</p>
<p><strong>$ telnet ip-адрес порт</strong></p>
<p>Например:</p>
<p><code class="user">telnet 192.168.1.5 443</code></p>
<p>В данной команде будет проверен 443 порт у машины с ip-адресом 192.168.1.5. Если на порту 443 на удаленной машине разрешено входящее соединение и правила на локальной машине разрешают исходящее соединение на порту 443, то получим сообщение:</p>
<p><code class="message">Connection closed by foreign host.</code></p>
<p>Или неожиданно можем получить приглашение доступа к данной машине, если на этом порте ожидает подключения серверная часть telnet.</p>
<p>Если же правила запрещают входящее соединение на удаленной машине, или исходящее соединение на нашей локальной машине на порту 443, то получим сообщение:</p>
<p><code class="message">telnet: Unable to connect to remote host: Connection timed out</code></p>
<p><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-28975" src="https://losst.ru/wp-content/uploads/2019/12/Draw-3-6-1024x558.jpg" sizes="auto, (max-width: 806px) 100vw, 806px" srcset="https://losst.ru/wp-content/uploads/2019/12/Draw-3-6-1024x558.jpg 1024w, https://losst.ru/wp-content/uploads/2019/12/Draw-3-6.jpg 1417w" alt="" width="806" height="439" /></p>
<p><strong>Примечание:</strong> Чтобы получить результаты необходимо подождать довольно продолжительное время, чтобы telnet получил результат попытки соединения по указанному порту.</p>
<div class="code-block code-block-4"></div>
<h2><strong>ВЫВОДЫ</strong></h2>
<p>Итак, сегодня мы рассмотрели как открыть порт 80 iptables или любой другой на локальной машине. Теперь мы знаем, как открыть (или закрыть) конкретный порт, диапазон портов, в чем разница между входящими и исходящими соединениями, как работать с новыми и уже установленными соединениями.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Linux]]></category><category><![CDATA[Безопастность(IPTABLES)]]></category><category><![CDATA[iptables]]></category><category><![CDATA[ports]]></category><category><![CDATA[порты]]></category><category><![CDATA[открыть]]></category><category><![CDATA[закрыть]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/09/unnamed.jpg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%bd%d0%b0%d1%81%d1%82%d1%80%d0%be%d0%b9%d0%ba%d0%b0-%d1%83%d0%b4%d0%b0%d0%bb%d0%b5%d0%bd%d0%bd%d0%be%d0%b3%d0%be-%d0%b4%d0%be%d1%81%d1%82%d1%83%d0%bf%d0%b0-mysql-%d0%b8-mariadb-%d0%b2-linux-ubuntu/</link>
					<title><![CDATA[Настройка удаленного доступа MySQL и MariaDB в Linux Ubuntu]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Wed, 15 Sep 2021 02:57:33 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="441" src="https://blog.sefdar.ru/wp-content/uploads/2021/09/e71622e27771413e335353e51a5e3a51-1024x538.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Настройка удаленного доступа MySQL и MariaDB в Linux Ubuntu</h1>
													</header>
													<p>По умолчанию сервер MySQL настроен таким образом, что к нему разрешены подключения только с локальной машины, следовательно, подключиться из-вне (по интернет или локальной сети) не получится.</p>
<p>Убедиться в этом можно набрав на сервере команду:</p>
<pre>sudo netstat -tlp</pre>
<p>В результате получите что-то типа этого:</p>
<pre>Активные соединения с интернетом (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 localhost:mysql *:* LISTEN 634/mysqld 
tcp 0 0 *:http *:* LISTEN 987/nginx -g daemon
tcp 0 0 *:ssh *:* LISTEN 375/sshd 
tcp6 0 0 [::]:http [::]:* LISTEN 987/nginx -g daemon
tcp6 0 0 [::]:ssh [::]:* LISTEN 375/sshd</pre>
<p>Отсюда видно, что mysql слушает только интерфейс localhost (127.0.0.1). Это не всегда удобно, особенно когда есть необходимость выделить под сервер mysql отдельный сервер. А в рамках корпоративной локальной сети такое бывает очень часто.</p>
<p>Чтобы разрешить серверу MySQL принимать запросы из-вне необходимо предпринять несколько несложных шагов:</p>
<ol>
<li>Поменять одну строчку в конфигурационном файле MySQL;</li>
<li>Создать сетевого пользователя с необходимыми правами.</li>
</ol>
<h2>Разрешаем MySQL слушать интерфейс, который смотрит во внешнюю сеть</h2>
<p>Открываем конфигурационный файл любимы редактором, например nano, из под привилегированного пользователя:</p>
<pre>sudo nano /etc/mysql/my.cnf</pre>
<p>Если у вас установлен сервер mariaDB, то конфигурационный файл находится в другом месте:</p>
<pre>sudo nano /etc/mysql/mariadb.conf.d/50-server.cnf</pre>
<p>Находим строчки:</p>
<pre># Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 127.0.0.1</pre>
<p>и меняем 127.0.0.1 на 0.0.0.0 — тогда сервер будет слушать все интерфейсы компьютера, либо задаем конкретный ip-адрес локального интерфейса, который смотрит в локальную сеть. Например — 192.168.122.10.</p>
<p>Получаем</p>
<pre># Instead of skip-networking the default is now to listen only on
# localhost which is more compatible and is not less secure.
bind-address = 0.0.0.0</pre>
<p>Теперь остается только перезапустить сервис MySQL:</p>
<pre>sudo service mysql restart</pre>
<p>Теперь осталось только завести пользователя, которому разрешено обращаться к серверу MySQL извне.</p>
<h2>Создание внешнего пользователя MySQL</h2>
<p>Теперь нужной подключиться к MySql с паролем суперпользователя системы (системы!!! а не MySQL):</p>
<pre>sudo mysql</pre>
<p>После подключения к MySQL можно создать пользователя и дать привилегию, например:</p>
<pre>mysql&gt; GRANT ALL PRIVILEGES ON userdata.* TO 'user'@'%' IDENTIFIED BY 'password';</pre>
<p>Здесь дается полный доступ к базе данных userdata пользователю с логином <em>user</em> и паролем <em>password</em>, подключающемуся с любого ip.</p>
<p>Можно ограничить права пользователя, разрешив ему подключаться к базе только с определенного ip. Для этого меняем % на конкретный ip-адрес, например 192.168.122.16</p>
<pre>mysql&gt; GRANT ALL PRIVILEGES ON userdata.* TO 'user'@'192.168.122.16' IDENTIFIED BY 'password';</pre>
<p>А можно и разрешить пользователю всё — подключаться ко всем базам с любого ip-адреса</p>
<pre>mysql&gt; GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'password';</pre>
<p>Это делать не желательно, если конечно вы не заводите себя.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="4">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Linux]]></category><category><![CDATA[SQL]]></category><category><![CDATA[MySQL]]></category><category><![CDATA[база данных]]></category><category><![CDATA[db]]></category><category><![CDATA[ьфкшфви]]></category><category><![CDATA[mariadb]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/09/e71622e27771413e335353e51a5e3a51-1024x538.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%ba%d0%b0%d0%ba-%d1%81%d0%be%d1%85%d1%80%d0%b0%d0%bd%d0%b8%d1%82%d1%8c-%d0%b8%d0%bc%d1%8f-%d0%bf%d0%be%d0%bb%d1%8c%d0%b7%d0%be%d0%b2%d0%b0%d1%82%d0%b5%d0%bb%d1%8f-%d0%b8-%d0%bf%d0%b0%d1%80%d0%be/</link>
					<title><![CDATA[Как сохранить имя пользователя и пароль в Git?]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Fri, 27 Aug 2021 05:38:03 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="420" src="https://blog.sefdar.ru/wp-content/uploads/2021/08/30c29ce4cc08523ecc6e1f205bc207d0-1024x512.jpeg" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Как сохранить имя пользователя и пароль в Git?</h1>
													</header>
													<p><strong>Рекомендуемый и безопасный метод: SSH</strong></p>
<p>Создайте ключ ssh Github. Перейдите в <a href="https://www.github.com/" rel="nofollow noreferrer">github.com</a> -&gt; Настройки -&gt; ключи SSH и GPG -&gt; Новый ключ SSH. Теперь сохраните свой закрытый ключ на вашем компьютере.</p>
<p>Затем, если закрытый ключ сохранен как <em>id_rsa</em> в каталоге ~/.ssh/, мы добавим его для аутентификации как таковой:</p>
<pre class="prettyprint-override prettyprinted"><code>ssh-add -K ~/.ssh/id_rsa</code></pre>
<p><strong>Более Безопасный Метод: Кэширование</strong></p>
<p>Мы можем использовать git-credential-store для кэширования нашего имени пользователя и пароля в течение определенного периода времени. Просто введите следующее в CLI (terminal или в командной строке):</p>
<pre class="prettyprint-override prettyprinted"><code>git config --global credential.helper cache</code></pre>
<p>Вы также можете установить период ожидания (в секундах) как таковой:</p>
<pre class="prettyprint-override prettyprinted"><code>git config --global credential.helper 'cache --timeout=3600'</code></pre>
<p><strong>Еще Менее Безопасный Метод</strong></p>
<p>Git-credential-store также может использоваться, но сохраняет пароли в обычном текстовом файле на вашем диске как таковом:</p>
<pre class="prettyprint-override prettyprinted"><code>git config credential.helper store</code></pre>
<p><strong>Устаревший ответ &#8212; Быстрый и небезопасный</strong></p>
<p>Это <strong>небезопасный</strong> способ хранения пароля в виде обычного текста. Если кто-то получит контроль над вашим компьютером, ваш пароль будет раскрыт!</p>
<p>Вы можете установить свое имя пользователя и пароль следующим образом:</p>
<pre class="prettyprint-override prettyprinted"><code>git config --global user.name "your username"

git config --global user.password "your password"</code></pre>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[GIT]]></category><category><![CDATA[git]]></category><category><![CDATA[github]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/08/30c29ce4cc08523ecc6e1f205bc207d0-1024x512.jpeg" type="image/jpeg" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d0%bc%d1%83%d0%bb%d1%8c%d1%82%d0%b8%d0%b7%d0%b0%d0%b3%d1%80%d1%83%d0%b7%d0%be%d1%87%d0%bd%d1%8b%d0%b9-%d0%b4%d0%b8%d1%81%d0%bausb-%d1%84%d0%bb%d0%b5%d1%88%d0%ba%d0%b0-ventoy/</link>
					<title><![CDATA[Мультизагрузочный диск(USB-флешка) Ventoy]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Mon, 16 Aug 2021 12:39:39 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="630" src="https://blog.sefdar.ru/wp-content/uploads/2021/08/1595316236_2020-07-21_130355.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Мультизагрузочный диск(USB-флешка) Ventoy</h1>
													</header>
													<p>Как я устал каждый раз искать программы для создания универсального загрузочного диска. И наконец нашол самое универсальное. Ventoy – бесплатная программа для создания мультзагрузочных USB-носителей.  Так же программа поддерживает образы и файлы следующих типов ISO, WIM, IMG, VHD(x), EFI.</p>
<h4>Возможности</h4>
<p>Ventoy обладает массой возможностей и полезных свойств, часть из которых перечислена ниже.</p>
<ul>
<li>Его очень легко установить и использовать.</li>
<li>Он быстрый (ограничением может являться только скорость копирования iso-файла).</li>
<li>Вам не нужно разархивировать ISO-файлы. Загрузка осуществляется непосредственно из ISO.</li>
<li>Программа поддерживает Legacy + UEFI.</li>
<li>Поддерживается UEFI Secure Boot.</li>
<li>Вы можете создавать загружаемые диски с ISO-файлами, размер которых больше 4 ГБ.</li>
<li>Поддерживаются практически все типы ОС. Разработчик утверждает, что более 200 файлов ISO были протестированы с Ventoy.</li>
<li>Поддерживается автоматическая установка. Это значит, что вы можете добавить свой шаблон или скрипт для автоматического развертывания. Например, скрипт kickstart для Redhat / CentOS, autoYast xml для SUSE, скрипт preseed для Debian. Копируйте скрипт или шаблон на USB-накопитель и укажите Ventoy, что нужно использовать его для автоматической установки. Вы также можете обновить эти скрипты в любое время. Не нужно создавать новый файл ISO, просто используйте оригинальный ISO.</li>
<li>Режим Read-only для USB-диска во время загрузки.</li>
<li>Сохраняется возможность обычного использования USB-дисков. То есть вы можете использовать USB-диск в других целях, например, для копирования файлов.</li>
<li>Обновление Ventoy, когда появляется новая версия, возможно без пересоздания загрузочного USB-диска &#171;с нуля&#187;. При обновлении версии имеющиеся данные не затрагиваются.</li>
<li>Нет необходимости обновлять Ventoy, если выпускается новая версия дистрибутива.</li>
<li>Чтобы добавить новую ОС, просто скопируйте ISO-файл на USB-диск. Не нужно начинать все сначала.</li>
<li>Поддерживается режим Memdisk. На некоторых машинах ISO могут не загружаться. В таких случаях вы можете использовать режим Memdisk. В этом режиме Ventoy загрузит весь файл ISO в память и затем загрузит его.</li>
<li>Фреймворк для плагинов.</li>
<li>Поддерживается родной стиль меню загрузки для Legacy &amp; UEFI.</li>
<li>Кросс-платформенность. Поддерживаются Linux и Windows.</li>
<li>Это свободное и бесплатное ПО с открытым исходным кодом!!</li>
</ul>
<h4>Как создать загрузочной USB-носитель в Windows с помощью Ventoy</h4>
<p>Скачиваем <a href="http://disk.sefdar.ru/index.php/s/hj2RDgoKrhXuqMW">Ventoy</a>, разархивируем архив и запускаем файл <strong>Ventoy2Disk.exe</strong>.</p>
<p>Для создания мультизагрузочной флешки в разделе «Устройство» выбираем наш USB-носитель и нажимаем на кнопку «<strong>Установить</strong>». Соглашаемся на форматирование накопителя. Об окончании форматирования нас уведомит соответствующее окошко. Программа Ventoy создала два раздела, один с файловой системой ExFAT, а другой с файловой системой FAT. В Проводнике будет отображаться первый раздел ExFAT и он будет большего размера. Именно в данный раздел нужно перемещать образы. Теперь при загрузки с данной мультизагрузочной флешки будет отображаться меню GRUB 2 с выбором загрузки перемещенных образов.</p>
<p><strong>Важно</strong>. Стоит отметить, что названия образов не должны содержать пробелов и кириллицы.</p>
<p>Вы можете удалять образы, переименовывать их, перемещать другие образы в папку Ventoy без необходимости повторного запуска программы Ventoy. В случае, если после добавления новых образов, изменения не будут отображаться в меню GRUB загрузочной флешки, то стоит запустить программу Ventoy и выбрать опцию «<strong>Обновить</strong>».</p>
<h4>Как создать загрузочной USB-носитель в GNU/Linux с помощью Ventoy</h4>
<p>Начиная с версии Ventoy 1.0.36 для Linux в программе появился графический веб-интерфейс. Рассмотрим работу Ventoy с запуском графического веб-интерфейса.</p>
<p>Скачиваем <a href="http://disk.sefdar.ru/index.php/s/J3KxeSyXk3eqAy7">Ventoy для Linux</a>, разархивируем архив и переходим в папку ventoy. В папке нас интересует файл VentoyWeb.sh, его мы запустим. Открываем терминал в папке с программой и вводим команду запуска:</p>
<p>sudo sh VentoyWeb.sh<br />
В адресной строке браузера открываем ссылку локального веб-сервера Ventoy:</p>
<p>http://127.0.0.1:24680</p>
<p>отображается привычный интерфейс, подобный интерфейсу в Windows.</p>
<p>Дальнейшие действия аналогичны инструкции версии Ventoy для Windows. Нажимаем на кнопку «Установить» и дважды соглашаемся с форматированием USB устройства. По окончанию установки образы можно переместить в раздел Ventoy съемного носителя. Для закрытия Ventoy в Linux нужно закрыть вкладку браузера с ссылкой Ventoy, а затем в терминале воспользоваться комбинацией клавиш CTRL+C для завершения процесса Ventoy. Так же есть <a href="http://disk.sefdar.ru/index.php/s/Bnm2vTCb9b8RCqO">образ .iso</a> для создания всего этого добра.</p>
<p>&nbsp;</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="5">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Linux]]></category><category><![CDATA[USB]]></category><category><![CDATA[usb-флешка]]></category><category><![CDATA[Флешки]]></category><category><![CDATA[флешка]]></category><category><![CDATA[диск]]></category><category><![CDATA[загрузочный]]></category><category><![CDATA[UEFI]]></category><category><![CDATA[UEFI-BOOT]]></category><category><![CDATA[howto]]></category><category><![CDATA[как создать загрузочную флешку]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/08/1595316236_2020-07-21_130355.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/%d1%83%d0%b2%d0%b5%d0%bb%d0%b8%d1%87%d0%b8%d0%b2%d0%b0%d0%b5%d0%bc-%d0%be%d0%b7%d1%83-%d0%b1%d0%b5%d0%b7-%d1%83%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b8-%d0%b4%d0%be%d0%bf-%d0%be%d0%b1%d0%be/</link>
					<title><![CDATA[Увеличиваем ОЗУ без установки доп. оборудования]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Mon, 16 Aug 2021 07:13:33 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="420" src="https://blog.sefdar.ru/wp-content/uploads/2021/08/memory-chip-ram-microchip-107142-1024x512.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Увеличиваем ОЗУ без установки доп. оборудования</h1>
													</header>
													<p>Все мы хотим увеличить оперативную память, да вот денег на нее нет. И что делать? А есть выход &#8212; конечно это не доконца снимет вопрос о нехватки ОЗУ, но даст возможнось перебится до покупки.</p>
<p>Технология zRam ранее известная как compcache &#8212; реализована в виде модуля ядра Linux и позволяет сжимать содержимое оперативной памяти, и таким образом увеличивать ее объем в несколько раз. Работает это так: модуль zRam создает сжатое блочное устройство в оперативной памяти и используется как swap. Своп (swap) — это файл, либо раздел, т.е. определенное место на жестком диске (HDD), которое используется для «выгрузки» в него неиспользуемых страниц из оперативной памяти. В нашем же случае мы не отключаем своп с диска, а создаем еще один в ОЗУ. И устанавливаем приоритет.</p>
<p><strong>ZRam</strong> хорошо поможет тем, у кого на компьютерах установлен небольшой объем оперативной памяти и возникают проблемы с производительностью и «отзывчивостью» операционной системы.</p>
<h4><strong>Debian/Ubuntu/Linux Mint/MX linux:</strong></h4>
<p><strong>Установка zRam для Debian</strong><br />
Проверяем свап раздел перед установкой.</p>
<pre><code>swapon -s
sudo apt install zram-tools
sudo nano /etc/default/zramswap</code></pre>
<p>Редактируем, снимаем комментарии. Должно получится что-то вроде этого:</p>
<pre><code># Specifies amount of zram devices to create.
# By default, zramswap-start will use all available cores.
CORES=1
# Specifies the amount of RAM that should be used for zram
# based on a percentage the total amount of available memory
PERCENTAGE=10
# Specifies a static amount of RAM that should be used for
# the ZRAM devices, this is in MiB
ALLOCATION=256
# Specifies the priority for the swap devices, see swapon(2)
# for more details.
PRIORITY=100</code></pre>
<p>Параметр <code>CORES</code> для каждого свой. У меня одно ядро поэтому значение равно единице.</p>
<p>Создаем скрипт запуска <strong>zram</strong></p>
<pre>sudo nano /etc/init.d/zram</pre>
<p>Вставляем сам скрипт:</p>
<pre><code># Author: Antonio Galea &lt;antonio.galea@gmail.com&gt;
#
# Thanks to Przemysław Tomczyk for suggesting swapoff parallelization
# Distributed under the GPL version 3 or later, see terms at
# https://gnu.org/licenses/gpl-3.0.txt

### BEGIN INIT INFO
# Provides: zram
# Required-Start: $local_fs
# Required-Stop: $local_fs
# Default-Start: S
# Default-Stop: 0 1 6
# Short-Description: Use compressed RAM as in-memory swap
# Description: Use compressed RAM as in-memory swap
### END INIT INFO

FRACTION=75
MEMORY=$(perl -ne '/^MemTotal:\s+(\d+)/ &amp;&amp; print $1*1024' &lt; /proc/meminfo)
CPUS=$(nproc)
SIZE=$((MEMORY * FRACTION / 100 / CPUS))

case "$1" in
start)
param=$(modinfo zram | grep num_devices | cut -f2 -d: | tr -d ' ')
modprobe zram $param=$CPUS

for n in $(seq $CPUS)
do
i=$((n - 1))
echo $SIZE &gt; /sys/block/zram$i/disksize
mkswap /dev/zram$i
swapon /dev/zram$i --priority 10
done
;;
stop)
for n in $(seq $CPUS)
do
i=$((n - 1))
swapoff /dev/zram$i &amp;&amp; echo "zram: disabled disk $n of $CPUS" &amp;
done

wait
sleep .5
modprobe --remove zram
;;
*)
echo "Usage: $(basename $0) (start | stop)"
exit 1
;;
esac
# End of file</code></pre>
<p>Делаем файл исполняемым:</p>
<pre><code>sudo chmod +x /etc/init.d/zram</code></pre>
<p>Запускаем скрипт:</p>
<pre><code>sudo /etc/init.d/zram start</code></pre>
<p>Проверяем swap разделы</p>
<pre><code>swapon -s
Filename Type Size Used Priority
/dev/sda2 partition 2097148 494848 -2
/dev/zram0 partition 1505464 0 10</code></pre>
<p><strong>Установка zRam на Ubuntu:</strong></p>
<p>Для активизации zRam достаточно установить пакет <em><strong>zram-config:</strong></em></p>
<pre><code>sudo apt install zram-config</code></pre>
<p>После установки можно проверить работоспособность:</p>
<pre><code>swapon -s</code></pre>
<p>Если вы видите что-то похожее, то все нормально:</p>
<pre><code>Filename Type Size Used Priority
/dev/sda2 partition 2097148 494848 -2
/dev/zram0 partition 1505464 0 10</code></pre>
<p>Если же zRAM автоматически не запустился, то необходимо сделать следующее:</p>
<pre><code>sudo apt install linux-image-generic -y</code> <code>sudo reboot</code> <code>sudo systemctl start zram-config
sudo systemctl enable zram-config</code></pre>
<p>OpenSuse/Fedora/ROSA/ARCH/manjaro:</p>
<p>На этих дистрибутивах все давольно просто. OpenSuse:</p>
<pre><code>sudo zypper in systemd-zram-service &amp;&amp; sudo zramswapon

fedora:
</code></pre>
<pre><code>dnf install zram
systemctl enable zram-swap.service
reboot</code></pre>
<p>ROSA:</p>
<pre><code>sudo urpmi zramstart
sudo systemctl start zram.service</code></pre>
<p>ARCH</p>
<p>Простая установка и настройка с помощью ezzram из AUR</p>
<p>В AUR есть сценарий установки пакета <strong>ezzram</strong>, который представляет из себя python-скрипт с простым конфигурационным файлом и файлом сервиса для systemd. Устанавливается как обычно любым AUR-хелпером, например yay:</p>
<pre><code>yay -Sa ezzram</code></pre>
<p>После установки нужно добавить а втозапуск и запустить сервис ezzram:</p>
<pre><code>sudo systemctl enable ezzram.service 
sudo systemctl start ezzram.service</code></pre>
<p>Конфигурационный файл лежит по пути <em>/etc/ezzram.conf</em>. В нём всего три пораметра:</p>
<ul>
<li><strong>size</strong> — размер раздела zram в мегабайтах</li>
<li><strong>algorithm</strong> — алгоритм сжатия данных в zram разделе</li>
<li><strong>cores</strong> — количество используемых ядер ЦП</li>
</ul>
<p>Алгоритм сжатия по-умолчанию является оптимальным для абсолютного большинства пользователей, размер zram разумно установить в пределах 30-50% от полного объёма ОЗУ, ну а в «cores» указываем количество физических ядер своего центрального процессора. После внесения изменений сохраняем файл и активируем новую конфигурацию перезапуском сервиса:</p>
<pre><code>sudo systemctl restart ezzram.service</code></pre>
<p>И на этом все!</p>
<p>Совет: так как разделы создаются в оперативной памяти, то я не советую вам изменять параметр <strong>vm.swappines </strong>(изменяется в файле <code>/etc/sysctl.conf</code><em> </em>), который часто рекомендуют выставить в значение 10 или вообще 0.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="2">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[RAM]]></category><category><![CDATA[ОЗУ]]></category><category><![CDATA[увеличение памяти]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/08/memory-chip-ram-microchip-107142-1024x512.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/opera-%d0%b1%d1%80%d0%b0%d1%83%d0%b7%d0%b5%d1%80-%d1%87%d0%b8%d0%bd%d0%b8%d0%bc-%d0%b2%d0%b8%d0%b4%d0%b5%d0%be/</link>
					<title><![CDATA[Opera браузер чиним видео]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 15 Aug 2021 11:28:39 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
															<figure>
									<img width="840" height="395" src="https://blog.sefdar.ru/wp-content/uploads/2021/08/opera-1024x482.png" class="attachment-large size-large wp-post-image" alt="" decoding="async" loading="lazy" />								</figure>
														<h1>Opera браузер чиним видео</h1>
													</header>
													
<p>Так случилось что некоторые кодеки(Н.264) не свободны, из-за этого видео в браузере <a href="https://opera.com" target="_blank" rel="noreferrer noopener">Opera</a> не работает, да и в не которых дистрибутивах, и в других браузерах тоже. По этому предлагаю рабочее решение. Это решение лежит на <a href="https://github.com/" target="_blank" rel="noreferrer noopener">GitHub </a>, есть такой проект<a href="https://github.com/iteufel/nwjs-ffmpeg-prebuilt/releases" target="_blank" rel="noreferrer noopener">nwjs-ffmpeg-prebuilt</a>. Советую перед скачкой узнать последнею версию.</p>



<p>Для Ubuntu/LinuxMint/Debian/Deepin:</p>



<pre class="wp-block-preformatted">sudo apt install unzip
wget https://github.com/iteufel/nwjs-ffmpeg-prebuilt/releases/download/0.55.0/0.55.0-linux-x64.zip
unzip 0.55.0-linux-x64.zip
// после распаковки нужно удалить старую библиотеку и заменить новой
sudo rm /usr/lib/x86_64-linux-gnu/opera/libffmpeg.so
sudo mv libffmpeg.so /usr/lib/x86_64-linux-gnu/opera/</pre>



<p>Вот и все перед использованием советую перезагрузить браузер.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="3">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[LINUX]]></category><category><![CDATA[Linux]]></category><category><![CDATA[nix]]></category><category><![CDATA[opera]]></category><category><![CDATA[browser]]></category><category><![CDATA[bash]]></category><category><![CDATA[terminal]]></category><category><![CDATA[console]]></category><category><![CDATA[h.264]]></category><category><![CDATA[не работает видео]]></category><category><![CDATA[линукс не работает видео]]></category><category><![CDATA[видео]]></category><enclosure url="https://blog.sefdar.ru/wp-content/uploads/2021/08/opera-1024x482.png" type="image/png" />				</item>
											<item turbo="true">
					<link>https://blog.sefdar.ru/hello-world/</link>
					<title><![CDATA[Hello world!]]></title>
                    					    <author><![CDATA[devel]]></author>
                    										    <pubDate>Sun, 15 Aug 2021 10:14:03 +0000</pubDate>
										<turbo:content>
						<![CDATA[
						<header>
														<h1>Hello world!</h1>
													</header>
													
<p>Как и все программы так и я начну с приветствия)))</p>



<p>Я инженер-исследователь, программист. Занимаюсь разработкой приложений и IoT устройств.</p>
												<div data-block="share" data-network="odnoklassniki,telegram,vkontakte"></div>		<form action="https://blog.sefdar.ru/?s={text}" method="GET">
			<input type="search" name="text" placeholder="Поиск>" />
		</form>
				<div itemscope itemtype="http://schema.org/Rating">
			<meta itemprop="ratingValue" content="1">
			<meta itemprop="worstRating" content="1">
			<meta itemprop="bestRating" content="5">
		</div>
								]]>
					</turbo:content>
					<category><![CDATA[Uncategorized]]></category>				</item>
								</channel>
</rss>
