Merge pull request 'states/01' (#6) from states/01 into main
continuous-integration/drone/push Build is passing Details

Reviewed-on: #6
states/02^2
thest1tch 2 years ago
commit 065af3abac

@ -0,0 +1,3 @@
# Blogs
{{ blog_content }}

@ -0,0 +1,28 @@
# Настройка и использование консольных команд Админа в Ark Survival Evolved
Как использовать администраторские команды консоли в **Ark: Survival Evolved**? Для этого потребуется открыть консоль, нажав кнопку **TAB**.
Некоторые из этих команд будут недоступны, пока вы не выполнили аутентификацию с помощью команды **enablecheats**.
Команды, отмеченные тегом _cheat_ должны указываться с префиксом **admincheat**.
## Использование
### Первый способ
1. Выключаем сервер.
2. В конфиге сервера **GameUserSettings.ini** указываем пароль администратора переменной **ServerAdminPassword.** (Пример: _ServerAdminPassword password_).
3. Включаем сервер.
4. Заходим в игру и на сервер, открываем консоль нажатием кнопки **TAB**.
5. Авторизируемся на сервере как администратор указывая команду: **enablecheats «AdminPassword».** (Пример: enablecheats password).
### Второй способ
Добавляем игроков в белый список.
1. Выключаем сервер.
2. Создать файл **AllowedCheaterSteamIDs.txt** (_Путь: ShooterGame/Saved/AllowedCheaterSteamIDs.txt_).
3. Указать Steam ID игрока, если администраторов несколько, Steam ID нужно указывать с новой строчки.
4. Включаем сервер.
5. Авторизация на сервере командой **enablecheats «AdminPassword»** не требуется.
6. Открываем графическую админку командой **ShowMyAdminManager**.

@ -0,0 +1,9 @@
Каждый раз, когда я в интернете натыкался на фишинговый сайт, у меня был сложный квест куда писать и что делать, чтобы его закрыть. У меня, обычно это были сайты, которые притворялись игровыми. Каждый раз даже интересно, как у тебя пытаются узнать пароль.
При обнаружении такого сайта, необходимо сделать:
1. через [whois](https://whois.ru/) узнать регистратора домена и подать запрос
2. попробовать по ip определить принадлежность к хостеру и подать запрос ему.
3. подать запрос в [CERT-GIB](https://www.group-ib.ru/cert.html) и [RU-CERT](https://www.cert.ru/ru/abuse.shtml)
4. подать запросы в поисковики [Яндекс](https://yandex.ru/support/search/troubleshooting/delspam.html) и [Google](https://safebrowsing.google.com/safebrowsing/report_phish/?hl=en)

@ -0,0 +1,367 @@
# Руководство по Traefik Forward Auth Простая защита через Google SSO
![](https://st1t.ru/wp-content/uploads/2022/11/traefik-forward-auth-google-flow-840x525.png)
----------
Хотите защитить свой стек Docker чем-то более надежным, чем обычная HTTP-аутентификация? Google OAuth2 SSO с Traefik Forward Auth — ваш выбор.
Я был очень удивлен, узнав, что образ Thomseddon [Traefik Forward Auth](https://github.com/thomseddon/traefik-forward-auth) может защитить мои службы в Docker. Этот образ обеспечивает вход и аутентификацию OAuth/SSO для обратного прокси-сервера Traefik с использованием Traefik.
> Почему Traefik Google OAuth2 для служб Docker?
>
> Google OAuth2 позволяет вам использовать свою учетную запись Google для входа в свои службы. Использование **Google OAuth с Traefik** позволит вам добавлять учетные записи в белый список, внедрять двухфакторную аутентификацию Google, а также обеспечивать единый вход (SSO) для ваших служб. Это не только обеспечивает удобство, поскольку вам не нужно часто входить в систему, но и повышает безопасность.
Добавление Traefik OAuth2 для ваших служб Docker будет простым шагом и важным дополнением к вашему стеку Docker Traefik.
## НАСТРОЙКА TRAEFIK FORWARD AUTH ПРИ ПОМОЩИ GOOGLE OAUTH2
Добавление базовой аутентификации, предоставляемой Traefik, — это самый простой способ защитить ваш Docker и другие службы.
В нашем предыдущем руководстве мы рассмотрели, как использовать учетные данные для входа .htpasswd и промежуточное ПО **Traefik auth middleware** для добавления базовой аутентификации с использованием меток.
Для одной службы это может быть полезно, но это быстро становится неудобным и утомительным, когда приходится входить в несколько служб и для каждого сеанса браузера.
После внедрения **Traefik forward authentication** теперь нужно войти в систему только один раз. И внедрив _Traefik OAuth2 с Google_, можно добавить двухфакторную аутентификацию (2FA), что делает этот метод намного более безопасным и удобным, чем использование обычной аутентификации.
Если вы предпочитаете частную self-hosted систему многофакторной аутентификации (а не полагаться на Google), обратите внимание на Authelia или Keycloak. Я использовал Authelia для ранее, а сейчас перешел на Keyсloak для управления несколькими пользователями. Traefik OAuth2 я использую для домашних проектов.
> ### Что такое OAuth?
>
> **OAuth** — открытый протокол (схема) [авторизации](https://ru.wikipedia.org/wiki/%D0%90%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F "Авторизация"), обеспечивающий предоставление третьей стороне ограниченный доступ к защищённым ресурсам пользователя без передачи ей (третьей стороне) логина и пароля [ Wikipedia](https://ru.wikipedia.org/wiki/OAuth)
Прежде чем настраивать Traefik Forward Auth с Google OAuth2, давайте посмотрим, как все это сочетается друг с другом.
### Как работает Google OAuth2 с Traefik?
Вход и аутентификация Google OAuth для Traefik действует как посредник для ваших служб, разрешая или запрещая доступ после проверки авторизованного файла cookie в вашем браузере. Подводя итог, процесс выглядит примерно так:
1. Для нашего хоста сделан **запрос** (например, https://traefik.example.com)
2. Запрос направляется нашим провайдером DNS на наш IP-адрес WAN, где порты 80 и 443 перенаправляются в контейнер Traefik.
3. Traefik видит входящий запрос и распознает, что **Forward Auth** определен в **метках** для этого хоста, поэтому запрос перенаправляется в контейнер **Traefik Forward Auth**.
4. Затем контейнер проверяет, есть ли в браузере авторизованный файл cookie. Если файл cookie отсутствует, запрос отправляется на **сервер авторизации Google OAuth2**.
5. После успешного входа в Google запрос отправляется на **URI перенаправления**, указанный для **веб-приложения** (https://oauth.example.com/_oauth).
6. Затем авторизованный файл cookie сохраняется в браузере, и пользователь отправляется во внутреннюю службу.
В следующий раз, когда этот браузер попытается получить доступ к службе, защищенной входом и аутентификацией на основе OAuth, файл cookie будет распознан, и пользователь будет перенаправлен на их службу без запроса на вход!
![](https://st1t.ru/wp-content/uploads/2022/11/traefik-forward-auth-google-flow-1024x654.png)
Этот процесс происходит очень быстро, и как только ваш браузер получит файл cookie, вы забудете, что даже включили Google OAuth с Traefik!
**Примечание.** Образ Traefik Forward Auth использует [**OpenID** **Connect**](https://en.wikipedia.org/wiki/OpenID_Connect) (**OIDC**),который представляет собой уровень аутентификации поверх протокола [OAuth 2.0](https://en.wikipedia.org/wiki/OAuth#OAuth_2.0 "OAuth"). Образ Docker, представленный в этом руководстве, поддерживает Google, а также [других поставщиков OIDC](https://github.com/thomseddon/traefik-forward-auth/wiki/Provider-Setup).
Позаботившись об основах, давайте перейдем к настройке прямой аутентификации Google OAuth Traefik для наших сервисов Docker.
> ### Как настроить OAuth?
>
> Настройка Google OAuth для Docker с помощью Traefik включает в себя 3 этапа:
>
> 1. создание записей DNS,
> 2. настройку службы Google OAuth2 и
> 3. изменение файлов компоновки Docker и добавление меток Traefik для активации прямой аутентификации.
Итак, во-первых, нам нужно настроить службу Traefik OAuth2. Давайте настроим все предварительные условия сейчас:
### Шаг 1. Создайте записи DNS
Начните с создания новой DNS-записи CNAME для нашей службы OAuth (Google перенаправит на этот адрес после аутентификации). В этом руководстве мы будем использовать доменное имя **example.com**.
Установите запись DNS как **oauth.example.com**. На рисунках ниже показан скриншот из Cloudflare. В зависимости от вашего провайдера DNS, для вас все может выглядеть по-разному, но по сути иметь одно и то же содержание.
![](https://st1t.ru/wp-content/uploads/2022/11/01-clouldflare-dns-for-google-oauth-1024x367.png)
Обратите внимание, что для распространения и активации записей DNS может потребоваться несколько часов.
В качестве альтернативы, если вы включили запись CNAME с подстановочными знаками, указывающую на ваш корневой домен, вы можете пропустить этот шаг.
### Шаг 2. Настройте службу Google OAuth2
Создав записи DNS, давайте перейдем к настройке Google OAuth.
#### Шаг 2.1. Создайте проект Google.
Нам нужно создать **проект Google**, который будет содержать наше **веб-приложение**, **экран согласия** и **учетные данные**.
Перейдите в [Google Cloud Developers Console](https://console.developers.google.com/) и убедитесь, что вы вошли в правильный аккаунт Google, который хотите использовать (обычно это будет ваш адрес электронной почты).
**Примечание.** Выйдите из других активных аккаунтов Google, чтобы убедиться, что на каждом этапе используется правильный аккаунт.
При появлении запроса вам нужно будет согласиться с **Условиями использования Google Cloud Platform**, чтобы использовать их API.
Сервис OAuth от Google можно использовать бесплатно, поэтому пока мы можем **отказаться** от бесплатной пробной версии. Нажмите «**Select a project**» и «**New project**».
![](https://st1t.ru/wp-content/uploads/2022/11/02-google-cloud-oauth-create-new-project-1024x498.png)
Введите уникальное имя для идентификации проекта, например **“Traefik Authentication”**. Нажмите **Create**.
![](https://st1t.ru/wp-content/uploads/2022/11/03-google-cloud-oauth-new-project-details.png)
#### Шаг 2.2. Создайте учетные данные OAuth
Теперь, когда наш проект создан, нам нужно создать идентификатор клиента и секрет клиента, чтобы пройти аутентификацию в Google. Выберите наш проект **Traefik Authentication** и в меню навигации выберите **APIs & Services > Credentials**. Нажмите **Create Credentials > OAuth client ID**.
![](https://st1t.ru/wp-content/uploads/2022/11/04-google-cloud-oauth-create-oauth-client-id.png)
#### Шаг 2.3: Настройте Consent Screen
После того, как вы нажмете Идентификатор клиента OAuth, вы увидите примечание о настройке consent screen, как показано ниже. Перед продолжением необходимо настроить consent screen.
После того, как вы нажмете **OAuth Client ID**, вы увидите примечание о настройке consent screen, как показано ниже. Перед продолжением необходимо настроить consent screen.
![](https://st1t.ru/wp-content/uploads/2022/11/05-google-cloud-oauth-configure-consent-screen.png)
Если автоматический запрос не появится, выберите **OAuth consent screen** на левой панели.
Далее выберите тип пользователей приложения. Выбираем тип **External** и нажимаем **Create**.
![](https://st1t.ru/wp-content/uploads/2022/11/06-google-cloud-oauth-consent-screen-type.png)
Выберите имя для своего приложения, например **Traefik Auth**, затем в разделе **Authorized domains** введите свой домен, например **example.com**. Убедитесь, что вы нажимаете **Enter**, чтобы добавить его, а затем нажмите **Save**.
![](https://st1t.ru/wp-content/uploads/2022/11/07-google-cloud-oauth-consent-screen.png)
После нажатия кнопки **Save** вы перейдете на следующий шаг. Везде нажимаем снизу **Save and Continue**.
#### **Шаг 2.4. Создайте идентификатор клиента OAuth.**
Выберите наш проект **Traefik Authentication** и в меню навигации выберите **APIs & Services > Credentials**. Нажмите **Create Credentials > OAuth client ID**.
Теперь выберите тип **Web Application** и введите имя для своего веб-приложения, например, **Traefik**. Кроме того, вам потребуется ввести **Authorized redirect URI** в виде _https://oauth.example.com/_oauth_. Убедитесь, что вы нажимаете **Enter**, чтобы добавить его, а затем нажмите **Save**.
**Примечание.** Вам разрешено добавлять только **URI перенаправления**, которые ведут на ваши **авторизованные домены**. Вернитесь к экрану согласия OAuth, если вам нужно их отредактировать.
![](https://st1t.ru/wp-content/uploads/2022/11/08-oauth-authorized-redirect-uris.png)
Учетные данные для нашего единого входа для Docker созданы! Скопируйте и сохраните **client ID** и **client secret**; нам нужно будет использовать их на следующем шаге.
![](https://st1t.ru/wp-content/uploads/2022/11/09-oauth-client-id-and-secret.png)
### Шаг 3. Настройте прямую аутентификацию Traefik с помощью OAuth2
Теперь, когда учетные данные OAuth настроены, осталось настроить контейнер OAuth. Войдите на свой локальный компьютер или используйте SSH-клиен для удаленного входа.
Обязательно остановите Traefik (при необходимости) и отредактируйте файл docker-compose, добавив метки Traefik и контейнер OAuth, как описано ниже.
Предполагается, что вы уже прочитали и выполнили большую часть моего руководства по Traefik 2 и читаете этот пост только для того, чтобы внедрить Google OAuth.
#### Шаг 3.1. Создайте промежуточное ПО Traefik Auth и цепочку
Давайте теперь укажем промежуточное ПО для аутентификации Traefik для OAuth2. Создайте новый файл middlewares-oauth.yml и добавьте следующие строки:
```yaml
http:
middlewares:
middlewares-oauth:
forwardAuth:
address: "http://oauth:4181" # Make sure you have the OAuth service in docker-compose.yml
trustForwardHeader: true
authResponseHeaders:
- "X-Forwarded-User"
```
Кроме того, давайте создадим новую цепочку промежуточного программного обеспечения для сервисов, которые будут использовать Google OAuth. Откройте файл **middleware-chains.yml**, созданный в моем руководстве по Traefik, и добавьте следующие строки ниже того, что уже есть:
```yaml
http:
middlewares:
chain-oauth:
chain:
middlewares:
- middlewares-rate-limit
- middlewares-https-redirectscheme
- middlewares-secure-headers
- middlewares-oauth
- middlewares-compress
```
**Примечание:** Промежуточное ПО для ограничения скорости, перенаправления HTTPS, заголовков безопасности и сжатия должно быть определено в соответствии с моим руководством Traefik. В противном случае Traefik не запустится.
Сохраните файлы и выйдите из редактирования.
#### Шаг 3.2: Добавьте секреты прямой аутентификации Traefik
Вместо того, чтобы создавать несколько секретов, мы создадим один секретный файл для прямой аутентификации Traefik, который будет содержать все учетные данные.
Создайте файл с именем **traefik_forward_auth** в папке **secrets** ($DOCKERDIR\secrets, если ваша установка основана на моих руководствах) и добавьте в него следующее содержимое:
```
providers.google.client-id=yourGOOGLEclientID
providers.google.client-secret=yourCLIENTsecret
secret=yourOAUTHsecret
whitelist=yourEMAILaddress1
whitelist=yourEMAILaddress2
```
Настройте вышеуказанное, используя информацию ниже:
- **yourGOOGLEclientID** и **yourCLIENTsecret**: полученные ранее в этом руководстве по Traefik Oauth2.
- **yourOAUTHsecret**: используется для подписи файла cookie и должен быть случайным. Создайте случайный секрет с помощью:
`openssl rand -hex 16`
Кроме того, вы можете использовать [онлайн-сервис, подобный этому](https://www.browserling.com/tools/random-string), для создания случайного секрета.
![](https://st1t.ru/wp-content/uploads/2022/11/10-random-secret.png)
- **yourEMAILAddress1**: идентификатор электронной почты Google, который будет использоваться для аутентификации. При желании вы можете добавить дополнительные адреса электронной почты, которым разрешено проходить аутентификацию (например, **yourEMAILAddress2**; удалите эту строку, если вы хотите разрешить только один идентификатор электронной почты).
Сохранить и выйти.
Обратите внимание, что папка **secrets** и файл **traefik_forward_auth** должны иметь разрешение **600** и принадлежать пользователю **root**.
Далее давайте настроим контейнер OAuth Forwarder.
#### Шаг 3.3: Добавляем OAuth Forwarder контейнер
Откройте файл docker-compose, который был создан на основе нашего предыдущего руководства по Traefik 2, и добавьте в него следующее.
# Google OAuth - Single Sign On using OAuth 2.0
```yaml
version: '3.7'
services:
oauth:
container_name: oauth
image: thomseddon/traefik-forward-auth:latest
restart: unless-stopped
security_opt:
- no-new-privileges:true
environment:
- CONFIG=/config
- COOKIE_DOMAIN=$DOMAINNAME_CLOUD_SERVER
- INSECURE_COOKIE=false
- AUTH_HOST=oauth.$DOMAINNAME_CLOUD_SERVER
- URL_PATH=/_oauth
- LOG_LEVEL=info
- LOG_FORMAT=text
- LIFETIME=86400 # 1 day
- DEFAULT_ACTION=auth
- DEFAULT_PROVIDER=google
secrets:
- source: traefik_forward_auth
target: /config
labels:
- "traefik.enable=true"
## HTTP Routers
- "traefik.http.routers.oauth-rtr.tls=true"
- "traefik.http.routers.oauth-rtr.entrypoints=https"
- "traefik.http.routers.oauth-rtr.rule=Host(`oauth.$DOMAINNAME_CLOUD_SERVER`)"
## Middlewares
- "traefik.http.routers.oauth-rtr.middlewares=chain-oauth@file"
## HTTP Services
- "traefik.http.routers.oauth-rtr.service=oauth-svc"
- "traefik.http.services.oauth-svc.loadbalancer.server.port=4181"
```
**$DOMAINNAME_CLOUD_SERVER** = имя вашего домена в файле .env
Обратите внимание, что мы используем цепочку промежуточного программного обеспечения аутентификации Traefik (**chain-oauth**) для аутентификации вместо базовой аутентификации. Используйте правильный образ для архитектуры вашей системы.
Вы также можете изменить продолжительность (**LIFETIME**), в течение которой аутентификация действительна, с 1 дня, указанного в секундах, на другую продолжительность. Сначала установите **LOG_LEVEL** для **trace** или **debug**. Когда все заработает, вы можете изменить его на **warn**.
При желании остальные переменные среды, определенные для oauth , можно настроить по своему вкусу (если вы знаете, что делаете).
После этого используйте команду docker-compose up. Теперь вы должны быть перенаправлены на страницу входа в систему Google OAuth перед доступом к службе.
#### Шаг 3.4. Добавление Google OAuth для служб Docker
Возьмем пример панели инструментов Traefik 2. Если вы следовали моему руководству по Traefik, теперь у вас должна быть базовая аутентификация с использованием промежуточного программного обеспечения:
```
## Middlewares
- "traefik.http.routers.traefik-rtr.middlewares=middlewares-basic-auth@file"
```
Или цепочка промежуточного программного обеспечения:
```
- "traefik.http.routers.traefik-rtr.middlewares=chain-basic-auth@file"
```
Мы уже определили цепочку промежуточного программного обеспечения для Traefik oauth (**chain-oauth**) выше.
Перейти с базовой аутентификации на oauth теперь так же просто, как изменить **chain-basic-auth** на **chain-oauth** в файле **docker-compose** (показано ниже).
```
- "traefik.http.routers.traefik-rtr.middlewares=chain-oauth@file"
```
Итак, вот и все, вход и аутентификация на основе OAuth для стека обратного прокси-сервера Traefik.
После этого используйте команду **docker-compose up**.
#### Шаг 3.5. Добавление OAuth в другие (не Docker) службы
Приложениями, не относящимися к Docker, могут быть любые службы, находящиеся в хост-системе или в удаленной системе.
Поставщик файлов Traefik позволяет нам добавлять динамические маршрутизаторы, промежуточное ПО и службы. Раньше мы использовали наш каталог rules только для добавления промежуточного программного обеспечения, но мы можем легко добавить внешний хост, добавив новый файл в этот каталог. Traefik автоматически обнаружит и обновит свои конфигурации.
Давайте для примера возьмем сервис ex1, работающий на другом хосте (192.168.1.100).
Чтобы добавить к сервису возможность аутентификации Traefik OAuth2, вам нужно всего лишь создать промежуточное ПО маршрутизатора, как показано ниже.
```
http:
routers:
ex1-rtr:
rule: "Host(`ex1.{{env "DOMAINNAME_CLOUD_SERVER"}}`)"
entryPoints:
- https
middlewares:
- chain-oauth
service: ex1-svc
tls:
certResolver: dns-cloudflare
services:
ex1-svc:
loadBalancer:
servers:
- url: "http://192.168.1.100:80" # or whatever your external host's IP:port is
```
Интерфейс ex1 будет доступен по адресу **ex1.example.com**, при условии, что для переменной среды **DOMAINNAME_CLOUD_SERVER** установлено значение **example.com** и она передается в контейнер Traefik.
Поскольку каталог rules является динамическим, просто добавив этот файл в этот каталог, мы создали маршрут. Вы должны иметь возможность подключиться к ex1 через Google OAuth2 без перезапуска Traefik!
## ОБХОД OAUTH / ВЫБОРОЧНАЯ АУТЕНТИФИКАЦИЯ
Некоторые приложения не могут аутентифицировать себя и пройти через авторизацию Oauth. Для этого есть обход Oauth на основе правил [Auth Forwarder GitHub](https://github.com/thomseddon/traefik-forward-auth).
Вы можете обойти аутентификацию на основе определенных ключей в заголовках, регулярных выражениях, хосте, пути, запросе и многом другом.
**Примечание.** Используя неправильно указанное правило, вы можете легко отключить аутентификацию, когда не собираетесь этого делать. Поэтому я настоятельно рекомендую конкретные и узкие правила обхода аутентификации.
### Определение правила обхода
Как мы можем выяснить, какие конкретные правила использовать?
Это может быть довольно сложно. Как указано в приведенной ниже ссылке, общий способ обхода аутентификации — использование пути.
Но это может ослабить безопасность, и я рекомендую установить определенные правила. Например, если в заголовке запроса содержится ключ API, аутентификация будет пропущена.
Проверьте журналы Docker для контейнера OAuth (основные команды Docker). Это выдаст почти все, что происходит в этом контейнере, что может быть ошеломляющим. Вы можете сократить это до интересующего вас приложения, введя команду grep ****.
### Указание правила обхода OAuth
Обратите внимание, что **uri** в логах может содержать ключ API (X-Api-Key:[apikey]). Таким образом, вы можете установить использование обхода на основе этого следующим образом. На примере файла middleware сервиса ex1:
В строчку
```
rule: "Host(`ex1.{{env "DOMAINNAME_CLOUD_SERVER"}}`)"
```
Дописываем
```
rule: "Host(`ex1.{{env "DOMAINNAME_CLOUD_SERVER"}}`) && Headers(`X-Api-Key`, `$API_KEY`)"
```
Перезапустите контейнер OAuth и попробуйте сейчас получить доступ к ex1 через приложение и браузер. Браузер должен представить логин OAuth, а приложение должно направить вас напрямую к сервису.
### Использование пользовательских заголовков
Некоторые приложения позволяют добавлять собственные заголовки. Поэтому, когда приложение пытается связаться с вашим Radarr, Sonarr и т. д., может быть отправлен собственный заголовок.
Затем этот настраиваемый заголовок можно отслеживать и, если он присутствует, можно использовать для запуска обхода. Это альтернатива поиску ключей API. Вы можете установить один стандартный заголовок для всех приложений и использовать для всех одно и то же правило обхода. Это также устраняет догадки и пробы и ошибки, описанные выше.
## OAUTH И ЗАГОЛОВКИ БЕЗОПАСНОСТИ
Одна вещь, которую следует отметить при использовании службы **Traefik OAuth2**, — это ваши заголовки безопасности. Если служба использует **OAuth** и вы пытаетесь проверить, применяются ли ваши заголовки безопасности, вы, вероятно, получите более низкую оценку.
## FAQ
### **Что такое traefik-forward-auth-provider?**
Прямая аутентификация Traefik — это служба, которая интегрируется со сторонним поставщиком аутентификации (например, Google, Microsoft, Authelia и т. д.) для защиты ваших служб и веб-приложений.
### **В чем разница между OIDC и OAuth?**
OIDC или OpenID Connect (OIDC) — это протокол аутентификации. Это набор спецификаций, основанный на OAuth 2.0, который добавляет дополнительные функции. По сути, OIDC — это аутентичный протокол, а OAuth — набор спецификаций для доступа к ресурсам и их совместного использования.
### Существуют ли другие (более частные) альтернативы Google OAuth?
Да. [Authelia](https://github.com/authelia/authelia) и [Keycloak](https://github.com/keycloak/keycloak) два, о которых я могу вспомнить. ИМХО, Authelia была намного проще в настройке, чем Keycloak. Существует также [Authentik](https://goauthentik.io/).

@ -0,0 +1,19 @@
# Настройка бекапов в Veeam Agent
----------
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_1.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_2.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_3.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_4.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_6.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_7.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_5.png)
![](https://st1t.ru/wp-content/uploads/2023/04/veeam_agent_configure_backup_8.png)

@ -0,0 +1,38 @@
Собрал несколько настроек для docker-compose, чтобы проверять работоспособность различных баз данных
## MySQL / MariaDB
```yaml
healthcheck:
test: out=$$(mysqladmin ping -h 127.0.0.1 -P 3306 -u root --password=$$(cat $${MARIADB_ROOT_PASSWORD_FILE}) 2>&1); echo $$out | grep 'mysqld is alive' || { echo $$out; exit 1; }
interval: 1m
timeout: 10s
retries: 5
```
## Redis
```yaml
healthcheck:
test: [ 'CMD', 'redis-cli', 'ping' ]
interval: 5m
timeout: 10s
retries: 5
```
## PostgreSQL
pg_isready не очень полезно, потому что часто служба может работать, но БД недоступна.
```yaml
healthcheck:
test: [ "CMD", "psql", "-U", "postgres", "-c", "SELECT 1;" ]
interval: 1m
timeout: 10s
retries: 5
```
## Curl
Ensure you use --fail or your health check will always succeed.
```yaml
healthcheck:
test: [ "CMD", "curl", "--fail", "http://localhost" ]
interval: "60s"
timeout: "5s"
retries: 3
```

@ -0,0 +1,196 @@
# Запуск своего сервера игры Valheim
![Valheim](https://raw.githubusercontent.com/lloesche/valheim-server-docker/main/misc/Logo_valheim.png)
!!! note
Для запуска используем docker образ от [lloesche](https://github.com/lloesche). Полная информация по запуску, доступна на [Github](https://github.com/lloesche/valheim-server-docker).
Запуск сервера будем производить на Ubuntu, по ссылке выше на Github, можно найти инструкцию, как запустить на других системах.
Запустить сервер можно 2 путями: через **консоль** (базовое) или через **docker-compose**
## Требования к серверу
Без игроков сервер потребляет в среднем 3Гб RAM и 30% одного ядра CPU на процессоре Intel Xeon E5-2620 v3 (частота 2,4ГГц)
При подключении игроков, нагрузка на CPU возрастает на 15% за хаждого игрока.
| | Минимальные | Рекомендуемые |
|----------|----------|-------|
| CPU | 2 Core | 4 Core, 2.8+Ghz |
| RAM | 4 Gb | 8 Gb |
Большая тактовая частота ЦПУ лучше, чем большее количество ядер.
## Запуск через docker-compose
Я рекомендую именно этот способ
Скопируйте и вставьте следующее в консоль
```
mkdir -p $HOME/valheim-server/config $HOME/valheim-server/data
cd $HOME/valheim-server/
cat > $HOME/valheim-server/.env << EOF
SERVER_NAME=My Server
WORLD_NAME=Dedicated
SERVER_PASS=secret
SERVER_PUBLIC=true
PUID=1000
PGID=1000
UPDATE_IF_IDLE=true
UPDATE_CRON="30 5 * * *"
BEPINEX=true
EOF
```
Далее создадим сам docker-compose файл:
```
nano docker-compose.yml
```
и заполним его
```yaml
version: '3.7'
services:
valheim:
image: ghcr.io/lloesche/valheim-server:latest
container_name: valheim-server
cap_add:
- sys_nice
volumes:
- $HOME/valheim-server/config:/config
- $HOME/valheim-server/data:/opt/valheim
ports:
- "2456-2458:2456-2458/udp"
- "9001:9001/tcp"
env_file:
- $HOME/valheim-server/valheim.env
restart: always
stop_grace_period: 2m
```
Запуск через
```
docker-compose up
```
## Базовое использование (консоль)
Имя образа Docker — `ghcr.io/lloesche/valheim-server`.
Каталог монтирования конфигурации сервера `/config` в контейнере Docker.
Если у вас есть существующий мир в системе Windows, вы можете скопировать его, например:
`C:\Users\Lukas\AppData\LocalLow\IronGate\Valheim\worlds_local` в
`$HOME/valheim-server/config/worlds_local` , и запустить образ с `$HOME/valheim-server/config`томом, смонтированным `/config` внутри контейнера.
Каталог контейнера `/opt/valheim` содержит загруженный сервер. При желании его можно смонтировать в томе, чтобы не загружать сервер при каждом новом запуске.
```
$ mkdir -p $HOME/valheim-server/config/worlds_local $HOME/valheim-server/data
# copy existing world
$ docker run -d \
--name valheim-server \
--cap-add=sys_nice \
--stop-timeout 120 \
-p 2456-2457:2456-2457/udp \
-v $HOME/valheim-server/config:/config \
-v $HOME/valheim-server/data:/opt/valheim \
-e SERVER_NAME="My Server" \
-e WORLD_NAME="Neotopia" \
-e SERVER_PASS="secret" \
ghcr.io/lloesche/valheim-server
```
!!! warning
`SERVER_PASS` должен быть не менее 5 символов. Иначе `valheim_server.x86_64` откажется запускаться!
Новый запуск займет несколько минут в зависимости от скорости вашего интернет-соединения, поскольку контейнер загрузит выделенный сервер Valheim из Steam (~ 1 ГБ).
Не забудьте изменить `WORLD_NAME`, чтобы отразить название вашего мира! Для существующих миров это имя файла в `worlds_local/` папке без `.db/.fwl` расширения.
!!! note
Если вы хотите играть с друзьями через Интернет и находитесь за NAT, убедитесь, что порты UDP 2456-2457 перенаправлены на хост-контейнер.
**Кроссплей:** чтобы включить кроссплей между разными платформами, добавьте `-crossplay` в `SERVER_ARGS`:
```
-e SERVER_ARGS="-crossplay"
```
Более подробная информация находится в разделе [Как найти свой сервер](https://github.com/lloesche/valheim-server-docker#finding-your-server) .
Информацию об игре только по локальной сети см. в разделе [Избранные сервера Steam и LAN](https://github.com/lloesche/valheim-server-docker#steam-server-favorites--lan-play).
Предоставление `CAP_SYS_NICE` контейнеру не является обязательным. Это позволяет библиотеке Steam, которую использует Valheim, увеличить количество циклов процессора. Без него вы увидите сообщение `Warning: failed to set thread priority` в журнале запуска.
### Значения переменных
Я не буду описывать значения всех переменных, используемых к образе. Я опишу лишь те. что использовал на своем сервере. По [ссылке](https://github.com/lloesche/valheim-server-docker#environment-variables) можно найти другие.
!!! note
Все имена и значения переменных чувствительны к регистру!
| Name | Default | Purpose |
|----------|----------|-------|
| `SERVER_NAME` | `My Server` | Имя сервера, отображаемое в браузере серверов |
| `WORLD_NAME` | `Dedicated` | Имя мира без `.db/.fwl` |
| `SERVER_PASS` | `secret` | Пароль для входа на сервер, минимум **5 символов!** |
| `SERVER_PUBLIC` | `true` | Отображение сервера в браузере серверов (`true`) или нет (`false`) |
| `UPDATE_CRON` | `*/15 * * * *` | [Cron расписание](https://en.wikipedia.org/wiki/Cron#Overview) для проверки обновлений (отключено, если задана пустая строка или установлен `UPDATE_INTERVAL`) |
| `UPDATE_IF_IDLE` | `true` | Запуск проверки обновлений, когда на сервере пусто (`true` или `false`) |
| `BEPINEX` | `false` | Должен быть загружен мод [BepInExPack Valheim](https://valheim.thunderstore.io/package/denikson/BepInExPack_Valheim/) (конфиг в `/config/bepinex`, плагины в `/config/bepinex/plugins`). Не использовать вместе с `VALHEIM_PLUS`. |
| `PUID` | `0` | UID для запуска valheim-сервера как |
| `PGID` | `0` | GID для запуска valheim-сервера как |
### Развертывание
Создайте файл конфигурации `/etc/sysconfig/valheim-server`
```
SERVER_NAME=My Server
SERVER_PORT=2456
WORLD_NAME=Dedicated
SERVER_PASS=secret
SERVER_PUBLIC=true
```
Затем включите контейнер Docker при загрузке системы.
```
$ sudo mkdir -p /etc/valheim /opt/valheim
$ sudo curl -o /etc/systemd/system/valheim.service https://raw.githubusercontent.com/lloesche/valheim-server-docker/main/valheim.service
$ sudo systemctl daemon-reload
$ sudo systemctl enable valheim.service
$ sudo systemctl start valheim.service
```
## Обновления
По умолчанию контейнер будет проверять наличие обновлений сервера Valheim каждые 15 минут, если в данный момент к серверу не подключены игроки. Если обновление найдено, оно загружается, и сервер перезапускается. Это расписание обновлений можно изменить с помощью `UPDATE_CRON` переменной.
В перменных выше, указана чистота проверки обновлений "30 5 * * *" - это означает, что сервер будет првоерять обновления раз в сутки, в 5:30. Чтобы было проще указывать параметры cron, я советую использовать [crontab.guru](https://crontab.guru/)
## Бекап сервера, когда наигрались.
Какой бы не была эта игра прекрасной, приходит время закончить играть в нее. Я не хочу в рамках этого руководства рассказывать в чем ее проблема для долгой игры. Вы можете и сами почитать отрицательные отзывы в Steam. Скажу лишь, что у меня и 2 моих друзей сгорели жепы в последней добавленной локации Mistland. Но, мы не бросем эту игру и вернемся в нее еще.
Для того чтобы сохранить ваш сервер или перенести куда либо еще, нужно забекапить папку `$HOME/valheim-server/config`:
```
cd $HOME/valheim-server
sudo tar -czvf valheim-server.tar.gz config
```
проверить созданный архив можно командой
```
tar -ztvf valheim-server.tar.gz
```
---
## Полезности
- [Генератор карты](https://valheim-map.world/)
- Моды для сервера или клиента:
- [Nexusmods](https://www.nexusmods.com/valheim/mods/)
- [Thunderstore](https://valheim.thunderstore.io/package/)
---
[Github](https://github.com/lloesche/valheim-server-docker){ .md-button .md-button--primary }

@ -0,0 +1,30 @@
# Exception during scan .. is locked
Столкнулся с такой проблемой, в логах nextcloud стала всплывать ошибка
`Error: opendir(/mnt/downloads/): Failed to open directory: Permission denied at /var/www/html/lib/private/Files/Storage/Local.php#153`
Поиск решения проблемы, привело к запуску команды на сканирование файлов пользователей. Для Docker запускается командой:
```bash
docker exec -ti -u 33 nextcloud php -f /var/www/html/console.php files:scan --all
```
В ходе сканирования файлов пользователей, всплыла новая ошибка:
`Exception while scanning: "files/0e3e13890e7b79a0edc572f53b262079" is locked #0 /volume1/web/nextcloud/lib/private/Files/Storage/Common.php(680)`
Согласно [базе знаний Nextcloud](https://help.nextcloud.com/t/file-is-locked-how-to-unlock/1883), для её решения, нужно:
=== "Вручную отключить состояние блокировки"
- Переведите Nextcloud в режим обслуживания: отредактируйте `config/config.php`и измените эту строку:
`'maintenance' => true,`
- Пустая таблица `oc_file_locks`: используйте такие инструменты, как phpmyadmin, или подключитесь напрямую к своей базе данных и запустите (префикс таблицы по умолчанию — `oc_`, этот префикс может быть другим или даже пустым):
`DELETE FROM oc_file_locks WHERE 1`
- Отключите режим обслуживания (отменить первый шаг).
- Убедитесь, что ваши cron-jobs работают правильно (страница администратора сообщает вам, когда cron запускался в последний раз): [Docs Nextcloud](https://docs.nextcloud.org/server/13/admin_manual/configuration_server/background_jobs_configuration.html)
=== "Постоянное решение"
- На вашем **собственном сервере** : используйте Redis для этой функции. Это быстрее, и до сих пор никаких проблем не было зарегистрировано. Вы можете следовать [инструкциям по кэшированию памяти в документах](https://docs.nextcloud.org/server/13/admin_manual/configuration_server/caching_configuration.html#id4)
- **Общий хостинг** (Те, кто не может установить Redis): вы можете отключить блокировку файлов, отредактировав файл конфигурации `config/config.php`:
`'filelocking.enabled' => false,` однако отключение не является хорошим решением. Вы можете столкнуться с проблемами, когда несколько процессов пытаются записать в файл (особенно онлайн-редакторы в веб-интерфейсе). В однопользовательских и одноклиентских средах это, вероятно, не такая уж проблема.
- У меня поднят [redis](../redis.md) для кеширования с веб-мордой redis-commander, поэтому идем в веб-интерфейс и делаем flushall.
- После запускаем сканирование файлов. Проблема решена. Файлы доступны. Ошибок в логе нет.

@ -0,0 +1,63 @@
```env
PUID=
PGID=
TZ=
DOCKER_APP=
SECRETSDIR=
NEXTCLOUD_DOMAIN_NAME=
REDIS_PASSWORD=
```
docker-compose.yml
```yaml
version: "3.7"
secrets:
nextcloud_admin_password:
file: $SECRETSDIR/nextcloud_admin_password # put admin password in this file
nextcloud_admin_user:
file: $SECRETSDIR/nextcloud_admin_user # put admin username in this file
nextcloud_postgres_db:
file: $SECRETSDIR/nextcloud_postgres_db # put postgresql db name in this file
nextcloud_postgres_password:
file: $SECRETSDIR/nextcloud_postgres_password # put postgresql password in this file
nextcloud_postgres_user:
file: $SECRETSDIR/nextcloud_postgres_user # put postgresql username in this file
services:
# Nextcloud Docker Application
nextcloud:
image: nextcloud:25.0.4
container_name: nextcloud
restart: always
volumes:
- $DOCKER_APP/nextcloud:/var/www/html
- $DOCKER_APP/nextcloud/apps:/var/www/html/custom_apps
- $DOCKER_APP/nextcloud/config:/var/www/html/config
- /mnt/NAS/Nextcloud:/var/www/html/data
- /mnt:/mnt
environment:
- POSTGRES_HOST=192.168.1.12
- POSTGRES_DB_FILE=/run/secrets/nextcloud_postgres_db
- POSTGRES_USER_FILE=/run/secrets/nextcloud_postgres_user
- POSTGRES_PASSWORD_FILE=/run/secrets/nextcloud_postgres_password
- NEXTCLOUD_ADMIN_PASSWORD_FILE=/run/secrets/nextcloud_admin_password
- NEXTCLOUD_ADMIN_USER_FILE=/run/secrets/nextcloud_admin_user
- REDIS_HOST=172.18.3.249
- REDIS_HOST_PASSWORD=$REDIS_PASSWORD
- PUID=$PUID
- PGID=$PGID
- TZ=$TZ
- NEXTCLOUD_TRUSTED_DOMAIN=$NEXTCLOUD_DOMAIN_NAME
- TRUSTED_PROXIES=172.18.0.253
- OVERWRITEPROTOCOL=https
secrets:
- nextcloud_admin_password
- nextcloud_admin_user
- nextcloud_postgres_db
- nextcloud_postgres_password
- nextcloud_postgres_user
labels:
- com.centurylinklabs.watchtower.enable=False
```

@ -0,0 +1,16 @@
# Module php-imagick in this instance has no SVG support
При использовании официального Nextcloud образа Docker вы увидите сообщение вроде:
![](../images/docker/nextcloud-docker-php-imagick.png)
Чтобы исправить это предупреждение в docker нужно установить пакет `libmagickcore-6.q16-6-extra`:
```bash
docker exec nextcloud apt -y update
docker exec nextcloud apt -y install libmagickcore-6.q16-6-extra
```
После этого предупреждение пропало.
Если мы создадим контейнер заново, это изменение будет потеряно. На мой взгляд, здесь лучше выбрать простое решение и делать это каждый раз при обновлении образа, в отличие от постоянной, но гораздо более трудоемкой процедуры. Такой, как обновление docker-контейнера и возврата к официальному образу.

@ -137,4 +137,50 @@ trakt:
refresh_token:
scope: public
created_at:
```
Для сериалов:
```yaml
Сериалы:
metadata_path:
- file: config/TV-Shows/Collections.yml
- folder: config/TV-Shows/Metadata/Anime
- folder: config/TV-Shows/Metadata/TV
- pmm: basic
- pmm: imdb
overlay_path:
- remove_overlays: false
- reapply_overlay: false
- pmm: ratings
template_variables:
rating1: critic
rating1_image: imdb
rating2: audience
rating2_image: trakt
rating3: user
rating3_image: tmdb
horizontal_position: right
- pmm: resolution
template_variables:
overlay_level: season
- pmm: resolution
template_variables:
overlay_level: episode
- pmm: ratings # 3, 4
template_variables:
rating1: audience
rating1_image: trakt
horizontal_position: right # the set of ratings is on the right of the poster
overlay_level: episode
- pmm: status
template_variables:
font_size: 75
#font: config/fonts/Juventus-Fans-Bold.ttf
back_color: "#262626" # darker
back_width: 1920
back_height: 125
horizontal_align: center
vertical_align: top
vertical_offset: 0
```

@ -0,0 +1,71 @@
Сервис добавляет двустороннюю сихронизацию между trakt.tv и Plex Media Server. Для этого требуется учетная запись trakt.tv, но без премиум-подписки Plex или VIP-подписки Trakt, в отличие от приложения Plex, предоставляемого Trakt.
## Функции
- Медиа из Plex добавлено в коллекцию Trakt
- Сихронизация рейтингов
- Сихронизация статуса просмотра (даты не синхронизируются от Trakt до Plex)
- Списки понравившегося в Trakt загружаются, все фильмы в Plex, принадлежащие к этому списку, объединяются в коллекцию
- Сихронизация списков налюдения
- Можно отредактировать файл конфигурации, чтобы выбрать, что синхронизировать
Ни одно из вышеперечисленных действий не требует членства в Plex Pass или Trakt VIP. Недостаток: необходимо выполнять вручную или через cronjob, нельзя использовать оперативные данные через веб-хуки.
## Установка через docker-compose
```yaml
version: "3.7"
services:
plextraktsync:
image: ghcr.io/taxel/plextraktsync
container_name: plextraktsync
restart: on-failure:2
volumes:
- ./config:/app/config
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Yekaterinburg
command: sync
```
Запустить синхронизацию: `docker-compose run --rm plextraktsync sync`
Для запуска автоматически по расписанию можно использовать crontab или sheduler:
=== "Crontab"
```
$ crontab -e
0 */2 * * * $HOME/.local/bin/plextraktsync sync
```
=== "Sheduler"
```yaml
version: '2'
services:
scheduler:
image: mcuadros/ofelia:latest
container_name: scheduler
depends_on:
- plextraktsync
command: daemon --docker
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
labels:
ofelia.job-run.plextraktsync.schedule: "@every 6h"
ofelia.job-run.plextraktsync.container: "plextraktsync"
```
## Настройки
Если будет ошибка, что не найден сервер Plex, то надо в ручную прописать сервер в файле `servers.yml`:
```yaml
servers:
default:
token: token
urls:
- http://plex:32400
```
[Github](https://github.com/Taxel/PlexTraktSync){ .md-button .md-button--primary }

@ -0,0 +1,450 @@
# Защита хоста Docker
Первая категория охватывает все, что вы можете сделать для защиты вашего хоста докеров.
## 1. Поддерживайте актуальность Docker Host
Здесь действительно не нужно никаких объяснений. Это самая простая из лучших практик безопасности Docker, и она буквально занимает секунды.
Держите свою хост-систему Docker в курсе обновлений безопасности. В моем стеке Docker Traefik на базе Linux я часто обновляю пакеты и обновляю систему, используя следующие команды:
```bash
sudo apt-get update
sudo apt-get upgrade
```
## 2. Используйте обратный прокси
Лучший способ — не открывать какие-либо порты для Интернета, а вместо этого использовать VPN в вашей частной сети и получать локальный доступ к приложениям. Но это слишком громоздко, и размещение приложений за обратным прокси-сервером — удобная, но худшая альтернатива.
Вам нужно будет настроить переадресацию портов на вашем интернет-шлюзе, чтобы перенаправить определенные порты на хост Docker.
Я настоятельно рекомендую не выставлять все приложения Docker в Интернет. Вместо этого поместите их за обратным прокси. Я использую Traefik и выставляю в Интернет только порты **80** и **443**. Даже приборная панель traefik, использующая порт **8080**, находится за обратным прокси-сервером.
# Защита Докера
Следующая большая категория: Docker. Давайте рассмотрим, как я считаю, контрольный список безопасности Docker , чтобы убедиться, что ваша установка защищена.
## 3. Не меняйте владельца сокета Docker
Не связывайтесь с владением Docker Socket (`/var/run/docker.sock` в Linux). По умолчанию сокет принадлежит пользователю **root** и группе **docker** .
Для удобства я рекомендовал добавить себя (ваше имя пользователя) в группу докеров в прошлом.
Преимущество заключается в том, что вы можете запускать команды docker без использования sudo. Но это угроза безопасности. Я отошел от него и не рекомендую.
## 4. Не запускайте контейнеры Docker от имени root
По умолчанию контейнеры запускаются от имени пользователя root внутри контейнера, что дает привилегии root. Это угроза безопасности.
Одна из лучших практик безопасности Docker — запускать контейнер от имени пользователя без полномочий root (UID не 0). Известные и надежные образы используют эту передовую практику безопасности при создании образов. Например, LinuxServer.io предоставляет образы докеров для нескольких приложений домашнего сервера. Их образы позволяют явно указать UID и GID в качестве переменных окружения.
В идеале, это должно выглядеть так, как показано в блоке кода ниже.
```yaml
environment:
- PUID=$PUID
- PGID=$PGID
```
## 5. Осторожно используйте привилегированный режим
По умолчанию контейнеры Docker работают в «непривилегированном» режиме. Это означает, что эти контейнеры не могут запускать демон Docker внутри себя. Это также запрещает использование хост-устройств или определенных функций ядра.
Обычно это делается путем добавления следующей строки в services:
```yaml
privileged: true
```
Для некоторых служб требуется привилегированный режим. Например, только четыре службы в моем файле компоновки Docker используют привилегированный режим:
1. Home Assistant — для доступа к USB-контроллеру Z-wave.
2. Socket Proxy — требование для Socket proxy, повышающее безопасность.
3. Glances для мониторинга системы
4. APCUPSD — для связи демона ИБП APC с ИБП через USB.
В таких ситуациях используйте образы докеров только из надежных источников (подробнее об этом позже). Еще лучший подход — использовать возможности докеров .
Кроме того, добавление следующей строки гарантирует, что контейнеры не получат дополнительных привилегий:
```yaml
security_opt:
- no-new-privileges:true
```
## 6. Используйте доверенные образы Docker
По возможности всегда используйте изображения от проверенных издателей или официальных источников.
Это дает немедленное доверие и обеспечивает безопасность контейнера Docker.
С непопулярными образами трудно предсказать или предположить, были ли соблюдены/реализованы передовые методы безопасности Docker.
!!! note
К сожалению, для многих приложений для домашних серверов, таких как Sonarr, Radarr и т. д., нет «официальных» или «проверенных» издателей. Поэтому вам придется ориентироваться на популярность изображения (количество загрузок/звезд).
## 7. Используйте секреты Docker
Указание всей вашей конфиденциальной информации (например, ключей API) в файле `.env`, `/etc/environment` или файле `docker-compose.yml` может представлять угрозу безопасности.
Именно поэтому были введены [секреты Docker](https://www.docker.com/blog/docker-secrets-management/): для управления конфиденциальными данными.
Реализация секретов Docker для вашего стека — это многоэтапный процесс.
### А. Создать папку секретов
Сначала создайте папку secrets внутри корневой папки docker .
```bash
sudo mkdir secrets
```
Установите для этой папки права доступа 600 , принадлежащие пользователю root и группе root .
```bash
sudo chown root:root ~/docker/secrets
sudo chmod 600 ~/docker/secrets
```
Это делает эту папку доступной только для пользователя *root*, добавляя уровень безопасности при доступе к конфиденциальной информации.
### B. Создайте секретные файлы
Затем вам нужно будет поместить вашу конфиденциальную информацию в файл. В качестве примера давайте определим секрет для электронной почты учетной записи Cloudflare.
Давайте создадим файл внутри папки секретов с именем **cloudflare_email** . Помните, что для создания файла вам потребуются root-права. В моей системе Ubuntu я использую:
```bash
sudo su
nano cloudflare_email
```
Вы можете использовать любой другой текстовый редактор.
Единственное, что нужно добавить в файл, — это адрес электронной почты вашей учетной записи Cloudflare.
Сохранить и выйти.
### C. Определите секреты в файле Docker Compose
Теперь, когда секрет Docker создан, давайте определим его в файле компоновки Docker. Делается это с помощью блока: secrets.
В приведенном ниже примере показаны два секрета: `cloudflare_email` и `cloudflare_api_key`.
```yaml
########################### SECRETS
secrets:
cloudflare_email:
file: $SECRETSDIR/cloudflare_email
cloudflare_api_key:
file: $SECRETSDIR/cloudflare_api_key
```
`$SECRETSDIR` — это переменная окружения, содержащая путь к папке секретов Docker.
### D. Используйте секреты в службах Docker
После глобального определения мы можем использовать секреты в сниппетах docker-compose для отдельных сервисов. Поскольку мы добавили данные учетной записи Cloudflare в качестве секретов Docker, давайте посмотрим, как их использовать во фрагменте кода docker-compose для Traefik.
Во-первых, мы должны сделать секреты доступными внутри контейнера Traefik. Для этого вам нужно добавить следующий блок в сниппет docker-compose для Traefik:
```yaml
secrets:
- cloudflare_email
- cloudflare_api_key
```
Это делает секретный файл доступным в папке `/run/secrets` внутри контейнера.
Затем мы можем установить переменные среды для чтения конфиденциальных данных из этих секретных файлов с помощью блока `environment:` как показано ниже:
```yaml
environment:
- CF_API_EMAIL_FILE=/run/secrets/cloudflare_email
- CF_API_KEY_FILE=/run/secrets/cloudflare_api_key
```
Обратите внимание, что к переменным окружения теперь добавляется **_FILE** в конце. Не пропустите это, иначе это не сработает.
Сохраните и заново создайте службу и проверьте журналы на наличие ошибок. Если контейнер не сможет правильно прочитать секреты, вы увидите это как ошибку в журналах.
!!! note
Чтобы секреты Docker работали правильно, базовый образ контейнера должен их поддерживать. Если образ имеет репутацию/надежный образ, очень высока вероятность того, что разработчики внедрили передовые методы обеспечения безопасности Docker , включая секреты Docker.
## 8. Используйте прокси-сервер Docker Socket
Каждый раз, когда вы предоставляете сокет Docker службе, вы упрощаете для контейнера получение root-доступа в хост-системе.
Но некоторым приложениям требуется доступ к сокету Docker и API (например, Traefik, Glances, Dozzle, Watchtower и т. д.).
Если Traefik будет скомпрометирован, ваша хост-система может быть скомпрометирована. Собственная документация Traefik перечисляет использование Socket Proxy в качестве решения.
Прокси-сервер сокета похож на брандмауэр для сокета/API докера. Вы можете разрешить или запретить доступ к определенному API.
Я начал с [Socket Proxy от Tecnativa](https://hub.docker.com/r/tecnativa/docker-socket-proxy), но недавно перешел на [Socket Proxy от FluenceLab](https://hub.docker.com/r/fluencelabs/docker-socket-proxy), так как он обеспечивает более детальный контроль .
Добавьте сеть в свой файл compose (игнорируйте первую строку, если у вас уже есть блок network:):
```yaml
networks:
socket_proxy:
name: socket_proxy
driver: bridge
ipam:
config:
- subnet: 192.168.91.0/24
```
И, наконец, вот фрагмент кода docker-compose для добавления прокси-сервера сокета для повышения безопасности докера:
```yaml
# Docker Socket Proxy - Security Enchanced Proxy for Docker Socket
socket-proxy:
container_name: socket-proxy
image: tecnativa/docker-socket-proxy
restart: always
networks:
socket_proxy:
ipv4_address: 192.168.91.254 # You can specify a static IP
# privileged: true # true for VM. False for unprivileged LXC container.
ports:
- "127.0.0.1:2375:2375" # Port 2375 should only ever get exposed to the internal network. When possible use this line.
# I use the next line instead, as I want portainer to manage multiple docker endpoints within my home network.
# - "2375:2375"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock"
environment:
- LOG_LEVEL=info # debug,info,notice,warning,err,crit,alert,emerg
## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.).
# 0 to revoke access.
# 1 to grant access.
## Granted by Default
- EVENTS=1
- PING=1
- VERSION=1
## Revoked by Default
# Security critical
- AUTH=0
- SECRETS=0
- POST=1 # Watchtower
# Not always needed
- BUILD=0
- COMMIT=0
- CONFIGS=0
- CONTAINERS=1 # Traefik, portainer, etc.
- DISTRIBUTION=0
- EXEC=0
- IMAGES=1 # Portainer
- INFO=1 # Portainer
- NETWORKS=1 # Portainer
- NODES=0
- PLUGINS=0
- SERVICES=1 # Portainer
- SESSION=0
- SWARM=0
- SYSTEM=0
- TASKS=1 # Portainer
- VOLUMES=1 # Portainer
```
!!! warning "Внимание"
никогда не открывайте порт 2375 для доступа в Интернет. Вас взломают/ Это еще более важно для виртуальных частных серверов, которые обычно предоставляют доступ ко всем портам. Включите брандмауэр, чтобы разрешить только порты 80 и 443 (и заблокировать остальные) для прохождения на ваш сервер, а также реализовать обходной путь Docker IP Tables, описанный далее в этом руководстве.
!!! note
Кроме того, порт `2375` должен быть открыт только для внутренней сети (*127.0.0.1:2375*).
В блоке **environment:** указываем раздел Docker API, который хотим открыть или закрыть. Я добавил комментарии, чтобы описать, какие службы требуют каких разделов API. Например, если вы не используете WatchTower, вы можете ввести **0** для нескольких разделов API.
После запуска контейнера прокси-сервера Socket вы можете заменить прямой доступ к сокету Docker прокси-сервером Socket для всех служб, которые в нем нуждаются. Это можно сделать несколькими способами, в зависимости от того, как это поддерживает образ контейнера.
Для Traefik замените следующий аргумент CLI (если вы используете аргументы CLI вместо статических конфигураций):
`- --providers.docker.endpoint=unix:///var/run/docker.sock`
на
`- --providers.docker.endpoint=tcp://socket-proxy:2375`
Для других служб вы можете удалить указание Docker Socket в качестве тома (следующая строка под томами: ):
`- /var/run/docker.sock:/var/run/docker.sock:ro`
и добавьте переменную окружения DOCKER_HOST , как показано ниже:
`DOCKER_HOST: tcp://socket-proxy:2375`
Это то, что я делаю для Portainer и WatchTower.
Воссоздайте свой стек, и ваши службы должны использовать защищенный прокси-сервер сокета Docker вместо сокета Docker.
## 9. Измените DOCKER_OPTS на Respect IP Table Firewall
Случайно наткнулся на эту тему. Я включил UFW, как всегда делаю на своем VPS Digital Ocean, и заблокировал все, кроме 80 и 443. Я непреднамеренно попытался получить доступ к одной из служб, используя номер порта, и был шокирован тем, что я был подключен.
Покопавшись дальше, я наткнулся на этот открытый вопрос на GitHub . Почему это было открыто больше года, несмотря на огромное количество людей, запрашивающих исправление, мне не понятно.
Поэтому, если у вас включен прокси-сервер сокета и включен брандмауэр, из-за недостатка безопасности в докере хакеры все равно могут взломать вашу систему, используя порт прокси-сервера сокета (2375).
К счастью, есть обходной путь. В системах на базе Ubuntu/Debian отредактируйте **/etc/default/docker** и добавьте следующую строку:
`DOCKER_OPTS="--iptables=false"`
Сохраните файл и перезапустите службу Docker.
Попробуйте подтвердить исправление, обратившись к одной из ваших служб с помощью WAN-IP:PORT.
## 10. Контролируйте использование ресурсов Docker
Мне понравилось, что я могу устанавливать ресурсы для сервисов Docker. К сожалению, это возможно только с [Docker-Compose версии 2](https://docs.docker.com/compose/compose-file/compose-file-v2/#cpu-and-other-resources) или режимом Docker Swarm.
Если вы используете любой из них, вы можете установить [ограничения ресурсов для служб Docker](https://docs.docker.com/config/containers/resource_constraints/) .
Вот пример docker-compose для установки ограничений ресурсов в режиме Docker Swarm:
```yaml
deploy:
resources:
limits:
cpus: '0.50'
memory: 50M
reservations:
cpus: '0.25'
memory: 20M
```
Установив ограничения ресурсов, вы можете ограничить любую службу, которая становится мошеннической и потребляет ваши системные ресурсы.
**Защита приложений Docker с помощью Traefik**
Есть вещи, которые можно сделать на стороне Traefik, чтобы защитить ваш стек от вредоносных атак. Давайте рассмотрим некоторые меры безопасности Traefik, которые можно реализовать.
## 11. Ограничение скорости
Ограничение скорости довольно распространено для смягчения атак методом грубой силы или отказа в обслуживании. В моем стеке Traefik Docker есть промежуточное ПО для определения ограничения скорости .
```yaml
middlewares-rate-limit:
rateLimit:
average: 100
burst: 50
```
Приведенный выше общий набор чисел отлично работает для меня. Его можно настроить в соответствии с вашей ситуацией, используя документацию Traefik по ограничению скорости .
## 12. Заголовки безопасности Traefik
Заголовки безопасности — это основные требования к безопасности веб-сайта. Они защищают от различных атак, включая XSS, кликджекинг, внедрение кода и многое другое.
Вот заголовки безопасности Traefik, которые я определил как промежуточное ПО:
```yaml
middlewares-secure-headers:
headers:
accessControlAllowMethods:
- GET
- OPTIONS
- PUT
accessControlMaxAge: 100
hostsProxyHeaders:
- "X-Forwarded-Host"
sslRedirect: true
stsSeconds: 63072000
stsIncludeSubdomains: true
stsPreload: true
forceSTSHeader: true
# frameDeny: true #overwritten by customFrameOptionsValue
customFrameOptionsValue: "allow-from https:example.com" #CSP takes care of this but may be needed for organizr.
contentTypeNosniff: true
browserXssFilter: true
# sslForceHost: true # add sslHost to all of the services
# sslHost: "example.com"
referrerPolicy: "same-origin"
# Setting contentSecurityPolicy is more secure but it can break things. Proper auth will reduce the risk.
# the below line also breaks some apps due to 'none' - sonarr, radarr, etc.
# contentSecurityPolicy: "frame-ancestors '*.example.com:*';object-src 'none';script-src 'none';"
featurePolicy: "camera 'none'; geolocation 'none'; microphone 'none'; payment 'none'; usb 'none'; vr 'none';"
customResponseHeaders:
X-Robots-Tag: "none,noarchive,nosnippet,notranslate,noimageindex,"
server: ""
```
В Traefik была ошибка, из-за которой нельзя было определить заголовки безопасности как в динамической, так и в статической конфигурации. Это с тех пор было закрыто.
Так что теперь можно добавить **sslForceHost** и **sslHost** к отдельным службам, если хотите, для дополнительной безопасности.
## 13. Параметры TLS
Параметры TLS позволяют настраивать соединения TLS для защиты соединения между клиентом и вашей службой. Дополнительные пояснения можно найти в [документации TLS от Traefik](https://doc.traefik.io/traefik/https/tls/).
В моей настройке я определил следующие параметры TLS для Traefik:
```yaml
tls:
options:
default:
minVersion: VersionTLS12
sniStrict: true
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305
- TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305
- TLS_AES_128_GCM_SHA256
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
curvePreferences:
- CurveP521
- CurveP384
```
## 14. Многофакторная аутентификация
Это становится все более и более очевидным / обязательным. Если вы еще не защитили свои приложения Docker с помощью многофакторной аутентификации, сделайте это прямо сейчас. Я тестировал и использовал три системы аутентификации: Google OAuth, Authelia и Keycloak.
## 15. Защитите контейнеры Docker с помощью Cloudflare
Вот краткое изложение ключевых настроек Cloudflare для повышения безопасности контейнеров Docker при подключении к Интернету.
- **Cloudflare Proxy** — позволяет использовать улучшения безопасности и производительности Cloudflare.
- **Режим SSL** — полный или строгий. Это шифрует соединение между исходным сервером и Cloudflare и между Cloudflare и клиентом.
- **Пограничные сертификаты**:
- **Всегда использовать HTTPS**: ВКЛ.
- **HTTP Strict Transport Security (HSTS)**: Включить (будьте осторожны)
- **Минимальная версия TLS**: 1.2
- **Оппортунистическое шифрование**: ВКЛ.
- **TLS 1.3**: ВКЛ.
- **Автоматическая перезапись HTTPS**: ВКЛ.
- **Мониторинг прозрачности сертификата**: ВКЛ.
- Правила брандмауэра. Создайте правила для разрешения или запрета определенного трафика (например, я разрешаю трафик только из РФ в мои частные приложения, так как я получаю к нему доступ только из РФ).
- **Настройки брандмауэра**:
- **Уровень безопасности**: Высокий
- **Режим боя с ботом**: ВКЛ.
- **Прохождение испытания**: 30 минут
- **Проверка целостности браузера**: ВКЛ.
Это настройки Cloudflare, связанные с безопасностью Docker.
**Другие улучшения безопасности для стека Docker Traefik**
Все вышеперечисленные рекомендации по безопасности докеров — это то, что я реализовал до сих пор. Но есть и другие, и я настоятельно рекомендую изучить следующее для дополнительной безопасности.
## 16. Fail2ban
Fail2ban сканирует ваши лог-файлы и блокирует IP-адреса, которые показывают злонамеренные намерения (например, поиск эксплойтов, неудачных паролей и т. д.). При обнаружении подозрительной активности он обновляет правила брандмауэра, чтобы заблокировать IP-адрес на указанный период времени.
## 17. Безопасность Docker Bench
Docker Bench for Security — это скрипт, который проверяет десятки распространенных передовых методов развертывания контейнеров Docker в рабочей среде .
## 18. RBAC
RBAC — это управление доступом на основе ролей. Если вы представляете предприятие или имеете несколько пользователей, это обязательно. Это может быть довольно дорого реализовать, но [portainer делает это очень простым](https://www.funkypenguin.co.nz/note/docker-rbac-with-portainer/) (поскольку кулинарная книга FunkyPenguin потрясающая … проверьте ее, если вы этого не сделали) за символическую плату.
## 19. Сканер уязвимостей контейнеров
Последним в списке лучших практик для безопасности докеров является сканер уязвимостей. Здесь есть несколько примеров, но я перечислю только один: Clair.
Clair — проект с открытым исходным кодом для статического анализа уязвимостей в контейнерах приложений.
Он использует Clair API для индексации образов контейнеров, а затем сопоставляет их с известными уязвимостями безопасности Docker.

@ -0,0 +1,376 @@
Traefik — это обратный прокси-сервер с открытым исходным кодом, обеспечивающий простую работу с микросервисами и/или просто контейнерами с вашими приложениями.
Обратный прокси-сервер (reverse proxy, реверс-прокси) служит для ретрансляции запросов из внешней сети к каким-либо серверам/сервисам внутренней сети (например веб-сервера, БД или файловые хранилища) и позволяет:
- обеспечить сокрытие структуры внутренней сети и подробностей о находящейся в ней сервисах;
- осуществлять балансировку нагрузки (load balancing) между экземплярами одного и того же сервиса или серверами с одинаковыми задачами;
- обеспечить зашифрованное (HTTPS) соединение между клиентом и любым сервисом, в таком случае SSL сессия создается между клиентом и прокси, а между прокси и сервисом во внутренней сети устанавливается незашифрованное HTTP соединение, если сервис поддерживает HTTPS то можно организовать зашифрованное соединение и во внутренней сети;
- организовать контроль доступа к сервисам (аутентификацию клиента), а также установить файрвол (брандмауэр).
В статье будет описываться использование Traefik в Docker в качестве реверс-прокси для других контейнеров Docker, а также не контейнеризированных сервисов.
## Введение
Traefik позиционируется разработчиками как “Edge Router”, то есть можно направить его непосредственно в глобальную сеть одной стороной и во внутреннюю другой. Если у читателя создалось впечатление что таким образом создается единая точка отказа всей системы, то так и есть, но есть несколько моментов:
- во-первых, **Traefik** имеет развитый функционал для автоматического восстановления при сбоях;
- во-вторых, существует **Traefik EE** — платная версия, в которой помимо прочих преимуществ имеется HA (Hight Availability, Высокая доступность), что подразумевает распределение нагрузки между несколькими экземплярами сервиса (узлами), таким образом при отказе одного его задачи перераспределяются на другие узлы, а отказавший узел отключается и затем немедленно вводится обратно в эксплуатацию.
> В качестве примечания отметим, что в статье будет рассматриваться бесплатная версия Traefik.
Одним из основных достоинств Traefik является возможность изменения его конфигурации без приостановки работы (“на лету”) при применении любого из поддерживаемых бэкэндов, называемых провайдерами.
Список основных провайдеров:
- Docker
- Kubernetes
- Consul Catalog
- Marathon
- Rancher
- File
В рамках этой статьи будут рассмотрены первый и последний провайдеры из этого списка.
Вероятно, не знакомому с темой читателю будет не понятно, чем является провайдер с именем — “File”, это некоторый файл (или папка с файлами), в котором описана конфигурация какого-либо сервиса, не связанного с другими провайдерами, но который должен быть скрыт за реверс-прокси. Остальные же провайдеры являются различными системами оркестрации контейнеров.
Файл конфигурации Traefik, а также файлы для провайдера “File” могут быть написаны на TOML либо YAML, в статье будут приведены примеры на YAML так как этот синтаксис больше нравится автору, а какой-либо функциональной разницы между ними нет, а также не составляет трудности переписать файлы на другой формат конфигурации. Traefik будет развернут в Docker. Для развертывания будет использоваться docker-compose, для обеспечения простоты повторного развертывания.
> В статье будут приведены команды для ОС Linux.
## Деплой Traefik
Предполагается что у читателя установлены и настроены `docker` и `docker-compose`, их установка выходит за рамки этой статьи.
Создадим в домашней папке пользователя папку `traefik`, в которой будем хранить всю конфигурацию, и перейдем в эту папку
```bash
mkdir ~/traefik
cd ~/traefik
```
Для развертывания (деплоя) Traefik создадим файл `docker-compose.yml` и отредактируем его в любом удобном вам редакторе. Для начала этот файл будет иметь следующий вид:
```yaml
version: '3.9'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
```
Во внешний мир будут смотреть порты 80 и 443 для HTTP и HTTPS соответственно. Также пробросим в контейнер сокет демона Docker для работы механизма автоматической конфигурации. Конфигурацию Traefik будем описывать в файле `traefik.yml` находящемся в папке `data` в текущей директории.
> Если для разделения внешней и внутренней сетей используются networks Docker-а, то Traefik должен иметь доступ к внешней сети и ко всем внутренним в которых находятся целевые сервисы.
Создадим и будем постепенно наполнять этот файл.
Для начала опишем точки входа в наш прокси (те самые порты, которые смотрят во внешний мир):
```yaml
entryPoints:
http:
address: ":80"
https:
address: ":443"
```
Здесь `http` и `https` это просто названия (могут быть любыми, хоть `a` и `b`) и были выбраны так для удобства.
Теперь добавим первого провайдера — Docker, это делается следующим образом:
```yaml
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
```
Параметром указываем что Traefik не должен брать все контейнеры подряд, далее будет объяснено каким образом мы будем сообщать какие контейнеры нас интересуют. Также здесь видно зачем мы пробрасывали сокет в контейнер — именно через него Traefik будет получать сведения о запускаемых контейнерах на этом хосте (можно подключиться и к демону на другом хосте).
Следующим шагом развернем весь HTTP трафик в HTTPS (почему это было сделано именно таким образом будет описано дальше):
```yaml
http:
routers:
http-catchall:
rule: HostRegexp(`{host:.+}`)
entrypoints:
- http
middlewares:
- redirect-to-https
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
permanent: false
```
Traefik может проксировать не только HTTP трафик, но и просто TCP и UDP, поэтому указываем что этот блок конфигурации относится к `http`.
Здесь мы встречаем два из трех основных элементов роутинга в Traefik 2 routers (роутеры) и middlewares(промежуточные обработчики), рассмотрим их подробнее.
### Routers (роутеры)
Рассмотрим на примере описанного выше роутера:
- `http-catchall` — имя роутера, может быть любым, но обязано быть уникальным в рамках блока `http` всей конфигурации Traefik;
- `rule:` — правило, описывает какой трафик попадает в этот роутер, в данном случае описывается `HostRegexp`, то есть поле `Host` запроса должно попадать под регулярное выражение `.+` (то есть любое), здесь мы видим специфику регулярных выражений в Traefik — оно должно быть заключено в фигурные скобки и иметь наименование (`host` в данном случае), то есть синтаксис имеем вид `{name:reg_exp}`;
- `entrypoints` — массив описанных ранее точек входа, которые будут использоваться этим роутером, в нашем случае используем только `http`;
- `middlewares` — массив промежуточных обработчиков, куда попадает трафик перед передачей к сервису (сервисы будут рассмотрены позднее).
Подробнее о различных видах правил можно прочитать в [документации](https://docs.traefik.io/routing/routers/#rule).
### Middlewares(промежуточные обработчики)
- `redirect-to-https` — имя обработчика, может быть любым, но обязано быть уникальным в рамках блока `http` всей конфигурации Traefik;
- `redirectScheme` — тип обработчика, в данном случае изменение схемы запроса;
- `scheme: https` — вынуждает клиента использовать схему HTTPS при запросе к прокси;
- `permanent: false` — говорит клиенту что это не навсегда и может измениться в будущем.
Подробнее о различных обработчиках можно прочитать в [документации](https://docs.traefik.io/middlewares/overview/) (дальше в статье будет описан ещё один обработчик — BasicAuth).
??? note "Полностью файл traefik.yml"
```yaml
entryPoints:
http:
address: ":80"
https:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
http:
routers:
http-catchall:
rule: HostRegexp(`{host:.+}`)
entrypoints:
- http
middlewares:
- redirect-to-https
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
permanent: false
```
Таким образом мы получим первую рабочую конфигурацию. Выполняем
```bash
sudo docker-compose up -d
```
И прокси должен подняться, можно почитать логи (`sudo docker-compose logs -f`) и убедиться, что всё работает.
## Lets Encrypt
Поскольку мы хотим использовать HTTPS нам нужно где-то взять SSL сертификаты для сервисов, есть возможность использовать свои сертификаты, но мы настроем автоматическое получение бесплатных сертификатов от Lets Encrypt.
Добавим в конфигурацию (`traefik.yml`) новый блок:
```yaml
certificatesResolvers:
letsEncrypt:
acme:
email: postmaster@example.com
storage: acme.json
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
httpChallenge:
entryPoint: http
```
Здесь:
- `letsEncrypt` — это просто имя резолвера;
- `acme` — тип резолвера (других типов в общем-то и нет);
- `storage` — файл, в котором хранятся сведения о полученных сертификатах;
- `httpChallenge` — тип acme-челенжа, дополнительно указываем параметр — точку входа;
- `caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"` — позволяет использовать не основной сервер Lets Encrypt в тестовых целях, так как основной имеет строгие лимиты API (можно закомментировать, когда наладите получение сертификатов).
Также дополним пункт `volumes` в файле `docker-compose.yml`, чтобы сохранять сертификаты при перезапуске контейнера (предварительно создав файл `data/acme.json`):
```yaml
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
```
## Docker провайдер
HTTPS настроен, пришло время поднять первый сервис, пусть это будет дашборд самого Traefik, так как Traefik у нас в Docker, воспользуемся этим провайдером.
Для описания конфигурации в Docker Traefik использует метки (labels) контейнеров. Допишем в наш файл `docker-compose.yml`:
```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=letsEncrypt"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.services.traefik-traefik.loadbalancer.server.port=888"
```
Разберем построчно:
- `traefik.enable=true` — указываем что Traefik должен обеспечить
доступ к этому контейнеру, необходимо для всего остального;
- `traefik.http.routers.traefik.entrypoints=https` — создаем новый
роутер с точной входа `https`;
- `traefik.http.routers.traefik.rule=Host(`traefik.example.com`)` —
роутер будет жить по адресу traefik.example.com;
- `traefik.http.routers.traefik.tls=true` — указываем что используется
TLS;
- `traefik.http.routers.traefik.tls.certresolver=letsEncrypt`
указываем через какой резолвер получать сертификат;
- `traefik.http.routers.traefik.service=api@internal` — указываем, что
сервер за этим роутером — `api@internal`, это специальный сервис,
созданный по умолчанию, это как раз и есть дашбоард который мы хотели
увидеть;
- `traefik.http.services.traefik-traefik.loadbalancer.server.port=888`
— издержки интерфейса, без этого не заработает, но можно написать
абсолютно любую цифру.
Дашбоард надо включить, для этого добавим в файл `traefik.yml`:
```yaml
api:
dashboard: true
```
На данном этапе можно пересоздать контейнер (нужно так как мы меняли `docker-compose.yml`):
```bash
sudo docker-compose down && sudo docker-compose up -d
```
Когда всё поднимется можно перейти на `traefik.example.com` (тут на самом деле должен быть ваш домен, который направлен на хост с Traefik) и увидеть дашборд.
Дашбоард это хорошо, но мы не хотим, чтобы все пользователи интернета имели к нему доступ, закроем его от внешнего мира с помощью BasicAuth, для это в Traefik есть специальный middleware.
Для начала сгенерируем для нас строку с логином и паролем (admin/password)^
```bash
$ htpasswd -nb admin password
admin:$apr1$vDSqkf.v$GTJOtsd9CBiAFFnHTI2Ds1
```
Теперь добавим в наш `docker-compose.yml` новые строчки:
```yaml
- "traefik.http.middlewares.traefik-auth.basicauth.users=admin:$$apr1$$vDSqkf.v$$GTJOtsd9CBiAFFnHTI2Ds1"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
```
Заметим, что символы `$` из полученной строки мы должны заменить на `$$`.
- `traefik.http.middlewares.traefik-auth.basicauth.users=...` — создаем middleware типа `basicauth` с параметром `users`;
- `traefik.http.routers.traefik.middlewares=traefik-auth` — указываем что роутер `traefik` использует только что-то созданный middleware.
??? note "Весь docker-compose.yml"
```yaml
version: '3.9'
services:
traefik:
image: traefik:v2.10
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=letsEncrypt"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.services.traefik-traefik.loadbalancer.server.port=888"
```
Теперь при попытке доступа к дашборду у нас спросят логин и пароль.
Приведем также кофигурацию некого другого сервиса, развернутого через docker-compose (аналогично работает и для обычного docker):
```yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.test.entrypoints=https"
- "traefik.http.routers.test.rule=Host(`test.example.com`)"
- "traefik.http.routers.test.tls=true"
- "traefik.http.routers.test.tls.certresolver=letsEncrypt"
- "traefik.http.services.test-service.loadbalancer.server.port=80"
```
Здесь одна новая метка `traefik.http.services.test-service.loadbalancer.server.port=80` — присваиваем этому контенеру имя сервиса `test-service` и порт 80, он автоматически присоединится к роутеру `test`, Traefik автоматически постороит маршрут до этого контенера, даже если он находится на другом хосте.
## File провайдер
С контейнерами работает, а как быть если есть какой-то сервис работающий на выделенном хосте (пускай IP 192.168.1.222 и порт 8080) и мы его хотим пропустить через этот же прокси, заодно закрыв его с помощью HTTPS. Для этого есть решение.
Добавим в `docker-compose.yml` ещё один `volume`:
```yaml
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/custom/:/custom/:ro
- ./data/acme.json:/acme.json
```
Пускай описания таких хостов у нас будут лежать в `data/custom/` (а что, вдруг ещё появятся).
Добавим в `traefik.yml` конфигурацию file провайдера для этих файлов:
```yaml
providers:
...
file:
directory: /custom
watch: true
```
Директория следует из нашего `docker-compose.yml`, а `watch: true` значит что Traefik будет автоматически обновлять конфигурацию при обнаружении изменений в этих файлах (помните про обновление конфигурации “на лету”, вот работает даже для файлов, а не только для оркестраторов).
Перезапускаем Traefik и теперь можно создать файл с описанием нашего отдельного хоста (`data/custom/host.yml`):
```yaml
http:
routers:
host:
entryPoints:
- https
service: service-host
rule: Host(`host.example.com`)
tls:
certResolver: letsEncrypt
services:
service-host:
loadBalancer:
servers:
- url: http://192.168.1.222:8080/
passHostHeader: true
```
Роутер описывался раньше, тут добавилось только `service: service-host` — связь с нашим сервисом, и конфигурация для TLS.
Описание для сервиса имеет вид:
```yaml
имя_сервиса:
loadBalancer:
servers:
- хосты для балансировки нагрузки
- ...
```
Дополнительно мы указываем параметр `passHostHeader: true` чтобы тот хост думал, что он на самом деле смотрит в сеть и прокси нет.

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

@ -1,10 +1,12 @@
# Welcome to MkDocs
# Приветствую на моем сайт
For full documentation visit [mkdocs.org](https://www.mkdocs.org).
Данный ресурс создан для структурирования моих знаний в различных областях IT.
## Commands
Прошло мого времени, прежде чем я пришел к такому виду. До этого были Mediawiki, Dokuwiki, WikiJS, Wordpress.
Сейчас MkDocs, но я изучаю еще Docusaurus
Надеюсь, что статьи будут полезны.
Для связи: https://t.me/thest1tch
* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.

@ -0,0 +1,52 @@
Часто в работе возникает необходимость обновить MacOS на следующую версию. Скачивать каждый раз с интернета долго. Поэтому ускорим процесс и сделаем себе USB флешку с образом установки.
Важно отметить, что вам не нужно создавать установщик USB для установки macOS. Вы можете использовать App Store для нужной версии системы:
- [Monterey 12.x](https://apps.apple.com/us/app/macos-monterey/id1576738294?mt=12)
- [Big Sur 11.x](https://apps.apple.com/ru/app/macos-big-sur/id1526878132?mt=12)
- [Catalina 10.x](https://apps.apple.com/ru/app/macos-catalina/id1466841314?mt=12)
## Выбор USB-накопителя
Прежде чем следовать этому руководству, вам необходимо убедиться, что у вас есть доступ к USB-накопителю, который может служить местом установки.
Как правило, USB-флеш-накопитель будет работать, если на нем есть не менее 16 ГБ памяти.
## Создание загрузочного установочного USB-накопителя macOS
1. Запустите **Mac App Store** и загрузите нужную ОС. Список с ссылками выше. Для примера будет использовать последнюю ОС - Monterey.
2. После завершения загрузки macOS автоматически запустится программа установки. Закройте программу установки через строку меню или с помощью ⌘+Q.
3. Подключите USB-накопитель, откройте его в **Finder** и убедитесь, что на нем нет ничего нужного. Если есть, важно сделать резервную копию любых данных на диске, которые вам нужны, потому что выполнение этих шагов приведет к очистке содержимого диска. ! Примечание. В этом руководстве нельзя использовать диски в формате APFS. Если диск отформатирован как APFS или вы не уверены, откройте Дисковую утилиту, выберите диск и нажмите «Стереть». Для формата обязательно выберите _Mac OS Extended (Journaled)_ и нажмите «Стереть».
4. Откройте **Finder** → Приложения. Щелкните правой кнопкой мыши « _Установить macOS Monterey_ » → « **Показать содержимое пакета»** .
![](https://st1t.ru/wp-content/uploads/2022/12/ri0oyskj-1024x657.png)
5. Откройте Содержание → Ресурсы.
![](https://st1t.ru/wp-content/uploads/2022/12/38egrg4j-1024x543.png)
6. Откройте новое окно Терминала, выбрав Приложения → Утилиты → Терминал.
7. Введите `**sudo**` , а затем пробел в окне терминала.
8. Перетащите **createinstallmedia** в окно терминала из папки «Ресурсы», открытой на шаге 5.
![](https://st1t.ru/wp-content/uploads/2022/12/bx2bs4ok-1024x677.png)
9. Введите `**--volume**` , а затем пробел.
![](https://st1t.ru/wp-content/uploads/2022/12/cgi471gt-1024x677.png)
10. Откройте Finder → Перейти → Перейти в папку…
11. Введите **/Volumes** и нажмите клавишу «Return».
12. Перетащите иконку USB-накопителя в окно терминала.
![](https://st1t.ru/wp-content/uploads/2022/12/6lmebw5u-1024x365.png)**
Примечание.** Обязательно выберите правильный USB-накопитель, иначе вы рискуете повредить не тот диск.
13. Нажмите клавишу « _Return_ » на клавиатуре, чтобы обработать полную команду терминала, и введите пароль администратора при появлении запроса.
14. При появлении запроса введите «y» и нажмите клавишу « _Return_ » на клавиатуре.
![](https://st1t.ru/wp-content/uploads/2022/12/ww7kegd1-1024x676.png)
15. Если вы еще не предоставили разрешение, утилита терминала может запросить доступ к файлам на съемном томе. Если это так, не забудьте нажать OK, чтобы разрешить доступ.
16. Процесс установки начнется с очистки содержимого подключенного USB-накопителя, создания загрузочного диска и копирования файлов установщика на диск. Поскольку этот процесс занимает несколько минут, наберитесь терпения.
![](https://st1t.ru/wp-content/uploads/2022/12/ifsdjj2f-1024x678.png)
## Использование установщика macOS Monterey USB
Чтобы использовать установщик на Mac с Apple Silicon, выключите Mac, подключите диск, нажмите и удерживайте кнопку питания, пока не увидите логотип Apple со словами _Загрузка параметров запуска_ внизу. Через некоторое время вы должны увидеть, что «Установить macOS Monterey» появится в качестве параметра запуска.
Для компьютеров Mac с процессором Intel подключите установочный USB-накопитель и нажмите и удерживайте клавишу **Option** после перезагрузки компьютера, пока не появится селектор запуска.
При установке macOS в вашем распоряжении будет несколько вариантов, например:
1. Обновление существующей установки macOS, переход с macOS Big Sur или предыдущих версий macOS на macOS Monterey.
2. Удаление существующей установки и запуск с нуля.

@ -0,0 +1,210 @@
# Настройка WireGuard на Mikrotik
# Что такое WireGuard
Если не касаться wiki и официального сайта, и объяснять как можно проще, то это VPN туннелирование через UDP.
Это возможность быстро, максимально просто и надёжно, с хорошим уровнем безопасности соединить две точки между собой.
Соединение одноранговое, открытый исходный код, и полу-автоматизированное создание маршрутов(для некоторых клиентов) что еще нужно, для счастья 😉
Возможность использовать WireGuard появилась в mikrotik начиная с седьмой версии RouterOS.
## Как работает подключение (простым языком)
У нас есть две точки:
- Точка А с внешним адресом 111.111.111.111
- Точка Б с внешним адресом 222.222.222.222
С точки зрения WireGuard эти адреса называются `Endpoint`.
Также у точек есть внутренние сети или LAN:
- Точка А. 192.168.100.0/24
- Точка Б. 192.168.200.0/24
Эти сети мы и хотим связать между собой. Для WireGuard это называется **AllowedAddress**, или разрешенные адреса для точки. Для Точки А нам нужно будет указать разрешенные адреса `192.168.200.0/24`. Для Точки Б, соответственно `192.168.100.0/24`
Помимо этого мы должны определить для точек А и Б их адреса. Они используются для интерфейса, который создает WireGuard и передачи внутри протокола. В настройках большинства клиентов это будет называться `Address`. В mikrotik мы создадим отдельный адрес.
- Точка А. 10.10.10.1
- Точка Б. 10.10.11.1
Всё! Этого достаточно для создания подключения и его работы.
В итоге всё это будет выглядеть так:
![Краткая схема работы WireGuard](https://habrastorage.org/r/w1560/getpro/habr/upload_files/ba4/847/961/ba48479616baa45e5a2d49e35668e926.png)
## Отличия WireGuard и OpenVPN
Я не являются специалистом по сетевым протоколов и криптографических систем, поэтому не могу дать детальное сравнение этих решений. Но могу выделить несколько основных отличий для меня, как пользователя и администратора:
- В WireGuard не нужно создавать сертификаты, в отличии от OpenVpn, и следить за ними. Это и плюс и минус в зависимости от цели использования.
- В WireGuard создаются одноранговые соединения, где каждая точка может быть как сервером так и клиентом. Это позволяет создавать, помимо классических “звёзд”, ещё и mesh сети.
- OpenVPN позволяет более тонко управлять клиентами и их подключениями. Например, можно индивидуально раздавать маршруты и DNS-серверы для клиентов. WireGuard так не умеет.
- Отдельно для mikrotik есть недостаток в том, что для каждой подсети нужно настраивать маршруты. Для win-клиентов они определяются и задаются исходя из `AllowedAddress`.
В целом я для себя сделал вывод, что для внешних пользователей удобнее и, возможно, безопаснее использовать OpenVPN. А для железных(ака аппаратных) или программных роутеров и их связи между собой удобнее WireGuard. По принципу настроил и забыл.
## Подготовка к настройке
Для начала нужно убедится в том, что наш роутер Mikrotik умеет работать с WireGuard. Далее я буду показывать на примере интерфейса winbox. Если Вы пользуете командную строку, то Вы, скорее всего, сами сможете определить наличие WireGuard.
Проверить, это можно просто взглянув на пункты меню (актуально для версии 7.5):
![](https://habrastorage.org/r/w1560/getpro/habr/upload_files/a70/2fb/4ac/a702fb4ac21cbfc064c036eceae95c7c.png)
Обновить можно попробовать так:
![стандартный способ обновления](https://habrastorage.org/r/w1560/getpro/habr/upload_files/fb4/029/b5d/fb4029b5d003f6b1ed3a639b140f47fa.png "стандартный способ обновления")
стандартный способ обновления
Если так не получилось, то смотрите свою версию в заголовке winbox устройства
![в данном случае это mipsbe](https://habrastorage.org/r/w1560/getpro/habr/upload_files/a59/8d9/653/a598d9653e2ad09ce2ff88de5bc85854.png "в данном случае это mipsbe")
в данном случае это mipsbe
и идите на [официальный сайт mikrotik](https://mikrotik.com/download) для скачивания последней версии ОС.
Коротко, как обновить через загрузку файла на Mikrotik:
![](https://habrastorage.org/r/w1560/getpro/habr/upload_files/cde/592/687/cde592687e0b10fc7cb74d0255d31c3f.png)
Если у Вас много точек и так же для удобства настройки и дальнейшего обслуживания я рекомендую создать Вам подобную таблицу:
| Name | Address | Endpoint | EndpointIp | AllowedIPs | ListenPort | PrivateKey | PublicKey |
|--|--|--|--|--|--|--|--|
| PointA | 10.10.10.1 | www.pointA.com | 222.222.222.222 | 10.10.11.1/32,192.168.200.0/24 | 13231 | `<your_key>` | `ucwL8IWLNYrPHOu9qk70ZOagPgjJXhzvvkg7ZLooaj4=` |
| PointB | 10.10.11.1 | www.pointB.com | 111.111.111.111 | 10.10.10.1/32,192.168.100.0/24 | 13231 | `<your_key>` | `FxNwKIFINspWh5pkoFpS5LzNKMDjkqcAV/Ypo2Ed8ys=` |
Вам так будет проще ориентироваться в дальнейшем
## Настройка WireGuard на Mikrotik
Итак, у Вас есть WireGuard на Mikrotik, и теперь мы можем начать настройку.
Прежде всего нам нужно создать интерфейс, чтобы получить публичный ключ или `Public Key`. Я ранее про него не писал умышленно, чтобы было проще понять принцип работы WireGuard.
Но без публичного ключа установить соединение не получится. Он служит ключом шифрования и, можно сказать, паролем точки и для каждой точки он должен быть уникальным. При создании интерфейса он генерируется автоматически, так что Вам не нужно об этом переживать:
![Создаем интерфейсы и копируем публичные ключи](https://habrastorage.org/r/w1560/getpro/habr/upload_files/e22/93a/b58/e2293ab586ed08adc7734ded260ea949.png "
## Скрипт для быстрой настройки
Далее я дам два варианта настройки простой и быстрый, и немного подольше. Для начала простой, которым пользуюсь сам. Вот скрипт который, я сделал для Вашего удобства:
```
# EXAMPLE start
# Peer A params
# Name peerAname "PointA"
# Interaface Address peerAifAddress "10.10.10.1/24"
# AllowedIPs peerAallowed 10.10.11.1/32,192.168.200.0/24
# EndPoint peerAendAddress "111.111.111.111"
# EndPort peerAendPort 13231
# PublicKey peerAkey "ucwL8IWLNYrPHOu9qk70ZOagPgjJXhzvvkg7ZLooaj4="
# Peer B params
# Name peerBname "PointB"
# Interaface peerBif "PointB"
# AllowedIPs peerBallowed 10.10.10.1/32,192.168.100.0/24
# EndPoint peerBendAddress "222.222.222.222"
# EndPort 13231
# PublicKey "FxNwKIFINspWh5pkoFpS5LzNKMDjkqcAV/Ypo2Ed8ys="
# EXAMPLE end
{
# Peer A params
# SET PARAMS HERE
:local peerAname "PointA"
:local peerAifAddress "10.10.10.1/24"
:local peerAallowed 10.10.11.1/32,192.168.200.0/24
:local peerAendAddress "111.111.111.111"
:local peerAendPort 13231
:local peerAkey "ucwL8IWLNYrPHOu9qk70ZOagPgjJXhzvvkg7ZLooaj4="
# Peer B params
:local peerBname "PointB"
:local peerBifAddress "10.10.11.1/24"
:local peerBallowed 10.10.10.1/32,192.168.100.0/24
:local peerBendAddress "222.222.222.222"
:local peerBendPort 13231
:local peerBkey "FxNwKIFINspWh5pkoFpS5LzNKMDjkqcAV/Ypo2Ed8ys="
# start select
:local input do={:put $input;:return}
:local selectedPeer [$input "Enter current Peer A or B"]
:put "You select is $selectedPeer. Finished!"
# end select
{
# start for A
:if ($selectedPeer = "A") do={
# add address
/ip address
add address=$peerAifAddress interface=$peerAname comment=$peerAname
# add firewall rule
/ip firewall filter
add action=accept chain=input dst-port=$peerAendPort in-interface-list=WAN protocol=udp comment="WireGuard $peerAname"
# add peer
/interface/wireguard/peers
add allowed-address=$peerBallowed endpoint-address=$peerBendAddress endpoint-port=$peerBendPort interface=$peerAname public-key=$peerBkey persistent-keepalive=10 comment=$peerBname
# add route
/ip/route
:foreach peer in=$peerBallowed do={
add dst-address=$peer gateway=$peerAname comment=$peerBname
}
}
# end for A
# start for B
:if ($selectedPeer = "B") do={
# add address
/ip address
add address=$peerBifAddress interface=$peerBname comment=$peerBname
# add firewall rule
/ip firewall filter
add action=accept chain=input dst-port=$peerBendPort in-interface-list=WAN protocol=udp comment="WireGuard $peerBname"
# add peer
/interface/wireguard/peers
add allowed-address=$peerAallowed endpoint-address=$peerAendAddress endpoint-port=$peerAendPort interface=$peerBname public-key=$peerAkey persistent-keepalive=10 comment=$peerAname
# add route
/ip/route
:foreach peer in=$peerAallowed do={
add dst-address=$peer gateway=$peerBname comment=$peerAname
}
}
# end for B
}
}
```
Его можно запускать прямо из терминала, либо из winbox открыв терминал. Так же вы можете добавить его в `System -> Scripts` и запустить из терминала, но так как это разовая процедура, не вижу в этом особого смысла.
> Для начала внесите все необходимые параметры в строки переменных
`:local`, затем скопируйте и вставьте скрипт в терминал. Вам нужно будет только выбрать точку в которой вы находитесь `А` или `B`. Введите её и нажмите `Enter`.
Так нужно будет повторить в каждой точке!
Скрипт создаёт `address`, правило firewall для доступа из вне по списку `interface list` `WAN`. Список интерфейсов `WAN` создаётся по умолчанию. Если его нет, то добавьте.
Далее, скрипт создаёт настройки точки `Peers` для подключения и добавляет все необходимые маршруты `Routes`, которые берёт из `Allowed Address`
Ну или вы можете прописать всё руками по следующим скриншотам:
![Создаём адрес и подсеть для нашего интерфейса](https://habrastorage.org/r/w1560/getpro/habr/upload_files/b6a/79c/890/b6a79c8907d945705ade7dd112fc5816.png)
Создаём адрес и подсеть для нашего интерфейса
![Создаём правило Firewall](https://habrastorage.org/r/w1560/getpro/habr/upload_files/776/c16/094/776c16094a52aa01d1b20ee7568ef440.png)
Создаём правило Firewall
![Прописываем маршруты](https://habrastorage.org/r/w1560/getpro/habr/upload_files/cb2/9d0/b13/cb29d0b1306b94391612fc9118770cdb.png "Прописываем маршруты")
Прописываем маршруты
![Добавляем точку к которой хотим подключится](https://habrastorage.org/r/w1560/getpro/habr/upload_files/291/636/634/291636634012a197fd5f611b026e9829.png)
Добавляем точку к которой хотим подключится
Надеюсь эта статья помогла кому-то быстро всё понять и настроить. Так как я на понимание, тесты и настройку потратил минимум один день, а то и больше.
И в конце добавлю общую схему со всеми параметрами:
![Общая схема работы и настройки WireGuard](https://habrastorage.org/r/w1560/getpro/habr/upload_files/7c0/a5c/cb8/7c0a5ccb8f649e9b51533b0ef75b1a1e.png)

@ -0,0 +1,9 @@
Добавление на контроллер
Чтобы добавить точку на контроллер (1-3) или сменить контроллер нужно (3):
1. зайти на точку по ssh
2. сбросить на заводские настройки `set-default`
3. привязать по новому адресу: `set-inform http://ip-server:8080/inform`
!!! info
по умолчанию логин пароль: ubnt:ubnt

@ -0,0 +1,19 @@
# Проблема при обновлении из контроллера: Update Failed update, error curl
Зайти на точку по ssh
Ввести `upgrade <ссылкааайл>`
файл выкладывать на **http** сервер в корень
пример:
!!! info "Пример"
Через консоль на точке:
```bash
upgrade http://ip-server/BZ.ar7240.v4.0.15.9872.181229.0259.bin
upgrade http://ip-server/UAP-LR-v2.v4.0.15.9872.181229.0259.bin
```
через SCP:
```bash
scp /var/www/unifi/fw/UAP-LR-v2.v4.0.80.10875.200111.2335/firmware.bin admin@10.118.13.250:/tmp/fwupdate.bin
```

@ -0,0 +1,10 @@
Google Chrome
## Блокировка медиакнопок
Одним словом, то пока можно только отключить. Но не весь браузер, а только упомянутую функцию поддержки мультимедийных кнопок в нем. Делается это путем отключения соответствующего «*флага*» (экспериментальной функции) в настройках Chrome. Для этого:
1. открываем браузер в адресную строку копируем `chrome:flags/#hardware-media-key-handling` и жмем Enter
2. далее для функции Hardware Media Key Handling вместо значения «`Default`» устанавливаем «`Disabled`
3. перезапускаем Chrome, чтобы активировать изменение.

@ -0,0 +1,24 @@
# Cоздание новой DNS-записи CNAME на Cloudflare
----------
Я рекомендую получить собственное доменное имя, указывающее на IP-адрес вашего дома в глобальной сети. Частное доменное имя через reg.ru будет стоить 850 рублей в год. Есть несколько причин, почему я рекомендую это:
- В моем тестировании я никогда не мог заставить некоторые контейнеры докеров работать в качестве подкаталога (даже на моем собственном частном доменном имени) за обратным прокси-сервером Traefik. В таких ситуациях вам останется создать несколько динамических субдоменов DNS, чтобы разместить все ваши службы. Большинство бесплатных динамических DNS-сервисов ограничивают количество субдоменов, которые вы можете создать.
- Afraid DNS не является одним из поддерживаемых поставщиков wildcard сертификатов. Хотя DuckDNS указан как поддерживаемый, он еще не тестировался.
В моей настройке использую собственное доменное имя, все мои приложения в качестве отдельных хостов и Traefik 2.9 с сертификатами Wildcard. Мой провайдер DNS — Cloudflare, который [протестирован и подтвержден](https://doc.traefik.io/traefik/v1.7/configuration/acme/#wildcard-domains) для работы с подстановочными сертификатами Traefik Lets Encrypt. Если у вас есть собственное доменное имя, а ваш провайдер DNS не указан в списке поддерживаемых, то я рекомендую перенести ваш DNS на Cloudflare, который удивительно быстр и бесплатен.
В Cloudflare вы должны указать свой корневой домен (example.com) на свой IP-адрес WAN. Затем добавьте CNAME с подстановочным знаком (*.example.com) или отдельные субдомены, указывающие на ваш корневой домен (@ для хоста), как показано ниже (для этого не требуется платная учетная запись).
[![Cloudflare Dns Entries](https://www.smarthomebeginner.com/images/2018/05/cloudflare-dns-records-screenshot-740x495.png "Traefik Tutorial: Traefik Reverse Proxy with LetsEncrypt for Docker Media Server 3")](https://www.smarthomebeginner.com/images/2018/05/cloudflare-dns-records-screenshot.png)
Cloudflare Dns Entries For Traefik Dns Challenge
In addition to creating the DNS records, you will have to adjust Cloudflares SSL settings to avoid indefinite redirects. Go to **Crypto** settings for the domain and change **SSL** to **Full** as shown below.
[![Cloudflare &Quot;Full&Quot; Ssl](https://www.smarthomebeginner.com/images/2018/05/cloudflare-crypto-full-ssl-740x358.png "Traefik Tutorial: Traefik Reverse Proxy with LetsEncrypt for Docker Media Server 4")](https://www.smarthomebeginner.com/images/2018/05/cloudflare-crypto-full-ssl.png)
Cloudflare “Full” Ssl
Note that you may have to wait for a few minutes for the DNS entries to propagate. If you run Traefik before that, DNS challenge may fail and no SSL certificate will be generated. If you keep trying, [Lets Encrypt may ban you temporarily](https://letsencrypt.org/docs/rate-limits/) for reaching the request limits. To counter this I have added a 5 min wait in the traefik configuration below but you may need longer. Until validation is complete, Traefiks default certificate will be used and your browser will throw a warning.

@ -0,0 +1,53 @@
Оптимальный вариант просмотра (в порядке выхода)
I. «Сага Бесконечности»
Первая фаза
1. «Железный человек» (2008)
2. «Невероятный Халк» (2008)
3. «Железный человек 2» (2010)
4. «Тор» (2011)
5. «Первый мститель» (2011)
6. «Мстители» (2012)
Вторая фаза
7. «Железный человек 3» (2013)
8. «Тор 2: Царство тьмы» (2013)
9. «Первый мститель: Другая война» (2014)
10. «Стражи Галактики» (2014)
11. «Мстители: Эра Альтрона» (2015)
12. «Человек-муравей» (2015)
Третья фаза
13. «Первый мститель: Противостояние» (2016)
14. «Доктор Стрэндж» (2016)
15. «Стражи Галактики. Часть 2» (2017)
16. «Человек-паук: Возвращение домой» (2017)
17. «Тор: Рагнарёк» (2017)
18. «Черная Пантера» (2018)
19. «Мстители: Война бесконечности» (2018)
20. «Человек-муравей и Оса» (2018)
21. «Капитан Марвел» (2019)
22. «Мстители: Финал» (2019)
23. «Человек-паук: Вдали от дома» (2019)
«Сага Мультивселенной»
Четвертая фаза
24. «Ванда/Вижн» (2021), сериал
25. «Сокол и Зимний Солдат» (2021), сериал
26. «Локи», 1-й сезон (2021), сериал
27. «Черная Вдова» (2021)
28. «Что, если…?», 1-й сезон (2021), мультсериал
29. «Шан-Чи и легенда десяти колец» (2021)
30. «Вечные» (2021)
31. «Соколиный Глаз» (2021), сериал
32. «Человек-паук: Нет пути домой» (2021)
33. «Лунный рыцарь» (2022), сериал
34. «Доктор Стрэндж: В мультивселенной безумия» (2022)
35. «Мисс Марвел» (2022), сериал
36. «Тор: Любовь и гром» (2022)
37. «Я есть Грут» (2022), мини-мультсериал
38. «Женщина-Халк: Адвокат» (2022), сериал
39. «Ночной оборотень» (2022), спешел
40. «Черная Пантера: Ваканда навеки» (2022)
41. «Стражи Галактики: Праздничный спецвыпуск» (2022), спешел
42. «Человек-муравей и Оса: Квантомания» (2023)

@ -0,0 +1,15 @@
## Отключение обновления экрана
```vba
Application.ScreenUpdating = False
' в конце
Application.ScreenUpdating = True
```
## Список уникальных значений VBA
```vba
PS = Range("A" & Rows.Count).End(xlUp).Row
Range("N6:N" & PS).AdvancedFilter Action:=xlFilterCopy, CopyToRange:=Range("T11"), Unique:=True
Range("T11:T300").Font.ColorIndex = 5
MsgBox "Создали уникальный список источников"
```

@ -0,0 +1,15 @@
# Исправление примечаний VBA
Бывает так, что ты вставляешь примечания и они уползают вниз при действиях со строками. 
Чтобы такого не было, используй этот макрос:
```vba
Sub align_comments()
Dim x As Comment
For Each x In ActiveSheet.Comments
x.Shape.Left = x.Parent.Offset(0, 1).Left + 10
x.Shape.Top = x.Parent.Top
Next
End Sub
```

@ -0,0 +1,12 @@
# Создание файла VBA
Простое
```vba
iFullName = ThisWorkbook.Path & "name.xlsx"
```
С именем из ячейки:
```vba
iFullName = ThisWorkbook.Path & "\" & Range("A1").Value & ".xlsx"
```

@ -0,0 +1,39 @@
# Открытие файла VBA
## 1 файл
Для открытия 1 файла и передачи его на дальнейшую обработку, используй этот код:
```vba
avFiles = Application.GetOpenFilename _
("Excel files(*.xls*),*.xls*", 1, "Выбери Excel файл", , False)
If VarType(avFiles) = vbBoolean Then
'была нажата кнопка отмены - выход из процедуры
Exit Sub
End If
Set avFiles1 = Workbooks.Open(Filename:=avFiles)
```
## Несколько файлов
Чтобы открыть много файлов и запустить обработку по ним, используем цикл:
```vba
FilesToOpen = Application.GetOpenFilename _
(FileFilter:="All files (*.*), *.*", _
MultiSelect:=True, Title:="Files to Merge")
If TypeName(FilesToOpen) = "Boolean" Then
MsgBox "Не выбрано ни одного файла!"
Exit Sub
End If
'проходим по всем выбранным файлам
x = 1
While x <= UBound(FilesToOpen)
With Workbooks.Open(FilesToOpen(x)).Sheets(1)
...
...
End With
x = x + 1
Wend
```

@ -0,0 +1,83 @@
# Прогресс бар VBA
> Использование APPLICATION.STATUSBAR
## Прогресс бар внизу страницы:
```vba
Application.StatusBar = "TEST"
DoEvents
...
Application.StatusBar = False
```
## Прогресс бар для циклов:
```vba
For i = 1 To n
Istochnik = Cells(i, 20)
Application.StatusBar = "Делаю источник " & i & "-" & Istochnik & "/" & 50 & ""
DoEvents
Next
```
## Можно сделать показ % завершения:
![](../../../images/other/office/excel-vba-progress-bar-01.png)
```vba
Sub ShowProgressBar()
Dim lAllCnt As Long, lr as Long
Dim rc As Range
'кол-во ячеек в выделенной области
lAllCnt = Selection.Count
'цикл по всем ячейкам в выделенной области
For Each rc In Selection
'прибавляем 1 при каждом шаге
lr = lr + 1
Application.StatusBar = "Выполнено: " & Int(100 * lr / lAllCnt) & "%"
DoEvents 'чтобы форма перерисовывалась
Next
'сбрасываем значение статусной строки
Application.StatusBar = False
End Sub
```
## Текст + блоки символов из 10 штук:
![](../../../images/other/office/excel-vba-progress-bar-02.png)
```vba
Sub StatusBar2()
Dim lr As Long, lp As Double
Dim lAllCnt As Long 'кол-во итераций
Dim s As String
lAllCnt = 10000
For lr = 1 To lAllCnt
lp = lr \ 100 'десятая часть всего массива
'формируем строку символов(от 1 до 10)
s = String(lp \ 10, ChrW(10152)) & String(11 - lp \ 10, ChrW(8700))
Application.StatusBar = "Выполнено: " & lp & "% " & s: DoEvents
DoEvents
Next
'очищаем статус-бар от значений после выполнения
Application.StatusBar = False
End Sub
```
## Текст + блоки квадратов из n штук:
количество квадратов можно менять
![](../../../images/other/office/excel-vba-progress-bar-03.png)
```vba
Sub StatusBar3()
Dim lr As Long
Dim lAllCnt As Long 'кол-во итераций
Const lMaxQuad As Long = 20 'сколько квадратов выводить
lAllCnt = 10000
For lr = 1 To lAllCnt
Application.StatusBar = "Выполнено: " & Int(100 * lr / lAllCnt) & "%" & String(CLng(lMaxQuad * lr / lAllCnt), ChrW(9632)) & String(lMaxQuad - CLng(lMaxQuad * lr / lAllCnt), ChrW(9633))
DoEvents
Next
'очищаем статус-бар от значений после выполнения
Application.StatusBar = False
End Sub
```

@ -0,0 +1,186 @@
# Удаление пароля VBA
> Пожалуйста, сделайте резервную копию ваших файлов в первую очередь!
{.is-warning}
## Для 32 битной версии
Откройте файл(ы), которые содержат ваши заблокированные проекты VBA
Создайте новый файл **xlsm** и сохраните этот код в `Module1`
```vba
code credited to Siwtom (nick name), a Vietnamese developer
Option Explicit
Private Const PAGE_EXECUTE_READWRITE = &H40
Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Long, Source As Long, ByVal Length As Long)
Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As Long, _
ByVal dwSize As Long, ByVal flNewProtect As Long, lpflOldProtect As Long) As Long
Private Declare Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, _
ByVal lpProcName As String) As Long
Private Declare Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As Long, _
ByVal pTemplateName As Long, ByVal hWndParent As Long, _
ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As Long
Dim Flag As Boolean
Private Function GetPtr(ByVal Value As Long) As Long
GetPtr = Value
End Function
Public Sub RecoverBytes()
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub
Public Function Hook() As Boolean
Dim TmpBytes(0 To 5) As Byte
Dim p As Long
Dim OriginProtect As Long
Hook = False
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
If TmpBytes(0) <> &H68 Then
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
p = GetPtr(AddressOf MyDialogBoxParam)
HookBytes(0) = &H68
MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
HookBytes(5) = &HC3
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
Flag = True
Hook = True
End If
End If
End Function
Private Function MyDialogBoxParam(ByVal hInstance As Long, _
ByVal pTemplateName As Long, ByVal hWndParent As Long, _
ByVal lpDialogFunc As Long, ByVal dwInitParam As Long) As Integer
If pTemplateName = 4070 Then
MyDialogBoxParam = 1
Else
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
hWndParent, lpDialogFunc, dwInitParam)
Hook
End If
End Function
```
Вставьте этот код под вышеуказанным кодом в Module1 и запустите его
```vba
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
```
Возвращайтесь к своим проектам VBA и наслаждайтесь.
## Для 64 битной версии:
Откройте файл (ы), содержащий ваши заблокированные проекты VBA.
Создайте новый файл xlsm и сохраните этот код в `Module1`
```vba
Option Explicit
Private Const PAGE_EXECUTE_READWRITE = &H40
Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As LongPtr, Source As LongPtr, ByVal Length As LongPtr)
Private Declare PtrSafe Function VirtualProtect Lib "kernel32" (lpAddress As LongPtr, _
ByVal dwSize As LongPtr, ByVal flNewProtect As LongPtr, lpflOldProtect As LongPtr) As LongPtr
Private Declare PtrSafe Function GetModuleHandleA Lib "kernel32" (ByVal lpModuleName As String) As LongPtr
Private Declare PtrSafe Function GetProcAddress Lib "kernel32" (ByVal hModule As LongPtr, _
ByVal lpProcName As String) As LongPtr
Private Declare PtrSafe Function DialogBoxParam Lib "user32" Alias "DialogBoxParamA" (ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer
Dim HookBytes(0 To 5) As Byte
Dim OriginBytes(0 To 5) As Byte
Dim pFunc As LongPtr
Dim Flag As Boolean
Private Function GetPtr(ByVal Value As LongPtr) As LongPtr
GetPtr = Value
End Function
Public Sub RecoverBytes()
If Flag Then MoveMemory ByVal pFunc, ByVal VarPtr(OriginBytes(0)), 6
End Sub
Public Function Hook() As Boolean
Dim TmpBytes(0 To 5) As Byte
Dim p As LongPtr
Dim OriginProtect As LongPtr
Hook = False
pFunc = GetProcAddress(GetModuleHandleA("user32.dll"), "DialogBoxParamA")
If VirtualProtect(ByVal pFunc, 6, PAGE_EXECUTE_READWRITE, OriginProtect) <> 0 Then
MoveMemory ByVal VarPtr(TmpBytes(0)), ByVal pFunc, 6
If TmpBytes(0) <> &H68 Then
MoveMemory ByVal VarPtr(OriginBytes(0)), ByVal pFunc, 6
p = GetPtr(AddressOf MyDialogBoxParam)
HookBytes(0) = &H68
MoveMemory ByVal VarPtr(HookBytes(1)), ByVal VarPtr(p), 4
HookBytes(5) = &HC3
MoveMemory ByVal pFunc, ByVal VarPtr(HookBytes(0)), 6
Flag = True
Hook = True
End If
End If
End Function
Private Function MyDialogBoxParam(ByVal hInstance As LongPtr, _
ByVal pTemplateName As LongPtr, ByVal hWndParent As LongPtr, _
ByVal lpDialogFunc As LongPtr, ByVal dwInitParam As LongPtr) As Integer
If pTemplateName = 4070 Then
MyDialogBoxParam = 1
Else
RecoverBytes
MyDialogBoxParam = DialogBoxParam(hInstance, pTemplateName, _
hWndParent, lpDialogFunc, dwInitParam)
Hook
End If
End Function
```
Вставьте этот код в Module2 и запустите его
```vba
Sub unprotected()
If Hook Then
MsgBox "VBA Project is unprotected!", vbInformation, "*****"
End If
End Sub
```

@ -0,0 +1,34 @@
# Защита страницы через VBA
Каждый кто хоть раз писал макросы, сталкивался с тем, что требуется защитить лист и формулы на нем от шаловливых ручек пользователей. При том, нужно чтобы макросы на листе работали. Самое просто решение, это перед кодом макроса, добавить это:
```vba
Worksheets("Лист1").Unprotect Password:="123"
'тут макрос делает действия
Worksheets("Лист1").Protect Password:="123"
```
Это будет работать, но у такого подхода есть и свои минусы. Во-первых, нужно эту конструкцию размещать в каждом макросе. Во-вторых - если будет ошибка, лист останется без защиты.
## Есть другой способ
Нажмите `Alt+F11`, чтобы попасть в редактор Visual Basic. Затем в левом верхнем углу в окне Project Explorer (если его не видно, то нажмите Ctrl+R) модуль ЭтаКнига (ThisWorkbook) и откройте двойным щелчком:
![](../../../images/other/office/excel_vba_01.png){ loading=lazy }
Вставьте этот код:
```vba
Private Sub Workbook_Open()
'включаем защиту первого листа для пользователя, но не макроса
Worksheets("Лист1").Protect Password:="123", UserInterfaceOnly:=True
'второй лист защищаем аналогично, но с возможностью пользоваться группировкой
Worksheets("Лист2").EnableOutlining = True
Worksheets("Лист2").Protect Password:="555", UserInterfaceOnly:=True
End Sub
```
Данный код будет автоматически запускаться при открытии файла и ставить защиту на заданные листы. Параметр `UserInterfaceOnly` указывает Excel, что защита не должна работать для действий макроса, а только на операции юзера.
Второй параметр `EnableOutlining` разрешает пользоваться группировкой.

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save