diff --git a/README b/README index cb4bfb2..c746ade 100644 --- a/README +++ b/README @@ -1,149 +1,4 @@ -# Installation - -1. Install Gitolite - -Follow instructions at https://gitolite.com/gitolite/fool_proof_setup.html -When Gitolite is installed, clone the gitolite-admin repository and add this to -conf/gitolite.conf: - - repo CREATOR/..* - C = @all - RW+ = CREATOR - R = @all - -The rule above will allow any registered user (@all) to create a repository. CREATOR -is a gitolite keywords and it's replaced with the username who created the repo. -To create a new repository, just use "git clone git@domain:username/reponame". -Since the regexp CREATOR/..* will replace CREATOR with the user name, the logged -in user will be allowed to create new repositories *only* under their username. - -Adding new users is as simple as adding their key to gitolite-admin/keydir/.pub - -Gitolite does not do authentication, it only does authorization. The name of the -logged in user is provided as an environment variable. In order to allow anonymous -HTTP clones, ie. for allowing "git clone https://..." without any authentication, -the web app automatically sets a generic username value of "anonymous". We need -to let Gitolite know what the unauthenticated user is going to be called so that -it can check authorization. To do this, just add the following to ~/.gitolite.rc -in the section marked "rc variables used by various features". This is explained -at https://gitolite.com/gitolite/http.html#allowing-unauthenticated-access - - HTTP_ANON_USER => 'anonymous', - -Enable some non-core commands that are useful to us. This is done by editing ~/.gitolite.rc: - - 'ENABLE' => [ - ... existing commands - - # Allow to change HEAD reference (default branch) like this: - # ssh git@host symbolic-ref HEAD refs/heads/ - 'symbolic-ref', - ] - - -2. Emails - -Start by downloading the clif repository: - - git clone /home/git - -Change the settings inside the emails.py file. - -Add the following to /etc/postfix/main.cf. This will forward all emails to the -system user "git" - - luser_relay = git - local_recipient_maps = - -Then add the following to /home/git/.forward. ".forward" is a sendmail file, also -used by postfix, used for deciding how to deliver the message the the system user. -For our purposes, we instruct postfix to pipe all the emails for user "git" to our -script: - - |/home/git/clif/emails.py - -make sure the script is executable: - - chmod +x /home/git/clif/emails.py - -3. Web UI - -Start by downloading the clif repository: - - git clone /home/git - -Install the requirements: - - cd /home/git/clif - python3 -m venv venv - source venv/bin/activate - pip install -r requirements.txt - -Change the settings inside the web.py file. - -Install a SystemD service: - - cp web.service /etc/systemd/system/clif-web.service - systemctl daemon-reload - systemctl enable clif-web - systemctl start clif-web - -4. TLS certificate - -Now we create a new TLS certificate for supporting HTTPS connections: - - apt-get install certbot - certbot certonly --webroot -w /var/www/html -d domain.tld - -The cert is created in /etc/letsencrypt/live// - -Lighttpd requires the certificate and private key to be in a single file: - - cat privkey.pem cert.pem > privkey+cert.pem - -Configure lighttpd reverse proxy: - - vim /etc/lighttpd/lighttpd.conf - - server.modules += ( - "mod_fastcgi", - "mod_proxy", - ) - - $HTTP["scheme"] == "http" { - url.redirect = ("" => "https://${url.authority}${url.path}${qsa}") - url.redirect-code = 308 - } - - $SERVER["socket"] == ":443" { - ssl.engine = "enable" - ssl.pemfile = "/etc/letsencrypt/live//privkey+cert.pem" - ssl.ca-file = "/etc/letsencrypt/live//chain.pem" - - $HTTP["host"] == "" { - proxy.server = ( - "" => ( - ( "host" => "127.0.0.1", "port" => 5000 ) - ) - ) - # server.document-root = "/var/www/html" # Document Root - # server.errorlog = "/" - # accesslog.filename = "/" - } - } - -Let's Encrypt certificates expire every 90 days, so we need to setup a cron job -that will generate a new privkey+cert.pem file, and reload lighttpd too. - - vim /etc/cron.weekly/clif-letsencrypt - chmod +x /etc/cron.weekly/clif-letsencrypt - - certbot renew - cd /etc/letsencrypt/live/ - cat privkey.pem cert.pem > privkey+cert.pem - service lighttpd restart - -# Development - - gunicorn --reload --bind localhost:5000 web:application +CLI Forge +========= +Documentation is available in the "documentation" folder. diff --git a/documentation/administrators b/documentation/administrators new file mode 100644 index 0000000..6d56364 --- /dev/null +++ b/documentation/administrators @@ -0,0 +1,14 @@ +# Adding new users + +1. Clone gitolite-admin.git repository +2. Add user key into gitolite-admin/keydir/.pub + +# Assign namespaces to users + +1. Clone gitolite-admin.git repository +2. Add rule into gitolite-admin/conf/gitolite.conf + + repo namespace/..* + C = username + RW+ = username + R = @all diff --git a/documentation/developers b/documentation/developers new file mode 100644 index 0000000..78fa605 --- /dev/null +++ b/documentation/developers @@ -0,0 +1,3 @@ +# Test server + + gunicorn --reload --bind localhost:5000 web:application diff --git a/documentation/installation b/documentation/installation new file mode 100644 index 0000000..0fdaee7 --- /dev/null +++ b/documentation/installation @@ -0,0 +1,134 @@ +Gitolite +------------------------------------------------------------------------------- + +Follow instructions at https://gitolite.com/gitolite/fool_proof_setup.html + +TL;DR: + su - git + git clone https://github.com/sitaramc/gitolite + gitolite/install -to $HOME/bin + $HOME/bin/gitolite setup -pk .pub + +Gitolite does not do authentication, it only does authorization. The name of the +logged in user is provided as an environment variable. In order to allow anonymous +HTTP clones, ie. for allowing "git clone https://..." without any authentication, +the web app automatically sets a generic username value of "anonymous". We need +to let Gitolite know what the unauthenticated user is going to be called so that +it can check authorization. To do this, just add the following to ~/.gitolite.rc +in the section marked "rc variables used by various features". This is explained +at https://gitolite.com/gitolite/http.html#allowing-unauthenticated-access + + HTTP_ANON_USER => 'anonymous', + +Enable some non-core commands that are useful to us. This is done by editing ~/.gitolite.rc: + + 'ENABLE' => [ + ... existing commands + + # Allow to change HEAD reference (default branch) like this: + # ssh git@host symbolic-ref HEAD refs/heads/ + 'symbolic-ref', + ] + + + + +Web UI +------------------------------------------------------------------------------- + +The CLIF repository is assumed to having been cloned into /home/git/clif. + +1. There are a couple of settings at the top of web.py. Change them. + +2. Install the Python dependencies: + + cd /home/git/clif + python3 -m venv venv + venv/bin/pip install -r requirements.txt + +3. Install a SystemD service for controlling the UI: + + cp web.service /etc/systemd/system/clif-web.service + systemctl daemon-reload + systemctl enable clif-web + systemctl start clif-web + + + + +Mailing Lists +------------------------------------------------------------------------------- + +1. There are a couple of settings at the top of emails.py. Change them. + +2. Add the following to /etc/postfix/main.cf. This will forward all emails to the + system user "git" + + luser_relay = git + local_recipient_maps = + +3. Create the file /home/git/.forward with the content: + + |/home/git/clif/emails.py + + This is a sendmail file, also used by postfix, for deciding how incoming messages + shall be delivered to the the system user. For our purposes, we instruct postfix + to pipe all the emails for user "git" to our script. Make sure the script is + executable. + + + + +Let's Encrypt certificate +------------------------------------------------------------------------------- + + apt-get install certbot + certbot certonly --webroot -w /var/www/html -d your-domain.tld + +The cert is created in /etc/letsencrypt/live// + +Lighttpd requires the certificate and private key to be in a single file: + + cat privkey.pem cert.pem > privkey+cert.pem + +Configure lighttpd reverse proxy: + + vim /etc/lighttpd/lighttpd.conf + + server.modules += ( + "mod_fastcgi", + "mod_proxy", + ) + + $HTTP["scheme"] == "http" { + url.redirect = ("" => "https://${url.authority}${url.path}${qsa}") + url.redirect-code = 308 + } + + $SERVER["socket"] == ":443" { + ssl.engine = "enable" + ssl.pemfile = "/etc/letsencrypt/live//privkey+cert.pem" + ssl.ca-file = "/etc/letsencrypt/live//chain.pem" + + $HTTP["host"] == "" { + proxy.server = ( + "" => ( + ( "host" => "127.0.0.1", "port" => 5000 ) + ) + ) + # server.document-root = "/var/www/html" # Document Root + # server.errorlog = "/" + # accesslog.filename = "/" + } + } + +Let's Encrypt certificates expire every 90 days, so we need to setup a cron job +that will generate a new privkey+cert.pem file, and reload lighttpd too. + + vim /etc/cron.weekly/clif-letsencrypt + chmod +x /etc/cron.weekly/clif-letsencrypt + + certbot renew + cd /etc/letsencrypt/live/ + cat privkey.pem cert.pem > privkey+cert.pem + service lighttpd restart diff --git a/documentation/users b/documentation/users new file mode 100644 index 0000000..93db852 --- /dev/null +++ b/documentation/users @@ -0,0 +1,72 @@ +General usage +------------------------------------------------------------------------------- + +# List of available commands over SSH + + ssh git@example.org help + +# List of user repositories and access permissions + + ssh git@example.org info + + + + +Repositories +------------------------------------------------------------------------------- + +# Cloning a repository anonymously + + git clone https://example.org/repository.git + +# Cloning a repository as registered users + + git clone git@example.org:repository + +# Creating a new repository +Either clone, or push to, a nonexistent repository. It will be initiated automatically +as long as the user has write permission. + + git clone git@example.org:repository + git push git@example.org:repository master + +# Pushing to a repository + + git push git@example.org:repository.git + +# Change default branch by repoint HEAD to other branches + + ssh git@example.org symbolic-ref repository.git HEAD refs/heads/main + +# Delete repository (D command) + + ssh git@example.org D unlock + ssh git@example.org D rm + + + + +Mailing lists +------------------------------------------------------------------------------- + +Mailing lists are where collaboration happens, and they are stored in repositories +too. + +# Create a new mailing list + +Create a new repository with the suffix ".mlist": + + git clone git@example.org:project.mlist + +CLIF will then begin accepting emails for project@example.org and store them +inside the "project.mlist" repository. + +# New threads + +New threads are created simply by sending a new email to the list address. An account +is not required for starting new threads and participating in discussions. + +# Join an existing thread + +It is possible to join an existing thread by sending an email containing the header +"In-Reply-To: ", where is the ID value of any previous message. diff --git a/templates/about.html b/templates/about.html index 6274389..3be41ba 100644 --- a/templates/about.html +++ b/templates/about.html @@ -10,47 +10,20 @@

This is a place for collaborative software development. It offers hosting for - Git repositories and mailing lists, and it aims at being entirely usable from + Git repositories and mailing lists, while aiming at being entirely usable from your CLI by leveraging existing tools and an email-driven workflow. - Read on for a quick introduction to using this instace.


- New users -
     - You only need an account if you wish to host your repositories on this instance. - Collaboration is done on mailing lists and you don't need an account for that. - When new users join the instance, they are automatically assigned the namespace - /<username> under which they can add new repositories.
- Since this instance is still under testing it is not currently open for public - registrations, but you can still get an account by asking in #peers at irc.libera.chat. + Documentation about using CLIF is available for both users and administrators + in the CLIF repository.

- Adding repositories -
     - If you have an account, you can use CLIF as a remote for sharing your repositories. - Simply running git clone git@{{ domain }}:<namespace>/<repository> - will create a new empty repository that you can add to your list of remotes. -

- -

- Mailing lists -
     - Mailing lists are where collaboration happens, and they are stored in repositories - too. All you have to do in order to create a new mailing list is to create - a new repository with the suffix .mlist, for example - git clone git@{{ domain }}:alice/project.mlist. CLIF then will - begin accepting emails for alice/project@{{ domain }} and store - them inside the alice/project.mlist repository. -
- New threads are created simply by sending a new email to the list address. - An account is not required. - It is also possible to join an existing thread by sending an email containing - the header In-Reply-To: <Message-ID>, where Message-ID - is the ID value of any previous message. + This instance is still under testing and it is not currently open for public + registration, but you can still get an account by asking in #peers at irc.libera.chat.

{% endblock %} diff --git a/web.py b/web.py index 879b5c9..771b355 100644 --- a/web.py +++ b/web.py @@ -50,6 +50,10 @@ INSTANCE_DOMAIN = 'domain.local' ############################################################################### def list_repositories(): + """ + Scan GITOLITE_REPOSITORIES_ROOT for Git repositories, and return a list of them. + """ + repositories = [] # When topdown is True, the caller can modify the dirnames list in-place and