1. Что нужно бэкапить
Полная копия Jira состоит из двух частей. Потеря любой из них = потеря данных:
- База данных PostgreSQL — все задачи, проекты, пользователи, настройки
- Jira Home Directory (/var/atlassian/application-data/jira) — вложения к задачам, индексы поиска, кэш, конфиги
2. Бэкап PostgreSQL с pg_dump
pg_dump создаёт консистентный снапшот базы без необходимости останавливать Jira. Это главное преимущество перед файловым копированием данных PostgreSQL.
# Базовая команда
pg_dump -U jirauser -h localhost -d jiradb -F c -f /backup/jira-db-$(date +%Y%m%d).dump
# Параметры:
# -F c — кастомный бинарный формат (сжатый, оптимален для pg_restore)
# -F p — plain SQL (читаем, но большой размер)
# -Z 9 — максимальное сжатие
Создаём директорию для бэкапов:
mkdir -p /backup/jira-db
mkdir -p /backup/jira-home
chmod 750 /backup
chown postgres:postgres /backup/jira-db
Проверяем что бэкап создался:
ls -lh /backup/jira-db/
# jira-db-20260205.dump 156M
# Проверка целостности
pg_restore --list /backup/jira-db/jira-db-20260205.dump | head -20
3. Бэкап Jira Home Directory
Home-директория содержит вложения к задачам — это часто самое ценное что есть в Jira. Копируем с rsync:
# Останавливаем Jira перед бэкапом home-директории
# (или делаем бэкап на лету с пониманием что индексы могут быть в непоследовательном состоянии)
BACKUP_DIR="/backup/jira-home/$(date +%Y%m%d)"
mkdir -p "$BACKUP_DIR"
rsync -avz --exclude='log/' --exclude='tmp/' --exclude='cache/' \
/var/atlassian/application-data/jira/ \
"$BACKUP_DIR/"
echo "Backup size: $(du -sh $BACKUP_DIR | cut -f1)"
Что исключаем из бэкапа (не нужно восстанавливать):
log/ — логи (пересоздаются)
tmp/ — временные файлы
cache/ — кэш (пересоздаётся при старте)
plugins/ — плагины (можно исключить если ставите заново)
4. Автоматизация через cron
Создаём скрипт бэкапа:
#!/bin/bash
# /usr/local/bin/jira-backup.sh
BACKUP_ROOT="/backup"
DATE=$(date +%Y%m%d_%H%M)
DB_BACKUP="$BACKUP_ROOT/jira-db/jira-db-$DATE.dump"
HOME_BACKUP="$BACKUP_ROOT/jira-home/$DATE"
LOG_FILE="/var/log/jira-backup.log"
KEEP_DAYS=7
echo "$(date): Starting Jira backup" >> "$LOG_FILE"
# 1. Бэкап базы данных
pg_dump -U jirauser -h localhost -d jiradb -F c -f "$DB_BACKUP"
if [ $? -eq 0 ]; then
echo "$(date): DB backup OK: $(du -sh $DB_BACKUP | cut -f1)" >> "$LOG_FILE"
else
echo "$(date): DB backup FAILED!" >> "$LOG_FILE"
exit 1
fi
# 2. Бэкап home-директории
mkdir -p "$HOME_BACKUP"
rsync -a --exclude='log/' --exclude='tmp/' --exclude='cache/' \
/var/atlassian/application-data/jira/ "$HOME_BACKUP/"
echo "$(date): Home backup OK: $(du -sh $HOME_BACKUP | cut -f1)" >> "$LOG_FILE"
# 3. Удаляем старые бэкапы
find "$BACKUP_ROOT/jira-db" -name "*.dump" -mtime +$KEEP_DAYS -delete
find "$BACKUP_ROOT/jira-home" -maxdepth 1 -type d -mtime +$KEEP_DAYS -exec rm -rf {} +
echo "$(date): Backup complete" >> "$LOG_FILE"
chmod +x /usr/local/bin/jira-backup.sh
# Запускаем в cron каждый день в 3:00 ночи
crontab -e
# Добавить строку:
0 3 * * * /usr/local/bin/jira-backup.sh
5. Процедура восстановления
Восстановление делается в строгом порядке:
systemctl stop jira
# Дропаем старую базу
sudo -u postgres psql -c "DROP DATABASE jiradb;"
sudo -u postgres psql -c "CREATE DATABASE jiradb WITH ENCODING='UNICODE' LC_COLLATE='C' LC_CTYPE='C' TEMPLATE=template0;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE jiradb TO jirauser;"
# Восстанавливаем из дампа
pg_restore -U jirauser -h localhost -d jiradb /backup/jira-db/jira-db-20260205.dump
echo "DB restore exit code: $?"
# Бэкапим текущую (на всякий случай)
mv /var/atlassian/application-data/jira /var/atlassian/application-data/jira.old
# Восстанавливаем
rsync -av /backup/jira-home/20260205_030015/ \
/var/atlassian/application-data/jira/
chown -R jira:jira /var/atlassian/application-data/jira/
systemctl start jira
# Ждём полного запуска, затем:
# Administration → System → Indexing → Re-Index
6. Тестирование DR
Непроверенный бэкап — это не бэкап. Раз в квартал поднимайте тестовую среду из бэкапа и проверяйте:
- Jira запустилась
- Можно войти под администратором
- Открыть несколько задач с вложениями — вложения отображаются
- Поиск работает (если нет — запустить Re-Index)
- Зафиксировать время восстановления (RTO)