Захотел я поднять домашний git-сервер для хранения разных проектов. Вещь в хозяйстве очень полезная, т.к. с ним удобно шарить исходный код между разными машинами, плюс периодически делать резервное копирование сразу всех репозиториев с этим кодом из одного места одной командой. В качестве аппаратной платформы для этого дела было выбрано сетевое хранилище Western Digital My Book Live, которое уже много лет успешно выполняет свои обязанности в домашней локальной и представляет собой linux-машину (Debian) с 3-х террабайтным HDD.
Т.к. не смог найти в интернетах полного руководства по сабжу, отвечающего на все вопросы, решил собрать информацию в этой статье.
Первым шагом будет настройка 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:
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
На клиентской машине должен быть файл ~/.ssh/config со следующим содержимым:
Host * UseKeychain yes AddKeysToAgent yes IdentityFile ~/.ssh/id_rsa
Готово, теперь о вводе пароля можно забыть. Для того, чтобы разрешить доступ другим пользователям, достаточно добавить их публичный ключ в 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".