From e63885bcc0d46bfe58a32fcfc1d02daae8735929 Mon Sep 17 00:00:00 2001 From: Guilhem Moulin Date: Sun, 31 May 2015 18:02:27 +0200 Subject: Git (gitolite + git-http-backend + gitweb) configuration By default repos are be readable by gitweb and the web server ('gitweb' and 'www-data' are both in the 'gitolite' group). Private repo owners will have 'chmod -R og-rwx' manually. To automatically add new repos to gitweb's 'project.list' file, make it readable to the special 'gitweb' user. See /usr/share/doc/gitolite3/README.txt.gz for details. --- roles/git/files/etc/gitweb.conf | 40 +++++++++ roles/git/files/etc/nginx/sites-available/git | 78 +++++++++++++++++ roles/git/files/etc/nginx/sites-available/gitweb | 48 +++++++++++ roles/git/files/lib/systemd/system/gitweb.service | 13 +++ roles/git/files/lib/systemd/system/gitweb.socket | 11 +++ roles/git/handlers/main.yml | 9 ++ roles/git/tasks/gitolite.yml | 36 ++++++++ roles/git/tasks/gitweb.yml | 100 ++++++++++++++++++++++ roles/git/tasks/main.yml | 2 + 9 files changed, 337 insertions(+) create mode 100644 roles/git/files/etc/gitweb.conf create mode 100644 roles/git/files/etc/nginx/sites-available/git create mode 100644 roles/git/files/etc/nginx/sites-available/gitweb create mode 100644 roles/git/files/lib/systemd/system/gitweb.service create mode 100644 roles/git/files/lib/systemd/system/gitweb.socket create mode 100644 roles/git/handlers/main.yml create mode 100644 roles/git/tasks/gitolite.yml create mode 100644 roles/git/tasks/gitweb.yml create mode 100644 roles/git/tasks/main.yml (limited to 'roles') diff --git a/roles/git/files/etc/gitweb.conf b/roles/git/files/etc/gitweb.conf new file mode 100644 index 0000000..8c1dd61 --- /dev/null +++ b/roles/git/files/etc/gitweb.conf @@ -0,0 +1,40 @@ +$site_name = "Fripost Git"; + +# path to git projects (.git) +$projectroot = "/var/lib/gitolite/repositories"; + +# 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 = ""; + +# file with project list; by default, simply scan the projectroot dir. +$projects_list = "/var/lib/gitolite/projects.list"; + +#$projects_list = $projectroot; +#$export_ok = "git-daemon-export-ok"; + +# stylesheet to use +push @stylesheets, "static/gitweb.css"; + +# javascript code for gitweb +$javascript = "static/gitweb.js"; + +# logo to use +$logo = "static/git-logo.png"; + +# the 'favicon' +$favicon = "static/git-favicon.png"; + +# git-diff-tree(1) options to use for generated patches +#@diff_opts = ("-M"); +@diff_opts = (); + +# the base url +@git_base_url_list = ( 'git clone ssh://gitolite@git.fripost.org' + , 'git clone https://git.fripost.org' + ) diff --git a/roles/git/files/etc/nginx/sites-available/git b/roles/git/files/etc/nginx/sites-available/git new file mode 100644 index 0000000..9510620 --- /dev/null +++ b/roles/git/files/etc/nginx/sites-available/git @@ -0,0 +1,78 @@ +server { + listen 80; + listen [::]:80; + + server_name git.fripost.org; + + access_log /var/log/nginx/git.access.log; + error_log /var/log/nginx/git.error.log info; + + # Bypass the CGI to return static files stored on disk. Try first repo with + # a trailing '.git', then without. + location ~* "^/((?U)[^/]+)(?:\.git)?/objects/([0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(?:pack|idx))$" { + root /var/lib/gitolite/repositories; + try_files /$1.git/objects/$2 /$1/objects/$2 =404; + } + + # Disallow push over HTTP(S) + location ~* ^/[^/]+/git-receive-pack$ { + return 403; + } + + location ~* ^/[^/]+/(:?HEAD|info/refs|objects/info/[^/]+|git-upload-pack)$ { + fastcgi_param PATH_INFO $uri; + fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; + fastcgi_param GIT_HTTP_EXPORT_ALL 1; + fastcgi_param GIT_PROJECT_ROOT /var/lib/gitolite/repositories; + include fastcgi/params; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + gzip off; + } + + # Redirect to gitweb otherwise + location ~ ^/([^/]+/?)?$ { + return 302 $scheme://gitweb.fripost.org/$1; + } +} + + +server { + listen 443; + listen [::]:443; + + server_name git.fripost.org; + + include ssl/config; + ssl_certificate /etc/nginx/ssl/git.fripost.org.pem; + ssl_certificate_key /etc/nginx/ssl/git.fripost.org.key; + + access_log /var/log/nginx/git.access.log; + error_log /var/log/nginx/git.error.log info; + + # Bypass the CGI to return static files stored on disk. Try first repo with + # a trailing '.git', then without. + location ~* "^/((?U)[^/]+)(?:\.git)?/objects/([0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(?:pack|idx))$" { + root /var/lib/gitolite/repositories; + try_files /$1.git/objects/$2 /$1/objects/$2 =404; + } + + # Disallow push over HTTP(S) + location ~* ^/[^/]+/git-receive-pack$ { + return 403; + } + + location ~* ^/[^/]+/(:?HEAD|info/refs|objects/info/[^/]+|git-upload-pack)$ { + fastcgi_param PATH_INFO $uri; + fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; + fastcgi_param GIT_HTTP_EXPORT_ALL 1; + fastcgi_param GIT_PROJECT_ROOT /var/lib/gitolite/repositories; + include fastcgi/params; + fastcgi_pass unix:/var/run/fcgiwrap.socket; + gzip off; + } + + # Redirect to gitweb otherwise + location ~ ^/([^/]+/?)?$ { + return 302 $scheme://gitweb.fripost.org/$1; + } +} diff --git a/roles/git/files/etc/nginx/sites-available/gitweb b/roles/git/files/etc/nginx/sites-available/gitweb new file mode 100644 index 0000000..3814145 --- /dev/null +++ b/roles/git/files/etc/nginx/sites-available/gitweb @@ -0,0 +1,48 @@ +server { + listen 80; + listen [::]:80; + + server_name gitweb.fripost.org; + + access_log /var/log/nginx/gitweb.access.log; + error_log /var/log/nginx/gitweb.error.log info; + + location ^~ /static/ { + alias /usr/share/gitweb/static/; + } + + try_files $uri @fcgi; + location @fcgi { + root /var/lib/gitolite/repositories; + include fastcgi/params; + fastcgi_pass unix:/run/gitweb.socket; + gzip off; + } +} + + +server { + listen 443; + listen [::]:443; + + server_name gitweb.fripost.org; + + include ssl/config; + ssl_certificate /etc/nginx/ssl/git.fripost.org.pem; + ssl_certificate_key /etc/nginx/ssl/git.fripost.org.key; + + access_log /var/log/nginx/gitweb.access.log; + error_log /var/log/nginx/gitweb.error.log info; + + location ^~ /static/ { + alias /usr/share/gitweb/static/; + } + + try_files $uri @fcgi; + location @fcgi { + root /var/lib/gitolite/repositories; + include fastcgi/params; + fastcgi_pass unix:/run/gitweb.socket; + gzip off; + } +} diff --git a/roles/git/files/lib/systemd/system/gitweb.service b/roles/git/files/lib/systemd/system/gitweb.service new file mode 100644 index 0000000..a0f7a96 --- /dev/null +++ b/roles/git/files/lib/systemd/system/gitweb.service @@ -0,0 +1,13 @@ +[Unit] +Description=Gitweb Service +After=network.target +Requires=gitweb.socket + +[Service] +StandardInput=socket +User=gitweb +Group=gitweb +ExecStart=/usr/lib/cgi-bin/gitweb.fcgi + +[Install] +WantedBy=multi-user.target diff --git a/roles/git/files/lib/systemd/system/gitweb.socket b/roles/git/files/lib/systemd/system/gitweb.socket new file mode 100644 index 0000000..355b490 --- /dev/null +++ b/roles/git/files/lib/systemd/system/gitweb.socket @@ -0,0 +1,11 @@ +[Unit] +Description=Gitweb Listen Socket + +[Socket] +SocketUser=www-data +SocketGroup=www-data +SocketMode=0600 +ListenStream=/run/gitweb.socket + +[Install] +WantedBy=sockets.target diff --git a/roles/git/handlers/main.yml b/roles/git/handlers/main.yml new file mode 100644 index 0000000..e32bd2f --- /dev/null +++ b/roles/git/handlers/main.yml @@ -0,0 +1,9 @@ +--- +- name: systemctl daemon-reload + command: /bin/systemctl daemon-reload + +- name: Restart gitweb + service: name=gitweb state=restarted + +- name: Restart Nginx + service: name=nginx state=restarted diff --git a/roles/git/tasks/gitolite.yml b/roles/git/tasks/gitolite.yml new file mode 100644 index 0000000..5cbce23 --- /dev/null +++ b/roles/git/tasks/gitolite.yml @@ -0,0 +1,36 @@ +- name: Install gitolite + apt: pkg=gitolite3 + +- name: Create a user 'gitolite' + user: name=gitolite system=yes + groups=ssh-login + home=/var/lib/gitolite + shell=/bin/sh + password=* + state=present + +- name: Create directory ~gitolite/.ssh + file: path=/var/lib/gitolite/.ssh + state=directory + owner=gitolite group=gitolite + mode=0700 + +- name: Create /var/lib/gitolite/projects.list + file: path=/var/lib/gitolite/projects.list + owner=gitolite group=gitolite + mode=0644 + +# See /usr/share/doc/gitolite3/README.txt.gz for gitolite initiation or +# migration. +# sudo -u gitolite gitolite setup -pk /path/to/id_rsa + +- name: Configure gitolite + lineinfile: dest=/var/lib/gitolite/.gitolite.rc + "regexp=^(\\s*{{ item.var }}\\s*=>\\s*)" + "line= {{ item.var }} => {{ item.value }}," + owner=root group=root + mode=0644 + with_items: + # See /usr/share/doc/gitolite3/README.txt.gz + - { var: UMASK, value: "0027" } + - { var: GIT_CONFIG_KEYS, value: "'gitweb\\..* gc\\..*'" } diff --git a/roles/git/tasks/gitweb.yml b/roles/git/tasks/gitweb.yml new file mode 100644 index 0000000..81d8e3e --- /dev/null +++ b/roles/git/tasks/gitweb.yml @@ -0,0 +1,100 @@ +- name: Install gitweb + apt: pkg={{ item }} + with_items: + - gitweb + # for git-http-backend + - fcgiwrap + +- name: Configure gitweb + copy: src=etc/gitweb.conf + dest=/etc/gitweb.conf + owner=root group=root + mode=0644 + notify: + - Restart gitweb + +# See gitweb(1). To work in Fast CGI mode gitweb checks its filetype. +- name: Symlink 'gitweb.cgi' to 'gitweb.fcgi' + file: src=gitweb.cgi + dest=/usr/lib/cgi-bin/gitweb.fcgi + owner=root group=root + state=link force=no + +- name: Create a user 'gitweb' + user: name=gitweb system=yes + home=/var/www + shell=/usr/sbin/nologin + password=! + state=present + +- name: Add 'gitweb' & 'www-data' to the group 'gitolite' + user: name={{ item }} groups=gitolite append=yes + with_items: + # for the gitweb interface + - gitweb + # for pulls over HTTP/HTTPS + - www-data + +- name: Copy gitweb.{service,socket} + copy: src=lib/systemd/system/{{ item }} + dest=/lib/systemd/system/{{ item }} + owner=root group=root + mode=0644 + notify: + - systemctl daemon-reload + with_items: + - gitweb.service + - gitweb.socket + +- meta: flush_handlers + +- name: Enable gitweb + service: name=gitweb enabled=yes + +- name: Start gitweb + service: name=gitweb state=started + + +- name: Generate a private key and a X.509 certificate for Nginx + command: genkeypair.sh x509 + --pubkey=/etc/nginx/ssl/git.fripost.org.pem + --privkey=/etc/nginx/ssl/git.fripost.org.key + --ou=WWW --cn=git.fripost.org --dns=git.fripost.org --dns=gitweb.fripost.org + -t rsa -b 4096 -h sha512 + register: r1 + changed_when: r1.rc == 0 + failed_when: r1.rc > 1 + notify: + - Restart Nginx + tags: + - genkey + +- name: Copy /etc/nginx/sites-available/{git,gitweb} + copy: src=etc/nginx/sites-available/{{ item }} + dest=/etc/nginx/sites-available/{{ item }} + owner=root group=root + mode=0644 + with_items: + - git + - gitweb + register: r2 + notify: + - Restart Nginx + +- name: Create /etc/nginx/sites-enabled/{git,gitweb} + file: src=../sites-available/{{ item }} + dest=/etc/nginx/sites-enabled/{{ item }} + owner=root group=root + state=link force=yes + with_items: + - git + - gitweb + register: r3 + notify: + - Restart Nginx + +- name: Start Nginx + service: name=nginx state=started + when: not (r1.changed or r2.changed or r3.changed) + +- meta: flush_handlers diff --git a/roles/git/tasks/main.yml b/roles/git/tasks/main.yml new file mode 100644 index 0000000..b5422b7 --- /dev/null +++ b/roles/git/tasks/main.yml @@ -0,0 +1,2 @@ +- include: gitolite.yml tags=gitolite +- include: gitweb.yml tags=gitweb -- cgit v1.2.3