1
0
mirror of https://github.com/funkypenguin/geek-cookbook/ synced 2025-12-13 09:46:23 +00:00

Experiment with PDF generation

Signed-off-by: David Young <davidy@funkypenguin.co.nz>
This commit is contained in:
David Young
2022-08-19 16:40:53 +12:00
parent c051e0bdad
commit abf9309cb1
317 changed files with 124 additions and 546 deletions

View File

@@ -0,0 +1,277 @@
---
title: Install Mastodon in Kubernetes
description: How to install your own Mastodon instance using Kubernetes
---
# Install Mastodon in Kubernetes
[Mastodon](https://joinmastodon.org/) is an open-source, federated (*i.e., decentralized*) social network, inspired by Twitter's "microblogging" format, and used by upwards of 4.4M early-adopters, to share links, pictures, video and text.
![Mastodon Screenshot](/images/mastodon.png){ loading=lazy }
!!! question "Why would I run my own instance?"
That's a good question. After all, there are all sorts of public instances available, with a [range of themes and communities](https://joinmastodon.org/communities). You may want to run your own instance because you like the tech, because you just think it's cool :material-emoticon-cool-outline:
You may also have realized that since Mastodon is **federated**, users on your instance can follow, toot, and interact with users on any other instance!
If you're **not** into that much effort / pain, you're welcome to [join our instance][community/mastodon] :material-mastodon:
## Mastodon requirements
!!! summary "Ingredients"
Already deployed:
* [x] A [Kubernetes cluster](/kubernetes/cluster/) (*not running Kubernetes? Use the [Docker Swarm recipe instead][mastodon]*)
* [x] [Flux deployment process](/kubernetes/deployment/flux/) bootstrapped
* [x] An [Ingress](/kubernetes/ingress/) to route incoming traffic to services
* [x] [Persistent storage](/kubernetes/persistence/) to store persistent stuff
* [x] [External DNS](/kubernetes/external-dns/) to create an DNS entry
New:
* [ ] Chosen DNS FQDN for your epic new social network
* [ ] An S3-compatible bucket for serving media (*I use [Backblaze B2](https://www.backblaze.com/b2/docs/s3_compatible_api.html)*)
* [ ] An SMTP gateway for delivering email notifications (*I use [Mailgun](https://www.mailgun.com/)*)
* [ ] A business card, with the title "[*I'm CEO, Bitch*](https://nextshark.com/heres-the-story-behind-mark-zuckerbergs-im-ceo-bitch-business-card/)"
## Preparation
### GitRepository
The Mastodon project doesn't currently publish a versioned helm chart - there's just a [helm chart stored in the repository](https://github.com/mastodon/mastodon/tree/main/chart) (*I plan to submit a PR to address this*). For now, we use a GitRepository instead of a HelmRepository as the source of a HelmRelease.
```yaml title="/bootstrap/gitrepositories/gitepository-mastodon.yaml"
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
name: mastodon
namespace: flux-system
spec:
interval: 1h0s
ref:
branch: main
url: https://github.com/funkypenguin/mastodon # (1)!
```
1. I'm using my own fork because I've been working on improvements to the upstream chart, but `https://github.com/mastodon/mastodon` would work too.
### Namespace
We need a namespace to deploy our HelmRelease and associated ConfigMaps into. Per the [flux design](/kubernetes/deployment/flux/), I create this example yaml in my flux repo at `/bootstrap/namespaces/namespace-mastodon.yaml`:
```yaml title="/bootstrap/namespaces/namespace-mastodon.yaml"
apiVersion: v1
kind: Namespace
metadata:
name: mastodon
```
### Kustomization
Now that the "global" elements of this deployment (*just the GitRepository in this case*) have been defined, we do some "flux-ception", and go one layer deeper, adding another Kustomization, telling flux to deploy any YAMLs found in the repo at `/mastodon`. I create this example Kustomization in my flux repo:
```yaml title="/bootstrap/kustomizations/kustomization-mastodon.yaml"
apiVersion: kustomize.toolkit.fluxcd.io/v1beta1
kind: Kustomization
metadata:
name: mastodon
namespace: flux-system
spec:
interval: 15m
path: mastodon
prune: true # remove any elements later removed from the above path
timeout: 2m # if not set, this defaults to interval duration, which is 1h
sourceRef:
kind: GitRepository
name: flux-system
validation: server
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: mastodon-web
namespace: mastodon
- apiVersion: apps/v1
kind: Deployment
name: mastodon-streaming
namespace: mastodon
- apiVersion: apps/v1
kind: Deployment
name: mastodon-sidekiq
namespace: mastodon
```
### ConfigMap
Now we're into the mastodon-specific YAMLs. First, we create a ConfigMap, containing the entire contents of the helm chart's [values.yaml](https://github.com/bitnami-labs/mastodon/blob/main/helm/mastodon/values.yaml). Paste the values into a `values.yaml` key as illustrated below, indented 4 tabs (*since they're "encapsulated" within the ConfigMap YAML*). I create this example yaml in my flux repo:
```yaml title="mastodon/configmap-mastodon-helm-chart-value-overrides.yaml"
apiVersion: v1
kind: ConfigMap
metadata:
name: mastodon-helm-chart-value-overrides
namespace: mastodon
data:
values.yaml: |- # (1)!
# <upstream values go here>
```
1. Paste in the contents of the upstream `values.yaml` here, intended 4 spaces, and then change the values you need as illustrated below.
Values I change from the default are:
```yaml
spec:
values:
mastodon:
createAdmin:
enabled: true
username: funkypenguin
email: davidy@funkypenguin.co.nz
local_domain: so.fnky.nz
s3:
enabled: true
access_key: "<redacted>"
access_secret: "<redacted>"
bucket: "so-fnky-nz"
endpoint: https://s3.us-west-000.backblazeb2.com
hostname: s3.us-west-000.backblazeb2.com
secrets:
secret_key_base: "<redacted>"
otp_secret: "<redacted>"
vapid:
private_key: "<redacted>"
public_key: "<redacted>"
smtp:
domain: mg.funkypenguin.co.nz
enable_starttls_auto: true
from_address: mastodon@mg.funkypenguin.co.nz
login: mastodon@mg.funkypenguin.co.nz
openssl_verify_mode: peer
password: <redacted>
port: 587
reply_to: mastodon@mg.funkypenguin.co.nz
server: smtp.mailgun.org
tls: false
ingress:
enabled: true
annotations:
kubernetes.io/ingress.class: traefik
nginx.ingress.kubernetes.io/proxy-body-size: 10m
hosts:
- host: so.fnky.nz
paths:
- path: '/'
postgresql:
auth:
postgresPassword: "<redacted>"
username: postgres
password: "<redacted>"
primary:
persistence:
size: 1Gi
redis:
password: "<redacted>"
master:
persistence:
size: 1Gi
architecture: standalone
```
### HelmRelease
Finally, having set the scene above, we define the HelmRelease which will actually deploy the mastodon into the cluster. I save this in my flux repo:
```yaml title="/mastodon/helmrelease-mastodon.yaml"
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: mastodon
namespace: mastodon
spec:
chart:
spec:
chart: ./charts/mastodon
sourceRef:
kind: GitRepository
name: mastodon
namespace: flux-system
interval: 15m
timeout: 5m
releaseName: mastodon
valuesFrom:
- kind: ConfigMap
name: mastodon-helm-chart-value-overrides
valuesKey: values.yaml # (1)!
```
1. This is the default, but best to be explicit for clarity
## :material-mastodon: Install Mastodon!
Commit the changes to your flux repository, and either wait for the reconciliation interval, or force a reconcilliation[^1] using `flux reconcile source git flux-system`. You should see the kustomization appear...
```bash
~ flux get kustomizations | grep mastodon
mastodon main/d34779f False True Applied revision: main/d34779f
~
```
The helmrelease should be reconciled...
```bash
~ flux get helmreleases -n mastodon
NAME REVISION SUSPENDED READY MESSAGE
mastodon 1.2.2-pre-02 False True Release reconciliation succeeded
~
```
And you should have happy Mastodon pods:
```bash
~ k get pods -n mastodon
NAME READY STATUS RESTARTS AGE
mastodon-media-remove-27663840-l2xvt 0/1 Completed 0 22h
mastodon-postgresql-0 1/1 Running 0 5d20h
mastodon-redis-master-0 1/1 Running 0 5d20h
mastodon-sidekiq-5ffd544f98-k86qp 1/1 Running 0 5d20h
mastodon-streaming-676fdcf75-hz52z 1/1 Running 0 5d20h
mastodon-web-597cf7c8d5-2hzkl 1/1 Running 4 5d20h
~
```
... and finally check that the ingress was created as desired:
```bash
~ k get ingress -n mastodon
NAME CLASS HOSTS ADDRESS PORTS AGE
mastodon <none> so.fnky.nz 80, 443 8d
~
```
Now hit the URL you defined in your config, and you should see your beautiful new Mastodon instance! Login with your configured credentials, navigate to **Preferences**, and have fun tweaking and tooting away!
!!! question "What's my Mastodon admin password?"
The admin username _may_ be output by the post-install hook job which creates it, but I didn't notice this at the time I deployed mine. Since I had a working SMTP setup however, I just used the "forgot password" feature to perform a password reset, which feels more secure anyway.
Once you're done, "toot" me up by mentioning [funkypenguin@so.fnky.nz](https://so.fnky.nz/@funkypenguin) in a toot! :wave:
!!! tip
If your instance feels lonely, try using some [relays](https://github.com/brodi1/activitypub-relays) to bring in the federated firehose!
## Summary
What have we achieved? We now have a fully-swarmed Mastodon instance, ready to federate with the world! :material-mastodon:
!!! summary "Summary"
Created:
* [X] Mastodon configured, running, and ready to toot!
--8<-- "recipe-footer.md"
[^1]: There is also a 3rd option, using the Flux webhook receiver to trigger a reconcilliation - to be covered in a future recipe!