SelfHosted Git или Gitea

September 23, 2022, 7:44 pm
blog-header-image

Сегодня попробуем создать свой маленький уютный git, прямо у себя дома. В качестве которого будем использовать gitea. Данный сервис должен быть доступен из глобальной сети, и для это мы используем ранее поднятый vpn (wireguard) сервер. По сути мы просто пробросим порты (80 и 433) из сервера с белым ip до компьютера находящегося в комнате. А также прикрутим поддомены к ip vpn-сервера. Это позволит открывать наши сервисы по доменному имени.

Железо

Для начала нам нужен компьютер для использования его в роли сервера, подойдет любой старый ПК или ноут. Дальше устанавливаем на него последнюю Debian, снимая все галочки с предложениями доп пакетов.

После установки скорее всего вы заметите что интернет, подключенный проводом (который работал при установки системы) не работает, это связанно с тем что нужно вручную получить IP через DHCP. Делается это очень просто:

sudo dhclient
ip a

Последняя команда покажет этот ip. В случае если вы хотите продолжить работать с кабелем, можно включить автоматическое получение ip при подключении витой пары. Для этого нужно в конец конфига /etc/network/interfaces дописать следующие строки:

auto eth0
iface eth0 inet dhcp

Где eth0 это название вашего интерфейса.

Если же вы планируете подключать сервер через WiFi, то можно воспользоваться network-manager c nmtui, Однако сначала его нужно установить и да нужно обязательно сначала подключится по проводу, т.к. для настроики WiFi нужен специальный пакет, а для его установки нужен интернет. Когда интернет работает через провод устанавливаем network-manager:

sudo apt install network-manager
nmtui
# тут выбираем в консольной GUI свою сеть, и вводим пароль

После того как заработал интернет нужно установить оставшиеся пакеты для работы:

sudo apt install tmux htop git ssh

Также, если вы используете ноутбук, нужно решить проблему ухода системы в сон при закрытии крышки, это явно не то поведение которое мы ожидаем от сервера. Для этого нужно будет исправить один конфиг:

sudo nano /etc/systemd/logind.conf

Поменять и раскомментировать в нем пару параметров:

HandleLidSwitch=ignore
HandleLidSwitchDocked=ignore

Так-же могут пригодится команды для проверки состояния батареи:

cat /sys/class/power_supply/BAT0/capacity #уровень заряда в процентах
cat /sys/class/power_supply/BAT0/status   #статус батареи

Если вам (как и мне), не нравится то что терминал не отображает цвета при подключении по ssh то можно раскомментировать один параметр в файле ~/.bashrc:

force_color_prompt=yes

Сеть

Первым делом попробуем настроить сеть, и получить доступ к тестовым страницам через nginx.

Поддомены

Для работы со своими доменными именами я использую этот сервис. В нем (хотя в любом другом это будет работать точно так-же) нужно добавить 2 А записи (с www и без него):

dns

У меня это git.your_domain.com и www.git.your_domain.com.

Проброс портов

Далее нам нужно пробросить порты (80 и 443) от сетевого интерфейса с белым ip до виртуального интерфейса wireguard. Для этого сначала нужно сгенерировать конфиг клиента wireguard для домашнего сервера (это делается на VPN сервере), напомню что для easy-wg-quick который использовался тут делается это с помощью команд:

./easy-wg-quick server_git
sudo wg-quick down ./wghub.conf
sudo wg-quick up ./wghub.conf

В данном конфиге будет жёстко прописан ip (в дальнейшем он будет обозначатся как ) который будет присвоен домашнему серверу в сети vpn. Именно этот ip нужно будет использовать в правилах iptable:

[Interface]
Address = <client_ip_vpn>/24
...

Далее, для проброса портов необходимо разрешить forwarding:

sudo nano /etc/sysctl.conf

Там необходимо раскомментировать 2 строки:

net.ipv4.ip_forward=1
net.ipv6.conf.all.forwarding=1

Дальше нужно настроить непосредственно проброс портов, через iptables:

sudo iptables -A FORWARD -i eth0 -o wghub -j ACCEPT
sudo iptables -t nat -A PREROUTING -p tcp -d <server_ip_global> --dport 80 -j DNAT --to-destination <client_ip_vpn>:80
sudo iptables -t nat -A PREROUTING -p tcp -d <server_ip_global> --dport 443 -j DNAT --to-destination <client_ip_vpn>:443
sudo iptables -L -t nat

Тут используется ip адрес который мы посмотрели ранее в конфиге, а так-же физический ip () vpn сервера. POSTROUTING не нужен т.к. из-за использования сервера, как vpn, разрешены все маршруты.

Для удаления правила нужно сделать следующее:

sudo iptables -L -t nat --line-numbers
# тут смотрим номер нужного правила (например 3)
sudo iptables -t nat -D POSTROUTING 3

Эти настройки не сохранятся после перезагрузки, для того чтобы они применялись при старте системы, для начала, их нужно просто сохранить:

sudo /sbin/iptables-save | sudo tee /etc/iptables/rules.v4
sudo /sbin/ip6tables-save | sudo tee /etc/iptables/rules.v6

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

sudo apt install iptables-persistent

NGINX

Теперь попробуем поднять тестовую страницу, что-бы убедится в том что все вышеперечисленное работает.

Первое что необходимо сделать это подключится по SSH к домашнему серверу и подключить сервер к vpn. Подробно этот процесс описан тут, так что тут описывать его не буду. После чего устанавливаем nginx и php:

sudo apt install -y nginx curl mariadb-server wget

Далее рассмотрим создание тестовой страницы, которая будет доступна в глобальной сети через доменное имя. У меня это доменное имя это git.zenembed.com, но для удобства читателей в дальнейшем я буду обозначать его как git.your_domain.com:

sudo mkdir -p /var/www/git.your_domain.com/html
sudo chown -R $USER:$USER /var/www/git.your_domain.com/html
sudo chmod -R 755 /var/www/git.your_domain.com

Создаем страницу и конфиг:

nano /var/www/git.your_domain.com/html/index.html
<html>
    <head>
        <title>Welcome to git.your_domain.com!</title>
    </head>
    <body>
        <h1>Success!  The git.your_domain.com server block is working!</h1>
    </body>
</html>
sudo nano /etc/nginx/sites-available/git.your_domain.com
server {
    listen 80;
    listen [::]:80;

    root /var/www/git.your_domain.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name git.your_domain.com www.git.your_domain.com;

    location / {
            try_files $uri $uri/ =404;
    }
}

После включаем данный конфиг:

sudo ln -s /etc/nginx/sites-available/git.your_domain.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx

После этого по git.your_domain.com откроется тестовая страница.

SSL

Теперь необходимо получить сертификаты Let's Encrypt для нашей странице. Для этого будем использовать acme.sh. Скачиваем скрипт, переключаем на letsencrypt и генерируем ключи:

sudo su
curl https://get.acme.sh | sh
mkdir -p /etc/nginx/certs/git.your_domain.com
exec $SHELL
acme.sh --set-default-ca --server letsencrypt
acme.sh --nginx --issue -d git.your_domain.com -d www.git.your_domain.com --key-file /etc/nginx/certs/git.your_domain.com/key.pem --fullchain-file /etc/nginx/certs/git.your_domain.com/cert.pem --reloadcmd "service nginx force-reload"
exit

Генерация происходит пользователем root, это связанно с тем что скрипт вызывает nginx, а это доступно только рут пользователю. Так-же данный скрипт сам создаст задачу в cron которая раз в день будет проверять актуальность установленных сертификатов.

После этого нужно подправить конфиг nginx для тестовой страницы:

sudo nano /etc/nginx/sites-available/git.your_domain.com
server {
    listen 443 ssl;
    ssl_certificate     /etc/nginx/certs/git.your_domain.com/cert.pem;
    ssl_certificate_key /etc/nginx/certs/git.your_domain.com/key.pem;
    ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    root /var/www/git.your_domain.com/html;
    index index.html index.htm index.nginx-debian.html;

    server_name git.your_domain.com www.git.your_domain.com;

    location / {
            try_files $uri $uri/ =404;
    }
}
sudo systemctl restart nginx

Теперь наша тестовая страница открывается по запросу с git.your_domain.com https. Если вы попытаетесь открыть сайт без ssl (с http) то будет открыта страница описанная в конфиге default nginx. Для решения этой проблемы изменим дефолтный конфиг так, чтобы он всегда перенаправлял на версию сайта с SSL:

sudo nano /etc/nginx/sites-available/default
server {
    listen 80 default_server;

    server_name _;
    return 301 https://$host$request_uri;
}
sudo systemctl restart nginx

Gitea

Теперь разберемся как поднять гит.

User

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

sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' --group --disabled-password --home /home/git git
sudo passwd -d git

Mariabd

После установки mariadb-server (это сделано в блоке nginx) её необходимо настроить, для этого нужно сначала запустить конфигурационный скрипт:

sudo mysql_secure_installation

Далее нужно настроить БД и установить пароль:

    Enter current password for root (enter for none): Enter
    Switch to unix_socket authentication [Y/n] : Y
    Change the root password? [Y/n]: n
    Remove anonymous users? [Y/n]: Y
    Disallow root login remotely? [Y/n]: Y
    Remove test database and access to it? [Y/n]:  Y
    Reload privilege tables now? [Y/n]:  Y

После этого необходимо создать базу данных для нашего приложения:

sudo mysql -u root -p
> CREATE DATABASE gitea;
> GRANT ALL PRIVILEGES ON gitea.* TO 'gitea'@'localhost' IDENTIFIED BY "<your_bd_pass>";
> FLUSH PRIVILEGES;
> QUIT;

В <your_bd_pass> нужно подставить свой пароль.

Установка gitea

Далее необходимо скачать и установить исполняемый файл gitea:

curl -s  https://api.github.com/repos/go-gitea/gitea/releases/latest |grep browser_download_url  |  cut -d '"' -f 4  | grep '\linux-amd64$' | wget -i -

chmod +x gitea-*-linux-amd64
sudo mv gitea-*-linux-amd64 /usr/local/bin/gitea

gitea --version

Systemd

Для авто запуска необходимо создать сервис Systemd:

sudo mkdir -p /etc/gitea /var/lib/gitea/{custom,data,indexers,public,log}
sudo chown git:git /var/lib/gitea/{data,indexers,log}
sudo chmod 750 /var/lib/gitea/{data,indexers,log}
sudo chown root:git /etc/gitea
sudo chmod 770 /etc/gitea
sudo nano /etc/systemd/system/gitea.service
[Unit]
Description=Gitea (Git with a cup of tea)
After=syslog.target
After=network.target
After=mysql.service

[Service]
LimitMEMLOCK=infinity
LimitNOFILE=65535
RestartSec=2s
Type=simple
User=git
Group=git
WorkingDirectory=/var/lib/gitea/
ExecStart=/usr/local/bin/gitea web -c /etc/gitea/app.ini
Restart=always
Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable --now gitea

systemctl status gitea

Nginx

sudo nano /etc/nginx/sites-available/git.your_domain.com
server {
        listen 443 ssl;
        ssl_certificate     /etc/nginx/certs/git.your_domain.com/cert.pem;
        ssl_certificate_key /etc/nginx/certs/git.your_domain.com/key.pem;
        ssl_protocols       TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers         HIGH:!aNULL:!MD5;

        server_name git.your_domain.com www.git.your_domain.com;

        location / {
                proxy_pass http://localhost:3000;
        }
}
sudo systemctl restart nginx.service

После этого необходимо пройти по данному адресу и настроить пароль от БД а так-же прописать адрес сервера. Так-же было бы не плохо поменять некоторые парамеры в конфиге /etc/gitea/app.ini:

# домашнаяя страница будет показывать открытые проекты
[server]
LANDING_PAGE                      = explore

# отключение возможности регистрации
[service]
DISABLE_REGISTRATION              = true

# Так-же отключим показ версии пакета.
[other]
SHOW_FOOTER_VERSION               = false
SHOW_FOOTER_TEMPLATE_LOAD_TIME    = false

Для применения настроек нужно:

sudo systemctl restart gitea

Beckup

Последнее что необходимо сделать это настроить бекап для git, для чего используем скрипт:

dump_name=dump-$(date +"%d.%m.%Y-%H:%M")
dump_folder=/tmp/$dump_name

mkdir $dump_folder
chmod 777 $dump_folder
su - git -c "gitea dump -c /etc/gitea/app.ini --file $dump_folder/gitea.zip; chmod 666 $dump_folder/gitea.zip"
mysqldump -u gitea --password=<your_bd_pass> gitea > $dump_folder/gitea.sql
cd $dump_folder
tar -czvf $dump_folder.tar.gz *
chmod 666 $dump_folder.tar.gz
cd ~
mv $dump_folder.tar.gz .
rm -rf $dump_folder.tar.gz $dump_folder

Данный скрипт кидает архив с бекапом в home пользователя, не плохо было бы поменять это на внешний диск или флешку.

Для того чтобы этот скрипт запускался раз в день, нужно добавить задачу в cron:

crontab -e
# добавить строку
30 4 * * * ~/dump.sh

Интересные ссылки

Next Post Previous Post