2016-01-31 13:43:06 +01:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "utf-8" >
< meta http-equiv = "X-UA-Compatible" content = "IE=edge" >
< meta name = "viewport" content = "width=device-width, initial-scale=1" >
2016-01-31 14:26:18 +01:00
< title > Private Git Repo< / title >
2016-01-31 13:43:06 +01:00
2016-01-31 16:10:48 +01:00
< link href = "https://captainark.net/rss.xml" type = "application/atom+xml" rel = "alternate" title = "Sysadmining. All day. Every day. Full Atom Feed" / >
2016-01-31 13:43:06 +01:00
<!-- Bootstrap Core CSS -->
2016-01-31 14:32:17 +01:00
< link href = "https://captainark.net/theme/css/bootstrap.min.css" rel = "stylesheet" >
2016-01-31 13:43:06 +01:00
<!-- Custom CSS -->
2016-01-31 14:32:17 +01:00
< link href = "https://captainark.net/theme/css/clean-blog.min.css" rel = "stylesheet" >
2016-01-31 13:43:06 +01:00
<!-- Code highlight color scheme -->
2016-01-31 14:32:17 +01:00
< link href = "https://captainark.net/theme/css/code_blocks/github.css" rel = "stylesheet" >
2016-01-31 13:43:06 +01:00
<!-- Custom Fonts -->
2016-02-01 21:02:18 +01:00
< link href = "https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css" rel = "stylesheet" type = "text/css" >
2016-01-31 13:43:06 +01:00
< link href = 'https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel = 'stylesheet' type = 'text/css' >
< link href = 'https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel = 'stylesheet' type = 'text/css' >
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!-- [if lt IE 9]>
< script src = "https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" > < / script >
< script src = "https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" > < / script >
<![endif]-->
2016-03-06 15:05:28 +01:00
< meta name = "description" content = "I've decided to migrate this blog to Pelican. I've been playing around with it over the week-end, and it turns out to be way easier to ..." >
2016-01-31 13:43:06 +01:00
2016-03-06 15:05:28 +01:00
< meta name = "author" content = "Antoine Joubert" >
2016-01-31 13:43:06 +01:00
< meta property = "og:locale" content = "" >
< meta property = "og:site_name" content = "Sysadmining. All day. Every day." >
< meta property = "og:type" content = "article" >
2016-05-22 15:22:00 +02:00
< meta property = "article:author" content = "https://captainark.net/author/antoine-joubert.html" >
2016-01-31 14:32:17 +01:00
< meta property = "og:url" content = "https://captainark.net/private-git-repo.html" >
2016-01-31 14:26:18 +01:00
< meta property = "og:title" content = "Private Git Repo" >
2016-01-31 13:43:06 +01:00
< meta property = "article:published_time" content = "2016-01-31 00:00:00+01:00" >
2016-03-06 15:05:28 +01:00
< meta property = "og:description" content = "I've decided to migrate this blog to Pelican. I've been playing around with it over the week-end, and it turns out to be way easier to ..." >
< meta property = "og:image" content = "https://captainark.net//bg.png" >
2016-05-22 15:22:00 +02:00
< meta name = "twitter:card" content = "summary_large_image" >
< meta name = "twitter:site" content = "@captainark" >
< meta name = "twitter:title" content = "Private Git Repo" >
< meta name = "twitter:image" content = "https://captainark.net//bg.png" >
< meta name = "twitter:description" content = "I've decided to migrate this blog to Pelican. I've been playing around with it over the week-end, and it turns out to be way easier to ..." >
2016-01-31 13:43:06 +01:00
< / head >
< body >
<!-- Navigation -->
< nav class = "navbar navbar-default navbar-custom navbar-fixed-top" >
< div class = "container-fluid" >
<!-- Brand and toggle get grouped for better mobile display -->
< div class = "navbar-header page-scroll" >
< button type = "button" class = "navbar-toggle" data-toggle = "collapse" data-target = "#bs-example-navbar-collapse-1" >
< span class = "sr-only" > Toggle navigation< / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< span class = "icon-bar" > < / span >
< / button >
2016-01-31 14:32:17 +01:00
< a class = "navbar-brand" href = "https://captainark.net/" > Sysadmining. All day. Every day.< / a >
2016-01-31 13:43:06 +01:00
< / div >
<!-- Collect the nav links, forms, and other content for toggling -->
< div class = "collapse navbar-collapse" id = "bs-example-navbar-collapse-1" >
< ul class = "nav navbar-nav navbar-right" >
< li > < a href = "/" > Homepage< / a > < / li >
2016-01-31 16:10:48 +01:00
< li > < a href = "/rss.xml" > RSS< / a > < / li >
2016-01-31 13:43:06 +01:00
< li > < a href = "/categories.html" > Categories< / a > < / li >
2016-01-31 14:32:17 +01:00
< li > < a href = "https://captainark.net/pages/about.html" > About< / a > < / li >
< li > < a href = "https://captainark.net/pages/resume.html" > Resume< / a > < / li >
2016-01-31 13:43:06 +01:00
< / ul >
< / div >
<!-- /.navbar - collapse -->
< / div >
<!-- /.container -->
< / nav >
<!-- Page Header -->
< header class = "intro-header" style = "background-image: url('/bg.png')" >
< div class = "container" >
< div class = "row" >
< div class = "col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1" >
< div class = "post-heading" >
2016-01-31 14:26:18 +01:00
< h1 > Private Git Repo< / h1 >
2016-01-31 13:43:06 +01:00
< span class = "meta" > Posted by
2016-01-31 14:32:17 +01:00
< a href = "https://captainark.net/author/antoine-joubert.html" > Antoine Joubert< / a >
2016-01-31 13:43:06 +01:00
on Sun 31 January 2016
< / span >
< / div >
< / div >
< / div >
< / div >
< / header >
<!-- Main Content -->
< div class = "container" >
< div class = "row" >
< div class = "col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1" >
<!-- Post Content -->
< article >
2016-01-31 16:01:02 +01:00
< p > I've decided to migrate this blog to < a href = "http://blog.getpelican.com/" > Pelican< / a > . I've been playing around with it over the week-end, and it turns out to be way easier to manage than < a href = "https://jekyllrb.com/" > Jekyll< / a > . Themes are much easier to install and configure, so it ends up looking better as well !< / p >
2016-01-31 14:26:18 +01:00
< p > Since I'm basically recreating this blog from scratch, I've decided to delete the old git repo that was hosting it and to create a new one.< / p >
2016-01-31 13:43:06 +01:00
< p > Setting up your own private git repo is pretty easy to achieve and is already well-documented on the < a href = "https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server" > Git< / a > website.< / p >
2016-01-31 14:26:18 +01:00
< p > Every time I want to create a new repo, I've had time to forget how to do it and I end up looking for that page, so I figured I'd write a few lines on the subject.< / p >
2016-01-31 13:43:06 +01:00
< p > In this tutorial, I'll configure a git repo on a distant server running Debian 8 (Jessie). This repo will be remotely accessible using SSH. Two users will be able to connect to it : me and the www-data user on my webserver.< / p >
2016-01-31 14:26:18 +01:00
< h2 > SSH Keys< / h2 >
2016-01-31 13:43:06 +01:00
< p > If you don't have one already, you'll need a ssh-key to connect to the git repo.< / p >
< p > On your computer, in a shell, as your usual user :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > ssh-keygen -t rsa -b 3072
2016-01-31 13:43:06 +01:00
Generating public/private rsa key pair.
Enter file in which to save the key < span class = "o" > (< / span > /home/user/.ssh/id_rsa< span class = "o" > )< / span > :
Enter passphrase < span class = "o" > (< / span > empty < span class = "k" > for< / span > no passphrase< span class = "o" > )< / span > :
Enter same passphrase again:
Your identification has been saved in /home/user/.ssh/id_rsa.
Your public key has been saved in /home/user/id_rsa.pub.
The key fingerprint is:
< span class = "o" > [< / span > Redacted< span class = "o" > ]< / span >
< / pre > < / div >
2016-01-31 14:26:18 +01:00
< p > For security reasons, configuring a passphrase is recommended. On Mac OS X and most desktop environnements on Linux, you can store this passphrase for the duration of your session using the < code > ssh-add< / code > command, so you won't have to type it every time you want to connect to a host.< / p >
< p > On the server, we also have to create a ssh-key for the user that is running our webserver (you'll need to have sudo installed) :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > sudo -H -u www-data ssh-keygen -t rsa -b 3072
2016-01-31 13:43:06 +01:00
Generating public/private rsa key pair.
Enter file in which to save the key < span class = "o" > (< / span > /var/www/.ssh/id_rsa< span class = "o" > )< / span > :
Enter passphrase < span class = "o" > (< / span > empty < span class = "k" > for< / span > no passphrase< span class = "o" > )< / span > :
Enter same passphrase again:
Your identification has been saved in /var/www/.ssh/id_rsa.
Your public key has been saved in /var/www/.ssh/id_rsa.pub.
The key fingerprint is:
< span class = "o" > [< / span > Redacted< span class = "o" > ]< / span >
< / pre > < / div >
< p > If you decide to configure a passphrase for that ssh-key, you'll have to type it every time you'll want to pull from your repo.< / p >
< h2 > Server management< / h2 >
2016-01-31 14:26:18 +01:00
< p > All of the commands in this section have to be run as root.< / p >
< p > First thing first, we have to install the git package on the server that will be hosting our git repos :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > apt update < span class = "o" > & & < / span > apt install git -y
2016-01-31 13:43:06 +01:00
< / pre > < / div >
2016-01-31 14:26:18 +01:00
< p > Then, we have to create a user named git :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > useradd -s /usr/bin/git-shell -m -r git
2016-01-31 13:43:06 +01:00
< / pre > < / div >
< p > This will create a system user (UID < 1000) with a /home/git home directory. If you want to host your git repos somewhere else on your filesystem, you should add a < code > -d /home/directory/for/git< / code > in the previous command.< / p >
2016-01-31 14:26:18 +01:00
< p > This user will use the git-shell shell. This limits remote connection to that user to git commands (like the rssh shell can limit remote connection to a user to scp or rsync commands).< / p >
2016-01-31 13:43:06 +01:00
< p > We have to configure our system to allow the use of this shell :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > < span class = "nb" > echo< / span > < span class = "s1" > ' /usr/bin/git-shell' < / span > > > /etc/shells
2016-01-31 13:43:06 +01:00
< / pre > < / div >
2016-01-31 14:26:18 +01:00
< p > From this point, you should have to following output if you try to SSH to your server with that user :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > ssh git@git.captainark.net
2016-01-31 14:26:18 +01:00
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have < span class = "nb" > read< / span > and execute access.
Connection to git@git.captainark.net closed.
< / pre > < / div >
2016-01-31 13:43:06 +01:00
< p > We now need to create the .ssh/authorized_keys file for the git user with the correct permissions :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > sudo -H -u git mkdir /home/git/.ssh < span class = "o" > & & < / span > chmod < span class = "m" > 700< / span > /home/git/.ssh
2016-01-31 13:43:06 +01:00
sudo -H -u git touch /home/git/.ssh/authorized_keys < span class = "o" > & & < / span > chmod < span class = "m" > 600< / span > /home/git/.ssh/authorized_keys
< / pre > < / div >
2016-01-31 14:26:18 +01:00
< p > You can now copy/paste the content of the two < code > $HOME/.ssh/id_rsa.pub< / code > files we've created earlier using the < code > ssh-keygen< / code > command in < code > /home/git/.ssh/authorized_keys< / code > .< / p >
< p > The last thing we have to do is to create our first git repo. In this example, my project will be called 'captainarkdotnet' as it will be hosting this blog :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > sudo -H -u git mkdir /home/git/captainarkdotnet.git
2016-01-31 14:26:18 +01:00
< span class = "nb" > cd< / span > /home/git/captainarkdotnet.git
2016-01-31 13:43:06 +01:00
sudo -H -u git git init --bare
< / pre > < / div >
< p > The last command should give you the following output :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > Initialized empty Git repository in /home/git/captainarkdotnet.git/.git/
2016-01-31 13:43:06 +01:00
< / pre > < / div >
< p > We're done with the server configuration. Let's now actually push stuff to our repo !< / p >
< h3 > Initial push< / h3 >
2016-01-31 14:26:18 +01:00
< p > The files for my blog are store in the ~/Documents/projects/captainarkdotnet on my computer. Before doing anything else, we first have to make sure that we currently are in that folder :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > < span class = "nb" > cd< / span > ~/Documents/projects/captainarkdotnet
2016-01-31 13:43:06 +01:00
< / pre > < / div >
< p > Let's now push the content of that folder to our repo :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > git init
2016-01-31 13:43:06 +01:00
git add .
2016-01-31 14:26:18 +01:00
git commit -m < span class = "s1" > ' initial commit' < / span >
git remote add origin git@git.captainark.net:captainarkdotnet.git
2016-01-31 13:43:06 +01:00
git push origin master
< / pre > < / div >
2016-01-31 14:26:18 +01:00
< p > Please note that you'll need to edit < strong > git.captainark.net< / strong > to the FQDN or IP of your git server, and < strong > captainarkdotnet.git< / strong > to the name of the git project on your server.< / p >
< p > If everything went well, the last command should give you the following output :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > Counting objects: 69, < span class = "k" > done< / span > .
2016-01-31 14:26:18 +01:00
Delta compression using up to < span class = "m" > 4< / span > threads.
Compressing objects: 100% < span class = "o" > (< / span > 64/64< span class = "o" > )< / span > , < span class = "k" > done< / span > .
Writing objects: 100% < span class = "o" > (< / span > 69/69< span class = "o" > )< / span > , 1.01 MiB < span class = "p" > |< / span > < span class = "m" > 0< / span > bytes/s, < span class = "k" > done< / span > .
Total < span class = "m" > 69< / span > < span class = "o" > (< / span > delta 15< span class = "o" > )< / span > , reused < span class = "m" > 0< / span > < span class = "o" > (< / span > delta 0< span class = "o" > )< / span >
To git@git.captainark.net:captainarkdotnet.git
* < span class = "o" > [< / span > new branch< span class = "o" > ]< / span > master -> master
< / pre > < / div >
< p > That's it, we've now pushed our first commit to our server !< / p >
< h2 > First pull< / h2 >
< p > Alright, time to pull the files we've just pushed on our webserver. I personally store my web content in < code > /var/www< / code > ; if you don't, you'll have to adjust the path accordingly :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > < span class = "nb" > cd< / span > /var/www
2016-01-31 14:26:18 +01:00
sudo -H -u www-data git clone git@git.captainark.net:captainarkdotnet.git
< / pre > < / div >
< p > SSH will ask you to type 'yes' since it's the first time the www-data user connects to the server. If everything goes well, you should have the following output :< / p >
2016-03-01 19:32:16 +01:00
< div class = "highlight" > < pre > < span > < / span > Cloning into < span class = "s1" > ' captainarkdotnet' < / span > ...
2016-01-31 14:26:18 +01:00
remote: Counting objects: 70, < span class = "k" > done< / span > .
remote: Compressing objects: 100% < span class = "o" > (< / span > 65/65< span class = "o" > )< / span > , < span class = "k" > done< / span > .
remote: Total < span class = "m" > 70< / span > < span class = "o" > (< / span > delta 16< span class = "o" > )< / span > , reused < span class = "m" > 0< / span > < span class = "o" > (< / span > delta 0< span class = "o" > )< / span >
Receiving objects: 100% < span class = "o" > (< / span > 70/70< span class = "o" > )< / span > , 1.01 MiB < span class = "p" > |< / span > < span class = "m" > 0< / span > bytes/s, < span class = "k" > done< / span > .
Resolving deltas: 100% < span class = "o" > (< / span > 16/16< span class = "o" > )< / span > , < span class = "k" > done< / span > .
Checking connectivity... < span class = "k" > done< / span > .
< / pre > < / div >
< h2 > Conclusion< / h2 >
< p > That's it ! We now have a working private git repo ! I won't go into details into the git commands in this tutorial, but here's a quick overwiew of the ones I use the most :< / p >
< ul >
< li > < code > git add .< / code > recursively adds all files from the directory to the repo ;< / li >
< li > < code > git commit -a -m 'This is a comment'< / code > commits the current state of your local repo with the 'This is a comment' comment ;< / li >
< li > < code > git push< / code > pushes your commits to the distant repo ;< / li >
< li > < code > git pull< / code > pulls the latest version of the distant repo locally ;< / li >
< li > < code > git branch -av< / code > shows all available branches for the repo ;< / li >
< li > < code > git checkout -b testing remotes/origin/testing< / code > create a local 'testing' branch based on the remote 'remotes/origin/testing' branch ;< / li >
< li > once a branch has been copied locally, you can switch to it with the < code > git checkout {branch}< / code > command.< / li >
< / ul >
< p > For more information on git a command, use < code > man git-{command}< / code > !< / p >
< p > If you've found this tutorial in any way helpful, please feel free to leave a comment !< / p >
2016-01-31 13:43:06 +01:00
< / article >
< hr >
< div class = "sharing" >
< / div >
< hr >
< div class = "comments" >
< h2 > Comments !< / h2 >
< div id = "disqus_thread" > < / div >
< script type = "text/javascript" >
2016-01-31 14:36:18 +01:00
var disqus_shortname = 'captainark';
2016-01-31 13:43:06 +01:00
var disqus_identifier = 'private-git-repo.html';
2016-01-31 14:32:17 +01:00
var disqus_url = 'https://captainark.net/private-git-repo.html';
2016-01-31 13:43:06 +01:00
(function() {
var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
2016-01-31 14:36:18 +01:00
dsq.src = '//captainark.disqus.com/embed.js';
2016-01-31 13:43:06 +01:00
(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
})();
< / script >
< noscript > Please enable JavaScript to view the comments.< / noscript >
< / div >
< / div >
< / div >
< / div >
< hr >
<!-- Footer -->
< footer >
< div class = "container" >
< div class = "row" >
< div class = "col-lg-8 col-lg-offset-2 col-md-10 col-md-offset-1" >
< ul class = "list-inline text-center" >
< li >
< a href = "mailto:contact@captainark.net" >
< span class = "fa-stack fa-lg" >
< i class = "fa fa-circle fa-stack-2x" > < / i >
< i class = "fa fa-envelope fa-stack-1x fa-inverse" > < / i >
< / span >
< / a >
< / li >
< li >
< a href = "https://twitter.com/captainark" >
< span class = "fa-stack fa-lg" >
< i class = "fa fa-circle fa-stack-2x" > < / i >
< i class = "fa fa-twitter fa-stack-1x fa-inverse" > < / i >
< / span >
< / a >
< / li >
< li >
< a href = "https://github.com/captainark" >
< span class = "fa-stack fa-lg" >
< i class = "fa fa-circle fa-stack-2x" > < / i >
< i class = "fa fa-github fa-stack-1x fa-inverse" > < / i >
< / span >
< / a >
< / li >
< li >
2016-01-31 14:32:17 +01:00
< a href = "http://www.last.fm/user/captainark" >
2016-01-31 13:43:06 +01:00
< span class = "fa-stack fa-lg" >
< i class = "fa fa-circle fa-stack-2x" > < / i >
2016-01-31 14:32:17 +01:00
< i class = "fa fa-lastfm fa-stack-1x fa-inverse" > < / i >
2016-01-31 13:43:06 +01:00
< / span >
< / a >
< / li >
< li >
< a href = "https://steamcommunity.com/id/captainark" >
< span class = "fa-stack fa-lg" >
< i class = "fa fa-circle fa-stack-2x" > < / i >
< i class = "fa fa-steam fa-stack-1x fa-inverse" > < / i >
< / span >
< / a >
< / li >
< li >
< a href = "http://www.twitch.tv/captainark" >
< span class = "fa-stack fa-lg" >
< i class = "fa fa-circle fa-stack-2x" > < / i >
< i class = "fa fa-twitch fa-stack-1x fa-inverse" > < / i >
< / span >
< / a >
< / li >
< / ul >
< p class = "copyright text-muted" >
Blog powered by < a href = "http://getpelican.com" > Pelican< / a > ,
which takes great advantage of < a href = "http://python.org" > Python< / a > .
< / p > < / div >
< / div >
< / div >
< / footer >
<!-- jQuery -->
2016-01-31 14:32:17 +01:00
< script src = "https://captainark.net/theme/js/jquery.js" > < / script >
2016-01-31 13:43:06 +01:00
<!-- Bootstrap Core JavaScript -->
2016-01-31 14:32:17 +01:00
< script src = "https://captainark.net/theme/js/bootstrap.min.js" > < / script >
2016-01-31 13:43:06 +01:00
<!-- Custom Theme JavaScript -->
2016-01-31 14:32:17 +01:00
< script src = "https://captainark.net/theme/js/clean-blog.min.js" > < / script >
2016-01-31 13:43:06 +01:00
2016-01-31 16:10:48 +01:00
< script type = "text/javascript" >
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-53658366-1']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
< / script >
2016-01-31 13:43:06 +01:00
< script type = "text/javascript" >
2016-01-31 14:36:18 +01:00
var disqus_shortname = 'captainark';
2016-01-31 13:43:06 +01:00
(function () {
var s = document.createElement('script'); s.async = true;
s.type = 'text/javascript';
s.src = '//' + disqus_shortname + '.disqus.com/count.js';
(document.getElementsByTagName('HEAD')[0] || document.getElementsByTagName('BODY')[0]).appendChild(s);
}());
< / script >
< / body >
< / html >