September 23, 2025

GitHub backup

Для автоматического создания резервной копии всех репозиториев в GitHub

git и shh должны уже быть настроены и уметь работать с GitHub.

Генерируем api-key он же personal access tokens

Идет в GitHub и переходим по пути

Домашняястраница GitHub -> Settings -> Developer settings ->Personal access token -> Fine-grained tokens -> Generate new token

Repository access - выбираем "All repositories". Так как будем делать бэкапы не только на публичные, но и на приватные репозитории.

В Repository permissions необходимо выбрать только один пункт "Metadata" и установить его в Read-only

Имя токена, его описание и срок годности - на своё усмотрение.

Далее обязательно копируем токен и сохраняем его. Больше его не покажут. В противном случае придется повторить процедуру.

Можно не закрывать вкладку и вставить его сразу в скрипт на следующем шаге.

Подготавливаем каталог и файлы

В качестве примера возьмем каталог /home/github

Тут создаем файл github_backuper.py и вставляем:

#! /bin/python3
import requests
from git import Repo
import os
import shutil
from time import gmtime, strftime, time

api_token = '' # свежесгенерированный токен
user_name = '' # имя учетной записи на GitHub справа от значка на домашней странице
path = '' # каталог где будем хранить бэкапы

def repo_link_getter(username: str, api_key: str) -> dict:
	header = {'Authorization': f'Bearer {api_key}'} # заголовок для использования авторизации через api_key
    url = f'https://api.github.com/search/repositories?q=user:{username}' # ссылка
    req_json_dict = requests.get(url, headers=header).json()  # отправка запроса и получение в формате json
    
    # создание словаря имя_каталога:ссылка_ssh
    repo_info = req_json_dict['items']
    repo_dict = {rep['name']: rep['ssh_url'] for rep in repo_info}
    return repo_dict

print(f'Starting script - {strftime("%d.%m.%Y", gmtime(time()))}\n')
for name, link in repo_link_getter(user_name, api_token).items():
    time_line = strftime("%H:%M:%S", gmtime(time()))
    repo_path = f'{path}{name}' # путь до каталога репозитория
    print(f'start download {link} - {time_line}')
    
    # удаление старого каталога репозитория при его наличия
    if os.path.exists(repo_path):
        shutil.rmtree(repo_path)
    
    # клонирование репозитория
    Repo.clone_from(link, to_path=repo_path)
    time_line = strftime("%H:%M:%S", gmtime(time()))
    print(f'repo {name} downloaded - {time_line}\n')

Устанавливаем зависимости

pip install requests GitPython time

Настраиваем планировщик cron

Следующим шагом окунемся в мир небытия и пороков - встроенным планировщиком в *nix систему запустим python скрипт.

В /etc/crontab необходимо скорректировать несколько строк.

В переменную PATH добавить наш каталог для хранения (добавлять следует после символа ":").

В нашем случае будет выглядеть вот так

PATH=/bin:/sbin:/home/github

Затем добавляем расписание в конец файла.

Для создания бэкапов каждый день в 00:00 добавим строку

00 00 * * * user /home/github/github_backuper.py >> /home/github/log_github_backuper.log

Участок строки >> /home/github/log_github_backuper.log нужен для логированияработы скрипта. Если эта информация не требуется то можно не писать. В таком случае все функции print в фале github_backuper.py можно закомментировать.

user - пользователь из под которого будет запускаться скрипт.

Для упрощения формирования расписания, можно воспользоваться прекрасным сервисом.