Домашний git-сервер на WD My Book Live

WD MyBookLive git-serverX

git и WD My Book Live

Захотел я поднять домашний git-сервер для хранения разных проектов. Вещь в хозяйстве очень полезная, т.к. с ним удобно шарить исходный код между разными машинами, плюс периодически делать резервное копирование сразу всех репозиториев с этим кодом из одного места одной командой. В качестве аппаратной платформы для этого дела было выбрано сетевое хранилище Western Digital My Book Live, которое уже много лет успешно выполняет свои обязанности в домашней локальной и представляет собой linux-машину (Debian) с 3-х террабайтным HDD.

Т.к. не смог найти в интернетах полного руководства по сабжу, отвечающего на все вопросы, решил собрать информацию в этой статье.

Начинаем - ssh + ipkg

Первым шагом будет настройка ssh-доступа к хранилищу. А для этого надо знать его ip-адрес, в моём случае это 192.168.1.3. По умолчанию ssh-доступ закрыт, и разрешить его можно в веб-интерфейсе WD-шки http://192.168.1.3/UI/ssh. Рутовый пароль по умолчанию welc0me, и его лучше сразу же сменить на что-то более надёжное. Особенно, если сервер будет использоваться не только в локальной сети, и к нему будет открыт доступ в "большой" интернет. Логинимся на сервер:

ssh root@192.168.1.3

и вводим команду смены пароля

passwd

Дваждый вводим новый пароль и запоинаем/записываем его (т.к. на странице http://192.168.1.3/UI/ssh всегда будет показывается дефолтный welc0me).

Теперь можно одной командой apt-get установить пакет git и счастливо пользоваться им. Но только до первой перезагрузки. После чего файловое хранилище волшебным образом должно превратиться в кирпич (сам я не проверял, но так пишут в интернетах). Впрочем, восстановить после этого девайс в исходное рабочее состояние будет не сложно, но это уже другая история.

ВАЖНО: для установки дополнительных пакетов нельзя использовать apt-get, т.к., это приводит к нарушению работы установленного производителем софта. Вместо этого надо подключить репозиторий пакетов Optware, содержащий сотни различных полезных (и не очень) программ, включая git. Подробности можно посмотреть тут, а для подключения репозитория достаточно ввести несколько команд в терминале:

wget http://mybookworld.wikidot.com/local--files/optware/setup-mybooklive.sh
sh setup-mybooklive.sh

Далее выполняем

echo "export PATH=$PATH:/opt/bin:/opt/sbin" >> /root/.bashrc
echo "export PATH=$PATH:/opt/bin:/opt/sbin" >> /etc/profile

Чтобы прописать пути к новому пакетному менеджеру. После чего закрываем сессию ssh и подключаемся заново.

Теперь обновляем базу пакетов

ipkg update

Установка git-а

Устанавливаем сам git:

ipkg install git

Тут заодно сразу можно поставить Midnight Commander - пригодится.

ipkg install mc

Далее в веб-интерфейсе создаём нового пользователя git со своей share. После чего изменяем его домашний каталог на /shares/git и командный интерпретатор на /opt/bin/git-shell. Для этого редактируем последнюю добавленную строку в файле /etc/passwd

vi /etc/passwd

У меня получилось так:

git:x:1001:1000:,3,,:/shares/git:/opt/bin/git-shell

Теперь надо настроить ssh-доступ для этого пользователя. Открываем файл конфигурации демона ssh

vi /etc/ssh/sshd_config

ищем там строку "AllowUsers" и добавляем пользователя git:

AllowUsers root git

также проверяем, что следующая строка закомментирована:

#AcceptEnv LANG LC_*

настраиваем права доступа и владельца для директории шары (без этого ssh не станет работать):

chmod o-w /shares/git
chown git /shares/git

Логинимся от имени пользователя git и переходим в его домашнюю директорию и создаём там подкаталог bin.:

sudo -u git bash
cd /shares/git/
mkdir /shares/git/bin

Создаём файл профиля

vi /shares/git/.profile

со следующим содержимым

export PATH=\$PATH:~/bin
export LANG=C
umask 022

И выполняем его

source /shares/git/.profile

Всё. На этом базовая настройка git-а завершена.

Создание репозитория

Репозиторий создаётся на сервере следующей командой (тут my-new-repo - имя создаваемого репозитория)

sudo -u git bash -c "cd /shares/git/ && /opt/bin/git init --bare my-new-repo.git && chmod g+rw my-new-repo.git"

Теперь забрать это репозиторий на локальную машину можно командой

git clone git@192.168.1.3:my-new-repo.git

Система запросит пароль пользователя git и загрузит созданный репо. Вариант рабочий, но не совсем удобный - вводить каждый раз пароль утомляет.

Настройка доступа по ключу

Чтобы не вводить пароль каждый раз можно настроить доступ по ключу. Для этого создаём каталог .ssh

mkdir /shares/git/.ssh
chown git /shares/git/.ssh
chmod 700 /shares/git/.ssh

и файл authorized_keys в нём:

vi /shares/git/.ssh/authorized_keys

В этот файл надо скопировать свой публичный ключ (который обычно хранится в файле ~/.ssh/id_rsa.pub в *nix-системах, файл из одной строки). Затем прописываем права доступа

chown git /shares/git/.ssh/authorized_keys 
chmod 600 /shares/git/.ssh/authorized_keys
chmod g-w /shares/git

и открываем в редакторе sshd_config:

vi /etc/ssh/sshd_config

Там убеждаемся, что следующие строки присутствуют и раскомментированы:

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile     %h/.ssh/authorized_keys

В завершении перезапускаем ssh-демона

/etc/init.d/ssh restart

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

Глобальный доступ

Сейчас репозиторий доступен только в домашней сети. Для того, чтобы открыть к нему доступ отовсюду, надо пробросить 22й порт в настройках роутера, что позволит подключаться к серверу из большого интернета по его внешнему ip-адресу. Но это неудобно, особенно, если ip выдаётся динамически и постоянно меняется. Тут можно воспользоваться сервисом вроде dyndns, но лично у меня опыт их использования не особо положителен (доступ периодически отваливался, а от пользователя требовались постоянные перерегистрации с целью мтотивировать его перейти на платную подписку). В качестве альтернативы, можно прописать доменное имя в файл /etc/hosts, а для автоматического обновления ip адреса в нём написать пару скриптов. Но для этого понадобится сайт с php и доменным именем (тут можно, например, воспользоваться подходящим бесплатным хостингом). Идея в том, что git-сервер будет периодически вызывать этот php-скрипт и передавать ему свой ip-адрес, а php-скрипт будет этот адрес сохранять в файл. На машинах клиента будет работать другой скрипт, который будет запрашивать файл с сохранённым ip и обновлять запись в /etc/hosts. Этакий самопальный DNS.

PHP-скрипт тривиален:

<?PHP
  $ip = $_SERVER["REMOTE_ADDR"];
  echo $ip;
  $file = fopen("my_ip.txt", "w");
  echo fwrite($file, "$ip");
  fclose($file);
?>

Он сохраняет ip-адрес запрашивающего хоста в файл my_ip.txt. Помещаем этот скрипт на публичный веб-сервер (допустим, его адрес получился http://my-site-url-/update_ip.php). Теперь надо научить домаший сервер дёргать этот скрипт из своего cron-а. Для этого в терминале WD-шки вызываем

crontab -e

И добавляем туда строку

*/10 * * * *    curl 'http://my-site-url-/update_ip.php'

Теперь каждые 10 минут актуальный ip-адрес домашнего хранилища будет обновляться. И получить его можно по ссылке: http://my-site-url-/my_ip.txt

Осталось написать скрипт, который также будет вызываться по крону на клиентских машинах и обновлять записи в файле /etc/hosts (для MacOS X это файл /private/etc/hosts)

#!/usr/bin/python

# -*- coding: utf-8 -*-

import urllib2

# для linux-систем
#ETC_HOSTS = "/etc/hosts"

# для MacOS X
ETC_HOSTS = "/private/etc/hosts"

hosts = {
    'mydomain': 'http://my-site-url-/my_ip.txt'
}

ip = {}

for host in hosts:
    resolver = hosts[host]
    addr = urllib2.urlopen(resolver).read()
    ip[host] = addr

with open(ETC_HOSTS) as f:
    content = f.readlines()

new_content = []

for s in content:
    ss = s.strip()
    if len(ss) == 0 or ss.startswith('#'):
        new_content.append(s)
        continue
    found = False
    for host in hosts:
        if s.find(host) > 0 and hosts[host] is not None:
            new_content.append(ip[host]+ '\t' + host)
            hosts[host] = None
            found = True
            break
    if not found:
        new_content.append(s)

for host in hosts:
    if hosts[host] is not None:
        new_content.append(ip[host] + '\t' + host)

with open(ETC_HOSTS, "w") as f:
    for s in new_content:
        f.write(s)

Тут таблица hosts содержит в качестве ключей имена доменов, которые будут добавлены в файл hosts, а значениями служат url-ы, по которым будут получаться ip-адреса. Хостов можно добавить сколько угодно.

Прописываем вызов этого скрипта из крона на клиентских машинах (либо, как вариант, можно вызывать скрипт вручную) и всё - имеем свой git + sftp-сервер доступный отовсюду по доменному имени "mydomain".

Рейтинг: 
0
Голосов еще нет