Todos nós desenvolvedores, um dia, utilizaremos ou, senão, já usamos Controles de Versões de projetos. Nesse post, eu comentarei um pouco sobre a criação de um servidor Git particular para ser usado como repositório. Além disso, indicarei possíveis erros que possam ocorrer durante a criação do mesmo.
Primeiramente devemos instalar no servidor os pacotes necessários.
Aplicando o Gitosis
Com os pacotes já instalados, recomendamos que seja criado um usuário no servidor chamado 'git' exclusivo e sem senha,
Criado o usuário, vamos ter como resposta,
Como queremos acessar o usuário 'git' sem senha, criaremos uma chave RSA pública em nossa própria máquina e não no servidor. Primeiramente, devemos criar (se ela ainda não existir) uma pasta chamada .ssh em /home/git/ com,
Já em nossa máquina devemos criar a chave pública fazendo,
e compiamos ela para a pasta /tmp/ do servidor,
Feito isso, liberamos o acesso com,
Agora podemos acessar via SSH nosso usuário Git sem senha. Para começarmos a utilizar o Gitosis, devemos efetuar o seguinte comando no home folder do usuário git,
Sendo a saída esperada justamente duas vezes a mesma mensagem,
Devemos habilitar o script para execução do git update-server-info com,
Na sua máquina agora será possível realizar um git clone via SSH.
Você, primeiramente, irá clonar um repositório vazio e, posteriormente, poderá inserir arquivos a serem adicionados ao commit.
Para adicionar permissões, é possível editar o arquivo encontrado em /home/git/repositories/gitosis-admin.git/gitosis.conf no servidor. Editando-o da seguinte maneira,
Para adicionar mais grupos, repositórios ou membros, podemos exemplificar com o modelo abaixo,
* Importante: Se optarmos por garantir o acesso público utilizando o protocolo Git, devemos efetuar,
e iniciaremos o daemon com,
Assim, podemos usar o git clone efetuando,
Devemos lembrar que o protocolo Git é usado somente leitura. Portanto em casos de git push essa URL não será válida levando a erros que serão reportados em outros posts.
Criando outros Repositórios de Projetos
Podemos criar pastas no mesmo diretório que o gitosis-admin. No meu caso, como utilizarei o Gitweb criarei uma outra pasta dentro de /home/git/repositories/, chamada de "projects" e dentro de "projects" criarei o "meuprojeto".
Para fazer com que "meuprojeto" seja um repositório git, devemos realizar os seguintes comandos,
Voltando a máquina local, podemos cloná-lo para adicionar os arquivos referentes ao projeto. Obviamente, temos a liberdade de fazer isso diretamente no servidor, entretanto, essa é uma forma que eu acredito ser mais organizada e mais lógica. Portanto, efetuaremos o seguinte comando,
Uma mensagem de alerta aparecerá, informando que o repositório git clonado está vazio. Uma mensagem absolutamente normal.
Podemos copiar todos os arquivos referentes, efetuando, por exemplo,
O git push origin master irá realizar um commit inicial no branch master da origem que é o servidor. É muito importante realizar esse primeiro comando no primeiro push.
* Importante: Após realizarmos essas alterações no projeto, o mais lógico seria enviá-las ao servidor como forma de atualização do repositório do projeto, mas quando efetuamos o comando acima,
Uma mensagem como essa aparecerá,
Isso acontece graças ao clone realizado com o protocolo git, na qual, é um protocolo usado somente para leitura e não para a escrita de dados vindos do servidor. Então, quando efetuamos um push ele tentará acessar a URL usada no clone que será git://servidor_hostname/projects/meuprojeto, não obtendo sucesso. Para corrigirmos essa situação, temos a opção de atualizar as configurações do nosso projeto verificadas em,
podemos observar o campo remote.origin.url="..." como sendo igual a URL clonada. Para alterarmos, basta executar um editor e alterar esse campo com a URL destinada ao SSH.
e editarmos o campo,
Agora, podemos executar o git push,
Não iremos cobrir nesse post a configuração do Apache para assim usarmos o protocolo HTTP em clones de repositórios. Futuramente, iremos abordar melhor como fazer tal procedimento.
Finalizando, por questões de segurança, podemos limitar o acesso via SSH ao usuário Git fazendo,
Terminamos aqui uma configuração básica e essencial de um servidor Git utilizado para hospedar projetos e trabalhos.
Configurando o Gitweb
A configuração do Gitweb é relativamente fácil. Procedemos,
Criada a pasta, configuremos o Git no Apache,
preenchendo, então, o arquivo com os seguinte dados:
O Próximo passo é mover todos os arquivos provenientes do Gitweb para a nova pasta criada.
Para terminarmos a configuração, editemos o arquivo de configuração do Gitweb,
como o exemplo abaixo (que segue o exemplo da criação do repositório "meuprojeto"),
Terminamos assim a configuração do Gitweb e podemos acessar nossos projetos, seus commits, diffs via página HTML.
Problemas que podem ocorrer durante a configuração do Servidor
Alguns problemas já foram descritos acima, como problemas decorrentes do protocolo Git que se comporta como somente leitura sendo corrigida.
Um problema enfrentado quando eu solicitei um git clone foi o bloqueio da porta 9418 (utilizada pelo git daemon) recebendo um,
Para liberarmos o firewall para utilizarmos o Git, no meu caso eu abilitei a porta 9418, no iptables, da seguinte maneira,
Adicinando a seguinte linha ao Documento,
É sempre bom documentarmos para quem estamos adicionando uma liberação, isso ajuda outros utilizadores do servidor em caso de alguma manutenção ou outros usos. Documentação é essencial pra qualquer prática de programação.
Por fim reiniciaremos o firewall aplicando as mudanças com,
Quem seguiu as práticas citadas acima, verificou exatamente tudo, prestou a atenção em cada linha de comando, mas ainda não consegue realizar um clone ou um push, pode analisar os logs mantidos pelo git daemon. Esse arquivo, para mim, foi uma peça chave para identificar problemas relacionados a localização dos repositórios e a erros relacionados a conexão. Para analisarmos esse arquivo, realizemos um,
Na qual a minha saída no shell foi,
Mas há todo o tipo de mensagem que envolva o git-daemon.
Considerações Finais
Não há muita complexidade para criarmos um servidor de repositórios Git em um servidor pessoal, entretanto algumas dificuldades são providas com base em outros serviços que podem influenciar na conexão, ou os próprios protocolos muitas vezes merecem um estudo antes de serem usados como o protocolo Git. Erros também aparecem devido a erros de sintaxe no momento da configuração do servidor, por isso, é sempre bom estarmos atentos aos procedimentos.
As referências usadas no auxílio da elaboração desse post são listadas a seguir, bem como um tutorial básico da utilização do Git:
[Tutorial de Git] - Tutorial elaborado por mim que abrange o essencial de Git.
[scie.nti.st] - Tutorial bem bacana sobre Git Server.
[noroyalties.org] - Um outro tutorial usado na referência.
Pro Git - Professional Version Control - Livro on-line interessante a respeito de Git.
Primeiramente devemos instalar no servidor os pacotes necessários.
$ sudo apt-get install git-core gitosis gitweb
Aplicando o Gitosis
Com os pacotes já instalados, recomendamos que seja criado um usuário no servidor chamado 'git' exclusivo e sem senha,
$ sudo adduser \
--system \
--shell /bin/bash \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home /home/git \
git
--system \
--shell /bin/bash \
--gecos 'Git Version Control' \
--group \
--disabled-password \
--home /home/git \
git
Criado o usuário, vamos ter como resposta,
Adding system user 'git'...
Adding new group 'git' (211).
Adding new user 'git' (211) with group 'git'.
Creating home directory '/home/git'.
Adding new group 'git' (211).
Adding new user 'git' (211) with group 'git'.
Creating home directory '/home/git'.
Como queremos acessar o usuário 'git' sem senha, criaremos uma chave RSA pública em nossa própria máquina e não no servidor. Primeiramente, devemos criar (se ela ainda não existir) uma pasta chamada .ssh em /home/git/ com,
$ mkdir .ssh
Já em nossa máquina devemos criar a chave pública fazendo,
$ ssh-keygen -t rsa
e compiamos ela para a pasta /tmp/ do servidor,
$ scp ~/.ssh/id_rsa.pub seu_login@servidor_hostname:/tmp/
Feito isso, liberamos o acesso com,
$ sudo cat /tmp/id_rsa.pub >> /home/git/.ssh/authorized_keys
Agora podemos acessar via SSH nosso usuário Git sem senha. Para começarmos a utilizar o Gitosis, devemos efetuar o seguinte comando no home folder do usuário git,
$ sudo -H -u git gitosis-init < id_rsa.pub
Sendo a saída esperada justamente duas vezes a mesma mensagem,
Initialized empty Git repository in ./
Initialized empty Git repository in ./
Initialized empty Git repository in ./
Devemos habilitar o script para execução do git update-server-info com,
$ sudo chmod 755 /home/git/repositories/gitosis-admin.git/hooks/post-update
Na sua máquina agora será possível realizar um git clone via SSH.
$ git clone git@servidor_hostname:~/repositories/gitosis-admin.git
$ cd gitosis-admin.git
$ cd gitosis-admin.git
Você, primeiramente, irá clonar um repositório vazio e, posteriormente, poderá inserir arquivos a serem adicionados ao commit.
Para adicionar permissões, é possível editar o arquivo encontrado em /home/git/repositories/gitosis-admin.git/gitosis.conf no servidor. Editando-o da seguinte maneira,
[gitosis]
[group gitosis-admin]
writable = giosis-admin
members = nome_do_usuário
[group gitosis-admin]
writable = giosis-admin
members = nome_do_usuário
Para adicionar mais grupos, repositórios ou membros, podemos exemplificar com o modelo abaixo,
[group laboratório]
writable = projeto
members = usuário1 usuário2 usuário3
writable = projeto
members = usuário1 usuário2 usuário3
* Importante: Se optarmos por garantir o acesso público utilizando o protocolo Git, devemos efetuar,
$ touch ~/repositories/gitosis-admin.git/git-daemon-export-ok
e iniciaremos o daemon com,
$ sudo -u git git daemon --base-path=/home/git/repositories --export-all
Assim, podemos usar o git clone efetuando,
$ git clone git://servidor_hostname/gitosis-admin.git
Devemos lembrar que o protocolo Git é usado somente leitura. Portanto em casos de git push essa URL não será válida levando a erros que serão reportados em outros posts.
Criando outros Repositórios de Projetos
Podemos criar pastas no mesmo diretório que o gitosis-admin. No meu caso, como utilizarei o Gitweb criarei uma outra pasta dentro de /home/git/repositories/, chamada de "projects" e dentro de "projects" criarei o "meuprojeto".
$ cd /home/git/repositories/
$ mkdir projects
$ cd projects
$ mkdir meuprojeto
$ mkdir projects
$ cd projects
$ mkdir meuprojeto
Para fazer com que "meuprojeto" seja um repositório git, devemos realizar os seguintes comandos,
$ cd meuprojeto
$ git --bare init
$ cp ~/repositories/gitosis-admin.git/hooks/post-update /hooks/
$ touch ~/repositories/projects/meuprojeto/git-daemon-export-ok
$ git --bare init
$ cp ~/repositories/gitosis-admin.git/hooks/post-update /hooks/
$ touch ~/repositories/projects/meuprojeto/git-daemon-export-ok
Voltando a máquina local, podemos cloná-lo para adicionar os arquivos referentes ao projeto. Obviamente, temos a liberdade de fazer isso diretamente no servidor, entretanto, essa é uma forma que eu acredito ser mais organizada e mais lógica. Portanto, efetuaremos o seguinte comando,
$ git clone git://servidor_hostname/projects/meuprojeto
Uma mensagem de alerta aparecerá, informando que o repositório git clonado está vazio. Uma mensagem absolutamente normal.
Podemos copiar todos os arquivos referentes, efetuando, por exemplo,
$ cd meuprojeto
$ git add .
$ git commit -a -m "Qualquer informação válida sobre o commit"
$ git push origin master
$ git add .
$ git commit -a -m "Qualquer informação válida sobre o commit"
$ git push origin master
O git push origin master irá realizar um commit inicial no branch master da origem que é o servidor. É muito importante realizar esse primeiro comando no primeiro push.
* Importante: Após realizarmos essas alterações no projeto, o mais lógico seria enviá-las ao servidor como forma de atualização do repositório do projeto, mas quando efetuamos o comando acima,
$ git push origin master
Uma mensagem como essa aparecerá,
fatal: The remote end hung up unexpectedly
Isso acontece graças ao clone realizado com o protocolo git, na qual, é um protocolo usado somente para leitura e não para a escrita de dados vindos do servidor. Então, quando efetuamos um push ele tentará acessar a URL usada no clone que será git://servidor_hostname/projects/meuprojeto, não obtendo sucesso. Para corrigirmos essa situação, temos a opção de atualizar as configurações do nosso projeto verificadas em,
$ git config --list
podemos observar o campo remote.origin.url="..." como sendo igual a URL clonada. Para alterarmos, basta executar um editor e alterar esse campo com a URL destinada ao SSH.
$ vim .git/config
e editarmos o campo,
...
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@servidor_hostname:~/repositories/projects/meuprojeto
...
[remote "origin"]
fetch = +refs/heads/*:refs/remotes/origin/*
url = git@servidor_hostname:~/repositories/projects/meuprojeto
...
Agora, podemos executar o git push,
$ git push origin master
Não iremos cobrir nesse post a configuração do Apache para assim usarmos o protocolo HTTP em clones de repositórios. Futuramente, iremos abordar melhor como fazer tal procedimento.
Finalizando, por questões de segurança, podemos limitar o acesso via SSH ao usuário Git fazendo,
$ chsh -s /usr/bin/git-shell
Terminamos aqui uma configuração básica e essencial de um servidor Git utilizado para hospedar projetos e trabalhos.
Configurando o Gitweb
A configuração do Gitweb é relativamente fácil. Procedemos,
$ sudo mkdir /var/www/git
Criada a pasta, configuremos o Git no Apache,
$ sudo vim /etc/apache2/conf.d/git
preenchendo, então, o arquivo com os seguinte dados:
<Directory /var/www/git>
Allow from all
AllowOverride all
Order allow,deny
Options ExecCGI
<Files gitweb.cgi>
SetHandler cgi-script
</Files>
</Directory>
Allow from all
AllowOverride all
Order allow,deny
Options ExecCGI
<Files gitweb.cgi>
SetHandler cgi-script
</Files>
</Directory>
O Próximo passo é mover todos os arquivos provenientes do Gitweb para a nova pasta criada.
$ sudo mv /usr/share/gitweb/* /var/www/git/
$ sudo mv /usr/lib/cgi-bin/gitweb.cgi /var/www/git/
$ sudo mv /usr/lib/cgi-bin/gitweb.cgi /var/www/git/
Para terminarmos a configuração, editemos o arquivo de configuração do Gitweb,
$ sudo vim /etc/gitweb.conf
como o exemplo abaixo (que segue o exemplo da criação do repositório "meuprojeto"),
# path to git projects (<project>.git)
$projectroot = "/home/git/repositories/projects/";
# directory to use for temp files
$git_temp = "/tmp";
# target of the home link on top of all pages
#$home_link = $my_uri || "/";
# html text to include at home page
$home_text = "indextext.html";
# file with project list; by default, simply scan the projectroot dir.
$projects_list = $projectroot;
# stylesheet to use
$stylesheet = "gitweb.css";
# javascript code for gitweb
$javascript = "gitweb.js";
# logo to use
$logo = "git-logo.png";
# the 'favicon'
$favicon = "git-favicon.png";
$projectroot = "/home/git/repositories/projects/";
# directory to use for temp files
$git_temp = "/tmp";
# target of the home link on top of all pages
#$home_link = $my_uri || "/";
# html text to include at home page
$home_text = "indextext.html";
# file with project list; by default, simply scan the projectroot dir.
$projects_list = $projectroot;
# stylesheet to use
$stylesheet = "gitweb.css";
# javascript code for gitweb
$javascript = "gitweb.js";
# logo to use
$logo = "git-logo.png";
# the 'favicon'
$favicon = "git-favicon.png";
Terminamos assim a configuração do Gitweb e podemos acessar nossos projetos, seus commits, diffs via página HTML.
Problemas que podem ocorrer durante a configuração do Servidor
Alguns problemas já foram descritos acima, como problemas decorrentes do protocolo Git que se comporta como somente leitura sendo corrigida.
Um problema enfrentado quando eu solicitei um git clone foi o bloqueio da porta 9418 (utilizada pelo git daemon) recebendo um,
fatal: unable to connect a socket (Connection timed out)
Para liberarmos o firewall para utilizarmos o Git, no meu caso eu abilitei a porta 9418, no iptables, da seguinte maneira,
$ sudo vim /etc/init.d/iptables
Adicinando a seguinte linha ao Documento,
# git
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 9418 -j ACCEPT
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --destination-port 9418 -j ACCEPT
É sempre bom documentarmos para quem estamos adicionando uma liberação, isso ajuda outros utilizadores do servidor em caso de alguma manutenção ou outros usos. Documentação é essencial pra qualquer prática de programação.
Por fim reiniciaremos o firewall aplicando as mudanças com,
$ sudo /etc/init.d/iptables restart
Quem seguiu as práticas citadas acima, verificou exatamente tudo, prestou a atenção em cada linha de comando, mas ainda não consegue realizar um clone ou um push, pode analisar os logs mantidos pelo git daemon. Esse arquivo, para mim, foi uma peça chave para identificar problemas relacionados a localização dos repositórios e a erros relacionados a conexão. Para analisarmos esse arquivo, realizemos um,
$ sudo cat /var/log/git-daemon/current
Na qual a minha saída no shell foi,
2011-08-01_12:36:40.42770 git-daemon starting.
Mas há todo o tipo de mensagem que envolva o git-daemon.
Considerações Finais
Não há muita complexidade para criarmos um servidor de repositórios Git em um servidor pessoal, entretanto algumas dificuldades são providas com base em outros serviços que podem influenciar na conexão, ou os próprios protocolos muitas vezes merecem um estudo antes de serem usados como o protocolo Git. Erros também aparecem devido a erros de sintaxe no momento da configuração do servidor, por isso, é sempre bom estarmos atentos aos procedimentos.
As referências usadas no auxílio da elaboração desse post são listadas a seguir, bem como um tutorial básico da utilização do Git:
[Tutorial de Git] - Tutorial elaborado por mim que abrange o essencial de Git.
[scie.nti.st] - Tutorial bem bacana sobre Git Server.
[noroyalties.org] - Um outro tutorial usado na referência.
Pro Git - Professional Version Control - Livro on-line interessante a respeito de Git.
Interessante seu tutorial. No entanto devido executar operações em locais diferentes, não fica claro o suficiente, na sequência de execução de comandos, que usuário deve ser usado e onde. Por exemplo, seguindo os passos, fui executar sudo -H -u git gitosis-init < id_rsa.pub dentro do diretório /home/git, como você indicou, mas recebi erro de file not found.
ReplyDeleteOlá!
DeleteObrigado pela observação e pela dúvida! Realmente há um erro no comando citado! O correto seria "sudo -H -u git gitosis-init < /tmp/id_rsa.pub", executado no servidor. Caso o erro continue, estamos prontos a ajudar.