Compare commits

...

5 Commits

9 changed files with 3361 additions and 112 deletions

View File

@@ -6,6 +6,7 @@ GITEA_DB_NAME=
GITEA_HOST_DB_PORT=3306
GITEA_HOST_WEB_PORT=8080
GITEA_HOST_SSH_PORT=222
RUNNER_REG_TOKEN=
OG_DB_ROOT_PASSWORD=
OG_DB_USER=

3
.gitignore vendored
View File

@@ -1,4 +1,4 @@
/gitea/*.ini
/gitea/app.ini
/gitea/data/
/runner/*.yaml
@@ -17,7 +17,6 @@
*.sql
*.sql.*
*.log
*.ini
*dump*
*backup*

166
README.md
View File

@@ -5,110 +5,102 @@
Ниже краткая выжимка этого поста.
Стек:
- git, ssh, scp, nginx, certbot, docker, docker-compose-plugin, любой текстовый редактор
- gitea (latest) + mariadb 10.6
- opengist (latest) + mariadb 10.6
- git, docker, docker-compose-plugin; могут понадобиться ssh, scp, nginx, certbot, любой текстовый редактор
## Порядок действий
### Для переноса сервисов с другого сервера
1. Клонировать репозиторий
2. Выполнить `cp .env.example .env` и указать корректные данные для подключения
3. Перенос Gitea:
1. Потушить сервис (не сервер)
2. Скопировать существующий конфиг в `./gitea/app.ini` и скорректировать по необходимости
3. Снять дамп mysql и положить в `./gitea/dump.sql.gz`
4. Директории с данными скопировать в `./gitea/data`
4. Перенос Gitea Runner:
* Скопировать старый конфиг в `./runner/config.yaml` и скорректировать по необходимости
ИЛИ
* Выполнить `cp ./runner/config.example.yaml ./runner/config.yaml` и скорректировать по необходимости
5. Перенос OpenGist:
1. Потушить сервис (не сервер)
2. Скопировать существующий конфиг скопировать в `./opengist/opengist.yml` и скорректировать по необходимости
3. Снять дамп mysql и положить в `./opengist/dump.sql.gz`
4. Директории с данными скопировать в `./opengist/data`
6. Убедиться, что владельцем `./` является юзер с `UID`=`1000`, если не -- `cd ..; chown -R 1000:1000 gitea; cd -`
7. Запустить через `docker compose up -d --build`
8. Проверить логи через `docker logs -f ...`
9. Проверить веб-морды через `curl -I localhost:...`
2. Выполнить `cp ./.env.example ./.env` и указать корректные данные для подключения
3. Создать пользователя git, подробности [описаны в блоге](https://axenov.dev/gitea-to-docker)
4. Выполнить `cp ./gitea/app.example.ini ./gitea/app.ini` и указать необходимые настройки
**ИЛИ**
- (Необязательно) Для переноса инстанса Gitea:
- Потушить сервис (не сервер)
- Выполнить `cp ./compose.override.yml.example ./compose.override.yml`
- Скопировать существующий конфиг в `./gitea/app.ini` и скорректировать по необходимости
- Снять дамп mysql и положить в `./gitea/dump.sql.gz`
- Директории с данными скопировать в `./gitea/data`
- (Необязательно) Для переноса инстанса Gitea Runner:
- Выполнить `cp ./compose.override.yml.example ./compose.override.yml`, если ещё не
- Скопировать старый конфиг в `./runner/config.yaml` и скорректировать по необходимости
**ИЛИ**
- Выполнить `cp ./runner/config.example.yaml ./runner/config.yaml` и скорректировать по необходимости
- (Необязательно) Для переноса инстанса OpenGist:
- Потушить сервис (не сервер)
- Выполнить `cp ./compose.override.yml.example ./compose.override.yml`, если ещё не
- Скопировать существующий конфиг скопировать в `./opengist/opengist.yml` и скорректировать по необходимости
- Снять дамп mysql и положить в `./opengist/dump.sql.gz`
- Директории с данными скопировать в `./opengist/data`
5. Убедиться, что владельцем `./` является юзер `git`, если нет -- присвоить владение ему
6. Запустить через `docker compose up -d --build`
7. Проверить логи через `docker logs -f ...`
8. Проверить веб-морды через `curl -I localhost:...`
9. (Необязательно) Если есть домены:
- Настроить nginx на хосте как реверс-прокси из внешки в контейнеры:
(поменять `server_name` и порты на свои)
Опционально, если есть домены:
<details>
<summary>Файл: /etc/nginx/sites-available/gitea.conf</summary>
10. Настроить nginx на хосте как реверс-прокси из внешки в контейнеры: (поменять `server_name` и порты на свои)
```
server {
listen 80;
listen [::]:80;
server_name git.example.com
Файл: `/etc/nginx/sites-available/gitea.conf`
access_log /var/log/nginx/gitea-access.log;
error_log /var/log/nginx/gitea-error.log;
client_max_body_size 100M;
```
server {
listen 80;
listen [::]:80;
server_name git.example.com
location / {
proxy_pass http://127.0.0.1:8080;
}
}
```
access_log /var/log/nginx/gitea-access.log;
error_log /var/log/nginx/gitea-error.log;
client_max_body_size 100M;
</details>
location / {
proxy_pass http://127.0.0.1:8080;
}
}
```
<details>
<summary>Файл: /etc/nginx/sites-available/opengist.conf</summary>
Файл: `/etc/nginx/sites-available/opengist.conf`
```
server {
listen 80;
listen [::]:80;
server_name gist.example.com
```
server {
listen 80;
listen [::]:80;
server_name gist.example.com
access_log /var/log/nginx/opengist-access.log;
error_log /var/log/nginx/opengist-error.log;
client_max_body_size 100M;
access_log /var/log/nginx/opengist-access.log;
error_log /var/log/nginx/opengist-error.log;
client_max_body_size 100M;
location / {
proxy_pass http://127.0.0.1:8081;
}
}
```
location / {
proxy_pass http://127.0.0.1:8081;
}
}
```
</details>
Сделать линки и перезапустить `nginx`
- Сделать линки и перезапустить `nginx`
```shell
ln -s /etc/nginx/sites-available/gitea.conf /etc/nginx/sites-enabled/gitea.conf
ln -s /etc/nginx/sites-available/opengist.conf /etc/nginx/sites-enabled/opengist.conf
unlink /etc/nginx/sites-enabled/default
systemctl restart nginx
```
```shell
ln -s /etc/nginx/sites-available/gitea.conf /etc/nginx/sites-enabled/gitea.conf
ln -s /etc/nginx/sites-available/opengist.conf /etc/nginx/sites-enabled/opengist.conf
unlink /etc/nginx/sites-enabled/default
systemctl restart nginx
```
11. Переключить DNS на новый IP
12. Проверить веб-морды по доменам через `curl -i ...`
13. Настроить SSL через `certbot`
- Переключить DNS на новый IP
- Проверить веб-морды по доменам через `curl -i ...`
- (Необязательно) Настроить SSL через `certbot`
### Для деплоя с нуля
## Gitea + ssh через хостовый порт
Всё то же, но шаги 3 и 5 можно опустить.
## Gitea + ssh через хост
Проблема в том, что порт openssh на хосте занят (по дефолту 22), пробросить порт напрямую из докера не получится.
1. Запомнить абсолютный путь до скрипта [./gitea/gitea.sh](./gitea/gitea.sh) (например, `/home/user/gitea/gitea/gitea.sh`)
2. Назначить его оболочкой для юзера `git`
```shell
usermod -s /home/user/gitea/gitea/gitea.sh git
```
3. Создать конфиг `/etc/ssh/sshd_config.d/gitea.conf` следующее:
```shell
Match User git
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -e git -u %u -t %t -k %k
```
4. Перезапустить демона через `systemctl restart sshd`
Выполнить скрипт [`./gitea/config-gitea-ssh.sh`](./gitea/config-gitea-ssh.sh).
## Настройка Gitea Actions (runner)
@@ -119,17 +111,19 @@ systemctl restart nginx
ENABLED=true
```
Для версий выше этого делать не нужно.
Для начала нужно запустить всю среду.
Чтобы раннер заработал, его нужно зарегистрировать в Gitea с помощью токена регистрации.
Раннеры могут работать в разных скоупах: на уровне репозитория, организации или глобально.
Раннеры могут работать в разных скоупах: на уровне пользователя, репозитория, организации или глобально.
Базово, для создания глобального раннера, нужно зайти в раздел админки со [списком раннеров](http://localhost:8080/-/admin/actions/runners) и найти кнопку в правом верхнем углу.
![Скриншот админки из документации, весьма старый, но суть передаёт](https://docs.gitea.com/assets/images/register-runner-9a8b9ef53a945ba67fe002b581b1ecf4.png)
Токен из этого поля нужно скопировать в файл [`.env`](.env.example) в переменную `RUNNER_REG_TOKEN` и перезапустить контейнер `gitea-runner` или всю среду по желанию.
Токен из этого поля нужно скопировать в файл [`.env`](.env.example) в переменную `RUNNER_REG_TOKEN` и пересоздать контейнер `gitea-runner`.
В логах раннера должны быть подобные строчки:
@@ -147,12 +141,14 @@ time="2025-04-08T02:14:17Z" level=info msg="runner: gitea-runner, with version:
Если во время выполнения экшена `actions/checkout@v4` возникает ошибка `Could not resolve host`, то в конфиге `./runner/config.yaml` надо указать имя сети:
```yaml
#...
container:
network: "gitea_network"
#...
```
Доп. информация:
* https://axenov.dev/gitea-to-docker
* https://docs.gitea.com/installation/install-with-docker-rootless
* https://github.com/go-gitea/gitea/blob/main/custom/conf/app.example.ini
* https://docs.gitea.com/administration/config-cheat-sheet
* https://docs.gitea.com/usage/actions/quickstart
* https://docs.gitea.com/usage/actions/act-runner

View File

@@ -1,14 +1,34 @@
################################################
# Rename this file to compose.override.yml if
# you need to restore database backups. Also
# you can override another settings here.
################################################
x-common-attributes: &common-attributes
env_file: .env
restart: unless-stopped
networks: [network]
volumes:
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
services:
gitea-db:
volumes:
- ./gitea/dump.sql.gz:/docker-entrypoint-initdb.d/dump.sql.gz
# uncomment to import gitea database backup on first start
# gitea-db:
# volumes:
# - ./gitea/dump.sql.gz:/docker-entrypoint-initdb.d/dump.sql.gz
opengist-db:
# uncomment to import opengist database backup on first start
# opengist-db:
# volumes:
# - ./opengist/dump.sql.gz:/docker-entrypoint-initdb.d/dump.sql.gz
# uncomment to use gitea runner
gitea-runner:
<<: *common-attributes
container_name: gitea-runner
image: docker.io/gitea/act_runner:latest
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: http://gitea:3000
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_REG_TOKEN}
GITEA_RUNNER_NAME: gitea-runner
# GITEA_RUNNER_LABELS: ${RUNNER_LABELS}
volumes:
- ./opengist/dump.sql.gz:/docker-entrypoint-initdb.d/dump.sql.gz
- ./runner/config.yaml:/config.yaml
- ./runner/data:/data
- /var/run/docker.sock:/var/run/docker.sock

View File

@@ -36,21 +36,6 @@ services:
depends_on:
- gitea-db
gitea-runner:
<<: *common-attributes
container_name: gitea-runner
image: docker.io/gitea/act_runner:latest
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: http://gitea:3000
GITEA_RUNNER_REGISTRATION_TOKEN: ${RUNNER_REG_TOKEN}
GITEA_RUNNER_NAME: gitea-runner
# GITEA_RUNNER_LABELS: ${RUNNER_LABELS}
volumes:
- ./runner/config.yaml:/config.yaml
- ./runner/data:/data
- /var/run/docker.sock:/var/run/docker.sock
gitea-db:
<<: *common-attributes
container_name: gitea-db

2854
gitea/app.example.ini Normal file

File diff suppressed because it is too large Load Diff

48
gitea/config-gitea-ssh.sh Executable file
View File

@@ -0,0 +1,48 @@
#!/bin/bash
set -e
# ==================================================================================
echo "Configuring user 'git'..."
if ! id git; then
sudo adduser \
--system \
--disabled-password \
--group \
--gecos 'Gitea user' \
--home /home/git \
git
fi
sudo passwd -d git
sudo usermod -aG docker git
currentdir=$(dirname $(readlink -e -- "${BASH_SOURCE}"))
sudo cp -f "$currentdir/gitea-shell" /home/git/
sudo chmod a+x /home/git/gitea-shell
sudo usermod -s /home/git/gitea-shell git
sudo mkdir -p /home/git/.ssh
sudo chown -R git:git /home/git
sudo chmod 755 /home/git
sudo chmod 700 /home/git/.ssh
# ==================================================================================
cfgpath="/etc/ssh/sshd_config.d/gitea.conf"
echo "Installing new ssh config: $cfgpath"
sudo tee "$cfgpath" > /dev/null <<EOF
Match User git
PasswordAuthentication no
AuthorizedKeysCommandUser git
AuthorizedKeysCommand /usr/bin/docker exec -i gitea /usr/local/bin/gitea keys -e git -u %u -t %t -k %k
EOF
# ==================================================================================
echo "Reloading ssh configs..."
sudo systemctl reload ssh
# sudo systemctl reload sshd
echo "Done!"

346
s3-backup.sh.example Normal file
View File

@@ -0,0 +1,346 @@
#!/bin/bash
#####################################################################
# #
# Stupidly simple backup script for own projects #
# #
# Author: Anthony Axenov (Антон Аксенов) #
# Version: 1.2 #
# License: WTFPLv2 More info (RU): https://axenov.dev/?p=1272 #
# #
#####################################################################
source "./.env" || {
echo "ERROR: .env file not found"
exit 5
}
# use remote storages ===============================================
USE_SSH=0
USE_S3=1
# database credentials ==============================================
DBUSER=
DBPASS=
DBNAME=
DBCHARSET="utf8"
# dates for file structure ==========================================
TODAY_DIR="$(date +%Y.%m.%d)"
TODAY_FILE="$(date +%H.%M)"
# local storage =====================================================
LOCAL_BAK_DIR="/backup"
LOCAL_BAK_PATH="$LOCAL_BAK_DIR/$TODAY_DIR"
# database backup file
LOCAL_SQL_FILE="$TODAY_FILE-db.sql.gz"
LOCAL_SQL_PATH="$LOCAL_BAK_PATH/$LOCAL_SQL_FILE"
# project path and backup file
LOCAL_SRC_DIR="/var/www/html"
LOCAL_SRC_FILE="$TODAY_FILE-src.tar.gz"
LOCAL_SRC_PATH="$LOCAL_BAK_PATH/$LOCAL_SRC_FILE"
# log file
LOG_FILE="$TODAY_FILE.log"
LOG_PATH="$LOCAL_BAK_PATH/$LOG_FILE"
# remote storages ===================================================
SSH_HOST="user@example.com"
SSH_BAK_DIR="/backup"
SSH_BAK_PATH="$SSH_BAK_DIR/$TODAY_DIR"
SSH_SQL_FILE="$SSH_BAK_PATH/$LOCAL_SQL_FILE"
SSH_SRC_FILE="$SSH_BAK_PATH/$LOCAL_SRC_FILE"
SSH_LOG_FILE="$SSH_BAK_PATH/$LOG_FILE"
S3_BUCKET="s3://my.bucket"
S3_DIR="$S3_BUCKET/$TODAY_DIR"
S3_SQL_FILE="$S3_DIR/$LOCAL_SQL_FILE"
S3_SRC_FILE="$S3_DIR/$LOCAL_SRC_FILE"
S3_LOG_FILE="$S3_DIR/$LOG_FILE"
# autoremove ========================================================
# time to live on different storages
TTL_LOCAL=3
TTL_SSH=7
TTL_S3=60
# autoremove flags
CLEAR_SSH=1
CLEAR_S3=1
# notifications =====================================================
USE_NTFY=1
NTFY_TITLE="Backup script"
NTFY_CHANNEL=
#====================================================================
#
# Functions used for the whole backup flow
#
#====================================================================
# prints arguments to stdout and into log file
log() {
echo -e "[$(date +%H:%M:%S)] $*" | tee -a "$LOG_PATH"
}
# sends notification with information
ntfy_info() {
[ $USE_NTFY == 1 ] && ntfy send \
--title "$NTFY_TITLE" \
--message "$1" \
--priority 1 \
"$NTFY_CHANNEL"
}
# sends notification with warning
ntfy_warn() {
[ $USE_NTFY == 1 ] && ntfy send \
--title "$NTFY_TITLE" \
--tags "warning" \
--message "$1" \
--priority 5 \
"$NTFY_CHANNEL"
}
# prints initialized parameters
show_params() {
log "Initialized parameters:"
log "├ [ Remotes ]"
log "│\t├ USE_SSH = $USE_SSH"
[ $USE_SSH == 1 ] && log "│\t├ SSH_HOST = $SSH_HOST"
log "│\t├ USE_S3 = $USE_S3"
[ $USE_S3 == 1 ] && log "│\t├ S3_BUCKET = $S3_BUCKET"
log "├ [ Database ]"
log "│\t├ DBUSER = $DBUSER"
log "│\t├ DBNAME = $DBNAME"
log "│\t├ DBCHARSET = $DBCHARSET"
log "│\t├ LOCAL_SQL_PATH = $LOCAL_SQL_PATH"
[ $USE_SSH == 1 ] && log "│\t├ SSH_SQL_FILE = $SSH_SQL_FILE"
[ $USE_S3 == 1 ] && log "│\t├ S3_SQL_FILE = $S3_SQL_FILE"
log "├ [ Sources ]"
log "│\t├ LOCAL_SRC_DIR = $LOCAL_SRC_DIR"
log "│\t├ LOCAL_SRC_PATH = $LOCAL_SRC_PATH"
[ $USE_SSH == 1 ] && log "│\t├ SSH_SRC_FILE = $SSH_SRC_FILE"
[ $USE_S3 == 1 ] && log "│\t├ S3_SRC_FILE = $S3_SRC_FILE"
log "├ [ Log ]"
log "│\t├ LOG_PATH = $LOG_PATH"
[ $USE_SSH == 1 ] && log "│\t├ SSH_LOG_FILE = $SSH_LOG_FILE"
[ $USE_S3 == 1 ] && log "│\t├ S3_LOG_FILE = $S3_LOG_FILE"
log "├ [ Autoclear ]"
log "│\t├ TTL_LOCAL = $TTL_LOCAL"
[ $USE_SSH == 1 ] && {
log "│\t├ CLEAR_SSH = $CLEAR_SSH"
log "│\t├ TTL_SSH = $TTL_SSH"
}
[ $USE_S3 == 1 ] && {
log "│\t├ CLEAR_S3 = $CLEAR_S3"
log "│\t├ TTL_S3 = $TTL_S3"
}
log "└ [ ntfy ]"
log "\t├ USE_NTFY = $USE_NTFY"
[ $USE_NTFY == 1 ] && log "\t├ NTFY_TITLE = $NTFY_TITLE"
[ $USE_NTFY == 1 ] && log "\t└ NTFY_CHANNEL = $NTFY_CHANNEL"
}
# initializes directories for backup
init_dirs() {
if [ ! -d "$LOCAL_BAK_PATH" ]; then
mkdir -p $LOCAL_BAK_PATH
fi
[ $USE_SSH == 1 ] && ssh $SSH_HOST "mkdir -p $SSH_BAK_PATH"
}
# clears old local backups
clear_local_backups() {
log "\tLocal:"
log $(find "$LOCAL_BAK_DIR" -type d -mtime +"$TTL_LOCAL" | sort)
find "$LOCAL_BAK_DIR" -type d -mtime +"$TTL_LOCAL" | xargs rm -rf
}
# clears old backups on remote ssh storage
clear_ssh_backups() {
if [ $USE_SSH == 1 ] && [ $CLEAR_SSH == 1 ]; then
log "\tSSH:"
log $(ssh "$SSH_HOST" "find $SSH_BAK_DIR -type d -mtime +$TTL_SSH" | sort)
ssh "$SSH_HOST" "find $SSH_BAK_DIR -type d -mtime +$TTL_SSH | xargs rm -rf"
else
log "\tSSH: disabled (\$USE_SSH, \$CLEAR_SSH)"
fi
}
# clears backups on remote s3 storage
clear_s3_backups() {
# https://gist.github.com/JProffitt71/9044744?permalink_comment_id=3539681#gistcomment-3539681
if [ $USE_S3 == 1 ] && [ $CLEAR_S3 == 1 ]; then
log "\tS3:"
OLDER_THAN=$(date -d "$TTL_S3 days ago" "+%s")
s3cmd ls -r $S3_DIR | while read -r line; do
FILETIME=$(echo "$line" | awk {'print $1" "$2'})
FILETIME=$(date -d "$FILETIME" "+%s")
if [[ $FILETIME -le $OLDER_THAN ]]; then
FILEPATH=$(echo "$line" | awk {'print $4'})
if [ $FILEPATH != "" ]; then
log "$line"
s3cmd del $FILEPATH
fi
fi
done
else
log "\tS3: disabled (\$USE_S3 + \$CLEAR_S3)"
fi
}
# clears old backups
clear_backups() {
echo
log "1/7 Removing old backups..."
clear_local_backups
clear_ssh_backups
clear_s3_backups
}
# makes archive with database dump
backup_db() {
echo
log "2/7 Dumping DB: $DBNAME..."
mysqldump \
--user=$DBUSER \
--password=$DBPASS \
--opt \
--default-character-set=$DBCHARSET \
--quick \
$DBNAME | gzip > $LOCAL_SQL_PATH
if [ $? == 0 ]; then
log "\t- OK"
send_db_ssh
send_db_s3
else
log "\t- ERROR: failed to create dump. Exit-code: $?"
ntfy_warn "ERROR: failed to create dump"
log "3/7 Sending database backup to $SSH_HOST... skipped"
log "4/7 Sending database backup to $S3_DIR... skipped"
fi
}
# sends database archive into ssh remote storage
send_db_ssh() {
echo
log "3/7 Sending database backup to $SSH_HOST..."
if [ $USE_SSH == 1 ]; then
rsync --progress "$LOCAL_SQL_PATH" "$SSH_HOST:$SSH_SQL_FILE"
if [ $? == 0 ]; then
log "\t- OK"
else
log "\t- ERROR: failed to send DB backup to $SSH_HOST. Exit-code: $?"
ntfy_warn "ERROR: failed to send DB backup to $SSH_HOST"
fi
else
log "\t- disabled (\$USE_SSH)"
fi
}
# sends database archive into s3 remote storage
send_db_s3() {
echo
log "4/7 Sending database backup to $S3_DIR..."
if [ $USE_S3 == 1 ]; then
s3cmd put "$LOCAL_SQL_PATH" "$S3_SQL_FILE"
if [ $? == 0 ]; then
log "\t- OK"
else
log "\t- ERROR: failed to send DB backup to $S3_DIR. Exit-code: $?"
ntfy_warn "ERROR: failed to send DB backup to $S3_DIR"
fi
else
log "\t- disabled (\$USE_SSH)"
fi
}
# makes archive with project sources
backup_src() {
echo
log "5/7 Compressing project dir: $LOCAL_SRC_DIR..."
tar -zcf "$LOCAL_SRC_PATH" "$LOCAL_SRC_DIR"
if [ $? == 0 ]; then
log "\t- OK"
send_src_ssh
send_src_s3
else
log "\t- ERROR: failed to compress project. Exit-code: $?"
ntfy_warn "ERROR: failed to compress project"
log "6/7 Sending project backup to $SSH_HOST... skipped"
log "7/7 Sending project backup to $S3_DIR... skipped"
fi
}
# sends sources archive into ssh remote storage
send_src_ssh() {
echo
log "6/7 Sending project backup to $SSH_HOST..."
if [ $USE_SSH == 1 ]; then
rsync --progress "$LOCAL_SRC_PATH" "$SSH_HOST:$SSH_SRC_FILE"
if [ $? == 0 ]; then
log "\t- OK"
else
log "\t- ERROR: failed to send project backup to $SSH_HOST. Exit-code: $?"
ntfy_warn "ERROR: failed to send project backup to $SSH_HOST"
fi
else
log "\t- disabled"
fi
}
# sends sources archive into s3 remote storage
send_src_s3() {
echo
log "7/7 Sending project backup to $S3_DIR..."
s3cmd put "$LOCAL_SRC_PATH" "$S3_SRC_FILE"
if [ $? == 0 ]; then
log "\t- OK"
else
log "\t- ERROR: failed to send database backup to $S3_DIR. Exit-code: $?"
ntfy_warn "ERROR: failed to send project backup to $S3_DIR"
fi
}
# prints used/free space on local storage
show_finish() {
echo
log "Finish!"
log "Used space: $(du -h "$LOCAL_BAK_PATH" | tail -n1)" # вывод размера папки с бэкапами за текущий день
log "Free space: $(df -h "$LOCAL_BAK_PATH" | tail -n1 | awk '{print $4}')" # вывод свободного места на локальном диске
echo
}
# sends log file into both remote storage
send_log() {
[ $USE_SSH == 1 ] && rsync --progress "$LOG_PATH" "$SSH_HOST:$SSH_LOG_FILE"
[ $USE_S3 == 1 ] && s3cmd put "$LOG_PATH" "$S3_LOG_FILE"
}
# main flow =========================================================
log "Start ----------------------------------------------------------"
show_params
init_dirs
clear_backups
backup_db
backup_src
show_finish
send_log
ntfy_info "Finish!"