pi-hoole-0.2.0.0: README.md
# pi-hoole
`pi-hoole` is a collection of tools to enforce access control for self-hosted
pijul repositories. It can be seen as a cgit-like solution, for authenticated
(public key, SSH) and anonymous accesses. You can grant read and write accesses
to a whole repository, or to a determined subset of branches.
`pi-hoole` is distributed under the terms of the AGPL v3.
## Getting Started
### Building From Source
It should not be a surprise that `pi-hoole` is versioned under `pijul`, with the
patch format introduced by `pijul-0.9`. Fair warning, use `pijul-0.10.1` and you
should be able to clone the `pi-hoole` repository.
```bash
pijul clone https://pijul.lthms.xyz/pijul/pi-hoole
```
Under the hood, `pi-hoole` is implemented in Haskell. We will need `stack` to
build it.
```bash
cd pi-hoole
stack build
```
We are using the latest lts available, but `pi-hoole` has already been built
with `lts-10` (but does not build with older ones).
This build three executables:
* `pi-hoole-cfg` generates a `.authorized_keys` file to enforce access control
for SSH.
* `pi-hoole-shell` is called to determine if a authenticated user is allowed to
perform a given `pijul` command.
* `pi-hoole-web` is a HTTP proxy to enforce access control for anonymous
requests.
### Installing
In order to use `pi-hoole` on your server, the first step is to create a new,
dedicated user (*e.g.* `pijul`). You then need to make `pijul` and
`pi-hoole-shell` available to this user. Currently, we do not provide any
packaging solution to that end, but this might change in the future. Although it
is not mandatory, we consider both `pi-hoole-cfg` and `pi-hoole-web` have also
been made available for the `pijul` user.
### Configuring
`pi-hoole` executables assume the configuration files are stored at
`${XDG_CONFIG_DIRECTORY}/pi-hoole`, that is `~/.config/pi-hoole` by default.
In this directory, `pi-hoole` will scan the `keys/` directory, if it exists,
to know the list of authorized authenticated users. One user may have as many
public key as required. Keys should be saved in file with the following filename
scheme: `<user>(\.<label>)?\.pub`. Thus, `lthms.pub`, `lthms.laptop.pub` and
`lthms.work.pub` are three valid public key filenames for the `lthms` user.
To generate a `.ssh/authorized_keys`, use `pi-hoole-cfg`.
```bash
pi-hoole-cfg generate > ~/.ssh/authorized_keys
```
Resulting file will be of the forms:
command="pi-hoole-shell \".lthms\" \"${SSH_ORIGINAL_COMMAND}\"",no-port-forwarding,no-x11-forwarding,no-agent-forwarding <ssh_keys_1>
command="pi-hoole-shell \".lthms\" \"${SSH_ORIGINAL_COMMAND}\"",no-port-forwarding,no-x11-forwarding,no-agent-forwarding <ssh_keys_2>
To configure the authorized accesses for the users, you have to set up a valid
`pi-hoole` configuration file. The latter uses the YAML syntax, and is located
at `${XDG_CONFIG_DIRECTORY}/pi-hoole/config.yaml`. It has two root fields:
`groups` and `repositories`.
You can define groups of users, and grant certain rights to a group, effectively
granting there rights to each users who are member of the group.
Group names are prefixed by `+`, and user names are prefixed by `.`.
Then, if you want to create one group `ogma` which contains the users `lgeorget`
and `lthms`:
groups:
+ogma: [.lthms, .lgeorget]
You can create as many groups as you want, and one user may be added to several
groups. Currently, nested groups are not allowed (*i.e.* a group being member of
another group).
The `repositories` field allows for defining which repositories are available, and
what given users can do with these repositories. The contents of the
`repositories` is a map, where keys are `path` to the repositories (relative to
`HOME` directory), and values are maps from role to rights.
For instance, given the following configuration:
repositories:
my/first/repo:
.lthms: +w
+contrib: +r +w[master]
anon: +r
my/second/repo:
.lthms: +r
.lgeorget: +w
We declare two repositories, one located at `${HOME}/my/first/repo`, and another
at `${HOME}/my/second/repo`. The user `lthms` (identified with `.lthms`) can
read and write to this repository, to arbitrary branches. The members of the
group `contrib` can read to any branch, but can only write to the `master`
branch. Finally, the anonymous user (through HTTP), can read to any branch.
Read means being able to clone or pull. Write means being able to push.
For the second repository, `lthms` can read to any branch, when `lgeorget` can
read and write to any branch. Therefore, it is not possible to clone
`my/second/repo` through HTTP, because `anon` has not been granted any
particular rights.
### Setting Up HTTP Proxy
`pi-hoole-web` is a very simple HTTP proxy. It receives HTTP request, ideally
issued by a `pijul` client, and turns them into `pijul` commands if the `anon`
role has been granted the required rights.
Currently, `pi-hoole-web` cannot be configured, and listen the port 8080. Also,
it does not daemonify itself. The easiest way to set up a `pi-hoole-web`
instance in a reliable way is to use systemd, for instance with the following
unit:
```
[Unit]
Description=HTTP Proxy for Pijul anonymous accesses
[Service]
Type=simple
User=pijul
Group=pijul
ExecStart=/usr/bin/pi-hoole-web
Restart=of-failure
TimeoutStopSec=300
[Install]
WantedBy=multi-user.target
```
For reference, the instance of `pi-hoole-web` responsible for `pijul.lthms.xyz`
is behind a nginx server. One very straightforward nginx configuration can be:
```
server {
listen 80;
server_name pijul.lthms.xyz;
access_log /var/log/nginx/pijul.lthms.xyz.access.log;
error_log /var/log/nginx/pijul.lthms.xyz.error.log;
location / {
proxy_pass http://localhost:8080/;
}
}
```
For `pi-hoole-web` to work correcty, it needs an additional configuration file,
assumed to be at `${XDG_CONFIG_DIRECTORY}/pi-hoole/web.yaml`. This file is
currently very simple, it contains only three fields:
* `title`: The title of the summary page
* `baseUrl`: The base URL used to clone the repositories
* `example`: Should be one of the public repositories
Here is an example:
```
title: "my repositories"
baseUrl: "https://my.repo.com"
example: "pi-hoole"
```
If you add a file called `description` in the `.pijul` directory of your public
repositories, its content will be used by `pi-hoole-web` when it gives a summary
of the public repositories.
## Limitations
### Private Branches
The command `pijul patch` does not have an argument to specify the branch from
which a patch is initially fetched; as a consequence, having read access to a
repo, even for another branch where the patch is not applied, is enough. For
this reason, if a user who obtains a hash for a patch of a branch they cannot
access can fetch the patch. That is, a patch is as private as its hash. Private
branches will eventually be supported in a better manner, but for now, private
branches should mean separated repositories.