Taskd

taskd
is a lightweight, secure server for
Taskwarrior
(
task
). It allows users to intelligently synchronize their tasks between multiple clients, including between desktop and mobile ones.
Server
Installation
Install
taskd-git
AUR
.
Configuration
Once taskd is installed, you need to set it up. The first step is to
$ export TASKDDATA=/var/lib/taskd
otherwise you need to append
--data /var/lib/taskd
to every taskd command.
Next, edit the
/usr/lib/taskd/pki/vars
file. The
CN=
line must either match the server's hostname or IP address, depending on how you connect.
Once the file is edited to your heart's content, change to the directory
/usr/lib/taskd/pki/
and run
./generate
. This will create self-signed certificates for your server.
Copy all generated
.pem
to
/var/lib/taskd
. Note that at least the
ca.cert.pem
and
ca.key.pem
must remain in the
pki
folder for the user-certificate generation later on.
Then make sure only taskd can read the certificates and keys in
/var/lib/taskd
:
# chown taskd:taskd ca.cert.pem ca.key.pem server.cert.pem server.crl.pem server.key.pem
# chmod 400 ca.cert.pem ca.key.pem server.cert.pem server.crl.pem server.key.pem
Now you need to configure taskd. Use
taskd config
or add the following to
/var/lib/taskd/config
directly:
/var/lib/taskd/config
client.cert=/var/lib/taskd/client.cert.pem
client.key=/var/lib/taskd/client.key.pem
server.cert=/var/lib/taskd/server.cert.pem
server.key=/var/lib/taskd/server.key.pem
server.crl=/var/lib/taskd/server.crl.pem
ca.cert=/var/lib/taskd/ca.cert.pem
Additionally you should change where taskd logs to, since the default is
/tmp/taskd.log
. This can be done by running
# touch /var/log/taskd.log
# chown taskd:taskd /var/log/taskd.log
# taskd config --force log /var/log/taskd.log
The last step is to set taskd's server name, which must be the same as the one used in the certificates:
# taskd config --force server servername:port
Note that taskd has no default port and it must be set manually.
Running
Start/enable
taskd.service
.
Adding a user in taskd
taskd organizes data into organizations and users, with each user being in an organization.
To add a user, run the following commands, substituting
organization
and
username
as you wish.
# taskd add org
organization
# taskd add user
organization
username
Note the key the last command returns, the user will need it to synchronize.
Make sure new organization and user are readable by user
taskd
.
# chown -R taskd:taskd /var/lib/taskd/orgs
Return to
/usr/lib/taskd/pki/
and run
# ./generate.client
username
This will return
username
.cert.pem
and
username
.key.pem
.
The
username
.key.pem
,
username
.cert.pem
and
ca.cert.pem
must be copied into to the user's Taskwarrior user data directory (default
~/.task
).
Client
User configuration
Once the
.pem
files have been copied to a user's Taskwarrior data directory, their configuration file (default
~/.taskrc
) must be updated to point to the files and server:
~/.taskrc
taskd.server=
servername
:
port
taskd.credentials=
organization
/
username
/
key
taskd.certificate=~/.task/
username
.cert.pem
taskd.key=~/.task/
username
.key.pem
taskd.ca=~/.task/ca.cert.pem
Paths are relative to the directory in which
task
is executed, so paths should be relative to
~
or absolute.
The key in
taskd.credentials
is name of the created directory in
/var/lib/taskd/orgs/
organization
/users/
on the server which contains a config file with the chosen username:
config
user=
username
Perform the initial synchronization and consent to sending your Taskwarrior data to the server:
$ task sync init
Send local changes to the server:
$ task sync
Using the Android Taskwarrior app
Before you even download the android app, you need to create a folder. On your external storage (or if you only have an internal one, then there) create the folder
Android/data/kvj.taskw/files/key
where "key" is the same as the key given when creating the user with
taskd
. Then add the
username
.key.pem
,
username
.cert.pem
and
ca.cert.pem
files to that folder.
Create a new file in that folder called
.taskrc.android
. It should look like this:
/sdcard/Android/data/kvj.taskw/files/
uuid
/.taskrc.android
taskd.server=
servername
:
port
taskd.credentials=
organization
/
username
/
key
taskd.certificate=
username
.cert.pem
taskd.key=
username
.key.pem
taskd.ca=ca.cert.pem
Note
Ensure that the configuration file
.taskrc.android
has a newline at the end. Otherwise, it will not be parsed correctly.
Now download the app and start it. When prompted to add a profile, choose the data folder that you just created. Taskwarrior should now sync and work as expected.
Troubleshooting
Unreachable Server
Should the server be unreachable but running, it bound itself to an IPv6 address. You can force IPv4 by adding
family=IPv4
to
/var/lib/taskd/config
.
If the server stalls on "Server starting", it may be failing to resolve the address you have specified in the
server
option. After a while the server will time out with "Name or service not known". In that case, try adding an external
/etc/hosts
entry aliasing that address to your external IP address (see
Domain name resolution
),
Restart taskd after attempting these, then check if your issue is fixed.
"Bad Key"
If the server responds with a "Bad Key" error even though you just generated them, check the permissions of the created folders (everything in
/var/lib/taskd/
and subfolders). taskd does not set its own uid / gid, so those folders must be manually chowned to taskd.
taskd.service fails on boot
Taskd 1.1's systemd unit does not have the correct network target dependency so might fail at times on boot. The snippet below adds the correct dependencies, this was already fixed
upstream
.
/etc/systemd/system/taskd.service.d/online.conf
[Unit]
After=
Wants=network-online.target
After=network-online.target

[Install]
WantedBy=
WantedBy=network.target
systemd hardening
Taskd is not sandboxed by default, the overrides below disallow taskd from writing in anything except
/var/lib/taskd
and
/var/log/taskd.log
.
/etc/systemd/system/taskd.service.d/hardening.conf
[Service]
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/taskd /var/log/taskd.log
ProtectKernelTunables=true
ProtectControlGroups=true
ProtectHostname=true
NoNewPrivileges=true
MemoryDenyWriteExecute=true
LockPersonality=true