Compare commits
18 Commits
86506f744a
...
tmp
| Author | SHA1 | Date | |
|---|---|---|---|
| 00cc795a8e | |||
| d46c56d386 | |||
| d180f06ab0 | |||
| c729ca850b | |||
| 4de49b9d0e | |||
| d2a796e67f | |||
| 96176d2f0c | |||
| 4836eabc2c | |||
| 63d729aec4 | |||
| 04737ff93c | |||
| 9d7a9207f6 | |||
| c22af5a786 | |||
| cf8a68b72a | |||
| 89a278d0bc | |||
| 25be7bab30 | |||
| cb5a34ac95 | |||
| 2bd26f9d4d | |||
| 31b893a85a |
@@ -8,8 +8,16 @@ on:
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: self-hosted
|
||||
container:
|
||||
image: python:3.12-slim
|
||||
options: --volume /var/www/knowledge-base:/var/www/knowledge-base
|
||||
steps:
|
||||
- name: Clone repository
|
||||
- name: Install git
|
||||
run: |
|
||||
apt-get update
|
||||
apt-get install -y --no-install-recommends git
|
||||
|
||||
- name: Checkout repository
|
||||
run: |
|
||||
git clone --depth 1 --branch main https://git.tishenko.dev/tish/knowledge-base.git
|
||||
|
||||
@@ -21,8 +29,8 @@ jobs:
|
||||
|
||||
- name: Deploy site
|
||||
run: |
|
||||
# Удаляем только содержимое /var/www/knowledge-base,
|
||||
# чтобы сохранить права и владельца самой папки
|
||||
cd knowledge-base
|
||||
rm -rf /var/www/knowledge-base/*
|
||||
# Удаляем старую версию сайта
|
||||
rm -rf /var/www/knowledge-base/site
|
||||
# Копируем новую
|
||||
cp -r site/ /var/www/knowledge-base/site/
|
||||
|
||||
@@ -36,9 +36,15 @@
|
||||
- `a` - создать файл.
|
||||
- `shift + a` - создать папку.
|
||||
|
||||
Быстрый переход к определению функции, метода, etc. В дополнение к F12. Удобно использовать вместе с `alt + ←/→`.
|
||||
Быстрый переход к определению и типу функции, метода, переменной, etc. В дополнение к `F12`. Удобно использовать вместе с `alt + ←/→`.
|
||||
|
||||
- `alt + d` - перейти к определению.
|
||||
- `alt + t` - перейти к определению типа.
|
||||
- `alt + i` - перейти к реализации (актуально для Java).
|
||||
|
||||
Обычно я отключаю `explorer.autoReveal` в настройках, чтобы боковая панель с проводником не изменялась, когда я переключаюсь по файлам. Если мне всё-таки требуется выделить открытый файл в `Explorer View`, то я использую дополнительное сочетание клавиш.
|
||||
|
||||
- `alt + shift + r` - показать открытый файл в `Explorer View`.
|
||||
|
||||
```json
|
||||
[
|
||||
@@ -56,6 +62,21 @@
|
||||
"key": "alt+d",
|
||||
"command": "editor.action.revealDefinition",
|
||||
"when": "editorHasDefinitionProvider && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"key": "alt+t",
|
||||
"command": "editor.action.goToTypeDefinition",
|
||||
"when": "editorHasTypeDefinitionProvider && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"key": "alt+i",
|
||||
"command": "editor.action.goToImplementation",
|
||||
"when": "editorHasImplementationProvider && editorTextFocus"
|
||||
},
|
||||
{
|
||||
"key": "shift+alt+r",
|
||||
"command": "workbench.files.action.showActiveFileInExplorer",
|
||||
"when": "editorTextFocus"
|
||||
}
|
||||
]
|
||||
```
|
||||
@@ -1,11 +1,266 @@
|
||||
# Кастомизация Gitea
|
||||
# Gitea
|
||||
|
||||
Шпаргалки актуальны для Gitea 1.24.
|
||||
|
||||
## Установка с Docker
|
||||
|
||||
Эта заметка лишь дополнение к [документации](https://docs.gitea.com/installation/install-with-docker#basics).
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
# Создаём служебного пользователя
|
||||
sudo useradd --create-home --shell /bin/bash --system gitea
|
||||
|
||||
# Даём пользователю права использовать Docker
|
||||
# Строго говоря это необязательно для разворачивания Gitea,
|
||||
# но скорее всего и ранеры будут запускаться от этого пользователя,
|
||||
# так что ему в любом случае потребуются права на Docker
|
||||
sudo usermod -aG docker gitea
|
||||
|
||||
# Переключаемся на пользователя gitea
|
||||
sudo su - gitea
|
||||
|
||||
# Узнаём его uid и gid
|
||||
id
|
||||
|
||||
# Создаём docker-compose.yml по примеру
|
||||
# Указываем переменные USER, USER_UID и USER_GID и порты
|
||||
nano docker-compose.yml
|
||||
|
||||
# Создаём директорию для данных Gitea из-под пользователя gitea,
|
||||
# иначе Docker сам создаст её из-под root
|
||||
# см. секцию "volumes" в docker-compose.yml
|
||||
mkdir data
|
||||
|
||||
# Запускаем Gitea
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
=== "docker-compose.yml"
|
||||
|
||||
```yaml
|
||||
networks:
|
||||
gitea:
|
||||
external: false
|
||||
|
||||
services:
|
||||
server:
|
||||
image: docker.gitea.com/gitea:1.24.6
|
||||
container_name: gitea
|
||||
environment:
|
||||
- USER=<user>
|
||||
- USER_UID=<uid>
|
||||
- USER_GID=<gid>
|
||||
restart: always
|
||||
networks:
|
||||
- gitea
|
||||
volumes:
|
||||
- ./data:/data
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
ports:
|
||||
- "28500:3000"
|
||||
- "28522:22"
|
||||
```
|
||||
|
||||
Теперь можно перейти по адресу `http://<IPv4>:28500` и завершить установку Gitea.
|
||||
|
||||
Подключиться к контейнеру можно командой.
|
||||
|
||||
```sh
|
||||
docker exec --user gitea -it gitea bash
|
||||
|
||||
# Уже внутри контейнера можно запускать бинарник gitea
|
||||
/usr/local/bin/gitea help
|
||||
```
|
||||
|
||||
## Создание бэкапа
|
||||
|
||||
Ссылка на [документацию](https://docs.gitea.com/administration/backup-and-restore).
|
||||
|
||||
### Gitea установлена из бинарника
|
||||
|
||||
```sh
|
||||
# gitea - это пользователь под которым запущен Gitea, часто это просто git
|
||||
sudo su - gitea
|
||||
|
||||
mkdir gitea-backup
|
||||
cd gitea-backup
|
||||
|
||||
# Нужно указать актуальный путь к конфигу
|
||||
/usr/local/bin/gitea dump -c /etc/gitea/app.ini
|
||||
|
||||
# Если планируется восстановление с другой базой данных,
|
||||
# то нужно указать параметр --database <sqlite3|mysql|postgres>
|
||||
/usr/local/bin/gitea dump --database sqlite3 -c /etc/gitea/app.ini
|
||||
```
|
||||
|
||||
### Gitea установлена с Docker
|
||||
|
||||
Предполагается, что Gitea развёрнута с помощью Docker Compose как описано в инструкции [выше](#установка-с-docker).
|
||||
|
||||
Подключаемся к контейнеру.
|
||||
|
||||
```sh
|
||||
docker exec --user gitea -it gitea bash
|
||||
```
|
||||
|
||||
Внутри контейнера выполняем.
|
||||
|
||||
```sh
|
||||
# Бэкап нужно создать в директории /data, потому что она прокинута на хост
|
||||
cd /data
|
||||
|
||||
# (Опционально) Создаём директорию для бэкапов
|
||||
mkdir backups
|
||||
cd backups
|
||||
|
||||
# Нужно указать актуальный путь к конфигу
|
||||
/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini
|
||||
|
||||
# Если планируется восстановление с другой базой данных,
|
||||
# то нужно указать параметр --database <sqlite3|mysql|postgres>
|
||||
/usr/local/bin/gitea dump --database sqlite3 -c /data/gitea/conf/app.ini
|
||||
```
|
||||
|
||||
То же самое в одну команду.
|
||||
|
||||
```sh
|
||||
docker exec -u gitea -w /data gitea /usr/local/bin/gitea dump -c /data/gitea/conf/app.ini
|
||||
```
|
||||
|
||||
### Перенос бэкапа на другую машину
|
||||
|
||||
Перенести бэкап на другую машину можно, например, так:
|
||||
|
||||
```sh
|
||||
# Запускаем HTTP сервер (с scp загрузка больших файлов займёт много времени)
|
||||
python3 -m http.server 8080
|
||||
|
||||
# На другой машине скачиваем бэкап
|
||||
curl -O http://<IP>:8080/gitea-dump-1760203345.zip
|
||||
```
|
||||
|
||||
|
||||
## Восстановление из бэкапа в Docker
|
||||
|
||||
Предполагается, что Gitea разворачивается из [бэкапа](#создание-бэкапа) с помощью Docker Compose как описано в инструкции [выше](#установка-с-docker). В [документации](https://docs.gitea.com/1.24/administration/backup-and-restore#using-docker-restore) есть соответствующая инструкция, однако она не полная и содержит ошибки.
|
||||
|
||||
```sh
|
||||
# Если создавали пользователя по инструкции выше,
|
||||
# то команды выполняем от него
|
||||
sudo su - gitea
|
||||
|
||||
# Распаковываем бэкап
|
||||
unzip -q gitea-dump-*.zip -d dump
|
||||
|
||||
# Создаём директорию для данных Gitea
|
||||
mkdir data
|
||||
|
||||
# Копируем данные
|
||||
cp -r dump/data/ data/gitea/
|
||||
|
||||
# Копируем репозитории
|
||||
mkdir data/git/
|
||||
cp -r dump/repos/ data/git/repositories/
|
||||
|
||||
# Копируем кастомные стили и шаблоны
|
||||
cp -r dump/custom/. data/gitea/
|
||||
|
||||
# Если Gitea в Docker будет работать с SQLite,
|
||||
# то восстановить базу данных можно так.
|
||||
# Команды для других баз данныех есть в документации
|
||||
sqlite3 data/gitea/gitea.db < dump/gitea-db.sql
|
||||
|
||||
# Копируем конфиг
|
||||
mkdir data/gitea/conf
|
||||
cp dump/app.ini data/gitea/conf/app.ini
|
||||
```
|
||||
|
||||
Если до этого Gitea была запущена не через Docker, то нужно отредактировать конфиг.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
vim data/gitea/conf/app.ini
|
||||
```
|
||||
|
||||
=== "`app.ini` для Docker"
|
||||
|
||||
Это не полноценный конфиг, а лишь часть настроек для запуска Gitea Docker.
|
||||
Подразумевается, что конфиг был перенесён из бэкапа.
|
||||
|
||||
`SSH_PORT` нужно указать тот же, что и в `docker-compose.yml`.
|
||||
|
||||
```ini
|
||||
RUN_USER = gitea
|
||||
WORK_PATH = /data/gitea
|
||||
|
||||
[server]
|
||||
LOCAL_ROOT_URL = http://localhost:3000
|
||||
APP_DATA_PATH = /data/gitea
|
||||
DOMAIN = localhost
|
||||
SSH_DOMAIN = localhost
|
||||
HTTP_PORT = 3000
|
||||
SSH_PORT = 28522
|
||||
|
||||
[repository]
|
||||
ROOT = /data/git/repositories
|
||||
|
||||
[database]
|
||||
PATH = /data/gitea/gitea.db
|
||||
DB_TYPE = sqlite3
|
||||
HOST = localhost:3306
|
||||
NAME = gitea
|
||||
USER = root
|
||||
PASSWD =
|
||||
LOG_SQL = false
|
||||
|
||||
[lfs]
|
||||
PATH = /data/git/lfs
|
||||
|
||||
[log]
|
||||
ROOT_PATH = /data/gitea/log
|
||||
```
|
||||
|
||||
Запускаем Gitea, скорее всего она начнёт падать с ошибкой `permission denied`, а Docker будет пытаться её перезапустить. При первом запуске Gitea создаёт директории для ssh ключей, но по какой-то причине они создаются из-под `root`, а не из-под пользователя `gitea`.
|
||||
|
||||
```sh
|
||||
# Специально без -d, ждём когда в логах повалятся ошибки и нажимаем Ctrl+C
|
||||
docker compose up
|
||||
```
|
||||
|
||||
Теперь нужно из-под `root` или с помощью `sudo` указать нужные права.
|
||||
|
||||
```sh
|
||||
# Выходим из пользователя gitea (Ctrl + D или exit)
|
||||
# и выполняем команду с root правами
|
||||
sudo chown -R gitea:gitea ~gitea/data
|
||||
```
|
||||
|
||||
Снова запускаем Gitea.
|
||||
|
||||
```sh
|
||||
sudo su - gitea
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Если всё работает корректно, то файлы бэкапа можно удалить.
|
||||
|
||||
```sh
|
||||
rm -rf dump gitea-dump-*.zip
|
||||
```
|
||||
|
||||
|
||||
## Кастомизация Gitea
|
||||
|
||||
Во всех командах подразумевается, что Gitea [установлена из бинарника](https://docs.gitea.com/installation/install-from-binary) и [запускается как `systemd` сервис](https://docs.gitea.com/installation/linux-service).
|
||||
|
||||
В документации есть страница, посвящённая [кастомизации Gitea](https://docs.gitea.com/administration/customizing-gitea).
|
||||
|
||||
|
||||
## Свой `css`
|
||||
### Свой `css`
|
||||
|
||||
Добавляем ссылку на свой файл со стилями.
|
||||
|
||||
@@ -131,7 +386,7 @@ sudo systemctl restart gitea
|
||||
|
||||
После изменения стилей, страницу в браузере нужно обновить с помощью `ctrl + f5`.
|
||||
|
||||
## Настройка `app.ini`
|
||||
### Настройка `app.ini`
|
||||
|
||||
Перечень всех возможных настроек представлен в [документации](https://docs.gitea.com/administration/config-cheat-sheet).
|
||||
|
||||
@@ -172,7 +427,7 @@ sudo systemctl restart gitea
|
||||
sudo systemctl restart gitea
|
||||
```
|
||||
|
||||
## Изменение шаблонов страниц
|
||||
### Изменение шаблонов страниц
|
||||
|
||||
Ищем шаблон для нужной версии в [репозитории Gitea](https://github.com/go-gitea/gitea/tree/main/templates), загружаем с помощью `wget` по такому же пути в `$GITEA_CUSTOM/templates` и редактируем.
|
||||
|
||||
|
||||
282
docs/misc/minecraft-server.md
Normal file
282
docs/misc/minecraft-server.md
Normal file
@@ -0,0 +1,282 @@
|
||||
# Minecraft Server
|
||||
|
||||
[docker-minecraft-server](https://github.com/itzg/docker-minecraft-server) - самый простой и удобный способ запуска своего Minecraft сервера. У проекта есть хорошая [документация](https://docker-minecraft-server.readthedocs.io/en/latest/), но всё же есть некоторые нюансы, которые стоит записать.
|
||||
|
||||
## Запуск сервера
|
||||
|
||||
1. Устанавливаем [`docker`](https://docs.docker.com/engine/install/ubuntu/#install-using-the-repository). Не забываем про [post-install steps](https://docs.docker.com/engine/install/linux-postinstall/#manage-docker-as-a-non-root-user).
|
||||
2. Создаём папку для сервера.
|
||||
```sh
|
||||
mkdir minecraft-server
|
||||
cd minecraft-server
|
||||
```
|
||||
3. Создаём файл `docker-compose.yml`.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
nano docker-compose.yml
|
||||
```
|
||||
|
||||
=== "docker-compose.yml"
|
||||
|
||||
```yaml
|
||||
# https://docker-minecraft-server.readthedocs.io/en/latest/
|
||||
services:
|
||||
mc:
|
||||
image: itzg/minecraft-server
|
||||
tty: true
|
||||
stdin_open: true
|
||||
ports:
|
||||
# Порт 25565 является стандартным, все клиенты по умолчанию
|
||||
# подключаются к нему, если порт не задан явно
|
||||
- "25565:25565"
|
||||
environment:
|
||||
# Полный список переменных можно найти в документации
|
||||
# https://docker-minecraft-server.readthedocs.io/en/latest/variables/
|
||||
|
||||
EULA: "TRUE"
|
||||
|
||||
# Не забудьте указать нужную версию Minecraft
|
||||
VERSION: 1.19.4
|
||||
|
||||
# Разрешаем подключаться без лицензии Minecraft
|
||||
ONLINE_MODE: false
|
||||
|
||||
# Указываем название игрового мира (будет храниться в ./data/<LEVEL>)
|
||||
# Чтобы изменить мир, достаточно изменить значение этой переменной
|
||||
# и перезапустить контейнер
|
||||
LEVEL: MyWorld
|
||||
|
||||
# Описание сервера
|
||||
MOTD: |
|
||||
Tish's Minecraft Server on %VERSION%
|
||||
|
||||
# Иконка сервера
|
||||
# Надо разместить файл icon.png в ./data/
|
||||
# ICON: /data/icon.png
|
||||
# OVERRIDE_ICON: true
|
||||
|
||||
# Автоотключение пустого сервера
|
||||
# ENABLE_AUTOSTOP: TRUE
|
||||
# AUTOSTOP_TIMEOUT_EST: 300
|
||||
# AUTOSTOP_TIMEOUT_INIT: 600
|
||||
|
||||
volumes:
|
||||
- ./data:/data
|
||||
```
|
||||
|
||||
4. Запускаем сервер.
|
||||
|
||||
```sh
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Остановка сервера
|
||||
|
||||
```sh
|
||||
docker compose stop
|
||||
```
|
||||
|
||||
## Консоль сервера
|
||||
|
||||
`ctrl + p ctrl + q` - отключиться от консоли.
|
||||
Если просто нажать `ctrl + c`, то сервер остановится.
|
||||
|
||||
```sh
|
||||
docker compose attach mc
|
||||
```
|
||||
|
||||
### Шпаргалка по командам
|
||||
|
||||
1. `/list` — список игроков.
|
||||
2. `/op <nickname>` — сделать игрока оператором.
|
||||
3. `/deop <nickname>` — удалить из списка операторов.
|
||||
4. Отдельной команды для просмотра списка операторов нет, но он хранится в файле `data/ops.json`.
|
||||
5. `/whitelist <on|off>` — включить или выключить белый список игроков.
|
||||
6. `/whitelist list` — вывести белый список игроков.
|
||||
7. `/whitelist add <nickname>` — добавить игрока в белый список.
|
||||
8. `/whitelist remove <nickname>` — удалить игрока из белого списка.
|
||||
9. `/gamemode <0|1|2|3>` — изменить режим игры (0 — выживание, 1 — креатив, 2 — приключение, 3 — наблюдатель).
|
||||
10. `/time set <day|night|<число>>` — установить время суток.
|
||||
11. `/weather <clear|rain|thunder>` — изменить погоду.
|
||||
12. `/tp <nickname1> <nickname2>` — телепортировать первого игрока ко второму.
|
||||
13. `/difficulty <peaceful|easy|normal|hard>` — изменить уровень сложности сервера.
|
||||
|
||||
## Домен для сервера
|
||||
|
||||
Если порт стандартный (`25565`), то при подключении можно просто указать домен в A-записи которого указан IP-адрес сервера. Однако если порт нестандартный или хочется сделать несколько доменных имён для одного сервера, то можно использовать SRV-записи.
|
||||
|
||||
Например, если я создам домен `minecraft.tishenko.dev` и запущу сервер на порте `12345`, то чтобы подключаться к серверу без указания порта, мне нужно будет добавить следующую SRV-запись для `minecraft.tishenko.dev`:
|
||||
|
||||
```dns
|
||||
_minecraft._tcp.minecraft.tishenko.dev. 3600 IN SRV 0 5 12345 minecraft.tishenko.dev.
|
||||
```
|
||||
|
||||
Обычно ДНС провайдеры предоставляют UI для создания записей, в нём скорее всего будут следующие поля:
|
||||
|
||||
- Поддомен: `minecraft`
|
||||
- Сервис: `minecraft` (SpaceWeb, например, сам подставляет `_`)
|
||||
- Протокол: `tcp`
|
||||
- TTL: `3600`
|
||||
- Приоритет: `0`
|
||||
- Вес: `5`
|
||||
- Порт: `12345`
|
||||
- Целевой домен: `minecraft.tishenko.dev.` (точка в конце обязательна)
|
||||
|
||||
Целевой домен не обязательно должен совпадать с поддоменом. Можно сделать подключение к серверу по домену `tishenko.dev` указан следующую SRV-запись для домена `tishenko.dev`:
|
||||
|
||||
```dns
|
||||
_minecraft._tcp.tishenko.dev. 3600 IN SRV 0 5 12345 minecraft.tishenko.dev.
|
||||
```
|
||||
|
||||
Домен `minecraft.tishenko.dev` в своей A-записи должен указывать на IP-адрес сервера, но при этом совершенно неважно какая A-запись будет у `tishenko.dev`.
|
||||
|
||||
DNS-записи распространяются не мгновенно, но обычно это занимает 15-30 минут. Отслеживать распространение записей можно с помощью сайта [DNS Checker](https://dnschecker.org/#SRV/_minecraft._tcp.tishenko.dev).
|
||||
|
||||
!!! note "Клиенты Minecraft читают SRV-запись"
|
||||
|
||||
С помощью SRV-записи можно подменять как порт, так и домен сервера. Стандартный клиент Minecraft Java Edition при подключении по домену автоматически ищет SRV-запись _minecraft._tcp.<домен> в DNS. Если такая запись есть, клиент использует указанные в ней порт и хост. С Bedrock Edition могут возникнуть сложности, там не все клиенты читают SRV-запись.
|
||||
|
||||
|
||||
## Автоматическое создание бэкапов
|
||||
|
||||
Скрипт ниже автоматически создаёт бэкапы при завершении работы сервера. Особенно удобно сочетать его с настройкой `ENABLE_AUTOSTOP`, тогда при завершении игровой сессии бэкап будет создан автоматически.
|
||||
|
||||
=== "Терминал"
|
||||
```sh
|
||||
# Создаём скрипт в директории рядом с docker-compose.yml
|
||||
nano run-and-backup.sh
|
||||
|
||||
# После создания скрипта надо дать ему права на выполнение
|
||||
chmod u+x run-and-backup.sh
|
||||
```
|
||||
|
||||
=== "run-and-backup.sh"
|
||||
|
||||
```bash
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# === настройки ===
|
||||
PROJECT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
DATA_DIR="${PROJECT_DIR}/data"
|
||||
BACKUP_DIR="${PROJECT_DIR}/backups"
|
||||
KEEP_BACKUPS=3
|
||||
TAR_COMPRESS_FLAGS="-czf"
|
||||
|
||||
mkdir -p "$BACKUP_DIR"
|
||||
|
||||
ts() { date +"%Y-%m-%d_%H-%M-%S"; }
|
||||
|
||||
show_help() {
|
||||
cat <<'EOF'
|
||||
run-and-backup.sh — запускает Minecraft-сервер через Docker Compose
|
||||
и создаёт резервную копию каталога ./data после завершения работы.
|
||||
|
||||
ИСПОЛЬЗОВАНИЕ:
|
||||
./run-and-backup.sh — запустить сервер в foreground
|
||||
./run-and-backup.sh -d — запустить в background (логи в run-and-backup.log)
|
||||
./run-and-backup.sh -b — только сделать бэкап и выйти
|
||||
./run-and-backup.sh -h — показать эту справку
|
||||
|
||||
ЧТО ДЕЛАЕТ:
|
||||
1) docker compose up (следит за завершением контейнера)
|
||||
2) по Ctrl+C или штатному выходу — docker compose down
|
||||
3) создаёт архив ./backups/mc-data-YYYY-MM-DD_HH-MM-SS.tar.gz
|
||||
4) хранит последние KEEP_BACKUPS бэкапов
|
||||
|
||||
КАК ВОССТАНОВИТЬ СЕРВЕР ИЗ БЭКАПА:
|
||||
1) Остановите сервер:
|
||||
docker compose down
|
||||
2) Очистите или перенесите текущие данные:
|
||||
mv ./data ./data.old
|
||||
mkdir ./data
|
||||
ИЛИ
|
||||
rm -rf ./data/*
|
||||
3) Распакуйте нужный архив в ./data:
|
||||
tar -xzf ./backups/mc-data-YYYY-MM-DD_HH-MM-SS.tar.gz -C ./data
|
||||
4) Запустите сервер
|
||||
|
||||
ПРИМЕЧАНИЯ:
|
||||
• Архив содержит всё из ./data (мир, плагины, конфиги, whitelist, ops и т.д.)
|
||||
• Для фонового режима логи скрипта пишутся в ./run-and-backup.log
|
||||
EOF
|
||||
}
|
||||
|
||||
backup() {
|
||||
local stamp archive
|
||||
stamp="$(ts)"
|
||||
archive="${BACKUP_DIR}/mc-data-${stamp}.tar.gz"
|
||||
|
||||
if [[ ! -d "$DATA_DIR" ]]; then
|
||||
echo "[!] Нет каталога DATA_DIR: $DATA_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "[*] Бэкап ${DATA_DIR} -> ${archive}"
|
||||
tar $TAR_COMPRESS_FLAGS "$archive" -C "$DATA_DIR" .
|
||||
echo "[+] Готово: $archive"
|
||||
|
||||
echo "[*] Ротация: оставляю последние ${KEEP_BACKUPS}"
|
||||
ls -1t "${BACKUP_DIR}"/mc-data-*.tar.* 2>/dev/null | tail -n +$((KEEP_BACKUPS+1)) | xargs -r rm -f
|
||||
}
|
||||
|
||||
graceful_down_and_backup() {
|
||||
echo "[*] Останавливаю docker compose (graceful)..."
|
||||
docker compose down || true
|
||||
backup
|
||||
}
|
||||
|
||||
# ---- разбор флагов ----
|
||||
bg=false
|
||||
do_backup_only=false
|
||||
|
||||
while getopts ":dbh" opt; do
|
||||
case "$opt" in
|
||||
d) bg=true ;;
|
||||
b) do_backup_only=true ;;
|
||||
h) show_help; exit 0 ;;
|
||||
\?) echo "Неизвестный флаг: -$OPTARG" >&2; show_help; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# -b имеет приоритет: просто делаем бэкап и выходим
|
||||
if $do_backup_only; then
|
||||
backup
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# запуск в фоне
|
||||
if $bg; then
|
||||
echo "[*] Запускаю в background (логи: ${PROJECT_DIR}/run-and-backup.log)"
|
||||
nohup "$0" >"${PROJECT_DIR}/run-and-backup.log" 2>&1 &
|
||||
echo "[✓] PID: $!"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# ---- основной режим ----
|
||||
trap graceful_down_and_backup INT TERM
|
||||
|
||||
echo "[*] Запускаю docker compose в foreground (Ctrl+C для остановки)..."
|
||||
if docker compose up; then
|
||||
echo "[*] docker compose завершился сам — делаю бэкап..."
|
||||
backup
|
||||
else
|
||||
echo "[!] docker compose завершился с ошибкой; если это был Ctrl+C, бэкап уже выполнен ловушкой."
|
||||
fi
|
||||
|
||||
echo "[✓] Готово."
|
||||
```
|
||||
|
||||
Теперь можно запускать сервер командой `./run-and-backup.sh`.
|
||||
|
||||
```sh
|
||||
./run-and-backup.sh -d
|
||||
```
|
||||
|
||||
Вывести справку можно командой.
|
||||
|
||||
```sh
|
||||
./run-and-backup.sh -h
|
||||
```
|
||||
51
docs/servers/bash.md
Normal file
51
docs/servers/bash.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Bash
|
||||
|
||||
## Поиск по истории команд в bash (`↑/↓`)
|
||||
|
||||
Включаем поиск по истории команд `bash` по префиксу.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
nano ~/.inputrc
|
||||
```
|
||||
|
||||
=== ".inputrc"
|
||||
|
||||
```sh
|
||||
"\e[A": history-search-backward
|
||||
"\e[B": history-search-forward
|
||||
```
|
||||
|
||||
После обновления `.inputrc` нужно либо начать сеанс заново, либо выполнить команду.
|
||||
|
||||
```sh
|
||||
bind -f ~/.inputrc
|
||||
```
|
||||
|
||||
## Поиск по истории команд (`ctrl + r`)
|
||||
|
||||
`ctrl + r` — начать поиск по истории команд. Дальше можно вводить любую часть команды, поиск будет инкрементально обновляться с каждым введённым символом.
|
||||
|
||||
- При повторном нажатии `ctrl + r` будет выведена следующая подходящая команда.
|
||||
- `Esc` или `ctrl + g` — прервать поиск и вернуться в обычный режим.
|
||||
- `→` или `ctrl + j` — вставить найденную команду в командную строку, но не выполнять. Пригождается, если нужно предварительно отредактировать команду.
|
||||
- `Enter` — выполнить найденную команду.
|
||||
|
||||
|
||||
## Сочетания клавиш
|
||||
|
||||
В Bash есть множество сочетаний клавиш для быстрой навигации и редактирования команд.
|
||||
Это функции [GNU Readline](https://en.wikipedia.org/wiki/GNU_Readline) (по этой же ссылке можно найти полный список сочетаний).
|
||||
|
||||
- `ctrl + l` — очистить экран (аналог `clear`).
|
||||
- `alt + .` — вставить последний аргумент предыдущей команды.
|
||||
- `ctrl + a` — в начало строки.
|
||||
- `ctrl + e` — в конец строки.
|
||||
- `alt + b` — назад на одно слово.
|
||||
- `alt + f` — вперед на одно слово.
|
||||
- `ctrl + b` и `ctrl + f` — назад/вперед на один символ (аналог `← / →`, но не нужно тянуться к стрелочкам).
|
||||
- `ctrl + p` и `ctrl + n` — переход по истории команд (аналог `↑ / ↓`, но не нужно тянуться к стрелочкам).
|
||||
- `alt + r` — отменить изменения в команде и вернуть к виду, в котором она хранится в истории команд.
|
||||
- `alt + d` — удалить слово справа от курсора.
|
||||
- `ctrl + w` — удалить слово слева от курсора.
|
||||
75
docs/servers/cleanup.md
Normal file
75
docs/servers/cleanup.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# Очистка места на сервере
|
||||
|
||||
## Полезные команды
|
||||
|
||||
```sh
|
||||
# Проверить место во всех разделах
|
||||
df -h
|
||||
|
||||
# Размер файла/папки
|
||||
du -sh <path>
|
||||
|
||||
# Показать самые большие директории в корне
|
||||
sudo du -h -d1 / | sort -hr
|
||||
|
||||
# В домашнем каталоге
|
||||
du -h -d1 ~ | sort -hr
|
||||
|
||||
# Показать файлы больше 100MB
|
||||
find . -type f -size +100M -exec ls -lh {} \; | awk '{print $5, $9}' | sort -hr
|
||||
```
|
||||
|
||||
## Логи `journalctl`
|
||||
|
||||
```sh
|
||||
# Посмотреть сколько занимают логи журнала
|
||||
sudo journalctl --disk-usage
|
||||
|
||||
# Оставить только 100MB самых актуальных логов
|
||||
sudo journalctl --rotate
|
||||
sudo journalctl --vacuum-size=100M
|
||||
|
||||
# Можно задать параметры SystemMaxUse и RuntimeMaxUse
|
||||
# Вместо MB надо использовать M
|
||||
sudo nano /etc/systemd/journald.conf
|
||||
|
||||
# Применить изменения в конфиге
|
||||
sudo systemctl restart systemd-journald
|
||||
```
|
||||
|
||||
## Другие логи
|
||||
|
||||
```sh
|
||||
# Посмотреть сколько места занимают логи
|
||||
sudo du -h -d1 /var/log | sort -hr
|
||||
|
||||
# Очищать файлы с логами лучше командой, чтобы процессы могли
|
||||
# дальше писать логи в этим файлы
|
||||
sudo truncate -s 0
|
||||
```
|
||||
|
||||
## Кэш пакетов
|
||||
|
||||
```sh
|
||||
sudo apt-get clean
|
||||
sudo apt-get autoremove --purge
|
||||
```
|
||||
|
||||
## Docker
|
||||
|
||||
```sh
|
||||
# Посмотреть сколько место занимает докер
|
||||
docker system df
|
||||
# Показать детализацию по образам, контейнерам, волюмам
|
||||
docker system df -v
|
||||
|
||||
# Удалить все нетегированные образы, остановленные контейнеры,
|
||||
# неиспользуемые сети, кэш сборки
|
||||
docker system prune
|
||||
|
||||
# Очистит также все образы, с которыми не связан ни один контейнер
|
||||
docker system prune -a
|
||||
|
||||
# Удалить волюмы, с которыми не связан ни один контейнер
|
||||
docker volume prune
|
||||
```
|
||||
454
docs/servers/mail.md
Normal file
454
docs/servers/mail.md
Normal file
@@ -0,0 +1,454 @@
|
||||
# Почта on-premise
|
||||
|
||||
Настройка почты на своём сервере со своим доменным именем. В качестве почтового сервера используется [Docker Mailserver](https://github.com/docker-mailserver/docker-mailserver) версии 15.1.0. Вебклиент — [Roundcube Webmail](https://github.com/roundcube/roundcubemail) версии 1.6.11.
|
||||
|
||||
## Открытие портов для почты
|
||||
|
||||
Многие хостинг провайдеры блокируют исходящие соединения на портах 25, 465 и 587, чтобы предотвратить спам или вредоносные рассылки с их серверов. Можно проверить доступность портов с помощью команды `nc`.
|
||||
|
||||
```sh
|
||||
# Выведет "Connection to smtp.gmail.com 25 port [tcp/*] succeeded!",
|
||||
# если порт открыт
|
||||
nc -vz smtp.gmail.com 25
|
||||
nc -vz smtp.gmail.com 465
|
||||
nc -vz smtp.gmail.com 587
|
||||
```
|
||||
|
||||
Если порты закрыты, то можно обратиться в поддержку хостинг провайдера с запросом на открытие портов.
|
||||
|
||||
??? abstract "Пример обращения в поддержку"
|
||||
```
|
||||
Добрый день!
|
||||
|
||||
Прошу разблокировать исходящие соединения на порты 25/tcp, 465/tcp и 587/tcp
|
||||
для моего сервера (<IP-адрес сервера>).
|
||||
Сервер используется для личного почтового домена <домен>, не для массовых рассылок.
|
||||
|
||||
Спасибо!
|
||||
```
|
||||
|
||||
## Настройка DNS
|
||||
|
||||
Настройка DNS на примере домена `tishenko.dev` (почта `@tishenko.dev`). Более подробное описание всех настроек можно прочитать в документации Docker Mailserver: [[1]](https://docker-mailserver.github.io/docker-mailserver/latest/usage/#minimal-dns-setup) и [[2]](https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/).
|
||||
|
||||
Со стороны DNS провайдера:
|
||||
|
||||
1. Добавляем поддомен для почты, например, `mail.tishenko.dev` и `www.mail.tishenko.dev`. В A-записи поддомена указываем IP-адрес сервера.
|
||||
|
||||
2. Добавляем MX-запись для основного домена `tishenko.dev`, именно этот домен будет использоваться для отправки и получения почты `@tishenko.dev`.
|
||||
```dns
|
||||
10 mail.tishenko.dev.
|
||||
```
|
||||
Обязательно с точкой в конце. Число 10 это приоритет MX-записи, чем меньше число, тем выше приоритет. Приоритет не играет роли, если запись только одна. MX-записи, созданные DNS провайдером, нужно удалить.
|
||||
|
||||
3. Добавляем TXT-запись для DMARC. Запись надо создать для домена `_dmarc.tishenko.dev.`.
|
||||
```dns
|
||||
v=DMARC1; p=quarantine; sp=quarantine; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:dmarc.report@tishenko.dev; ruf=mailto:dmarc.report@tishenko.dev
|
||||
```
|
||||
DMARC-записи, созданные DNS провайдером, нужно удалить.
|
||||
|
||||
4. Добавляем TXT-запись для SPF. Запись надо создать для домена `tishenko.dev.`.
|
||||
```dns
|
||||
v=spf1 mx -all
|
||||
```
|
||||
SPF-записи, созданные DNS провайдером, нужно удалить.
|
||||
|
||||
5. Для окончательной настройки нужно также добавить TXT-запись для DKIM. Однако это можно сделать только после настройки почтового сервера и создания пары ключей. Подробнее про настройку DKIM написано [ниже](#настройка-dkim).
|
||||
|
||||
Со стороны владельца IP-адреса, как правило это VDS провайдер, создаём или редактируем PTR запись для IP-адреса почтового сервера. Указываем в ней почтовый адрес: `mail.tishenko.dev.`.
|
||||
|
||||
??? question "Как проверить настройки DNS?"
|
||||
|
||||
Можно использовать [DNS Checker](https://dnschecker.org/) для проверки [A](https://dnschecker.org/#A/mail.tishenko.dev), [MX](https://dnschecker.org/#MX/tishenko.dev), [PTR](https://dnschecker.org/#PTR/146.103.98.219), [DMARC](https://dnschecker.org/#TXT/_dmarc.tishenko.dev) и [SPF](https://dnschecker.org/#TXT/tishenko.dev) записей.
|
||||
|
||||
Либо использовать команду `dig`.
|
||||
|
||||
```sh
|
||||
# Команда должна вывести IP-адрес сервера
|
||||
dig @1.1.1.1 +short A mail.tishenko.dev
|
||||
|
||||
# 10 mail.tishenko.dev.
|
||||
dig @1.1.1.1 +short MX tishenko.dev
|
||||
|
||||
# mail.tishenko.dev.
|
||||
dig @1.1.1.1 +short -x 146.103.98.219
|
||||
|
||||
# Проверить DMARC
|
||||
dig @1.1.1.1 +short TXT _dmarc.tishenko.dev
|
||||
|
||||
# Проверить SPF
|
||||
dig @1.1.1.1 +short TXT tishenko.dev
|
||||
```
|
||||
|
||||
Обновление DNS происходит не мгновенно, обычно это занимает около 20 минут.
|
||||
|
||||
??? abstract "Пример файла зоны"
|
||||
|
||||
В панели управления DNS провайдера можно выгрузить файл зоны и убедиться, что все записи добавились корректно.
|
||||
|
||||
```dns
|
||||
IN MX 10 mail.tishenko.dev.
|
||||
mail IN A 146.103.98.219
|
||||
www.mail IN A 146.103.98.219
|
||||
@ 600 IN TXT "v=spf1 mx -all"
|
||||
_dmarc 600 IN TXT "v=DMARC1; p=quarantine; sp=quarantine; fo=0; adkim=r; aspf=r; pct=100; rf=afrf; ri=86400; rua=mailto:dmarc.report@tishenko.dev; ruf=mailto:dmarc.report@tishenko.dev"
|
||||
```
|
||||
|
||||
## Docker Mailserver
|
||||
|
||||
Docker Mailserver (DMS) имеет отличную [документацию](https://docker-mailserver.github.io/docker-mailserver/latest/usage/). И DNS и почтовый сервер можно настроить просто пройдясь по ней. Эта заметка лишь дополняет документацию.
|
||||
|
||||
```sh
|
||||
# Открываем порты для почты (если используется ufw)
|
||||
sudo ufw allow 25,143,465,587,993/tcp
|
||||
|
||||
# Создаём отдельного пользователя для управления почтой
|
||||
# Пользователь vmail в контейнере DMS по умолчанию имеет uid 5000,
|
||||
# поэтому желательно, чтобы и на хосте он имел такой же uid
|
||||
sudo useradd -u 5000 --create-home --shell /bin/bash vmail
|
||||
sudo usermod -aG docker vmail
|
||||
|
||||
# Переключаемся на пользователя vmail
|
||||
sudo su - vmail
|
||||
|
||||
# Скачиваем compose.yaml и mailserver.env из репозитория DMS
|
||||
# Версия 15.1.0
|
||||
DMS_GITHUB_URL="https://raw.githubusercontent.com/docker-mailserver/docker-mailserver/refs/tags/v15.1.0"
|
||||
wget "${DMS_GITHUB_URL}/compose.yaml"
|
||||
wget "${DMS_GITHUB_URL}/mailserver.env"
|
||||
```
|
||||
|
||||
Теперь нужно отредактировать `compose.yaml` и `mailserver.env`.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
nano compose.yaml
|
||||
```
|
||||
|
||||
=== "compose.yaml"
|
||||
|
||||
В `image` указываем конкретную версию вместо `:latest`. В `hostname` указываем почтовый домен (e. g. mail.tishenko.dev).
|
||||
|
||||
Также прокидываем в контейнер волюм `/etc/letsencrypt` для подключения SSL сертификатов, актуально если на хосте используется letsencrypt.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
mailserver:
|
||||
image: ghcr.io/docker-mailserver/docker-mailserver:15.1.0
|
||||
container_name: mailserver
|
||||
# Provide the FQDN of your mail server here (Your DNS MX record should point to this value)
|
||||
hostname: mail.tishenko.dev
|
||||
env_file: mailserver.env
|
||||
# More information about the mail-server ports:
|
||||
# https://docker-mailserver.github.io/docker-mailserver/latest/config/security/understanding-the-ports/
|
||||
ports:
|
||||
- "25:25" # SMTP (explicit TLS => STARTTLS, Authentication is DISABLED => use port 465/587 instead)
|
||||
- "143:143" # IMAP4 (explicit TLS => STARTTLS)
|
||||
- "465:465" # ESMTP (implicit TLS)
|
||||
- "587:587" # ESMTP (explicit TLS => STARTTLS)
|
||||
- "993:993" # IMAP4 (implicit TLS)
|
||||
volumes:
|
||||
- ./docker-data/dms/mail-data/:/var/mail/
|
||||
- ./docker-data/dms/mail-state/:/var/mail-state/
|
||||
- ./docker-data/dms/mail-logs/:/var/log/mail/
|
||||
- ./docker-data/dms/config/:/tmp/docker-mailserver/
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/letsencrypt:/etc/letsencrypt:ro
|
||||
restart: always
|
||||
stop_grace_period: 1m
|
||||
# Uncomment if using `ENABLE_FAIL2BAN=1`:
|
||||
# cap_add:
|
||||
# - NET_ADMIN
|
||||
healthcheck:
|
||||
test: "ss --listening --ipv4 --tcp | grep --silent ':smtp' || exit 1"
|
||||
timeout: 3s
|
||||
retries: 0
|
||||
```
|
||||
|
||||
=== "mailserver.env"
|
||||
|
||||
В этой заметке DMS настраивается с антиспамом Rspamd. Как отмечено в [документации](https://docker-mailserver.github.io/docker-mailserver/v15.1/config/security/rspamd/), его планируется использовать по умолчанию в будущих версиях DMS. На той же странице документации перечислены legacy проверки, которые нужно отключить. Тут они также продублированы.
|
||||
|
||||
```sh
|
||||
# Указываем тип SSL сертификатов
|
||||
SSL_TYPE=letsencrypt
|
||||
|
||||
# Включаем Rspamd
|
||||
ENABLE_RSPAMD=1
|
||||
|
||||
# Отключаем legacy проверки, т. к. они уже включены в Rspamd
|
||||
ENABLE_OPENDKIM=0
|
||||
ENABLE_OPENDMARC=0
|
||||
ENABLE_POLICYD_SPF=0
|
||||
ENABLE_AMAVIS=0
|
||||
RSPAMD_GREYLISTING=1
|
||||
```
|
||||
|
||||
```sh
|
||||
# Создаём директории для волюмов DMS заранее,
|
||||
# чтобы у них был правильный владелец (vmail)
|
||||
mkdir -p ./docker-data/dms/{mail-data,mail-state,mail-logs,config}
|
||||
|
||||
# Запускаем DMS
|
||||
docker compose up -d
|
||||
|
||||
# В течение двух минут после первого запуска DMS нужно создать хотя бы один
|
||||
# почтовый адрес, иначе контейнер завершится с ошибкой
|
||||
# Команда предложит задать пароль для нового почтового аккаунта
|
||||
docker exec -it mailserver setup email add artem@tishenko.dev
|
||||
|
||||
# Обязательно добавляем alias для адреса postmaster
|
||||
docker exec -it mailserver setup alias add postmaster@tishenko.dev artem@tishenko.dev
|
||||
```
|
||||
|
||||
### Настройка SSL
|
||||
|
||||
В документации DMS есть отдельная [страница](https://docker-mailserver.github.io/docker-mailserver/latest/config/security/ssl/) про настройку SSL сертификатов.
|
||||
|
||||
Далее подразумевается, что волюм `/etc/letsencrypt` уже прокинут в контейнер, а также в `mailserver.env` указана переменная `SSL_TYPE=letsencrypt`.
|
||||
|
||||
Получаем сертификаты. Команды нужно выполнять от пользователя с правом использовать `sudo`. `certbot` можно установить с помощью [pip](https://certbot.eff.org/instructions?ws=other&os=pip).
|
||||
|
||||
```sh
|
||||
# Порт 80 нужен для получения и обновления сертификатов
|
||||
sudo ufw allow 80/tcp
|
||||
|
||||
# Если на сервере есть nginx или другой веб-сервер, используем соответствующий флаг
|
||||
sudo certbot certonly --nginx -d mail.tishenko.dev -d www.mail.tishenko.dev
|
||||
|
||||
# Если на сервере нет nginx (порт 80 не должен быть занят)
|
||||
sudo certbot certonly --standalone -d mail.tishenko.dev -d www.mail.tishenko.dev
|
||||
```
|
||||
|
||||
|
||||
### Настройка DKIM
|
||||
|
||||
В документации DMS есть отдельная [страница](https://docker-mailserver.github.io/docker-mailserver/latest/config/best-practices/dkim_dmarc_spf/) про настройку DKIM, DMARC и SPF. Про настройку DMARC и SPF написано [выше](#настройка-dns), а вот для настройки DKIM нужно сначала сгенерировать пару ключей. Публичный ключ как раз и указывается в DKIM.
|
||||
|
||||
Команда для генерации ключей. DMS должен быть запущен.
|
||||
|
||||
```sh
|
||||
# Выведет в консоль значение для TXT-записи
|
||||
# Также её можно узнать в файле
|
||||
# cat ./docker-data/dms/config/rspamd/dkim/rsa-2048-mail-tishenko.dev.public.dns.txt
|
||||
docker exec -it mailserver setup config dkim domain tishenko.dev
|
||||
```
|
||||
|
||||
Теперь добавляем TXT запись для DKIM в DNS. Имя записи должно быть `mail._domainkey.tishenko.dev.`. Проверить запись можно с помощью сайта [DNS Checker](https://dnschecker.org/#TXT/mail._domainkey.tishenko.dev) или команды `dig`.
|
||||
|
||||
```sh
|
||||
# Должна вывести "v=DKIM1; k=rsa; p=<публичный ключ>"
|
||||
dig @1.1.1.1 +short TXT mail._domainkey.tishenko.dev
|
||||
```
|
||||
|
||||
### Проверка
|
||||
|
||||
Работоспособность и настройки DMS можно проверить с помощью сайта [Mail-Tester](https://www.mail-tester.com/).
|
||||
|
||||
Пример команды для отправки тестового письма.
|
||||
```sh
|
||||
docker exec -it mailserver swaks \
|
||||
--to <адрес с mail-tester> \
|
||||
--from artem@tishenko.dev \
|
||||
--server mail.tishenko.dev \
|
||||
--port 587 \
|
||||
--tls \
|
||||
--auth LOGIN \
|
||||
--auth-user artem@tishenko.dev \
|
||||
--auth-password 'password'
|
||||
```
|
||||
|
||||
Если письмо дойдёт до тестового адреса, то сайт выведет результаты проверки DNS-записей и общую оценку настройки почтового сервера. Если всё сделано правильно, то оценка будет 10/10.
|
||||
|
||||
Дополнительно можно проверить настройки почтового сервера с помощью сайта [MX Toolbox](https://mxtoolbox.com/emailhealth).
|
||||
|
||||
### Администрирование
|
||||
|
||||
Администрировать DMS можно через скрипт `setup` внутри контейнера. Для этого можно подключиться к контейнеру с помощью команды.
|
||||
|
||||
```sh
|
||||
docker exec -it mailserver bash
|
||||
|
||||
# Уже внутри контейнера
|
||||
setup help
|
||||
```
|
||||
|
||||
Если нужно выполнить всего одну команду, то можно не запускать bash.
|
||||
|
||||
```sh
|
||||
docker exec -it mailserver setup help
|
||||
```
|
||||
|
||||
|
||||
## Roundcube
|
||||
|
||||
Roundcube проще всего развернуть с помощью Docker Compose. Актуальную версию образа можно выбрать на [Docker Hub](https://hub.docker.com/r/roundcube/roundcubemail). Там же можно посмотреть список переменных окружения и их значения. Далее подразумевается, что выбран образ `apache-nonroot`, а также что для управления почтой создан отдельный пользователь `vmail` с uid/gid 5000, как показано в инструкции [выше](#настройка-docker-mailserver).
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
# Переключаемся на пользователя vmail
|
||||
sudo su - vmail
|
||||
|
||||
mkdir ./roundcube
|
||||
cd ./roundcube
|
||||
|
||||
# Создаём директории для волюмов Roundcube заранее,
|
||||
# чтобы у них был правильный владелец (vmail)
|
||||
mkdir -p ./roundcube/{app,config,db,tmp}
|
||||
|
||||
nano docker-compose.yml
|
||||
```
|
||||
|
||||
=== "Пример docker-compose.yml"
|
||||
|
||||
```yaml
|
||||
services:
|
||||
roundcube:
|
||||
image: roundcube/roundcubemail:1.6.11-apache-nonroot
|
||||
container_name: roundcube
|
||||
restart: always
|
||||
user: "5000:5000"
|
||||
ports:
|
||||
- "25025:8000"
|
||||
environment:
|
||||
# IMAP
|
||||
- ROUNDCUBEMAIL_DEFAULT_HOST=ssl://mail.tishenko.dev
|
||||
- ROUNDCUBEMAIL_DEFAULT_PORT=993
|
||||
|
||||
# SMTP
|
||||
- ROUNDCUBEMAIL_SMTP_SERVER=tls://mail.tishenko.dev
|
||||
- ROUNDCUBEMAIL_SMTP_PORT=587
|
||||
- ROUNDCUBEMAIL_SMTP_USER=%u
|
||||
- ROUNDCUBEMAIL_SMTP_PASS=%p
|
||||
|
||||
# DB
|
||||
- ROUNDCUBEMAIL_DB_TYPE=sqlite
|
||||
|
||||
# Misc
|
||||
- ROUNDCUBEMAIL_USERNAME_DOMAIN=tishenko.dev
|
||||
volumes:
|
||||
- ./roundcube/app:/var/www/html
|
||||
- ./roundcube/config:/var/roundcube/config
|
||||
- ./roundcube/db:/var/roundcube/db
|
||||
- ./roundcube/tmp:/tmp/roundcube-temp
|
||||
```
|
||||
|
||||
Теперь Roundcube доступен на `http://localhost:25025`, чтобы его можно было использовать извне, нужно настроить nginx или аналогичный веб-сервер.
|
||||
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
sudo nano /etc/nginx/sites-available/mail.conf
|
||||
sudo ln -s /etc/nginx/sites-available/mail.conf /etc/nginx/sites-enabled/
|
||||
```
|
||||
|
||||
=== "Пример nginx конфига"
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name mail.tishenko.dev www.mail.tishenko.dev;
|
||||
|
||||
client_max_body_size 25m;
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:25025;
|
||||
include proxy_params;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Установить SSL сертификат можно с помощью certbot. Причём если сертификат уже был получен на этапе [настройки DMS](#настройка-ssl), то certbot предложит использовать его.
|
||||
|
||||
```sh
|
||||
sudo certbot --nginx -d mail.tishenko.dev -d www.mail.tishenko.dev
|
||||
```
|
||||
|
||||
### Конфиг
|
||||
|
||||
Некоторые настройки Roundcube нельзя задать через переменные окружения, они задаются в файле `config.inc.php`. Например, "название продукта", оно отображается в заголовке страницы, на странице входа и в других местах. По умолчанию это `Roundcube Webmail`. Его можно изменить в `config/config.inc.php`.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
nano roundcube/config/config.inc.php
|
||||
```
|
||||
|
||||
=== "config.inc.php"
|
||||
|
||||
```php
|
||||
<?php
|
||||
$config['product_name'] = 'Tish\'s Mail';
|
||||
```
|
||||
|
||||
### Настройки аккаунта
|
||||
|
||||
Настройки, относящиеся к конкретному аккаунту, можно задать через UI. Как минимум стоит установить отображаемое имя, иначе у получателей будет отображаться только адрес электронной почты: `Настройки` -> `Профили` -> `Отображаемое имя`. В разделе с профилями также можно указать подпись для писем.
|
||||
|
||||
Roundcube позволяет задать несколько профилей и соответствующих адресов для одного аккаунта и легко переключаться между ними через UI. Для этого в DMS нужно создать алиас для основного адреса, а затем добавить профиль через UI Roundcube в разделе `Настройки` -> `Профили`.
|
||||
|
||||
```sh
|
||||
docker exec -it mailserver setup email add <алиас> <основной адрес>
|
||||
```
|
||||
|
||||
### Внешний вид
|
||||
|
||||
Подразумевается, что прокинут волюм `./roundcube/app:/var/www/html`. Чтобы внешние изменения не терялись при перезапуске контейнера, нужно создать свою тему для Roundcube на основе темы по умолчанию и изменять её.
|
||||
|
||||
```sh
|
||||
# Желательно выполнять команды от пользователя vmail,
|
||||
# чтобы не было проблем с правами
|
||||
# Либо подключиться к контейнеру через docker exec -it roundcube bash
|
||||
# и редактировать темы из контейнера
|
||||
sudo su - vmail
|
||||
|
||||
# Переходим в директорию с docker-compose.yml для Roundcube
|
||||
cd ./roundcube
|
||||
|
||||
# В разделе environment добавляем переменную окружения
|
||||
# ROUNDCUBEMAIL_SKIN=custom
|
||||
nano docker-compose.yml
|
||||
|
||||
# Копируем тему по умолчанию
|
||||
# Roundcube должен был быть запущен хотя бы один раз,
|
||||
# чтобы тема по умолчанию появилась в волюме
|
||||
cp -r ./roundcube/app/skins/elastic/ ./roundcube/app/skins/custom/
|
||||
|
||||
# Перезапускаем Roundcube
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
Теперь любые изменения в теме `custom` будут сохраняться при перезапуске контейнера.
|
||||
|
||||
Подробнее про темы Roundcube можно посмотреть в [документации](https://github.com/roundcube/roundcubemail/wiki/Skins).
|
||||
|
||||
#### Favicon
|
||||
|
||||
Favicon находится в `skins/custom/images/favicon.ico`. Достаточно просто заменить его на свой.
|
||||
|
||||
```sh
|
||||
cp your-favicon.ico ./roundcube/app/skins/custom/images/favicon.ico
|
||||
```
|
||||
|
||||
#### Логотип
|
||||
|
||||
Логотип находится в `skins/custom/images/logo.svg`. Достаточно просто заменить его на свой.
|
||||
|
||||
```sh
|
||||
cp your-logo.svg ./roundcube/app/skins/custom/images/logo.svg
|
||||
```
|
||||
|
||||
|
||||
## Логотип в письмах
|
||||
|
||||
Для того чтобы у получателей вместо плейсхолдера рядом с именем отправителя отображался логотип, нужно добавить BIMI TXT-запись в DNS для домена `default._bimi.tishenko.dev.`. Нужно будет настроить Nginx или другой веб-сервер, чтобы логотип был доступен по указанному в BIMI адресу.
|
||||
|
||||
```dns
|
||||
v=BIMI1; l=https://tishenko.dev/logo.svg;
|
||||
```
|
||||
|
||||
Однако в gmail и некоторых других почтовых клиентах он всё равно не будет отображаться, так как они требуют для этого платные VMC сертификаты.
|
||||
@@ -1,24 +0,0 @@
|
||||
# Разное
|
||||
|
||||
## Поиск по истории команд в bash
|
||||
|
||||
Включаем поиск по истории команд `bash` по префиксу.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
nano ~/.inputrc
|
||||
```
|
||||
|
||||
=== ".inputrc"
|
||||
|
||||
```sh
|
||||
"\e[A": history-search-backward
|
||||
"\e[B": history-search-forward
|
||||
```
|
||||
|
||||
После обновления `.inputrc` нужно либо начать сеанс заново, либо выполнить команду.
|
||||
|
||||
```sh
|
||||
bind -f ~/.inputrc
|
||||
```
|
||||
@@ -8,7 +8,7 @@
|
||||
sudo nano /etc/nginx/sites-available/new-site.conf
|
||||
```
|
||||
|
||||
=== "Пример конфига"
|
||||
=== "Статический сайт"
|
||||
|
||||
```nginx
|
||||
server {
|
||||
@@ -24,6 +24,49 @@
|
||||
}
|
||||
```
|
||||
|
||||
=== "Веб-приложение"
|
||||
|
||||
```nginx
|
||||
server {
|
||||
server_name giga-chill.ru www.giga-chill.ru;
|
||||
listen 80;
|
||||
|
||||
# Все запросы к /api/* перенаправляются на бэкенд
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8081/;
|
||||
include proxy_params;
|
||||
}
|
||||
|
||||
# Спецификация API в формате OpenAPI
|
||||
location = /api/openapi.yml {
|
||||
alias /var/www/giga-chill/openapi.yml;
|
||||
types { text/yaml yml yaml; }
|
||||
charset utf-8;
|
||||
charset_types text/yaml application/yaml text/x-yaml application/x-yaml;
|
||||
}
|
||||
|
||||
# Документация API в Swagger UI
|
||||
location = /api/swagger { return 301 /api/swagger/; }
|
||||
location /api/swagger/ {
|
||||
proxy_pass http://127.0.0.1:1240/;
|
||||
include proxy_params;
|
||||
}
|
||||
|
||||
# Документация API в Redocly
|
||||
location = /api/redoc { return 301 /api/redoc/; }
|
||||
location /api/redoc/ {
|
||||
alias /var/www/giga-chill/redoc/;
|
||||
index index.html;
|
||||
}
|
||||
|
||||
# Все остальные запросы направляются на фронтенд
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:3000;
|
||||
include proxy_params;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Активируем конфиг.
|
||||
|
||||
```sh
|
||||
@@ -37,6 +80,25 @@ sudo systemctl reload nginx.service
|
||||
sudo nginx -t
|
||||
```
|
||||
|
||||
??? question "`open() "/etc/nginx/proxy_params" failed (2: No such file or directory)`"
|
||||
|
||||
Обычно файл `/etc/nginx/proxy_params` создаётся автоматически при установке Nginx, однако его несложно добавить самостоятельно, если по каким-то причинам он не был создан или был удалён.
|
||||
|
||||
=== "Терминал"
|
||||
|
||||
```sh
|
||||
sudo nano /etc/nginx/proxy_params
|
||||
```
|
||||
|
||||
=== "proxy_params"
|
||||
|
||||
```nginx
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
```
|
||||
|
||||
## Просмотр логов
|
||||
|
||||
По умолчанию логи находятся в `access.log` и `error.log` файлах.
|
||||
@@ -91,6 +153,11 @@ SSL-сертификат получается и устанавливается
|
||||
sudo ufw enable
|
||||
```
|
||||
|
||||
Либо насовсем открыть порт 80, тогда и `renew` точно будет работать.
|
||||
|
||||
```sh
|
||||
sudo ufw allow 80/tcp
|
||||
```
|
||||
|
||||
Несколько полезных команд.
|
||||
|
||||
|
||||
@@ -42,8 +42,11 @@ sudo reboot
|
||||
Можно придумать серверу имя, оно будет отображаться в терминале после `<user>@`.
|
||||
```sh
|
||||
sudo nano /etc/hostname
|
||||
sudo nano /etc/hosts
|
||||
sudo systemctl restart systemd-hostnamed
|
||||
|
||||
# В hosts тоже иногда есть строчка вида
|
||||
# 127.0.1.1 <hostname>
|
||||
sudo nano /etc/hosts
|
||||
```
|
||||
|
||||
|
||||
@@ -61,6 +64,10 @@ sudo nano /etc/ssh/sshd_config
|
||||
```sh
|
||||
# На некоторых системах ssh вместо sshd
|
||||
sudo systemctl reload sshd
|
||||
|
||||
# Иногда дополнительно нужно выполнить
|
||||
systemctl daemon-reload
|
||||
systemctl restart ssh.socket
|
||||
```
|
||||
|
||||
??? question "А что будет, если потерять SSH-ключ?"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
site_name: Tishenko's knowledge base
|
||||
site_name: Tish Knowledge Base
|
||||
site_url: https://kb.tishenko.dev
|
||||
copyright: Copyright © 2025
|
||||
repo_url: https://github.com/Arity-T/knowledge-base
|
||||
|
||||
Reference in New Issue
Block a user