home » zplus/clif.git
Author zPlus <zplus@peers.community> 2022-07-28 11:10:19
Committer zPlus <zplus@peers.community> 2022-07-28 11:10:19
Commit bcc46e1 (patch)
Tree 5d56a4c
Parent(s)

Add documentation. Remove the documentation from the "about" template, and create some documentation files instead.


commits diff: a515132..bcc46e1
7 files changed, 235 insertions, 180 deletionsdownload


Diffstat
-rw-r--r-- README 151
-rw-r--r-- documentation/administrators 14
-rw-r--r-- documentation/developers 3
-rw-r--r-- documentation/installation 134
-rw-r--r-- documentation/users 72
-rw-r--r-- templates/about.html 37
-rw-r--r-- web.py 4

Diff options
View
Side
Whitespace
Context lines
Inter-hunk lines
+3/-148 M   README
index cb4bfb2..c746ade
old size: 4K - new size: 79B
@@ -1,149 +1,4 @@
1 - # Installation
2 -
3 - 1. Install Gitolite
4 -
5 - Follow instructions at https://gitolite.com/gitolite/fool_proof_setup.html
6 - When Gitolite is installed, clone the gitolite-admin repository and add this to
7 - conf/gitolite.conf:
8 -
9 - repo CREATOR/..*
10 - C = @all
11 - RW+ = CREATOR
12 - R = @all
13 -
14 - The rule above will allow any registered user (@all) to create a repository. CREATOR
15 - is a gitolite keywords and it's replaced with the username who created the repo.
16 - To create a new repository, just use "git clone git@domain:username/reponame".
17 - Since the regexp CREATOR/..* will replace CREATOR with the user name, the logged
18 - in user will be allowed to create new repositories *only* under their username.
19 -
20 - Adding new users is as simple as adding their key to gitolite-admin/keydir/<username>.pub
21 -
22 - Gitolite does not do authentication, it only does authorization. The name of the
23 - logged in user is provided as an environment variable. In order to allow anonymous
24 - HTTP clones, ie. for allowing "git clone https://..." without any authentication,
25 - the web app automatically sets a generic username value of "anonymous". We need
26 - to let Gitolite know what the unauthenticated user is going to be called so that
27 - it can check authorization. To do this, just add the following to ~/.gitolite.rc
28 - in the section marked "rc variables used by various features". This is explained
29 - at https://gitolite.com/gitolite/http.html#allowing-unauthenticated-access
30 -
31 - HTTP_ANON_USER => 'anonymous',
32 -
33 - Enable some non-core commands that are useful to us. This is done by editing ~/.gitolite.rc:
34 -
35 - 'ENABLE' => [
36 - ... existing commands
37 -
38 - # Allow to change HEAD reference (default branch) like this:
39 - # ssh git@host symbolic-ref <repo> HEAD refs/heads/<name>
40 - 'symbolic-ref',
41 - ]
42 -
43 -
44 - 2. Emails
45 -
46 - Start by downloading the clif repository:
47 -
48 - git clone <clif-url> /home/git
49 -
50 - Change the settings inside the emails.py file.
51 -
52 - Add the following to /etc/postfix/main.cf. This will forward all emails to the
53 - system user "git"
54 -
55 - luser_relay = git
56 - local_recipient_maps =
57 -
58 - Then add the following to /home/git/.forward. ".forward" is a sendmail file, also
59 - used by postfix, used for deciding how to deliver the message the the system user.
60 - For our purposes, we instruct postfix to pipe all the emails for user "git" to our
61 - script:
62 -
63 - |/home/git/clif/emails.py
64 -
65 - make sure the script is executable:
66 -
67 - chmod +x /home/git/clif/emails.py
68 -
69 - 3. Web UI
70 -
71 - Start by downloading the clif repository:
72 -
73 - git clone <clif-url> /home/git
74 -
75 - Install the requirements:
76 -
77 - cd /home/git/clif
78 - python3 -m venv venv
79 - source venv/bin/activate
80 - pip install -r requirements.txt
81 -
82 - Change the settings inside the web.py file.
83 -
84 - Install a SystemD service:
85 -
86 - cp web.service /etc/systemd/system/clif-web.service
87 - systemctl daemon-reload
88 - systemctl enable clif-web
89 - systemctl start clif-web
90 -
91 - 4. TLS certificate
92 -
93 - Now we create a new TLS certificate for supporting HTTPS connections:
94 -
95 - apt-get install certbot
96 - certbot certonly --webroot -w /var/www/html -d domain.tld
97 -
98 - The cert is created in /etc/letsencrypt/live/<domain.tld>/
99 -
100 - Lighttpd requires the certificate and private key to be in a single file:
101 -
102 - cat privkey.pem cert.pem > privkey+cert.pem
103 -
104 - Configure lighttpd reverse proxy:
105 -
106 - vim /etc/lighttpd/lighttpd.conf
107 -
108 - server.modules += (
109 - "mod_fastcgi",
110 - "mod_proxy",
111 - )
112 -
113 - $HTTP["scheme"] == "http" {
114 - url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
115 - url.redirect-code = 308
116 - }
117 -
118 - $SERVER["socket"] == ":443" {
119 - ssl.engine = "enable"
120 - ssl.pemfile = "/etc/letsencrypt/live/<domain.tld>/privkey+cert.pem"
121 - ssl.ca-file = "/etc/letsencrypt/live/<domain.tld>/chain.pem"
122 -
123 - $HTTP["host"] == "<domain.tld>" {
124 - proxy.server = (
125 - "" => (
126 - ( "host" => "127.0.0.1", "port" => 5000 )
127 - )
128 - )
129 - # server.document-root = "/var/www/html" # Document Root
130 - # server.errorlog = "/"
131 - # accesslog.filename = "/"
132 - }
133 - }
134 -
135 - Let's Encrypt certificates expire every 90 days, so we need to setup a cron job
136 - that will generate a new privkey+cert.pem file, and reload lighttpd too.
137 -
138 - vim /etc/cron.weekly/clif-letsencrypt
139 - chmod +x /etc/cron.weekly/clif-letsencrypt
140 -
141 - certbot renew
142 - cd /etc/letsencrypt/live/<domain.tld>
143 - cat privkey.pem cert.pem > privkey+cert.pem
144 - service lighttpd restart
145 -
146 - # Development
147 -
148 - gunicorn --reload --bind localhost:5000 web:application
1 + CLI Forge
2 + =========
149 3
4 + Documentation is available in the "documentation" folder.

+14/-0 A   documentation/administrators
index 0000000..6d56364
old size: 0B - new size: 333B
new file mode: -rw-r--r--
@@ -0,0 +1,14 @@
1 + # Adding new users
2 +
3 + 1. Clone gitolite-admin.git repository
4 + 2. Add user key into gitolite-admin/keydir/<username>.pub
5 +
6 + # Assign namespaces to users
7 +
8 + 1. Clone gitolite-admin.git repository
9 + 2. Add rule into gitolite-admin/conf/gitolite.conf
10 +
11 + repo namespace/..*
12 + C = username
13 + RW+ = username
14 + R = @all

+3/-0 A   documentation/developers
index 0000000..78fa605
old size: 0B - new size: 75B
new file mode: -rw-r--r--
@@ -0,0 +1,3 @@
1 + # Test server
2 +
3 + gunicorn --reload --bind localhost:5000 web:application

+134/-0 A   documentation/installation
index 0000000..0fdaee7
old size: 0B - new size: 4K
new file mode: -rw-r--r--
@@ -0,0 +1,134 @@
1 + Gitolite
2 + -------------------------------------------------------------------------------
3 +
4 + Follow instructions at https://gitolite.com/gitolite/fool_proof_setup.html
5 +
6 + TL;DR:
7 + su - git
8 + git clone https://github.com/sitaramc/gitolite
9 + gitolite/install -to $HOME/bin
10 + $HOME/bin/gitolite setup -pk <admin_key>.pub
11 +
12 + Gitolite does not do authentication, it only does authorization. The name of the
13 + logged in user is provided as an environment variable. In order to allow anonymous
14 + HTTP clones, ie. for allowing "git clone https://..." without any authentication,
15 + the web app automatically sets a generic username value of "anonymous". We need
16 + to let Gitolite know what the unauthenticated user is going to be called so that
17 + it can check authorization. To do this, just add the following to ~/.gitolite.rc
18 + in the section marked "rc variables used by various features". This is explained
19 + at https://gitolite.com/gitolite/http.html#allowing-unauthenticated-access
20 +
21 + HTTP_ANON_USER => 'anonymous',
22 +
23 + Enable some non-core commands that are useful to us. This is done by editing ~/.gitolite.rc:
24 +
25 + 'ENABLE' => [
26 + ... existing commands
27 +
28 + # Allow to change HEAD reference (default branch) like this:
29 + # ssh git@host symbolic-ref <repo> HEAD refs/heads/<name>
30 + 'symbolic-ref',
31 + ]
32 +
33 +
34 +
35 +
36 + Web UI
37 + -------------------------------------------------------------------------------
38 +
39 + The CLIF repository is assumed to having been cloned into /home/git/clif.
40 +
41 + 1. There are a couple of settings at the top of web.py. Change them.
42 +
43 + 2. Install the Python dependencies:
44 +
45 + cd /home/git/clif
46 + python3 -m venv venv
47 + venv/bin/pip install -r requirements.txt
48 +
49 + 3. Install a SystemD service for controlling the UI:
50 +
51 + cp web.service /etc/systemd/system/clif-web.service
52 + systemctl daemon-reload
53 + systemctl enable clif-web
54 + systemctl start clif-web
55 +
56 +
57 +
58 +
59 + Mailing Lists
60 + -------------------------------------------------------------------------------
61 +
62 + 1. There are a couple of settings at the top of emails.py. Change them.
63 +
64 + 2. Add the following to /etc/postfix/main.cf. This will forward all emails to the
65 + system user "git"
66 +
67 + luser_relay = git
68 + local_recipient_maps =
69 +
70 + 3. Create the file /home/git/.forward with the content:
71 +
72 + |/home/git/clif/emails.py
73 +
74 + This is a sendmail file, also used by postfix, for deciding how incoming messages
75 + shall be delivered to the the system user. For our purposes, we instruct postfix
76 + to pipe all the emails for user "git" to our script. Make sure the script is
77 + executable.
78 +
79 +
80 +
81 +
82 + Let's Encrypt certificate
83 + -------------------------------------------------------------------------------
84 +
85 + apt-get install certbot
86 + certbot certonly --webroot -w /var/www/html -d your-domain.tld
87 +
88 + The cert is created in /etc/letsencrypt/live/<your-domain.tld>/
89 +
90 + Lighttpd requires the certificate and private key to be in a single file:
91 +
92 + cat privkey.pem cert.pem > privkey+cert.pem
93 +
94 + Configure lighttpd reverse proxy:
95 +
96 + vim /etc/lighttpd/lighttpd.conf
97 +
98 + server.modules += (
99 + "mod_fastcgi",
100 + "mod_proxy",
101 + )
102 +
103 + $HTTP["scheme"] == "http" {
104 + url.redirect = ("" => "https://${url.authority}${url.path}${qsa}")
105 + url.redirect-code = 308
106 + }
107 +
108 + $SERVER["socket"] == ":443" {
109 + ssl.engine = "enable"
110 + ssl.pemfile = "/etc/letsencrypt/live/<your-domain.tld>/privkey+cert.pem"
111 + ssl.ca-file = "/etc/letsencrypt/live/<your-domain.tld>/chain.pem"
112 +
113 + $HTTP["host"] == "<your-domain.tld>" {
114 + proxy.server = (
115 + "" => (
116 + ( "host" => "127.0.0.1", "port" => 5000 )
117 + )
118 + )
119 + # server.document-root = "/var/www/html" # Document Root
120 + # server.errorlog = "/"
121 + # accesslog.filename = "/"
122 + }
123 + }
124 +
125 + Let's Encrypt certificates expire every 90 days, so we need to setup a cron job
126 + that will generate a new privkey+cert.pem file, and reload lighttpd too.
127 +
128 + vim /etc/cron.weekly/clif-letsencrypt
129 + chmod +x /etc/cron.weekly/clif-letsencrypt
130 +
131 + certbot renew
132 + cd /etc/letsencrypt/live/<your-domain.tld>
133 + cat privkey.pem cert.pem > privkey+cert.pem
134 + service lighttpd restart

+72/-0 A   documentation/users
index 0000000..93db852
old size: 0B - new size: 2K
new file mode: -rw-r--r--
@@ -0,0 +1,72 @@
1 + General usage
2 + -------------------------------------------------------------------------------
3 +
4 + # List of available commands over SSH
5 +
6 + ssh git@example.org help
7 +
8 + # List of user repositories and access permissions
9 +
10 + ssh git@example.org info
11 +
12 +
13 +
14 +
15 + Repositories
16 + -------------------------------------------------------------------------------
17 +
18 + # Cloning a repository anonymously
19 +
20 + git clone https://example.org/repository.git
21 +
22 + # Cloning a repository as registered users
23 +
24 + git clone git@example.org:repository
25 +
26 + # Creating a new repository
27 + Either clone, or push to, a nonexistent repository. It will be initiated automatically
28 + as long as the user has write permission.
29 +
30 + git clone git@example.org:repository
31 + git push git@example.org:repository master
32 +
33 + # Pushing to a repository
34 +
35 + git push git@example.org:repository.git
36 +
37 + # Change default branch by repoint HEAD to other branches
38 +
39 + ssh git@example.org symbolic-ref repository.git HEAD refs/heads/main
40 +
41 + # Delete repository (D command)
42 +
43 + ssh git@example.org D unlock <repository>
44 + ssh git@example.org D rm <repository>
45 +
46 +
47 +
48 +
49 + Mailing lists
50 + -------------------------------------------------------------------------------
51 +
52 + Mailing lists are where collaboration happens, and they are stored in repositories
53 + too.
54 +
55 + # Create a new mailing list
56 +
57 + Create a new repository with the suffix ".mlist":
58 +
59 + git clone git@example.org:project.mlist
60 +
61 + CLIF will then begin accepting emails for project@example.org and store them
62 + inside the "project.mlist" repository.
63 +
64 + # New threads
65 +
66 + New threads are created simply by sending a new email to the list address. An account
67 + is not required for starting new threads and participating in discussions.
68 +
69 + # Join an existing thread
70 +
71 + It is possible to join an existing thread by sending an email containing the header
72 + "In-Reply-To: <Message-ID>", where <Message-ID> is the ID value of any previous message.

+5/-32 M   templates/about.html
index 6274389..3be41ba
old size: 2K - new size: 821B
@@ -10,47 +10,20 @@
10 10
11 11 <p>
12 12 This is a place for collaborative software development. It offers hosting for
13 - Git repositories and mailing lists, and it aims at being entirely usable from
13 + Git repositories and mailing lists, while aiming at being entirely usable from
14 14 your CLI by leveraging existing tools and an email-driven workflow.
15 - Read on for a quick introduction to using this instace.
16 15 </p>
17 16
18 17 <br />
19 18
20 19 <p>
21 - <i>New users</i>
22 - <br />&nbsp;&nbsp;&nbsp;&nbsp;
23 - You only need an account if you wish to host your repositories on this instance.
24 - Collaboration is done on mailing lists and you don't need an account for that.
25 - When new users join the instance, they are automatically assigned the namespace
26 - <code>/&lt;username&gt;</code> under which they can add new repositories.<br />
27 - Since this instance is still under testing it is not currently open for public
28 - registrations, but you can still get an account by asking in #peers at irc.libera.chat.
20 + Documentation about using CLIF is available for both users and administrators
21 + in the <a href="https://clif.peers.community/zplus/clif.git">CLIF repository</a>.
29 22 </p>
30 23
31 24 <p>
32 - <i>Adding repositories</i>
33 - <br />&nbsp;&nbsp;&nbsp;&nbsp;
34 - If you have an account, you can use CLIF as a remote for sharing your repositories.
35 - Simply running <code>git clone git@{{ domain }}:&lt;namespace&gt;/&lt;repository&gt;</code>
36 - will create a new empty repository that you can add to your list of remotes.
37 - </p>
38 -
39 - <p>
40 - <i>Mailing lists</i>
41 - <br />&nbsp;&nbsp;&nbsp;&nbsp;
42 - Mailing lists are where collaboration happens, and they are stored in repositories
43 - too. All you have to do in order to create a new mailing list is to create
44 - a new repository with the suffix <code>.mlist</code>, for example
45 - <code>git clone git@{{ domain }}:alice/project.mlist</code>. CLIF then will
46 - begin accepting emails for <code>alice/project@{{ domain }}</code> and store
47 - them inside the <code>alice/project.mlist</code> repository.
48 - <br />
49 - New threads are created simply by sending a new email to the list address.
50 - An account is not required.
51 - It is also possible to join an existing thread by sending an email containing
52 - the header <code>In-Reply-To: &lt;Message-ID&gt;</code>, where <code>Message-ID</code>
53 - is the ID value of any previous message.
25 + This instance is still under testing and it is not currently open for public
26 + registration, but you can still get an account by asking in #peers at irc.libera.chat.
54 27 </p>
55 28
56 29 {% endblock %}

+4/-0 M   web.py
index 879b5c9..771b355
old size: 21K - new size: 21K
@@ -50,6 +50,10 @@ INSTANCE_DOMAIN = 'domain.local'
50 50 ###############################################################################
51 51
52 52 def list_repositories():
53 + """
54 + Scan GITOLITE_REPOSITORIES_ROOT for Git repositories, and return a list of them.
55 + """
56 +
53 57 repositories = []
54 58
55 59 # When topdown is True, the caller can modify the dirnames list in-place and