Category Archives: Git

Use Radicale to get your own shared calendar !

Heyo,

I was looking for a shared calendar, my prerequisites were:

  • self hosted
  • open source and free
  • “cross-platform” (I want it on my laptop, PC and my mobile)

After some research, I ended up on Radicale it’s a small CalDAV and CardDAV python server, and it fulfills all my requirements. Also you can:

  • secure the connection (I don’t mind I use HAProxy on top with Let’s Encrypt certificate, but still it’s cool)
  • support authentication (I use .htpasswd)
  • rights access, you can set some pretty interesting rights to your calendars, like read only for some users, and write for some others to others’ calendar …
  • storage hook, you can add a hook for example git, so each time you modify a calendar it’s committed and pushed to git !
  • other cool stuff, I didn’t completely review it all

So if it’s still appealing to you, follow me !

Install Radicale

Open up your terminal and do the following (still only showing Debian version):

aptitude install python3-pip
python3 -m pip install --upgrade radicale
Install requirements and Radicale

Configure it

For security reasons and convenience, I run my Radicale server behind HAProxy, so my configuration file maybe won’t be useful to you, you just have to change the hosts though.

It’s possible you don’t want the same choice I’ve made within the configuration below either (storage, git hook, authentication, file rights) so I suggest you take a look at the wonderful documentation.

If you want to use git as a hook, and also to have an authentication mechanism which I highly recommand, do the following:

aptitude install git libffi-dev apache2-utils
python3 -m pip install --upgrade passlib bcrypt
Requirements for authentication and git hook

Do not forget to create the storage folder:

mkdir -p /var/lib/radicale/collections
Create storage folder

If you choose an “.htpasswd authentication”, you can create each access like that:

htpasswd -B /etc/radicale/users <username>
Create a user access

Now edit /etc/radicale/config:

[server]
hosts               = 127.0.0.1:5232
max_connections     = 5
timeout             = 2

[storage]
filesystem_folder   = /var/lib/radicale/collections
hook                = git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s)

[auth]
type                = htpasswd
htpasswd_filename   = /etc/radicale/users
htpasswd_encryption = bcrypt

[web]
#type                = none

[logging]
debug               = true

[rights]
type                = from_file
file                = /etc/radicale/rights
/etc/radicale/config

Some quick explanations:

  • server section is quite self explanatory
  • auth section, you can define several fields such as the type of auth, where is your file and the encryption
  • web needs some explanation, if you set type to none, then you won’t have the interface though the web (it’s cool when you are in production), there I comment it so I have access to the interface so I can create calendars
  • logging is easy to understand
  • rights, in my case I choose to load the rights from a file but there are other options

You have to init the git repository if you chose to use it:

cd /var/lib/radicale/collections
git init
Init the repository

Now create a .gitignore like that and you’re done:

.Radicale.cache
.Radicale.lock
.Radicale.tmp.*
.gitignore

Let’s move on to the configuration of rights in /etc/radicale/rights:

## GLOBAL ##

# any authenticated user can reach root collection
[read]
user = .+
collection =
permission = r

# specific to login to web panel, if not you can't login because only your data is allowed and not your root
[rw_own_root]
user = .+
collection = %(login)s
permission = rw

# any authenticated user can rw its data
[rw_own]
user = .+
collection = %(login)s/.*
permission = rw
/etc/radicale/rights

Again it’s quite easy to understand, a few notes:

  • the name within the bracket can be what you want
  • you cannot put several user in one section, let’s say you want to give rw to several user, you’ll have to repeat each section
  • careful between user = .* (matches everyone including anonymous users) and user = .+ (only matches authenticated users)

A special note, in my case I have more right with my user, it can rw an other user’s calendar and also only read an other. Here’s a preview if you want to adapt it for your own purpose:

# floreo can read blublu
[r_floreo_blublu]
user = floreo
collection = blublu/.*
permission = r

# floreo can read/write blibli
[rw_floreo_blibli]
user = floreo
collection = blibli/.*
permission = rw
Extra for /etc/radicale/rights

Check the configuration documentation for further details.

I suggest you have a look at the rights configuration since it can be very dangerous.

Supervisor

I use Supervisor to run Radicale in case it crashes. I know you can write an init script or you can use screen or tmux but that’s ugly.

aptitude install supervisor
Install Supervisor

Now let’s configure it to run Radicale in /etc/supervisor/conf.d/radicale.conf:

[program:radicale]
command=python3 -m radicale
stderr_logfile = /var/log/supervisor/radicale-stderr.log
stdout_logfile = /var/log/supervisor/radicale-stdout.log
/etc/supervisor/conf.d/radicale.conf

Time to start it:

supervisorctl reread
supervisorctl start radicale
reread and start Radicale

To be clean, let’s add a logrotate in /etc/logrotate.d/supervisor:

/var/log/supervisor/*.log {
    weekly
    rotate 52
    compress
    delaycompress
    notifempty
    missingok
    copytruncate
}
/etc/logrotate.d/supervisor

HAProxy

As I said previously I’m running HAProxy on top, here goes one possible configuration in /etc/haproxy/haproxy.cfg:

frontend https
        bind :::443 v4v6 ssl crt <path to your pem>
        http-request set-header X-Forwarded-Proto https

        use_backend radicale if { hdr(Host) -i <your domaine name> }

frontend http
        bind :::80 v4v6
        http-request redirect scheme https if { hdr(host) -i <your domaine name> } !{ ssl_fc }
        use_backend radicale if { hdr(Host) -i <your domaine name> }

backend radicale
        option forwardfor
        server radicale localhost:5232
/etc/haproxy/haproxy.cfg

Runtime !

Now if you connect to your Radicale web panel with one of your user created previously in the .htpasswd file, you should be able to create a new calendar or adressbook. So you can do it, that shouldn’t be hard, and it will give you a full link to your own collection, that’s the link you’ll have to insert in your clients !

Clients

On my computer I use Thunderbird with the lightning modules, careful because if you have several account in Radicale, Thunderbird only sticks to one, so I put the user and password in the URL (i.e http://username:password@example.com/) to avoid the login prompt …

On my mobile, I use Open Sync to deal with the sync of CalDAV and SolCalendar (it looks like it got removed from the Play Store recently …)

The end

If you followed well, you should remember that we have the Radicale web panel UP, I suggest to turn it off once you have created the calendar and addressbook for each of your users since you can manage events and contacts from your clients. To do so, open up /etc/radicale/config and uncomment the lines:

[server]
hosts               = 127.0.0.1:5232
max_connections     = 5
timeout             = 2

[storage]
filesystem_folder   = /var/lib/radicale/collections
hook                = git add -A && (git diff --cached --quiet || git commit -m "Changes by "%(user)s)

[auth]
type                = htpasswd
htpasswd_filename   = /etc/radicale/users
htpasswd_encryption = bcrypt

[web]
type                = none

[logging]
debug               = true

[rights]
type                = from_file
file                = /etc/radicale/rights
/etc/radicale/rights

And don’t forget to restart Radicale through Supervisor:

supervisorctl restart radicale
Restart Radicale through Supervisor

Done, it should all work well 🙂

Addendum : how to get your calendar back in case you fucked up

So it happened to me few minutes ago to completely destroy my calendar using a script trough WebDAV. Hopefully I use git hook to track all modifications to my calendar so here it goes to get your calendar back !

First, don’t panic.

Secondly, go to your Radicale root lib directory, it should be /var/lib/radicale/collections and list your modifications in git:

# git log
commit d78ec10d0b80ccae7fb25ecda26d5b5f05e2f69f
Author: root <root@xxx>
Date:   Thu Aug 17 18:55:30 2017 +0200

    Changes by fuckedup_script

commit 7fe7c14099834ef843175c06e6bd2bfa1212a68c
Author: root <root@xxx>
Date:   Thu Aug 17 18:50:20 2017 +0200

    Changes by floreo
git log

So in this example, we can see two commits, the last one was made by a script, and the other one by me directly. We need to go back to the previous commit made by me, and not by the script, so just write down the commit number, here it’s 7fe7c14099834ef843175c06e6bd2bfa1212a68c.

Let’s go back to our previous commit:

git reset --hard 7fe7c14099834ef843175c06e6bd2bfa1212a68c
git reset

And voilà, you got your calendar back, fiuuu !

Addendum 2: keep your Radicale up to date

It’s quite easy to do so, just run an upgrade once in a while, or read that page

python3 -m pip install --upgrade radicale
Upgrade Radicale

You now have to restart it, if you use Supervisor as I explained above, just kill nicely the pid and it will run automagically:

kill -3 $(ps aux | grep -i radicale | grep -v grep | awk '{ print $2 }')
Kill Radicale!

Check the version is alright:

radicale --version
Check Radicale's version

 

How to deal with several ssh keys easily

Hello, this post will be about how to use several ssh keys in a “simple” way.

I had the problem of having several ssh keys to connect to different servers and also to use git with a different key.
I know I’m not quite clear with this, so let’s take an example.

You have two keys, one to connect to a server and an other one to use git (github, bitbucket, whatever …).

You want to clone a project using git :

git clone git@git.florianleleu.com:/myAwesomeProject

And you would do this to connect to the server s1.farm.florianleleu.com :

ssh florian@s1.farm.florianleleu.com -p 2222

Your keys are in ~/.ssh/, though which one will be used for the server and which one for git? Stuck.

I hope it’s more clear now. 😀

Here’s one way to solve this problem.
You have to create this file ~/.ssh/config
Give it some “good” rights (i.e chmod 600 ~/.ssh/config)

Here is an example of what you can write in this file, the explanations will follow :

Host git git.florianleleu.com
    HostName git.florianleleu.com
    User git
    IdentityFile ~/.ssh/git/id_rsa

Host *.farm.florianleleu.com
    User florian
    Port 2222
    IdentityFile ~/.ssh/farm/id_rsa

Options shown :

  • Host => alias or the pattern(s) you want to match, some regex are allowed
  • Hostname => the real host you want to connect to
  • User => the user with which you will be connected on the remote server
  • Port => the port of the remote server (default 22)
  • IdentityFile => the path to your private key

And now how to use it :

git clone git:/myAwesomeProject

In this command: git clone git:/myAwesomeProject, what’s in bold will be replaced by git@git.florianleleu.com because it is matched by the first Host (i.e alias), and obviously, it will do what was wanted at first, which is to take the key ~/.ssh/git/id_rsa. Note that you can also write it git clone git@git.florianleleu.com:/myAwesomeProject, but the alias is quite handy.

ssh s1.farm.florianleleu.com

In this command: ssh s1.farm.florianleleu.com, it’s matched by the second Host, and will be replaced by florian@s1.farm.florianleleu.com -p 2222 and use the file ~/.ssh/farm/id_rsa.

Obviously, not everything is said, there are other options ! RTFM 🙂

man ssh_config