aboutsummaryrefslogtreecommitdiff
path: root/content/blog/miscellaneous/going-social.md
blob: 7cf1b7440683fe026859cad2be19a4d4a8f0fd36 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
---
title: Going Social
description: an ActivityPub server experiment (aka joining mastodon with a self hosted instance)
date: 2022-11-11
tags:
- kubernetes
- terraform
---

## Introduction

I never saw the appeal of social networks, but increasingly some friends or former colleagues cease to be reachable over IRC or using the only messaging app you had in common. They went social, and if I want to reach them or hear from them other than with an email or a text message I need to get a little involved.

I tried running a personal [pleroma](https://pleroma.social/) instance a few years ago, but stopped because beside not seeing the appeal I did not need it as friends were still available through other means. While advertised as lightweight it still consumed at least 300M of ram which is not light at all in my book. I looked around and did find a lot of alternatives, but only a few appealed to me.

## Choosing one

I was amused by [honk](https://humungus.tedunangst.com/r/honk) which clearly appeals to my sensibilities, but I settled on trying out [ktistec](https://github.com/toddsundsted/ktistec) which seems more writer oriented and is minimalist in other social aspects that I do not want to see like a global timeline. When going to my [social](https://social.adyxax.org) you should see my messages, not whatever I am following. I particularly like this for a personal instance.

It is still a little heavy for me with 100M of ram and might still be a little young under the hood. The repository does not seem to contain unit or integration tests but since the author is using its own software daily that counts as a little testing. The author is also very active on github issues.

## Building

I did not know the crystal language other than by name so I will not be able to contribute much on the coding front. There is a Dockerfile but it did not work out of the box, here is how I built an image:
```sh
git clone https://github.com/toddsundsted/ktistec
cd ktistec
git checkout dist
nvim Dockerfile  # add a step to `RUN shards update` before `shards install`
npm run build
buildah bud -t adyxax/ktistec:2.0.0-3p1
buildah push adyxax/ktistec quay.io/adyxax/ktistec:2.0.0-3p1
```

## Deploy to kubernetes using terraform

Here is the code I wrote to deploy this image to my k3s server.

### DNS
```hcl
resource "cloudflare_record" "social-cname-adyxax-org" {
  zone_id = lookup(data.cloudflare_zones.adyxax-org.zones[0], "id")
  name    = "social"
  value   = "myth.adyxax.org"
  type    = "CNAME"
  proxied = false
}
```

### Namespace
```hcl
resource "kubernetes_namespace" "myth-social" {
  provider = kubernetes.myth
  metadata {
    name = "social"
  }
}
```

### Deployment
```hcl
resource "kubernetes_manifest" "myth-deployment-social" {
  provider = kubernetes.myth
  manifest = {
    "apiVersion" = "apps/v1"
    "kind"       = "Deployment"
    "metadata" = {
      "name"      = "social"
      "namespace" = kubernetes_namespace.myth-social.id
    }
    "spec" = {
      "replicas" = 1
      "selector" = {
        "matchLabels" = {
          "app" = "ktistec"
        }
      }
      "strategy" = {
        "type" = "RollingUpdate"
        "rollingUpdate" = {
          "maxSurge"       = 1
          "maxUnavailable" = 0
        }
      }
      "template" = {
        "metadata" = {
          "labels" = {
            "app" = "ktistec"
          }
        }
        "spec" = {
          "containers" = [
            {
              "image" = "quay.io/adyxax/ktistec:2.0.0-3p1"
              "livenessProbe" = {
                "httpGet" = {
                  "path" = "/"
                  "port" = 3000
                }
                "initialDelaySeconds" = 5
                "timeoutSeconds"      = 5
              }
              "name" = "ktistec"
              "ports" = [
                {
                  "containerPort" = 3000
                },
              ]
              "readinessProbe" = {
                "httpGet" = {
                  "path" = "/"
                  "port" = 3000
                }
                "initialDelaySeconds" = 5
                "timeoutSeconds"      = 5
              }
              "lifecycle" = {
                "preStop" = {
                  "exec" = {
                    "command" = ["/bin/sh", "-c", "sleep 10"]
                  }
                }
              }
              "volumeMounts" = [
                {
                  "name"      = "ktistec-db"
                  "mountPath" = "/db"
                },
                {
                  "name"      = "ktistec-uploads"
                  "mountPath" = "/uploads"
                }
              ]
            },
          ]
          "terminationGracePeriodSeconds" = 1
          "volumes" = [
            {
              "name" = "ktistec-db"
              "hostPath" = {
                "path" = "/srv/ktistec-db"
                "type" = "Directory"
              }
            },
            {
              "name" = "ktistec-uploads"
              "hostPath" = {
                "path" = "/srv/ktistec-uploads"
                "type" = "Directory"
              }
            }
          ]
        }
      }
    }
  }
}
```

### Service
```hcl
resource "kubernetes_manifest" "myth-service-social" {
  provider = kubernetes.myth
  manifest = {
    "apiVersion" = "v1"
    "kind"       = "Service"
    "metadata" = {
      "name"      = "social"
      "namespace" = kubernetes_namespace.myth-social.id
    }
    "spec" = {
      "ports" = [
        {
          "port"       = 80
          "protocol"   = "TCP"
          "targetPort" = 3000
        },
      ]
      "selector" = {
        "app" = "ktistec"
      }
      "type" = "ClusterIP"
    }
  }
}
```

### Ingress
```hcl
resource "kubernetes_manifest" "myth-ingress-social" {
  provider = kubernetes.myth
  manifest = {
    "apiVersion" = "networking.k8s.io/v1"
    "kind"       = "Ingress"
    "metadata" = {
      "name"      = "social"
      "namespace" = kubernetes_namespace.myth-social.id
    }
    "spec" = {
      "ingressClassName" = "nginx"
      "rules" = [
        {
          "host" = "social.adyxax.org"
          "http" = {
            "paths" = [
              {
                "path"     = "/"
                "pathType" = "Prefix"
                "backend" = {
                  "service" = {
                    "name" = "social"
                    "port" = {
                      "number" = 80
                    }
                  }
                }
              },
            ]
          }
        },
      ]
      "tls" = [
        {
          "hosts"      = ["social.adyxax.org"]
          "secretName" = "wildcard-adyxax-org"
        },
      ]
    }
  }
}
```

## Conclusion

So far it seems to work as intended, I will see in a few days if I keep ktistec or try to find something else. You can reach me at [adyxax@social.adyxax.org](https://social.adyxax.org/@adyxax) if you want, I would like to hear from you and really try this social experiment.