Compare commits
27 Commits
976b221613
...
gitea-draf
| Author | SHA1 | Date | |
|---|---|---|---|
| 08a4112420 | |||
| a420980165 | |||
| c4ce5155fe | |||
| e34afe876c | |||
| b24d95ac83 | |||
| 0891a4dcc1 | |||
| c8d7f83fcc | |||
| abd5f2c97a | |||
| 868dec5ab3 | |||
| 4ef1bedad7 | |||
| 0f7e022a5f | |||
| 25cc09b930 | |||
| 7f0d996c00 | |||
| 69653d9883 | |||
| 49fc40b1f7 | |||
| 534f950565 | |||
| 7f7bdfa749 | |||
| 5174e06ce5 | |||
| 74ebd01b5f | |||
| 3d954256a8 | |||
| 46d036d2c1 | |||
| 607ee6297c | |||
| fa1d8dad61 | |||
| cdad11f2d1 | |||
| 631c25885c | |||
| be7c730423 | |||
| c722255161 |
@@ -11,11 +11,12 @@ jobs:
|
||||
steps:
|
||||
- name: Clone repository
|
||||
run: |
|
||||
git clone --branch main https://git.tishenko.dev/tish/knowledge-base.git
|
||||
git clone --depth 1 --branch main https://git.tishenko.dev/tish/knowledge-base.git
|
||||
|
||||
- name: Build site
|
||||
run: |
|
||||
cd knowledge-base
|
||||
pip install -r requirements.txt
|
||||
mkdocs build
|
||||
|
||||
- name: Deploy site
|
||||
|
||||
143
docs/VS-Code/attachments/latex.json
Normal file
143
docs/VS-Code/attachments/latex.json
Normal file
@@ -0,0 +1,143 @@
|
||||
{
|
||||
// Place your snippets for latex here. Each snippet is defined under a snippet name and has a prefix, body and
|
||||
// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the
|
||||
// same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
"Inclue image": {
|
||||
"prefix": [
|
||||
"\\fig",
|
||||
"\\img"
|
||||
],
|
||||
"body": [
|
||||
"\\begin{figure}[h!]",
|
||||
" \\centering",
|
||||
" \\includegraphics[width=0.${1:5}\\linewidth]{img/$2.png}",
|
||||
" \\caption{$3.}",
|
||||
" \\label{fig:$2}",
|
||||
"\\end{figure}"
|
||||
]
|
||||
},
|
||||
"Include listing": {
|
||||
"prefix": [
|
||||
"\\lst",
|
||||
"\\listing"
|
||||
],
|
||||
"body": [
|
||||
"\\begin{lstlisting}[caption={$1.}, label={lst:$2}]",
|
||||
"$3",
|
||||
"\\end{lstlisting}"
|
||||
]
|
||||
},
|
||||
"Texttt": {
|
||||
"prefix": "\\tt",
|
||||
"body": [
|
||||
"\\texttt{$1}",
|
||||
]
|
||||
},
|
||||
"Textit": {
|
||||
"prefix": "\\it",
|
||||
"body": [
|
||||
"\\textit{$1}",
|
||||
]
|
||||
},
|
||||
"Textbf": {
|
||||
"prefix": "\\bf",
|
||||
"body": [
|
||||
"\\textbf{$1}",
|
||||
]
|
||||
},
|
||||
"Picture reference": {
|
||||
"prefix": [
|
||||
"рис",
|
||||
"Рис"
|
||||
],
|
||||
"body": [
|
||||
"Рис.~\\ref{fig:$1}",
|
||||
]
|
||||
},
|
||||
"Special multiline cell for tables": {
|
||||
"prefix": "\\specialcell",
|
||||
"body": "\\newcommand{\\specialcell}[2][l]{\\begin{tabular}[#1]{@{}l@{}}#2\\end{tabular}}"
|
||||
},
|
||||
"TableX": {
|
||||
// c - это просто колонка с тектом по центру, X - максимальная по ширине
|
||||
"prefix": "\\tablex",
|
||||
"body": [
|
||||
"${1:\\usepackage{tabularx\\}}",
|
||||
"\\begin{table}[h!]",
|
||||
" \\centering",
|
||||
" \\caption{$2.}",
|
||||
" \\footnotesize",
|
||||
" \\begin{tabularx}{\\textwidth}{${3:|X|X|X|}}",
|
||||
" \\hline",
|
||||
" \\textbf{${4:Заголовок 1}} & \\textbf{${5:Заголовок 2}} & \\textbf{${6:Заголовок 3}} \\\\\\",
|
||||
" \\hline",
|
||||
" Один & Два & Три \\\\\\",
|
||||
" \\hline",
|
||||
" \\end{tabularx}",
|
||||
"\\end{table}"
|
||||
]
|
||||
},
|
||||
"Table": {
|
||||
"prefix": "\\table",
|
||||
"body": [
|
||||
"\\begin{table}[h!]",
|
||||
" \\centering",
|
||||
" \\caption{$1.}",
|
||||
" \\footnotesize",
|
||||
" \\begin{tabular}{${2:|c|c|c|}}",
|
||||
" \\hline",
|
||||
" \\textbf{${3:Заголовок 1}} & \\textbf{${4:Заголовок 2}} & \\textbf{${5:Заголовок 3}} \\\\\\",
|
||||
" \\hline",
|
||||
" Один & Два & Три \\\\\\",
|
||||
" \\hline",
|
||||
" \\end{tabular}",
|
||||
"\\end{table}"
|
||||
],
|
||||
},
|
||||
"Literature list": {
|
||||
"prefix": ["\\literature", "\\bibliography"],
|
||||
"body": [
|
||||
"\\newpage",
|
||||
"\\section*{Список литературы}",
|
||||
"\\addcontentsline{toc}{section}{Список литературы}",
|
||||
"",
|
||||
"\\vspace{-1.5cm}",
|
||||
"\\begin{thebibliography}{0}",
|
||||
" \\bibitem{novikov}",
|
||||
" Новиков, Ф. А. <<Дискретная математика для программистов>>. — 3-е изд. — Санкт-Петербург: Питер, 2009. — 383 с.",
|
||||
" \\bibitem{vostrov}",
|
||||
" Востров А. В, <<Лекции по теории графов>> URL: \\url{https://tema.spbstu.ru/tgraph_lect/}, Дата обращения: 17.09.2024",
|
||||
"\\end{thebibliography}",
|
||||
]
|
||||
},
|
||||
"change number": {
|
||||
"prefix": ["\\counter", "\\addtocounter"],
|
||||
"body": [
|
||||
"\\addtocounter{${1:table}}{-1}",
|
||||
]
|
||||
},
|
||||
"include pdf": {
|
||||
"prefix": ["\\includepdf", "\\pdf"],
|
||||
"body": [
|
||||
"${1:\\usepackage{pdfpages\\}}",
|
||||
"${2:\\usepackage{tikz\\}}",
|
||||
"\\addtocounter{figure}{1}",
|
||||
"\\includepdf[pages={1}, fitpaper, pagecommand={",
|
||||
"\\thispagestyle{empty}",
|
||||
" \\begin{tikzpicture}[remember picture, overlay]",
|
||||
" \\node at (current page.south) [anchor=north, yshift=35pt] {\\large{${3:Рис 3. }}};",
|
||||
" \\end{tikzpicture}",
|
||||
"}]{${4:pdf/$5.pdf}}"
|
||||
]
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 365 KiB After Width: | Height: | Size: 376 KiB |
@@ -11,11 +11,13 @@
|
||||
|
||||
!!! tip
|
||||
|
||||
`ctrl + shift + p` - главное сочетание клавиш, которое стоит запомнить.
|
||||
|
||||
Удалить множественные курсоры можно с помощью `Esc`.
|
||||
|
||||
Если с помощью `ctrl + d` выделили лишнее, то сочетанием `ctrl + u` можно убрать последнее выделение.
|
||||
|
||||
`ctrl + alt + ←/→` - перенести файл в левую/правую группу вкладок.
|
||||
|
||||
|
||||
`alt + z` - крайне полезно при работе с Latex, Markdown и другими "широкими" файлами.
|
||||
|
||||
|
||||
39
docs/VS-Code/latex.md
Normal file
39
docs/VS-Code/latex.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# LaTeX в VS Code
|
||||
|
||||
## Подготовка
|
||||
|
||||
Вся работа с LaTeX в VS Code завязана на расширении [LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop). Вот [документация](https://github.com/James-Yu/LaTeX-Workshop/wiki/Install) по установке. Вкратце:
|
||||
|
||||
1. Устанавливаем [Perl](https://strawberryperl.com/)
|
||||
2. Устанавливаем [MikTeX](https://miktex.org/)
|
||||
3. Устанавливаем [LaTeX Workshop](https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop)
|
||||
|
||||
После установки можно открыть любой `.tex` файл и попробовать скомпилировать его (`ctrl + alt + b`), а затем открыть предпросмотр (`ctrl + alt + v`). При сохранении файл будет автоматически компилироваться, а предпросмотр обновляться.
|
||||
|
||||
## Сниппеты
|
||||
|
||||
### Создание
|
||||
В LaTeX очень много повторяющихся конструкций, грех не использовать сниппеты. Нажимаем `ctrl + shift + p` (или `f1`), ищем пункт `Snippets: Configure Snippets`, затем ищем `latex`. Автоматически будет создан файл `latex.json`, в который можно добавлять сниппеты.
|
||||
|
||||
### Использование
|
||||
|
||||
Примеры [сниппетов](attachments/latex.json), которые я использую.
|
||||
|
||||
- `\img` - для вставки картинок.
|
||||
- `\lst` или `\listing` - для вставки листингов.
|
||||
- `\tablex` и `\table` - для вставки таблиц.
|
||||
- `\pdf` - для вставки PDF файлов.
|
||||
|
||||
## Примечание
|
||||
|
||||
- Работать с текстом в VS Code намного удобнее, в первую очередь за счёт [горячих клавиш](hotkeys.md). В особенности полезно сочетание `alt + z`, с помощью которого включается автоматический перенос строк.
|
||||
- При написании отчётов, которые обычно обрастают множеством правок, полезно использовать `Git`. `MikTex` создаёт много временных файлов, которые в `Git` добавлять не нужно, поэтому ниже представлена заготовка для `.gitignore`.
|
||||
```sh title=".gitignore"
|
||||
# Игнорировать всё,
|
||||
**/*
|
||||
# кроме
|
||||
!.gitignore
|
||||
!report.tex
|
||||
!img
|
||||
!img/*
|
||||
```
|
||||
28
docs/assets/logo.svg
Normal file
28
docs/assets/logo.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 175.000000 198.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
|
||||
<g transform="translate(0.000000,198.000000) scale(0.100000,-0.100000)"
|
||||
fill="#ffffff" stroke="none">
|
||||
<path d="M202 1689 l-92 -231 250 -620 c137 -342 262 -639 277 -661 31 -45 98
|
||||
-92 153 -107 47 -13 155 -13 205 1 58 16 123 65 155 116 32 49 100 214 100
|
||||
240 0 28 -153 434 -160 426 -4 -4 -42 -102 -85 -218 -42 -115 -86 -219 -96
|
||||
-230 -19 -19 -19 -19 -38 0 -10 11 -40 78 -66 150 -26 72 -89 243 -140 380
|
||||
-51 138 -152 412 -225 610 -73 198 -135 363 -139 367 -3 4 -48 -97 -99 -223z"/>
|
||||
<path d="M783 1906 c-60 -19 -107 -51 -139 -93 -27 -36 -114 -232 -114 -259 0
|
||||
-12 59 -178 130 -366 12 -32 25 -58 29 -58 4 0 43 96 86 213 43 116 85 220 95
|
||||
230 16 17 17 17 37 0 14 -12 111 -262 289 -743 147 -399 271 -736 276 -750 9
|
||||
-22 22 5 104 209 l93 234 -229 573 c-126 315 -241 598 -255 629 -35 79 -75
|
||||
126 -137 160 -45 24 -66 29 -138 32 -52 2 -101 -2 -127 -11z"/>
|
||||
<path d="M1412 1737 c-34 -94 -62 -178 -62 -185 0 -20 173 -443 179 -437 2 3
|
||||
35 80 73 171 l67 165 -91 230 c-51 126 -94 229 -97 229 -3 0 -34 -78 -69 -173z"/>
|
||||
<path d="M834 1116 c-35 -16 -72 -58 -80 -93 -17 -67 30 -145 99 -164 83 -22
|
||||
159 29 172 116 15 101 -97 184 -191 141z"/>
|
||||
<path d="M242 850 c-5 -14 -36 -90 -68 -169 -31 -79 -57 -150 -57 -156 0 -17
|
||||
176 -455 183 -455 7 0 130 333 130 353 0 15 -151 402 -170 437 -7 12 -10 10
|
||||
-18 -10z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -1,8 +1,5 @@
|
||||
# Алиасы команд в Git
|
||||
|
||||
## Полезные ссылки
|
||||
- [Раздел](https://githowto.com/ru/aliases) в GitHowTo
|
||||
|
||||
## Мои алиасы
|
||||
Просто выполнить в терминале:
|
||||
```sh
|
||||
@@ -36,4 +33,7 @@ git config --global --get-regexp alias
|
||||
[Вопрос](https://stackoverflow.com/a/48110875/17341937) на StatckOverflow
|
||||
```sh
|
||||
git config --global --unset-all alias.your-alias
|
||||
```
|
||||
```
|
||||
|
||||
## Полезные ссылки
|
||||
- [Раздел в GitHowTo](https://githowto.com/ru/aliases)
|
||||
|
||||
84
docs/git/git-filter-repo.md
Normal file
84
docs/git/git-filter-repo.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# git-filter-repo
|
||||
|
||||
С помощью [git-filter-repo](https://github.com/newren/git-filter-repo/) можно переписать историю репозитория.
|
||||
|
||||
## Установка
|
||||
|
||||
Глобально или в `virtualenv`
|
||||
|
||||
```sh
|
||||
pip install git-filter-repo
|
||||
```
|
||||
|
||||
## Замена метаданных коммитов
|
||||
|
||||
`git-filter-repo` позволяет создать скрипт на `Python`, который будет вызван для всех коммитов репозитория. Доступ к данным коммита, с возможностю их редактирования, предоставляется через объект `commit`. Таким образом можно описать любую логику изменения метаданных коммитов на обычном `Python`.
|
||||
|
||||
Ниже представлен пример изменения метаданных коммита по его хэшу. Узнать хэш коммита можно с помощью, например, `git log`.
|
||||
|
||||
=== "Command"
|
||||
|
||||
```sh
|
||||
git filter-repo --force --commit-callback "callback.py"
|
||||
```
|
||||
|
||||
=== "callback.py"
|
||||
|
||||
```python
|
||||
"""Файл создан для использования с git-filter-repo.
|
||||
|
||||
Пример команды:
|
||||
git filter-repo --force --commit-callback "callback.py"
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta, timezone
|
||||
|
||||
|
||||
def git_timestamp(date_str: str, tz_offset: int = 3) -> bytes:
|
||||
"""
|
||||
Преобразует строку с датой в формат временной метки для git-filter-repo.
|
||||
|
||||
Args:
|
||||
date_str (str): Дата в формате "DD.MM.YYYY HH:MM:SS".
|
||||
tz_offset (int, optional): Сдвиг временной зоны относительно UTC.
|
||||
По умолчанию 3 (московское время).
|
||||
|
||||
Returns:
|
||||
bytes: Байтовая строка с временной меткой и сдвигом временной зоны
|
||||
в формате `b"{timestamp} {timezone_offset}"`.
|
||||
"""
|
||||
tz = timezone(timedelta(hours=tz_offset))
|
||||
dt = datetime.strptime(date_str, "%d.%m.%Y %H:%M:%S").replace(tzinfo=tz)
|
||||
|
||||
timestamp = int(dt.timestamp())
|
||||
timezone_offset = f"{tz_offset:+03d}00"
|
||||
|
||||
return f"{timestamp} {timezone_offset}".encode("utf-8")
|
||||
|
||||
|
||||
# Обязательно нужно указывать полный хэш коммита
|
||||
if commit.original_id == b"72f6afa37aac4cdbf8d37f22470b77c221a8fce0":
|
||||
# Сообщение коммита
|
||||
commit.message = "Новое сообщение коммита!".encode("utf-8")
|
||||
|
||||
new_name = "Иван Иванов".encode("utf-8")
|
||||
new_email = "ivan-ivanov@mail.com".encode("utf-8")
|
||||
new_date = git_timestamp("01.01.2000 10:00:00")
|
||||
|
||||
# Автор изменений
|
||||
commit.author_name = new_name
|
||||
commit.author_email = new_email
|
||||
|
||||
# Автор коммита
|
||||
commit.committer_name = new_name
|
||||
commit.committer_email = new_email
|
||||
|
||||
# Дата изменений и дата коммита
|
||||
commit.author_date = new_date
|
||||
commit.committer_date = new_date
|
||||
```
|
||||
|
||||
## Полезные ссылки
|
||||
|
||||
- [git-filter-repo](https://github.com/newren/git-filter-repo/?tab=readme-ov-file#simple-example-with-comparisons) on GitHub
|
||||
- [usage examples](https://www.mankier.com/1/git-filter-repo)
|
||||
134
docs/git/undo.md
Normal file
134
docs/git/undo.md
Normal file
@@ -0,0 +1,134 @@
|
||||
# Отмена действий в Git
|
||||
|
||||
## Отмена изменений до `git add`
|
||||
|
||||
Вернуть состояние файла к последнему коммиту.
|
||||
|
||||
```sh
|
||||
git restore <path-to-dir-or-file>
|
||||
```
|
||||
|
||||
|
||||
## Отмена изменений после `git add` до `git commit`
|
||||
|
||||
Если нежелательные изменения уже проиндексированы, т. е. выполнена команда `git add`.
|
||||
|
||||
```sh
|
||||
# Отменяет git add
|
||||
git restore --staged <path-to-dir-or-file>
|
||||
# Возвращает к исходному состоянию
|
||||
git restore <path-to-dir-or-file>
|
||||
```
|
||||
|
||||
Можно и одной командой.
|
||||
|
||||
```sh
|
||||
git reset --hard <path-to-dir-or-file>
|
||||
```
|
||||
|
||||
|
||||
## Отмена коммитов до `git push`
|
||||
|
||||
### Изменение последнего коммита
|
||||
|
||||
Часто нужно что-то добавить/исправить/удалить в последнем коммите, в том числе сообщение коммита.
|
||||
|
||||
```sh
|
||||
# Добавляем/исправляем/удаляем
|
||||
# Индексируем изменения (git add)
|
||||
git commit -m "New message" --amend
|
||||
```
|
||||
|
||||
Можно без `-m` и сообщения, если не хотим его менять, тогда надо будет просто закрыть открывшийся редактор, либо добавить флаг `--no-edit`, чтобы `Git` даже и не предлагал изменять сообщение.
|
||||
|
||||
```sh
|
||||
# Добавляем/исправляем/удаляем
|
||||
# Индексируем изменения (git add)
|
||||
git commit --amend --no-edit
|
||||
```
|
||||
|
||||
!!! warning "Коммит не должен быть запушен!"
|
||||
|
||||
Команда `git commit --amend` изменяет историю репозитория, не нужно использовать её, если последний коммит уже оказался на сервере (была выполнена команда `git push`).
|
||||
|
||||
### Удаление последних коммитов
|
||||
|
||||
Можно полностью удалить коммит из истории репозитория с помощью `git reset`.
|
||||
|
||||
```sh
|
||||
# Можно добавить --hard, чтобы откатить изменения и вернуть рабочий каталог
|
||||
# к состоянию, в котором он был на предыдущем коммите
|
||||
git reset HEAD~1
|
||||
```
|
||||
|
||||
После такого удаления можно делать `git push`, не опасаясь, что кто-нибудь ещё сможет получить доступ к данным коммита, его следы могут остаться лишь в локальной копии репозитория.
|
||||
|
||||
!!! warning "Коммит не должен быть запушен!"
|
||||
|
||||
Команда `git reset` изменяет историю репозитория, не нужно использовать её, если последний коммит уже оказался на сервере (была выполнена команда `git push`).
|
||||
|
||||
??? info "Подробнее про `git reset`"
|
||||
|
||||
Команда `git reset <commit>` просто перемещает текущую ветку и `HEAD` на указанный коммит. Соответственно, вместо `HEAD~1` (указатель на предыдущий коммит) можно указать любой другой коммит в текущей ветке, например, `HEAD~3` - позволит отменить последние 3 коммита. Разумеется можно указать хэш коммита, к которому нужно откатиться.
|
||||
|
||||
Параметр `--hard` говорит о том, что нужно сбросить и индекс и рабочий каталог до состояния указанного коммита. Есть и другие варианты: `--soft` - оставить изменения в индексе и рабочем каталоге, `--mixed` (значение по умолчанию) - сбросить индекс, но не трогать рабочий каталог.
|
||||
|
||||
??? info "Как восстановить коммиты, удалённые с помощью `git reset`"
|
||||
|
||||
`Git` ведёт локальный журнал всех операций, так что хэш коммита ещё можно восстановить.
|
||||
|
||||
```sh
|
||||
git reflog
|
||||
```
|
||||
|
||||
Зная хэш коммита, можно вернуть состояние ветки к нему с помощью того же `git reset`.
|
||||
|
||||
```sh
|
||||
git reset <commit-hash>
|
||||
```
|
||||
|
||||
Или, например, вынести его в отдельную ветку.
|
||||
|
||||
```sh
|
||||
git checkout <commit-hash>
|
||||
git checkout -b branch-with-restored-commit
|
||||
```
|
||||
|
||||
|
||||
## Отмена коммитов после `git push`
|
||||
|
||||
### Отмена изменений последнего коммита
|
||||
|
||||
Если коммит уже оказался в удалённом репозитории, то самый простой вариант - просто сделать новый коммит, который будет отменять изменения предыдущего.
|
||||
|
||||
```sh
|
||||
git revert HEAD
|
||||
```
|
||||
|
||||
Можно указать диапазон коммитов, которые нужно отменить, или перечислить их хэши.
|
||||
|
||||
```sh
|
||||
# Создаст коммит с отменой изменений последних трёх коммитов
|
||||
git revert HEAD~3..HEAD
|
||||
```
|
||||
|
||||
После `git revert` можно спокойно делать `git push`, не опасаясь, что возникнут какие-либо конфликты с удалённым репозиторием.
|
||||
|
||||
!!! warning "Изменения сохраняются в репозитории"
|
||||
|
||||
Никакие данные ни из локального, ни из удалённого репозитория не удаляются, все коммиты остаются в истории той же самой ветки. `git revert` не подходит, если нужно полностью удалить нежелательные изменения (например, конфиденциальные данные) из локального и удалённого репозитория.
|
||||
|
||||
### Удаление последних коммитов из удалённого репозитория
|
||||
|
||||
Переписывать историю удалённого репозитория можно если над репозиторием работает один человек, либо, если на сервер была отправлена конфиденциальная информация, которую непременно нужно удалить, в других случаях лучше использовать `git revert`.
|
||||
|
||||
Для отмены коммитов можно использовать методы, описанные в предыдущем разделе, а затем перезаписать историю удалённого репозитория.
|
||||
|
||||
```sh
|
||||
git push --force
|
||||
```
|
||||
|
||||
## Полезные ссылки
|
||||
- GitHowTo [12](https://githowto.com/ru/undoing_local_changes), [13](https://githowto.com/ru/undoing_staged_changes), [14](https://githowto.com/ru/undoing_committed_changes), [15](https://githowto.com/ru/removing_commits_from_a_branch).
|
||||
- [Отмена нескольких коммитов](https://stackoverflow.com/questions/1463340/how-can-i-revert-multiple-git-commits#answer-1470452).
|
||||
- [Удаление запушенного коммита](https://stackoverflow.com/questions/3293531/how-to-permanently-remove-few-commits-from-remote-branch#answer-41726152).
|
||||
86
docs/misc/gitea.md
Normal file
86
docs/misc/gitea.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# Кастомизация Gitea
|
||||
|
||||
```sh
|
||||
sudo su - git
|
||||
cd /var/lib/gitea/custom
|
||||
```
|
||||
|
||||
```sh
|
||||
mkdir -p /var/lib/gitea/custom/public/css
|
||||
mkdir -p /var/lib/gitea/custom/templates/custom
|
||||
```
|
||||
|
||||
```sh
|
||||
sudo nano /var/lib/gitea/custom/templates/custom
|
||||
```
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="/custom/css/custom.css">
|
||||
```
|
||||
|
||||
```sh
|
||||
sudo -u git mkdir css
|
||||
sudo -u git nano css/custom.css
|
||||
```
|
||||
|
||||
```sh
|
||||
sudo systemctl restart gitea
|
||||
```
|
||||
|
||||
```sh
|
||||
sudo nano /etc/gitea/app.ini
|
||||
```
|
||||
https://docs.gitea.com/administration/customizing-gitea
|
||||
https://docs.gitea.com/administration/config-cheat-sheet
|
||||
|
||||
```ini title="app.ini"
|
||||
[server]
|
||||
LANDING_PAGE = explore
|
||||
|
||||
[other]
|
||||
SHOW_FOOTER_VERSION = false
|
||||
SHOW_FOOTER_TEMPLATE_LOAD_TIME = false
|
||||
SHOW_FOOTER_POWERED_BY = false
|
||||
ENABLE_FEED = false
|
||||
|
||||
[i18n]
|
||||
LANGS = en-US,ru-RU
|
||||
NAMES = English,Русский
|
||||
|
||||
[repository]
|
||||
DISABLE_STARS = true
|
||||
|
||||
[ui.meta]
|
||||
AUTHOR = Artem Tishenko: Personal Git Repository Hub
|
||||
DESCRIPTION = A personal hub for managing Git repositories by Artem Tishenko.
|
||||
KEYWORDS = Artem Tishenko, Artyom Tishchenko, Git, self-hosted, personal projects, repositories, Gitea
|
||||
```
|
||||
|
||||
|
||||
```sh
|
||||
mkdir -p /var/lib/gitea/custom/templates/base
|
||||
cd /var/lib/gitea/custom/templates/base
|
||||
# перейти туда
|
||||
wget https://raw.githubusercontent.com/go-gitea/gitea/refs/tags/v1.22.3/templates/base/footer_content.tmpl
|
||||
|
||||
# remove help - https://docs.gitea.com
|
||||
# remove explore - explore.repos
|
||||
# remove sign_in (just visit /user/login)
|
||||
wget https://github.com/go-gitea/gitea/raw/refs/tags/v1.22.3/templates/base/head_navbar.tmpl
|
||||
|
||||
|
||||
mkdir -p /var/lib/gitea/custom/templates/repo
|
||||
cd /var/lib/gitea/custom/templates/repo
|
||||
# remove packages
|
||||
# remove wiki
|
||||
# remove repo.activity
|
||||
# remove repo.issues
|
||||
# remove repo.pulls
|
||||
# remove watch, fork
|
||||
wget https://raw.githubusercontent.com/go-gitea/gitea/refs/tags/v1.22.3/templates/repo/header.tmpl
|
||||
```
|
||||
|
||||
```sh
|
||||
# <a class="item" href="https://kb.tishenko.dev/" target="_blank">Knowledge base</a>
|
||||
/var/lib/gitea/custom/templates/custom/extra_links.tmpl
|
||||
```
|
||||
248
docs/python/django-deployment.md
Normal file
248
docs/python/django-deployment.md
Normal file
@@ -0,0 +1,248 @@
|
||||
Предполагается, что на сервере установлена `Ubuntu`.
|
||||
|
||||
## Подготовка
|
||||
|
||||
В этом разделе общая последовательность действий для запуска `Django` приложения на сервере. Многое в нём зависит от конкретного проекта, поэтому команды и их последовательность может быть совсем другой. Главное, что в результате папка с приложением должна оказаться на сервере, а также должно быть создано виртуальное окружение `Python` (не обязательно через `venv`) со всеми зависимостями проекта.
|
||||
|
||||
### Установка Python
|
||||
|
||||
```sh
|
||||
# Для начала обновим установленные пакеты
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
|
||||
# Не забудьте указать нужную версию python
|
||||
sudo apt install python3.10 python3.10-venv -y
|
||||
```
|
||||
|
||||
Python может сходу не установиться и из-за следующей ошибки.
|
||||
```
|
||||
E: Unable to locate package python3.10
|
||||
E: Couldn't find any package by glob 'python3.10'
|
||||
E: Unable to locate package python3.10-venv
|
||||
E: Couldn't find any package by glob 'python3.10-venv'
|
||||
```
|
||||
|
||||
Нужно просто добавить репозиторий со списками пакетов Python.
|
||||
```sh
|
||||
sudo add-apt-repository ppa:deadsnakes/ppa
|
||||
sudo apt update
|
||||
# и снова пробуем установить python
|
||||
```
|
||||
|
||||
### Клонируем проект
|
||||
|
||||
На сервере создаём SSH ключ и копируем его в раздел `Deploy keys` (в случае `GitHub`) в настройках репозитория. Если проект публичный, то ключ создавать не обязательно.
|
||||
```sh
|
||||
ssh-keygen
|
||||
cat ~/.ssh/id_rsa.pub
|
||||
```
|
||||
|
||||
А затем клонируем репозиторий.
|
||||
```sh
|
||||
git clone <repo-url.git>
|
||||
```
|
||||
|
||||
Если вдруг `Git` не установлен.
|
||||
|
||||
```sh
|
||||
sudo apt install git
|
||||
```
|
||||
|
||||
### Готовим Django к запуску
|
||||
|
||||
Предварительно нужно добавить домен или IP-адрес сервера в `ALLOWED_HOSTS` в `settings.py`. Также стоит посмотреть на [deployment checklist](https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/), который предоставляет документация `Django`.
|
||||
|
||||
Настраиваем виртуальное окружение.
|
||||
|
||||
```sh
|
||||
python3.10 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
Создаём миграции и суперпользователя. Команды отличаются в зависимости от проекта.
|
||||
|
||||
```sh
|
||||
python manage.py makemigrations <app_name>
|
||||
python manage.py migrate
|
||||
python manage.py createsuperuser
|
||||
```
|
||||
|
||||
|
||||
## Gunicorn
|
||||
|
||||
### Установка
|
||||
```sh { .annotate }
|
||||
# В виртуальном окружении проекта выполнить
|
||||
pip install gunicorn
|
||||
|
||||
# Можно перейти по адресу сервера в браузере на порт 8000 и убедиться,
|
||||
# что всё работает (ну почти, статики тут не будет)
|
||||
# Не на всех VDS может быть открыт 8000 порт, в таком случае просто
|
||||
# смотрим на отсутствие ошибок
|
||||
gunicorn --bind 0.0.0.0:8000 django-app-name.wsgi # (1)!
|
||||
```
|
||||
|
||||
1. Не забудьте заменить `django-app-name.wsgi` на реальный путь к `wsgi.py` файлу проекта.
|
||||
|
||||
### UNIX-сокет
|
||||
Создаём UNIX-сокет в `systemd` для локального обмена данными между `Gunicorn`, в котором развёрнут `Django`, и `nginx`.
|
||||
|
||||
```sh
|
||||
sudo nano /etc/systemd/system/gunicorn.socket
|
||||
```
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=gunicorn socket
|
||||
|
||||
[Socket]
|
||||
ListenStream=/run/gunicorn.sock
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
||||
```
|
||||
|
||||
!!! tip "UNIX-сокет можно назвать как угодно"
|
||||
|
||||
Это особенно полезно, когда на одной машине с помощью `Gunicorn` нужно развёрнуть сразу несколько приложений. Кстати, имя сокета (`gunicorn.sock`) не обязательно должно совпадать с названием файла конфигурации сокета для `systemd` (`gunicorn.socket`). При этом в командах по типу `systemctl status` нужно будет использовать имя конфигурационного файла.
|
||||
|
||||
### Сервис в systemd
|
||||
|
||||
Создаём сервис в `systemd`, чтобы `Gunicorn` мог работать как фоновый процесс и запускался вместе с системой.
|
||||
|
||||
```sh
|
||||
sudo nano /etc/systemd/system/gunicorn.service
|
||||
```
|
||||
|
||||
В секции `Service` нужно указать актуального пользователя и путь до проекта, а также путь до `wsgi.py` внутри проекта.
|
||||
|
||||
```ini
|
||||
[Unit]
|
||||
Description=gunicorn daemon
|
||||
Requires=gunicorn.socket
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=user
|
||||
Group=user
|
||||
WorkingDirectory=/home/user/project-folder
|
||||
ExecStart=/home/user/project-folder/venv/bin/gunicorn \
|
||||
--access-logfile - \
|
||||
--workers 1 \
|
||||
--bind unix:/run/gunicorn.sock \
|
||||
django-app-name.wsgi:application
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
```
|
||||
|
||||
Теперь можно запустить сокет и добавить его в автозапуск. `systemd` автоматически запустит сервис `Gunicorn`, когда на сокет придёт первый запрос.
|
||||
|
||||
```sh
|
||||
# Предварительно перезагружаем systemd
|
||||
sudo systemctl daemon-reload
|
||||
|
||||
sudo systemctl start gunicorn.socket
|
||||
sudo systemctl enable gunicorn.socket
|
||||
```
|
||||
|
||||
|
||||
## Nginx
|
||||
|
||||
### Установка
|
||||
|
||||
После установки `nginx` должен запуститься автоматически, чтобы проверить можно перейти по адресу сервера в браузере.
|
||||
|
||||
```sh
|
||||
sudo apt install nginx
|
||||
```
|
||||
|
||||
### Собираем статику
|
||||
|
||||
Собираем статику (стили, скрипты, картинки) и переносим в `/var/www/` - именно этот каталог обычно используется для её хранения. Если поместить статику в другое место, то могут возникнуть проблемы с доступами. `nginx` просто не сможет работать с нашими файлами, если у него не будет прав на чтение файлов статики и прав на исполнение всех директорий в путях к этим файлам. В конфиге `/etc/nginx/nginx.conf` можно узнать от имени какого пользователя `nginx` обрабатывает запросы.
|
||||
|
||||
```bash
|
||||
# Команда собирает всю статику Django в папку, которая
|
||||
# указана в settings.py (см. STATIC_ROOT)
|
||||
python manage.py collectstatic
|
||||
|
||||
# Переносим статику из staticfiles (см. STATIC_ROOT) в /var/www/
|
||||
# Вместо static может потребоваться указать другую папку (см. STATIC_URL)
|
||||
sudo mkdir /var/www/django-project
|
||||
sudo cp -r staticfiles /var/www/django-project/static
|
||||
```
|
||||
|
||||
### Конфиг nginx
|
||||
|
||||
Теперь можно настроить `nginx`.
|
||||
```bash
|
||||
# Вместо my-site можно указать название проекта
|
||||
sudo nano /etc/nginx/sites-available/my-site
|
||||
```
|
||||
|
||||
Минимальный конфиг.
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
server_name your_domain_or_ip;
|
||||
|
||||
location = /favicon.ico { access_log off; log_not_found off; }
|
||||
location /static/ {
|
||||
root /var/www/django-project;
|
||||
}
|
||||
|
||||
location / {
|
||||
include proxy_params;
|
||||
proxy_pass http://unix:/run/gunicorn.sock;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Добавляем конфиг в активные конфиги, с которыми сейчас работает nginx.
|
||||
|
||||
```sh
|
||||
sudo ln -s /etc/nginx/sites-available/my-site /etc/nginx/sites-enabled
|
||||
```
|
||||
|
||||
Проверка корректности конфигов.
|
||||
|
||||
```sh
|
||||
sudo nginx -t
|
||||
```
|
||||
|
||||
Если всё в порядке, перезапускаем `nginx`.
|
||||
|
||||
```sh
|
||||
sudo systemctl restart nginx
|
||||
```
|
||||
|
||||
|
||||
## Если что-то идёт не так...
|
||||
|
||||
### Логи NGINX
|
||||
```bash
|
||||
# Информация обо всех запросах
|
||||
sudo tail -f /var/log/nginx/access.log
|
||||
|
||||
# Информация обо всех ошибках и предупреждениях
|
||||
sudo tail -f /var/log/nginx/error.log
|
||||
|
||||
# Проверка корректности конфигов
|
||||
sudo nginx -t
|
||||
|
||||
# Очистка логов без необходимости перезапуска NGINX
|
||||
sudo truncate -s 0 /var/log/nginx/access.log
|
||||
sudo truncate -s 0 /var/log/nginx/error.log
|
||||
```
|
||||
|
||||
### Логи Gunicorn
|
||||
```bash
|
||||
sudo journalctl -u gunicorn.service -f
|
||||
sudo journalctl -u gunicorn.socket -f
|
||||
```
|
||||
|
||||
## Полезные ссылки
|
||||
- [How to deploy Django](https://docs.djangoproject.com/en/5.1/howto/deployment/)
|
||||
- [Deployment checklist](https://docs.djangoproject.com/en/5.1/howto/deployment/checklist/)
|
||||
261
docs/servers/index.md
Normal file
261
docs/servers/index.md
Normal file
@@ -0,0 +1,261 @@
|
||||
# Начальная настройка сервера
|
||||
|
||||
## Первое подключение
|
||||
Подключаемся к серверу к `root` по паролю, который должен выдаваться вместе с VDS.
|
||||
```sh
|
||||
ssh root@<IPv4>
|
||||
```
|
||||
|
||||
Уже в терминале сервера выполняем.
|
||||
```sh { .code-wrap }
|
||||
# Создаём пользователя и наделяем правом использовать `sudo`.
|
||||
adduser <user>
|
||||
adduser <username> sudo
|
||||
|
||||
# Переключаемся на нового пользователя
|
||||
su - <user>
|
||||
|
||||
# Все файлы, созданные пользователем, по умолчанию будут иметь права 600, а директории - 700.
|
||||
echo 'umask 0077' >> .bashrc
|
||||
source ~/.bashrc
|
||||
|
||||
# Добавляем свой публичный SSH ключ (cat ~/.ssh/id_rsa.pub), чтобы подключаться к пользователю по SSH напрямую.
|
||||
mkdir .ssh
|
||||
echo "<your-id-rsa.pub>" >> .ssh/authorized_keys
|
||||
# Актуально, только если настройку umask не добавлять в .bashrc
|
||||
# chmod 700 ~/.ssh
|
||||
# chmod 600 ~/.ssh/authorized_keys
|
||||
```
|
||||
|
||||
Теперь можно попробовать подключиться к серверу по SSH-ключу.
|
||||
```sh
|
||||
ssh <user>@<IPv4>
|
||||
```
|
||||
|
||||
Желательно обновить все пакеты и перезагрузить сервер.
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo apt upgrade
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
Можно придумать серверу имя, оно будет отображаться в терминале после `<user>@`.
|
||||
```sh
|
||||
sudo nano /etc/hostname
|
||||
sudo nano /etc/hosts
|
||||
sudo systemctl restart systemd-hostnamed
|
||||
```
|
||||
|
||||
|
||||
## Настройка конфига SSH
|
||||
Открываем конфиг SSH.
|
||||
```sh
|
||||
sudo nano /etc/ssh/sshd_config
|
||||
```
|
||||
|
||||
- `Port <ssh-port>` - можно поменять со стандартного 22 на какой-нибудь другой. Лучше больше 10000, чтобы уменьшить вероятность конфликтов с другим ПО.
|
||||
- `PermitRootLogin no` - запрещаем авторизацию по SSH под `root`.
|
||||
- `PasswordAuthentication no` - запрещаем авторизацию по SSH по паролю.
|
||||
|
||||
После внесения изменений в конфиг, необходимо перезагрузить `sshd`.
|
||||
```sh
|
||||
# На некоторых системах ssh вместо sshd
|
||||
sudo systemctl reload sshd
|
||||
```
|
||||
|
||||
??? question "А что будет, если потерять SSH-ключ?"
|
||||
|
||||
Хостинг предоставляет доступ к `VNC` или другие методы подключения к серверу, которые не требуют подключения по SSH. Однако в таком случае будет необходим доступ к личному кабинету хостинга.
|
||||
|
||||
|
||||
На своей машине добавляем сервер в конфиг SSH.
|
||||
|
||||
```sh
|
||||
# На Windows надо будет нажать на Tab, чтобы раскрыть `~`.
|
||||
# code - VS Code
|
||||
code ~/.ssh/config
|
||||
```
|
||||
|
||||
```
|
||||
Host <host>
|
||||
HostName <IPv4>
|
||||
User <user>
|
||||
Port <ssh-port>
|
||||
```
|
||||
|
||||
Можно проверить, что подключение проходит без ошибок.
|
||||
```sh
|
||||
# Если конфиг настроен
|
||||
ssh <host>
|
||||
```
|
||||
```sh
|
||||
# Без конфига
|
||||
ssh <user>@<IPv4> -p <ssh-port>
|
||||
```
|
||||
|
||||
## Настройка фаерволла c UFW
|
||||
|
||||
|
||||
```sh
|
||||
# Установка UFW
|
||||
sudo apt update
|
||||
sudo apt install ufw -y
|
||||
|
||||
# Открываем порт, используемый для SSH (по умолчанию 22)
|
||||
sudo ufw allow <ssh-port>/tcp
|
||||
|
||||
# Закрываем все входные
|
||||
sudo ufw default deny incoming
|
||||
sudo ufw default allow outgoing
|
||||
|
||||
# Включаем фаерволл
|
||||
sudo ufw enable
|
||||
|
||||
# Показать состояние ufw и активные правила
|
||||
sudo ufw status verbose
|
||||
```
|
||||
|
||||
??? tip "Дополнительные команды `ufw`"
|
||||
|
||||
```sh
|
||||
# Отключить фаерволл
|
||||
sudo ufw disable
|
||||
|
||||
# Удалить правило (будут применены настройки по умолчанию)
|
||||
sudo ufw delete allow <port>/<protocol> # удалить разрешение
|
||||
sudo ufw delete deny <port>/<protocol> # удалить запрет
|
||||
|
||||
# Сброс всех правил
|
||||
sudo ufw reset
|
||||
|
||||
# Вывести логи ufw
|
||||
sudo tail -f -n 100 /var/log/ufw.log
|
||||
|
||||
# Изменить уровень логирования
|
||||
sudo ufw logging <low/medium/high>
|
||||
|
||||
# Разрешить доступ ко всем портам с определённого IP-адреса
|
||||
sudo ufw allow from <IPv4>
|
||||
|
||||
# Разрешить доступ к порту с определённого IP-адреса
|
||||
sudo ufw allow from <IPv4> to any port <port>
|
||||
```
|
||||
|
||||
Некоторые приложения, например `OpenSSH` или `Nginx`, добавляют пресеты с правилами для `ufw`, которые точно так же можно разрешать и запрещать.
|
||||
|
||||
```sh
|
||||
# Вывести список пресетов
|
||||
sudo ufw app list
|
||||
|
||||
# Открыть все соединения, которые нужны Nginx
|
||||
sudo ufw allow "Nginx Full"
|
||||
|
||||
# Удалить правило для пресета
|
||||
sudo ufw delete allow "Nginx Full"
|
||||
```
|
||||
|
||||
## Настройка Fail2Ban
|
||||
|
||||
[Fail2Ban](https://github.com/fail2ban/fail2ban) - базовая защита сервера от brute-force аттак.
|
||||
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo apt install fail2ban -y
|
||||
sudo systemctl enable fail2ban
|
||||
```
|
||||
|
||||
Теперь нужно [правильно настроить Fail2Ban](https://github.com/fail2ban/fail2ban/wiki/Proper-fail2ban-configuration).
|
||||
|
||||
```sh
|
||||
# Создаём файл с пользовательскими настройками
|
||||
sudo nano /etc/fail2ban/jail.local
|
||||
```
|
||||
|
||||
Настройка защиты SSH сервера.
|
||||
```ini
|
||||
[sshd]
|
||||
# Единственный обязательный параметр
|
||||
enabled = true
|
||||
|
||||
# Можно не указывать, если используется стандартный порт
|
||||
port = <ssh-port>
|
||||
|
||||
# Пример настроек. Эти параметры можно не указывать, тогда будут использованы
|
||||
# значения по умолчанию.
|
||||
# Если в течении 24 часов
|
||||
findtime = 86400
|
||||
# произведено 3 неудачных попытки логина,
|
||||
maxretry = 3
|
||||
# то банить IP навсегда.
|
||||
bantime = -1
|
||||
```
|
||||
|
||||
!!! tip "Более строгий конфиг для `fail2ban`"
|
||||
|
||||
Если на сервере настроена авторизация по ключу, можно смело использовать такой конфиг.
|
||||
|
||||
При авторизации по ключу, бан возможен только в случае указания неправильного имени пользователя, что исключено при использовании корректно настроенного SSH-конфига. В случае случайного бана всегда можно зайти на сервер через личный кабинет хостинга.
|
||||
|
||||
```ini
|
||||
[sshd]
|
||||
enabled = true
|
||||
port = <ssh-port>
|
||||
# Если произведена хотя бы одна неудачная попытка логина,
|
||||
maxretry = 1
|
||||
# то банить IP навсегда.
|
||||
bantime = -1
|
||||
```
|
||||
|
||||
|
||||
```sh
|
||||
# Применяем настройки
|
||||
sudo fail2ban-client reload
|
||||
```
|
||||
|
||||
После установки и первоначальной настройки `fail2ban` лучше перезагрузить сервер, иначе `fail2ban` может не заработать.
|
||||
```sh
|
||||
sudo reboot
|
||||
```
|
||||
|
||||
??? tip "Дополнительные команды `fail2ban`"
|
||||
|
||||
```sh
|
||||
# Вывести список активных jail's
|
||||
sudo fail2ban-client status
|
||||
|
||||
# Вывести информацию по конкретному jail, в т. ч. список заблокированных IP
|
||||
sudo fail2ban-client status <jail-name>
|
||||
|
||||
# Разблокировать IP
|
||||
sudo fail2ban-client set <jail-name> unbanip <IP>
|
||||
|
||||
# Вывести логи fail2ban
|
||||
sudo tail -f -n 100 /var/log/fail2ban.log
|
||||
```
|
||||
|
||||
## Дополнительно
|
||||
|
||||
```sh
|
||||
# Вывести записи о неудачных попытках входа в систему
|
||||
sudo lastb | head -n 20
|
||||
|
||||
# Очистить записи о неудачных попытках входа в систему
|
||||
sudo truncate -s 0 /var/log/btmp
|
||||
|
||||
# Показывает, кто в системе прямо сейчас
|
||||
sudo w
|
||||
|
||||
# Логи попыток входа
|
||||
sudo grep "Accepted password" /var/log/auth.log | tail -n 20
|
||||
sudo grep "Failed password" /var/log/auth.log | tail -n 20
|
||||
sudo grep "Invalid user" /var/log/auth.log | tail -n 20
|
||||
|
||||
# Очистить логи с попытками входа
|
||||
sudo truncate -s 0 /var/log/auth.log
|
||||
```
|
||||
|
||||
## Полезные ссылки
|
||||
- [Initial Server Setup with Ubuntu 20.04](https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04)
|
||||
- [UFW Essentials: Common Firewall Rules and Commands](https://www.digitalocean.com/community/tutorials/ufw-essentials-common-firewall-rules-and-commands)
|
||||
- [VPS cheatsheet](https://habr.com/ru/articles/756804/)
|
||||
- [Fail2Ban](https://github.com/fail2ban/fail2ban)
|
||||
50
docs/servers/nginx.md
Normal file
50
docs/servers/nginx.md
Normal file
@@ -0,0 +1,50 @@
|
||||
|
||||
|
||||
## SSL-сертификат с certbot
|
||||
|
||||
!!! tip "Актуальная версия Python"
|
||||
|
||||
Обычно системый `Python` достаточно старый. Для установки `certbot` может потребоваться более новая версия. Минимальные требования можно узнать на [pypi](https://pypi.org/project/certbot/).
|
||||
|
||||
```sh
|
||||
sudo apt update
|
||||
sudo add-apt-repository ppa:deadsnakes/ppa
|
||||
|
||||
# Вместо 3.1x нужно указать актуальную версию Python
|
||||
sudo apt install python3.1x python3.1x-venv
|
||||
```
|
||||
|
||||
Теперь вместо `python3` можно использовать `python3.1x`.
|
||||
|
||||
SSL-сертификат получается и устанавливается с помощью [certbot](https://github.com/certbot/certbot). На их сайте есть подробная пошаговая [инструкция](https://certbot.eff.org/instructions?ws=nginx&os=pip) о том, как правильно его установить, получить сертификаты и включить их автообновление.
|
||||
|
||||
??? note "Установка вкратце"
|
||||
|
||||
```sh { .code-wrap }
|
||||
# Установили certbot в venv
|
||||
# Вместо 3.1x нужно указать актуальную версию Python
|
||||
sudo python3.x -m venv /opt/certbot/
|
||||
sudo /opt/certbot/bin/pip install --upgrade pip
|
||||
sudo /opt/certbot/bin/pip install certbot certbot-nginx
|
||||
|
||||
# Добавили в PATH
|
||||
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot
|
||||
|
||||
# Автообновление сертификатов
|
||||
echo "0 0,12 * * * root /opt/certbot/bin/python -c 'import random; import time; time.sleep(random.random() * 3600)' && sudo certbot renew -q" | sudo tee -a /etc/crontab > /dev/null
|
||||
```
|
||||
|
||||
|
||||
Несколько полезных команд.
|
||||
|
||||
```sh
|
||||
# Получить сертификат для определённого домена. Предварительно нужно
|
||||
# настроить конфиг nginx для этого домена.
|
||||
sudo certbot --nginx -d example.com -d www.example.com
|
||||
|
||||
# Список сертификатов со сроками их жизни
|
||||
sudo certbot certificates
|
||||
|
||||
# Удалить сертификат (команда предложит выбор)
|
||||
sudo certbot delete
|
||||
```
|
||||
@@ -4,4 +4,18 @@
|
||||
|
||||
.md-footer {
|
||||
margin-top: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Достаточно добавить { .code-wrap } к блоку кода, чтобы включить автоперенос строк.
|
||||
attr_list, очевидно, должен быть подключен в markdown_extensions.
|
||||
|
||||
Пример:
|
||||
|
||||
```sh { .code-wrap }
|
||||
*very long line of code here*
|
||||
```
|
||||
*/
|
||||
.code-wrap code {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,14 @@ edit_uri: edit/main/docs/
|
||||
theme:
|
||||
name: material
|
||||
language: ru
|
||||
logo: assets/logo.svg
|
||||
favicon: assets/favicon.ico
|
||||
|
||||
icon:
|
||||
repo: fontawesome/brands/github
|
||||
|
||||
features:
|
||||
- navigation.indexes
|
||||
- navigation.instant
|
||||
- navigation.tabs
|
||||
- content.code.copy
|
||||
@@ -43,6 +45,11 @@ extra:
|
||||
markdown_extensions:
|
||||
- attr_list
|
||||
- admonition
|
||||
- pymdownx.tabbed:
|
||||
alternate_style: true
|
||||
slugify: !!python/object/apply:pymdownx.slugs.slugify
|
||||
kwds:
|
||||
case: lower
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
line_spans: __span
|
||||
|
||||
Reference in New Issue
Block a user