> Полный список статей есть в [llms.txt](https://docs.f3cloud.com/llms.txt). Markdown-версия есть у каждой страницы, достаточно добавить .md к её адресу. Эта страница в Markdown: [https://docs.f3cloud.com/ru/docker/gitea-installation.md](https://docs.f3cloud.com/ru/docker/gitea-installation.md).

# Gitea на VPS – свой Git-сервер в Docker, SSH, резервные копии и обновление

Установка Gitea на VPS в Docker Compose. Свой Git-сервер с веб-интерфейсом, первоначальная настройка, администратор, репозиторий, работа по HTTP и по SSH на порту 2222, закрытая регистрация, коллеги и права, резервные копии командой gitea dump, восстановление, обновление и частые ошибки. Проверено на Debian 12 с Gitea 28.2.0.

Свой Git-сервер нужен, когда код не хочется отдавать чужому сервису или когда проекту нужны собственные правила доступа. **Gitea** – это лёгкая программа с открытым кодом, которая превращает VPS в такой сервер. Она хранит репозитории, показывает их в браузере, ведёт учётные записи и права, а в придачу даёт задачи и запросы на слияние. При этом на сервере она занимает от 100 до 160 МБ памяти. В этой статье мы запустим Gitea в Docker, пройдём первоначальную настройку, создадим администратора и репозиторий, подключимся по HTTP и по SSH, закроем регистрацию, добавим коллегу, настроим резервные копии и разберём обновление. Все шаги мы повторили на тестовом сервере с Debian 12, версия Gitea на момент проверки **28.2.0**.

***

## Как устроен Git-сервер на Gitea

Сам Git не требует особого сервера. Каждая копия проекта на вашем компьютере уже хранит всю историю изменений, и после `git clone` команда `git log` показывает все прежние коммиты. Серверу остаётся быть общим местом, куда участники отправляют свои изменения и откуда забирают чужие. Gitea как раз и создаёт такое место. Она держит репозитории в папке на диске, ведёт список пользователей, решает, кому можно читать, а кому писать, и заодно рисует веб-страницы с кодом, историей и задачами. Сведения о пользователях и репозиториях хранятся в базе, а в нашей установке это обычный файл SQLite внутри той же папки, поэтому отдельный сервер баз данных не нужен.

К Gitea можно обращаться двумя способами. Первый идёт по HTTP на порт 3000, как обычная страница в браузере. Каждая операция требует логин и пароль, и пока адрес начинается с `http://`, а не с `https://`, они уходят по сети без шифрования. Мы проверили это на тестовом сервере. Пока шёл `git push`, мы записали трафик программой tcpdump, и заголовок `Authorization: Basic` с данными для входа был виден в потоке открытым текстом. Второй способ идёт по SSH. Вы один раз создаёте пару ключей, открытую часть добавляете в профиль Gitea, закрытая остаётся на вашем компьютере, и дальше Git подтверждает вашу личность ключом, без пароля. Для этого внутри контейнера работает собственный SSH-сервер Gitea на порту 22 контейнера. Порт 22 самого VPS уже занят вашим входом по SSH, поэтому контейнерный порт мы опубликуем наружу под номером 2222, и к Git нужно будет подключаться именно к нему.

Остальное определяется тем, где Gitea хранит данные. Всё, что меняется в работе, лежит в одной папке `/opt/gitea/data`. Там находятся файл настроек `app.ini`, база `gitea.db`, сами репозитории в папке `git/repositories` и ключи SSH-сервера в папке `ssh`. Сам контейнер ничего важного не хранит. Его можно удалить и создать заново из образа, а данные останутся на месте. Поэтому обновление Gitea сводится к смене образа, а резервная копия к сохранению данных из этой папки. SQLite хватает небольшой команде, и мы будем работать именно с ней. Для сервера с большим числом пользователей в официальной документации Gitea описан вариант с PostgreSQL.

> **Почему версия 28, а не 1.27.**
>
> В старых инструкциях вы встретите теги Gitea вида 1.27. Последним выпуском с такой нумерацией был 1.27.3, а следующий вышел под номером 28.0.0. Версия 28.2.0 была актуальной на момент нашей проверки, и ровно её мы использовали.

***

## Что понадобится

* **Сервер** с Debian 12 или Ubuntu 24.04, например тариф **DE-RZ9-1**. Gitea почти не нагружает сервер. На нашем контейнер с SQLite занимал от 100 до 160 МБ памяти в разное время, а образ около 260 МБ на диске. Место под репозитории зависит от ваших проектов. Если сервера ещё нет, закажите его по [инструкции](https://docs.f3cloud.com/ru/client-area/order-vps.md).
* **Docker и Docker Compose**. Как их установить, рассказано в статье про [Docker](https://docs.f3cloud.com/ru/docker/docker-installation.md). У нас стояли Docker 29.9.2 и Compose 5.6.1.
* **Подключение по SSH**, например через [Termius](https://docs.f3cloud.com/ru/vps/termius-connection.md). Команды на сервере выполняются от имени `root`.
* **Свободные порты 3000 и 2222**. Порт 22 остаётся за вашим входом на сервер.
* **Git на вашем компьютере**. Мы проверяли с Git 2.39.5.

***

## Шаг 1. Запустите Gitea в Docker

Создайте папку для Gitea и файл Compose. Эта папка будет хранить и сам файл, и все данные.

```bash
mkdir -p /opt/gitea
cd /opt/gitea
nano docker-compose.yml
```

Вставьте в файл конфигурацию ниже. Сохраните его сочетанием <kbd>Ctrl</kbd> + <kbd>O</kbd>, затем <kbd>Enter</kbd>, а выйдите из редактора сочетанием <kbd>Ctrl</kbd> + <kbd>X</kbd>.

```yaml
services:
  gitea:
    image: docker.gitea.com/gitea:28.2.0
    container_name: gitea
    restart: always
    environment:
      - USER_UID=1000
      - USER_GID=1000
    volumes:
      - ./data:/data
    ports:
      - "3000:3000"
      - "2222:22"
```

Что здесь написано.

* `image` указывает официальный образ Gitea. Номер версии записан явно, поэтому обновление произойдёт тогда, когда вы сами этого захотите.
* `USER_UID` и `USER_GID` задают пользователя, от имени которого Gitea работает внутри контейнера. По документации по умолчанию это 1000.
* `./data:/data` подключает папку `data` рядом с файлом. В ней окажутся база, репозитории и настройки.
* `"3000:3000"` открывает веб-интерфейс, а `"2222:22"` открывает SSH-сервер Gitea на порту 2222.
* `restart: always` заставляет Docker запускать контейнер после перезагрузки сервера. Подробнее об этом в статье про [Docker](https://docs.f3cloud.com/ru/docker/docker-installation.md).

Запустите контейнер и посмотрите на его состояние.

```bash
docker compose up -d
docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
```

Первый запуск скачивает образ. У нас это заняло около трёх секунд. В списке должна появиться строка `gitea` со статусом **Up**.

<figure><img src="https://docs.f3cloud.com/img/gitea-compose.png" alt="Файл docker-compose.yml, запуск docker compose up -d и контейнер gitea со статусом Up и портами 3000 и 2222"><figcaption><p>Контейнер Gitea запущен, порты 3000 и 2222 опубликованы</p></figcaption></figure>

> **Порты открываются без UFW.**
>
> Мы проверили с другого компьютера, что порты 3000 и 2222 отвечают, хотя в UFW для них нет ни одного правила. Docker публикует порты собственными правилами, и они срабатывают раньше правил UFW. Подробно об этом рассказано в статье про [Docker](https://docs.f3cloud.com/ru/docker/docker-installation.md), а в конце этой статьи показано, как спрятать веб-порт от интернета.

***

## Шаг 2. Пройдите первоначальную настройку

> **Не оставляйте страницу настройки открытой.**
>
> Пока вы не нажали кнопку установки, страница доступна каждому, кто знает адрес и порт, и любой посетитель может заполнить её сам, вплоть до учётной записи администратора. Пройдите настройку сразу после запуска контейнера.

Откройте в браузере адрес `http://IP-адрес-сервера:3000`. Появится страница **Начальная конфигурация**. Большинство полей уже заполнено правильно, поэтому изменить нужно всего несколько.

1. В блоке **Настройки базы данных** оставьте тип **SQLite3** и путь `/data/gitea/gitea.db`. Это путь внутри контейнера, а на сервере файл окажется в папке `/opt/gitea/data/gitea`.
2. В поле **Название сайта** впишите своё название или оставьте как есть.
3. В поле **Порт SSH сервера** замените 22 на **2222**. Так Gitea будет показывать в адресах клонирования тот порт, который мы открыли наружу. Внутри контейнера SSH-сервер по-прежнему слушает 22, и Gitea это учитывает сама.
4. Поле **Gitea Website URL** уже содержит адрес, по которому вы открыли страницу, например `http://IP-адрес-сервера:3000/`. Проверьте его.
5. Отметьте **Only administrators can create user accounts (no self-registration)**. Тогда зарегистрироваться на вашем сервере сможет только тот, кого создаст администратор.

<figure><img src="https://docs.f3cloud.com/img/gitea-install-form.png" alt="Страница Начальная конфигурация Gitea с базой SQLite3, портом SSH 2222, адресом сайта и отмеченным запретом самостоятельной регистрации"><figcaption><p>Порт SSH 2222 и запрет регистрации, остальное оставлено по умолчанию</p></figcaption></figure>

Рядом есть ещё два флажка.

* **Require sign-in to view pages** прячет страницы со списком репозиториев от гостей. Мы включили его на пробу, и страница обзора репозиториев отправила незалогиненного посетителя на форму входа. Это пригодится, если сервер только для своих.
* **Enable update checker** оставлен по умолчанию.

Теперь создайте администратора.

6. Внизу страницы раскройте **Расширенные настройки** и откройте блок **Настройки учётной записи администратора**.
7. Придумайте **Логин администратора**, укажите **Адрес эл. почты** и дважды введите пароль. Почтовый ящик может быть любым, письма Gitea не отправляет, пока вы не настроите почту. Пароль выберите длинный и сложный. В нашей проверке установщик принял даже пароль из трёх символов, то есть защищать вас от слабого пароля он не станет.

<figure><img src="https://docs.f3cloud.com/img/gitea-install-admin.png" alt="Блок Настройки учётной записи администратора с полями логин, адрес почты, пароль и подтверждение пароля"><figcaption><p>Учётная запись администратора создаётся прямо на странице установки</p></figcaption></figure>

8. Нажмите кнопку <kbd>Установить Gitea</kbd> внизу страницы. Через несколько секунд вы окажетесь на странице Gitea уже под своей учётной записью.

Настройки записаны в файл `/opt/gitea/data/gitea/conf/app.ini`, и дальше мы будем иногда его править.

***

## Шаг 3. Укажите адрес сервера в app.ini

На странице настройки нет поля с доменом, поэтому Gitea записала в файл `DOMAIN = localhost` и `SSH_DOMAIN = localhost`. Мы проверили, к чему это приводит. На странице репозитория SSH-адрес начинался с `ssh://git@localhost:2222/…`, и подключиться по нему с другого компьютера нельзя. Исправим две строки.

```bash
cd /opt/gitea
nano data/gitea/conf/app.ini
```

В блоке `[server]` замените `localhost` на IP-адрес сервера в строках `DOMAIN` и `SSH_DOMAIN`. Строки `SSH_PORT = 2222` и `SSH_LISTEN_PORT = 22` не трогайте. Первая задаёт порт, который показывается в адресах, а вторая порт SSH-сервера внутри контейнера. Сохраните файл и проверьте результат.

```bash
grep -n -E "DOMAIN|ROOT_URL|SSH_PORT|SSH_LISTEN" data/gitea/conf/app.ini
```

Затем перезапустите контейнер, чтобы Gitea прочитала файл заново.

```bash
docker restart gitea
```

<figure><img src="https://docs.f3cloud.com/img/gitea-domain.png" alt="Результат grep по app.ini, строки DOMAIN, SSH_DOMAIN и ROOT_URL с адресом сервера, SSH_PORT равен 2222, SSH_LISTEN_PORT равен 22, затем docker restart gitea"><figcaption><p>В адресах теперь IP-адрес сервера, адрес скрыт на скриншоте</p></figcaption></figure>

Когда у сервера появится домен, в эти же строки и в `ROOT_URL` вписывают его, об этом сказано в разделе про домен и HTTPS.

***

## Шаг 4. Создайте репозиторий

Нажмите значок **+** в правом верхнем углу и выберите **Новый репозиторий**.

1. В поле **Название репозитория** впишите `my-project`.
2. Отметьте **Сделать репозиторий приватным**. По умолчанию эта галочка не стоит, и репозиторий получится публичным.
3. В поле **Описание** при желании напишите пару слов о проекте.
4. Отметьте **Инициализировать репозиторий**. Gitea сразу создаст первый коммит с файлом README, и клонировать будет что.
5. Нажмите <kbd>Создать репозиторий</kbd>.

<figure><img src="https://docs.f3cloud.com/img/gitea-repo-create.png" alt="Форма Новый репозиторий с названием my-project, отмеченными флажками приватного репозитория и инициализации"><figcaption><p>Приватный репозиторий с первым коммитом</p></figcaption></figure>

На странице репозитория нажмите синюю кнопку <kbd>Код</kbd>. В открывшемся окне две вкладки с адресами для клонирования, **HTTP** и **SSH**. Сначала воспользуемся первой.

<figure><img src="https://docs.f3cloud.com/img/gitea-clone-http.png" alt="Страница репозитория my-project, окно Код с вкладкой HTTP и адресом для клонирования"><figcaption><p>Адрес для клонирования по HTTP, адрес сервера на скриншоте заменён</p></figcaption></figure>

***

## Шаг 5. Клонируйте репозиторий и отправьте изменения по HTTP

Перед первым коммитом Git должен знать, кто вы. Выполните две команды один раз на своём компьютере, подставив своё имя и почту.

```bash
git config --global user.name "Ваше Имя"
git config --global user.email "you@example.com"
```

Теперь склонируйте репозиторий, добавьте в него файл и отправьте изменения на сервер. Адрес возьмите из окна **Код**. Репозиторий приватный, поэтому Git дважды спросит **Username** и **Password**. Введите логин и пароль администратора. Пароль при вводе не показывается, это нормально.

```bash
# Клонируем репозиторий по HTTP
git clone http://IP-адрес-сервера:3000/gitadmin/my-project.git
cd my-project

# Добавляем файл и фиксируем изменение
echo "print(1)" > hello.py
git add hello.py
git commit -m "Add hello.py"

# Отправляем коммит на сервер
git push
```

Мы выполняли эти команды на самом сервере под отдельным пользователем, на вашем компьютере результат будет таким же.

<figure><img src="https://docs.f3cloud.com/img/gitea-git-http.png" alt="git clone по HTTP с запросом логина и пароля, коммит hello.py и git push в ветку main"><figcaption><p>Клонирование и отправка по HTTP, адрес сервера скрыт</p></figcaption></figure>

После `git push` откройте страницу репозитория в браузере. Файл `hello.py` уже там, а в истории два коммита.

> **Пароль по HTTP не защищён.**
>
> Адрес вида `http://IP-адрес-сервера:3000` не шифрует ни пароль, ни код. Для работы с реальными проектами используйте SSH, который описан в следующем шаге, или поставьте перед Gitea домен с HTTPS.

***

## Шаг 6. Подключите SSH на порту 2222

По SSH Git не спрашивает пароль и не отправляет его по сети. Сначала нужна пара ключей. Если у вас уже есть ключ, шаг создания можно пропустить, а о ключах подробнее рассказано в статье про [SSH-ключи](https://docs.f3cloud.com/ru/vps/security/ssh-klyuchi.md).

1. На своём компьютере создайте ключ. На все три вопроса можно просто нажимать <kbd>Enter</kbd>, но если ключ лежит на ноутбуке, надёжнее задать парольную фразу.

   ```bash
   ssh-keygen -t ed25519 -C "me@example.com"
   ```

2. Выведите на экран открытую часть ключа. Это файл с окончанием `.pub`. Закрытый файл `id_ed25519` без окончания никому не показывайте и никуда не вставляйте.

   ```bash
   cat ~/.ssh/id_ed25519.pub
   ```

<figure><img src="https://docs.f3cloud.com/img/gitea-ssh-keygen.png" alt="Создание ключа ssh-keygen -t ed25519 и вывод открытого ключа командой cat"><figcaption><p>Ключ создан, открытая часть выведена на экран</p></figcaption></figure>

3. В Gitea откройте меню профиля в правом верхнем углу, выберите **Настройки**, а затем **Ключи SSH / GPG**. В блоке **Управление ключами SSH** нажмите <kbd>Добавить ключ</kbd>.
4. В поле **Имя ключа** впишите любое понятное название, например «Мой компьютер». В поле **Содержимое** вставьте всю строку, которую вывела команда `cat`, от `ssh-ed25519` до почты в конце.
5. Нажмите <kbd>Добавить ключ</kbd>. Gitea ответит сообщением, что ключ добавлен.

<figure><img src="https://docs.f3cloud.com/img/gitea-ssh-key-add.png" alt="Страница Ключи SSH и GPG, форма добавления ключа с именем и содержимым открытого ключа"><figcaption><p>В поле вставляется только открытая часть ключа</p></figcaption></figure>

Теперь вернитесь на страницу репозитория, откройте окно **Код** и перейдите на вкладку **SSH**. Адрес начинается с `ssh://git@`, в нём стоит IP-адрес сервера и порт 2222.

<figure><img src="https://docs.f3cloud.com/img/gitea-clone-ssh.png" alt="Окно Код на вкладке SSH с адресом ssh://git@IP-адрес:2222/gitadmin/my-project.git"><figcaption><p>Адрес для клонирования по SSH с портом 2222</p></figcaption></figure>

Клонируйте репозиторий по этому адресу. При первом подключении SSH спросит, доверять ли ключу сервера. Это нормальный вопрос при любом первом подключении, ответьте `yes`.

```bash
# Клонируем по SSH, порт 2222 входит в адрес
git clone ssh://git@IP-адрес-сервера:2222/gitadmin/my-project.git my-project-ssh
cd my-project-ssh

# Меняем файл и отправляем изменение
echo "SSH works" >> README.md
git commit -am "Update README"
git push
```

Пароль на этот раз не спрашивали, а `hello.py` из прошлого шага уже лежал в клоне.

<figure><img src="https://docs.f3cloud.com/img/gitea-git-ssh.png" alt="git clone по SSH с подтверждением ключа сервера, коммит и git push без запроса пароля"><figcaption><p>Клонирование и отправка по SSH, адрес сервера скрыт</p></figcaption></figure>

Быстро проверить, что ключ принят, можно и без репозитория. Команда `ssh -p 2222 git@IP-адрес-сервера` отвечает строкой вида **Hi there, gitadmin! You've successfully authenticated with the SSH key named …** и сообщает, что доступа к командной строке Gitea не даёт. Это не вход на сервер, а только проверка ключа.

***

## Шаг 7. Добавьте коллегу и проверьте закрытую регистрацию

Откройте в браузере адрес `http://IP-адрес-сервера:3000/user/sign_up` без входа в учётную запись. Если вы отметили запрет регистрации на странице установки, Gitea ответит сообщением **Извините, возможность регистрации отключена. Пожалуйста, свяжитесь с администратором сайта.**

Если галочка осталась неотмеченной, поправьте настройку вручную. Откройте `/opt/gitea/data/gitea/conf/app.ini`, найдите в блоке `[service]` строку `DISABLE_REGISTRATION` и задайте значение `true`. После `docker restart gitea` регистрация закроется. Мы переключали эту строку в обе стороны, и страница регистрации менялась соответственно. Тем же способом включается и `REQUIRE_SIGNIN_VIEW = true`, о котором шла речь в шаге 2.

Теперь добавим коллегу. Учётные записи создаёт администратор.

1. Откройте меню профиля и выберите **Панель управления**.
2. В левом меню откройте **Идентификация и доступ**, затем **Пользователи** и нажмите <kbd>Создать новый аккаунт</kbd>.
3. Заполните **Имя пользователя**, **Адрес электронной почты** и **Пароль**. Флажок **Требовать смену пароля пользователем (рекомендуется)** лучше оставить включённым.
4. Нажмите <kbd>Создать новый аккаунт</kbd>.

<figure><img src="https://docs.f3cloud.com/img/gitea-new-user.png" alt="Форма Создать новый аккаунт в панели управления Gitea с именем пользователя, почтой и паролем"><figcaption><p>Администратор создаёт учётную запись коллеги</p></figcaption></figure>

Передайте коллеге временный пароль. Ему нужно один раз войти через браузер, и Gitea сама предложит задать новый пароль. Пока этого не сделано, Git по HTTP отвечает ошибкой, мы получили такой ответ на тестовом сервере.

```text
remote: Update your password
fatal: Authentication failed for 'http://IP-адрес-сервера:3000/gitadmin/my-project.git/'
```

Новый пользователь пока не видит ваш приватный репозиторий. Откройте репозиторий, выберите в меню с тремя точками пункт **Настройки**, затем **Соавторы**. Начните вводить имя коллеги, выберите его из подсказки и нажмите <kbd>Добавить соавтора</kbd>. Gitea подтвердит добавление, а доступ по умолчанию будет **Запись**.

<figure><img src="https://docs.f3cloud.com/img/gitea-collaborator.png" alt="Настройки репозитория, раздел Соавторы, пользователь mike добавлен с правом Запись"><figcaption><p>Соавтор добавлен, ему разрешено читать и записывать</p></figcaption></figure>

После этого мы клонировали репозиторий от имени коллеги и отправили в него коммит, всё прошло без ошибок.

***

## Резервные копии

В Gitea есть официальная команда **gitea dump**. Она собирает один архив с базой, репозиториями и настройками. В архиве лежат файл `app.ini`, папка `data` с вложениями и файлом SQLite, папка `repos` с репозиториями и файл `gitea-db.sql` с копией базы. Ключей SSH-сервера в архиве нет, и мы это проверили. Когда мы восстановили копию на чистом контейнере, у него были другие ключи, чем у исходного. Если ключи сменятся, у всех, кто уже подключался к серверу, SSH начнёт ругаться на смену ключа сервера. Поэтому скрипт ниже сохраняет папку `ssh` отдельным архивом.

Документация Gitea советует останавливать сервис на время копирования, чтобы данные были согласованными. Скрипт работает на включённом контейнере, и в нашей проверке копия нормально восстановилась. Если у вас большая команда, запускайте его ночью.

Создайте скрипт.

```bash
nano /opt/gitea/backup.sh
```

```bash
#!/bin/sh
# Резервная копия Gitea: официальный gitea dump и ключи SSH-сервера
set -e
cd /opt/gitea
STAMP=$(date +%F-%H%M)
mkdir -p backups

# Архив с базой, репозиториями и настройками, из папки /tmp внутри контейнера
docker exec -u git -w /tmp gitea gitea dump -q -c /data/gitea/conf/app.ini -f /tmp/gitea-dump.zip
docker cp -q gitea:/tmp/gitea-dump.zip backups/gitea-dump-$STAMP.zip
docker exec gitea rm /tmp/gitea-dump.zip

# Ключи SSH-сервера в архив не входят, сохраняем их отдельно
tar czf backups/gitea-ssh-$STAMP.tar.gz -C data ssh

# Храним 7 последних копий
ls -1t backups/gitea-dump-*.zip | tail -n +8 | xargs -r rm
ls -1t backups/gitea-ssh-*.tar.gz | tail -n +8 | xargs -r rm
```

Параметр `-u git` запускает команду от имени пользователя, под которым работает Gitea, а `-w /tmp` задаёт рабочую папку, как советует документация, чтобы не получить ошибок прав при сборке архива. Параметр `-q` оставляет в выводе только предупреждения. Сделайте скрипт исполняемым и запустите.

```bash
chmod +x /opt/gitea/backup.sh
/opt/gitea/backup.sh
ls -lh /opt/gitea/backups
```

На нашем сервере скрипт отработал меньше чем за секунду.

<figure><img src="https://docs.f3cloud.com/img/gitea-backup.png" alt="Запуск backup.sh и список папки backups с архивом gitea-dump и архивом gitea-ssh"><figcaption><p>Архив с данными и отдельный архив с ключами SSH-сервера</p></figcaption></figure>

Чтобы копии делались сами, добавьте задачу в cron командой `crontab -e`. Строка ниже запускает скрипт каждую ночь в 03:00. Как устроено расписание, рассказано в статье про [cron](https://docs.f3cloud.com/ru/linux/cron-linux.md).

```bash
0 3 * * * /opt/gitea/backup.sh
```

Мы проверили запуск скрипта планировщиком. Когда задача выполнялась каждую минуту, новые архивы появлялись без ошибок. Копии на том же сервере не спасут, если пропадёт сам сервер, поэтому время от времени скачивайте папку `backups` к себе, например командой [rsync](https://docs.f3cloud.com/ru/linux/rsync-linux.md).

***

## Восстановление из копии

Восстановление мы проверили на отдельном чистом контейнере с такой же конфигурацией. Порядок действий на новом сервере такой. Сначала установите Docker и создайте `/opt/gitea/docker-compose.yml` из шага 1. Затем, если вы сохраняли ключи SSH-сервера, распакуйте их до первого запуска. Мы проверили, что тогда у нового контейнера оказывается тот же отпечаток ключа, что и у старого.

```bash
mkdir -p /opt/gitea/data
tar xzf gitea-ssh-ДАТА.tar.gz -C /opt/gitea/data
cd /opt/gitea
docker compose up -d
```

Скопируйте архив в контейнер и распакуйте данные на место. Мы используем `cp -a`, а не `mv`, потому что папка `conf` в новом контейнере уже существует.

```bash
docker cp gitea-dump-ДАТА.zip gitea:/tmp/gitea-dump.zip
docker exec gitea sh -c "cd /tmp && unzip -q gitea-dump.zip -d restore && cp -a restore/data/. /data/gitea/ && cp -a restore/repos/. /data/git/repositories/ && chown -R git:git /data"
```

В конце пересоздайте хуки Git, как советует документация, и перезапустите контейнер.

```bash
docker exec -u git gitea gitea -c /data/gitea/conf/app.ini admin regenerate hooks
docker restart gitea
```

После этого прежний пароль администратора подошёл, история репозитория сохранилась, а новый коммит отправился без ошибок.

***

## Обновление Gitea

Версия Gitea записана в `docker-compose.yml`, поэтому обновление состоит из трёх действий. Заранее сделайте резервную копию, потому что при смене минорной или мажорной версии Gitea меняет структуру базы, и вернуться на старую версию без копии уже нельзя. Это сказано в документации Gitea. Перед обновлением загляните в список изменений на [странице релизов](https://github.com/go-gitea/gitea/releases), там отмечены несовместимые изменения.

Сначала сделайте копию и откройте файл Compose.

```bash
cd /opt/gitea
./backup.sh
nano docker-compose.yml
```

В строке `image` замените номер версии на новый и сохраните файл. Затем скачайте образ и пересоздайте контейнер. Данные в папке `data` при этом не затрагиваются.

```bash
docker compose pull
docker compose up -d
```

Мы проверили порядок на копии сервера, обновив её с версии 28.1.0 до 28.2.0. В примере на скриншоте номер заменён командой `sed`, результат такой же, как при правке в nano. После обновления API показал новую версию, а репозиторий и учётная запись остались на месте.

<figure><img src="https://docs.f3cloud.com/img/gitea-update.png" alt="Замена тега образа 28.1.0 на 28.2.0 в docker-compose.yml, docker compose pull, docker compose up -d и контейнер gitea со статусом Up"><figcaption><p>Обновление с 28.1.0 до 28.2.0, названия контейнера и папки приведены к основной установке</p></figcaption></figure>

Версию видно и в нижней строке любой страницы Gitea, рядом с надписью **Работает на Gitea**.

***

## Домен и HTTPS

Пока Gitea открыта по IP-адресу и порту 3000, у неё нет шифрования. Когда понадобится нормальный адрес, привяжите к серверу домен по статье про [домен для VPS](https://docs.f3cloud.com/ru/vps/domain-to-vps.md), поставьте перед Gitea веб-сервер [nginx](https://docs.f3cloud.com/ru/web/nginx-installation.md) и выпустите [бесплатный сертификат](https://docs.f3cloud.com/ru/web/ustanovka-besplatnogo-ssl-sertifikata-lets-encrypt-na-server-s-nginx-ili-apache.md). Настройку nginx именно для Gitea мы здесь не разбираем.

В самой Gitea после этого нужно поправить адреса в `app.ini`. В блоке `[server]` это строки `ROOT_URL`, `DOMAIN` и `SSH_DOMAIN`, в них вместо IP-адреса записывается домен.

Чтобы веб-интерфейс был виден только через веб-сервер, опубликуйте порт 3000 лишь на внутреннем адресе сервера. В файле Compose замените строку `"3000:3000"` на такую.

```yaml
      - "127.0.0.1:3000:3000"
```

Мы проверили, что после `docker compose up -d` порт 3000 перестаёт отвечать снаружи, а на самом сервере и через SSH-туннель страница по-прежнему открывается. Порт 2222 остаётся открытым, он нужен для Git по SSH.

***

## Полезные команды

```bash
docker compose ps                 # состояние контейнера, выполнять в /opt/gitea
docker logs gitea                 # журнал Gitea
docker restart gitea              # перезапустить Gitea
docker compose down               # удалить контейнер, данные в ./data останутся

# Список пользователей
docker exec -u git gitea gitea admin user list

# Новый пароль пользователю, например при потере пароля администратора
docker exec -u git gitea gitea admin user change-password --username gitadmin --password НОВЫЙ_ПАРОЛЬ --must-change-password=false

# Создать администратора из командной строки
docker exec -u git gitea gitea admin user create --admin --username имя --password ПАРОЛЬ --email me@example.com --must-change-password=false
```

Пароль, набранный в командной строке, попадает в историю команд оболочки. Поэтому после такой смены войдите в Gitea и поменяйте пароль на постоянный в настройках профиля.

***

## Частые вопросы

<details>

<summary>В адресе клонирования по SSH стоит localhost</summary>

Страница настройки записала в `app.ini` значения `DOMAIN = localhost` и `SSH_DOMAIN = localhost`. Мы получили адрес `ssh://git@localhost:2222/…`. Исправьте обе строки, как показано в шаге 3, и перезапустите контейнер.

</details>

<details>

<summary>git@IP-адрес: Permission denied (publickey).</summary>

Сервер не знает ваш ключ. Мы получили эту ошибку, когда пробовали клонировать репозиторий по SSH до того, как добавили ключ в Gitea.

1. Убедитесь, что в профиле Gitea на странице **Ключи SSH / GPG** лежит открытая часть именно того ключа, которым вы подключаетесь.
2. Проверьте, что вы добавили содержимое файла с окончанием `.pub`, а не закрытый ключ.
3. Если у вас несколько ключей, укажите нужный параметром `ssh -i`.

</details>

<details>

<summary>ssh: connect to host IP-адрес port 2222: Connection refused</summary>

На порту никто не отвечает. Мы получили эту ошибку, когда остановили контейнер командой `docker stop gitea`. Проверьте состояние командой `docker compose ps` и запустите контейнер командой `docker start gitea`. Если контейнер работает, а соединение зависает без ответа, порт закрывает брандмауэр на пути к серверу. С HTTP в том же случае Git сообщает **Failed to connect to IP-адрес port 3000 after 0 ms: Couldn't connect to server**.

</details>

<details>

<summary>remote: Failed to authenticate user</summary>

Неверный логин или пароль. Git показал нам следующие две строки, когда мы ввели неправильный пароль.

```text
remote: Failed to authenticate user
fatal: Authentication failed for 'http://IP-адрес-сервера:3000/gitadmin/my-project.git/'
```

Проверьте логин и пароль входа в веб-интерфейс. Если пароль потерян, задайте новый командой `gitea admin user change-password`, она есть в разделе про полезные команды.

</details>

<details>

<summary>remote: Update your password</summary>

У учётной записи включено требование сменить пароль, а пользователь ещё ни разу не входил в браузер. Пусть он откроет Gitea в браузере, войдёт и задаст новый пароль, как в шаге 7.

</details>

<details>

<summary>remote: Repository not found</summary>

Мы получили эту ошибку после правильного ввода пароля, когда в адресе была опечатка в названии репозитория. Строкой ниже Git пишет **fatal: repository … not found**. Сверьте адрес с тем, что показывает окно **Код**. Эта же ошибка бывает у коллеги, которого не добавили в соавторы приватного репозитория.

</details>

<details>

<summary>Author identity unknown</summary>

Git не знает, от чьего имени записать коммит. Мы получили это сообщение при первом `git commit` на чистом пользователе. Выполните две команды из шага 5, `git config --global user.name` и `git config --global user.email`, и повторите коммит.

</details>

<details>

<summary>Извините, возможность регистрации отключена</summary>

Коллега пытается зарегистрироваться сам, а регистрация закрыта. Так и задумано. Создайте ему учётную запись в панели управления, как в шаге 7.

</details>

***

## Наши ресурсы

**Telegram-канал:** [https://t.me/f3cloud_news](https://t.me/f3cloud_news)\
**Официальный сайт:** [https://f3cloud.com](https://f3cloud.com/ru)
