Sunday, 2020 April 19

This morning I decided I was going to get Taskwarrior's sync server (taskd, also known as taskserver) set up in my personal Kubernetes cluster.

This ended up taking about an hour; in terms of actual work it was maybe five minutes, but I had to spend a lot of time wading through shitty documentation. On the Taskwarrior side, this weird sorta-kinda-slide-deck thing appears to be the official documentation, augmented by this similarly configured troubleshooting guide.

I eventually more-or-less gave up on those, instead just referring to them occasionally for reference. I mostly ended up following the README for the docker image I used, although it was also missing a crucial step.

The first step was to open up a new port in my DigitalOcean loadbalancer.

TCP on port 53589 -> TCP on port 32009

Next I wrote up the appropriate YAML file.

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: taskd-volume
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: do-block-storage
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Service
metadata:
  name: taskd-service
spec:
  type: NodePort
  selector:
    stage: prod
    component: taskd
  ports:
  - protocol: TCP
    nodePort: 32009
    port: 53589
    targetPort: 53589
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: taskd-deployment
  labels:
    stage: prod
    component: taskd
  annotations:
    flux.weave.works/automated: 'true'
spec:
  replicas: 1
  selector:
    matchLabels:
      stage: prod
      component: taskd
  template:
    metadata:
      labels:
        stage: prod
        component: taskd
    spec:
      containers:
      - name: taskd
        image: x4121/taskd:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 53589
        env:
        - name: CERT_CN
          value: taskd.brutallogic.net
        - name: CERT_COUNTRY
          value: US
        - name: CERT_LOCALITY
          value: Kent
        - name: CERT_ORGANIZATION
          value: brutallogic.net
        - name: CERT_STATE
          value: WA
        volumeMounts:
        - mountPath: /var/taskd
          name: taskd-volume
      volumes:
      - name: taskd-volume
        persistentVolumeClaim:
          claimName: taskd-volume

I use flux to automatically apply changes to my cluster, but for development and testing I just use a simple kubectl apply -f.

Once the container was up and running I needed to run some commands on it.

local$ kubectl exec -ti taskd-deployment-00deadbeef-0beef -- sh
container# taskd add org Hamacher
Created organization 'Hamacher'
container# taskd add user Hamacher Josh
New user key: 
Created user 'Josh' for organization 'Hamacher'
container# cd pki
container# gosu taskd ./generate.client Josh

Now I needed to install some of the certs locally, and point taskwarrior at them.

local$ mkdir ~/.config/taskd
local$ kubectl cp taskd-deployment-00deadbeef-0beef:/var/taskd/pki/ca.cert.pem ~/.config/taskd/ca.cert.pem
tar: removing leading '/' from member names
local$ kubectl cp taskd-deployment-00deadbeef-0beef:/var/taskd/pki/Josh.cert.pem ~/.config/taskd/Josh.cert.pem
tar: removing leading '/' from member names
local$ kubectl cp taskd-deployment-00deadbeef-0beef:/var/taskd/pki/Josh.key.pem ~/.config/taskd/Josh.key.pem
tar: removing leading '/' from member names

And in my ~/.taskrc.

...
taskd.server=taskd.brutallogic.net:53589
taskd.certificate=\/home\/hamacher\/.config\/taskd\/Josh.cert.pem
taskd.key=\/home\/hamacher\/.config\/taskd\/Josh.key.pem
taskd.ca=\/home\/hamacher\/.config\/taskd\/ca.cert.pem
taskd.credentials=Hamacher\/Josh\/
...

At this point, I expected it to "just work". But, task sync init kept telling me that my account didn't exist. Eventually, lacking any other ideas, I restarted taskd. After this syncing worked. I'm fairly confident this point is not mentioned in any of the documentation I looked at.

Sunday, 2020 April 12 Monday, 2020 April 20