| 1 | # Running Klonkt for other people
|
|---|
| 2 |
|
|---|
| 3 | A runbook for someone who has a VPS and is about to host Klonkt instances for
|
|---|
| 4 | people who are not themselves.
|
|---|
| 5 |
|
|---|
| 6 | This is **not** an install guide. For that:
|
|---|
| 7 |
|
|---|
| 8 | | | |
|
|---|
| 9 | |---|---|
|
|---|
| 10 | | [DEPLOY.md](DEPLOY.md) | one Klonkt, from bare VPS to running |
|
|---|
| 11 | | [MULTI-INSTANCE.md](MULTI-INSTANCE.md) | the split layout, `klonkt@<slug>` units |
|
|---|
| 12 |
|
|---|
| 13 | Those tell you how. This one tells you what changes the moment the data on your
|
|---|
| 14 | disk stops being yours.
|
|---|
| 15 |
|
|---|
| 16 | ---
|
|---|
| 17 |
|
|---|
| 18 | ## 0. The question to answer first
|
|---|
| 19 |
|
|---|
| 20 | **Are you hosting for yourself, or for other people?**
|
|---|
| 21 |
|
|---|
| 22 | If it is only you, stop reading and use the two guides above. Everything below is
|
|---|
| 23 | about the second case, and the difference is not technical. One Klonkt is one
|
|---|
| 24 | person, so the moment there is a second instance there is a second person, and
|
|---|
| 25 | you are now holding their conversations, their contacts, and their identity.
|
|---|
| 26 |
|
|---|
| 27 | Read §5 before you accept your first user, not after.
|
|---|
| 28 |
|
|---|
| 29 | ---
|
|---|
| 30 |
|
|---|
| 31 | ## 1. Day one
|
|---|
| 32 |
|
|---|
| 33 | Follow [MULTI-INSTANCE.md](MULTI-INSTANCE.md) for the layout, then:
|
|---|
| 34 |
|
|---|
| 35 | ```bash
|
|---|
| 36 | sudo bash /opt/klonkt/scripts/klonkt-add-instance.sh <slug> <domain>
|
|---|
| 37 | ```
|
|---|
| 38 |
|
|---|
| 39 | Leave the port out and a free one is chosen. Then check it came up:
|
|---|
| 40 |
|
|---|
| 41 | ```bash
|
|---|
| 42 | systemctl status klonkt@<slug>
|
|---|
| 43 | ```
|
|---|
| 44 |
|
|---|
| 45 | Before you tell anyone it is ready, do these three:
|
|---|
| 46 |
|
|---|
| 47 | 1. **Test the backup, do not just install it.** Run `deploy/backup.sh` once by
|
|---|
| 48 | hand and then actually unpack the tarball somewhere and look inside. A backup
|
|---|
| 49 | you have never restored is a hope, not a backup.
|
|---|
| 50 | 2. **Check the disk.** Media grows quietly; databases do not. `df -h` now, and
|
|---|
| 51 | know what number worries you.
|
|---|
| 52 | 3. **Update once on purpose**, while nobody is depending on it, so the first time
|
|---|
| 53 | you run `klonkt-update` is not also the first time you find out what it does.
|
|---|
| 54 |
|
|---|
| 55 | ---
|
|---|
| 56 |
|
|---|
| 57 | ## 2. The weekly rhythm
|
|---|
| 58 |
|
|---|
| 59 | Nothing here takes long. Skipping it is how small problems become 3am problems.
|
|---|
| 60 |
|
|---|
| 61 | ```bash
|
|---|
| 62 | systemctl list-units 'klonkt@*' # everything still running?
|
|---|
| 63 | df -h # disk
|
|---|
| 64 | journalctl --since '7 days ago' -p warning --no-pager | grep klonkt
|
|---|
| 65 | ```
|
|---|
| 66 |
|
|---|
| 67 | The log line worth reading properly is anything about federation: a rejected
|
|---|
| 68 | signature, a delivery that keeps retrying. Those are usually the other side's
|
|---|
| 69 | problem, but they are also how you find out that one of your users has been
|
|---|
| 70 | invisible to half the fediverse for a week.
|
|---|
| 71 |
|
|---|
| 72 | ---
|
|---|
| 73 |
|
|---|
| 74 | ## 3. Updating, and getting back
|
|---|
| 75 |
|
|---|
| 76 | ```bash
|
|---|
| 77 | klonkt-update
|
|---|
| 78 | ```
|
|---|
| 79 |
|
|---|
| 80 | One command updates the shared code and restarts **every** instance on the
|
|---|
| 81 | machine. That is the point of the shared layout, and it is also the risk: a bad
|
|---|
| 82 | release takes all of your users down at once, not one.
|
|---|
| 83 |
|
|---|
| 84 | So before you update:
|
|---|
| 85 |
|
|---|
| 86 | - **know what you are on.** `git -C /opt/klonkt rev-parse --abbrev-ref HEAD`.
|
|---|
| 87 | `stable` is what you want unless you have decided otherwise on purpose.
|
|---|
| 88 | - **do it when you are awake.** Not before you leave the house.
|
|---|
| 89 |
|
|---|
| 90 | `klonkt-update` prints the previous commit and the command to go back. It looks
|
|---|
| 91 | like this:
|
|---|
| 92 |
|
|---|
| 93 | ```bash
|
|---|
| 94 | runuser -u klonkt -- git -C /opt/klonkt checkout -qf -B stable <previous-sha>
|
|---|
| 95 | systemctl restart 'klonkt@*'
|
|---|
| 96 | ```
|
|---|
| 97 |
|
|---|
| 98 | The glob only matches units systemd already has loaded. An instance that was
|
|---|
| 99 | stopped will be skipped, so check with `systemctl list-units 'klonkt@*'
|
|---|
| 100 | --all` afterwards rather than assuming.
|
|---|
| 101 |
|
|---|
| 102 | That only works if the checkout has history. Older installs were cloned shallow
|
|---|
| 103 | and could not roll back at all; the updater now deepens once, on its first run
|
|---|
| 104 | after this change. If you are not sure:
|
|---|
| 105 |
|
|---|
| 106 | ```bash
|
|---|
| 107 | git -C /opt/klonkt rev-parse --is-shallow-repository # want: false
|
|---|
| 108 | ```
|
|---|
| 109 |
|
|---|
| 110 | `true` means you cannot roll back yet. Run
|
|---|
| 111 | `sudo bash /opt/klonkt/scripts/klonkt-refresh-updater.sh` and then
|
|---|
| 112 | `klonkt-update` once.
|
|---|
| 113 |
|
|---|
| 114 | **Roll back is not atomic.** All instances share one checkout, so during the
|
|---|
| 115 | switch the code is briefly half-old. For a handful of instances this is seconds
|
|---|
| 116 | and nobody notices. It is still the reason to keep a maintenance page in mind if
|
|---|
| 117 | you ever grow.
|
|---|
| 118 |
|
|---|
| 119 | ---
|
|---|
| 120 |
|
|---|
| 121 | ## 4. When it breaks
|
|---|
| 122 |
|
|---|
| 123 | **An instance will not start.**
|
|---|
| 124 |
|
|---|
| 125 | ```bash
|
|---|
| 126 | journalctl -u klonkt@<slug> -n 50 --no-pager
|
|---|
| 127 | ```
|
|---|
| 128 |
|
|---|
| 129 | Nine times out of ten it is the `.env`: a missing `SESSION_SECRET`, or a path
|
|---|
| 130 | that points at a directory that no longer exists. The app refuses to boot rather
|
|---|
| 131 | than come up half-configured, which is deliberate.
|
|---|
| 132 |
|
|---|
| 133 | **One instance is broken, the rest are fine.** Do not run `klonkt-update` hoping
|
|---|
| 134 | it helps — it restarts everyone to fix one. Restart the single unit.
|
|---|
| 135 |
|
|---|
| 136 | **Everything is broken after an update.** Roll back (§3) first, ask why second.
|
|---|
| 137 |
|
|---|
| 138 | **Disk full.** Media, then logs. `journalctl --vacuum-size=200M` buys you room
|
|---|
| 139 | immediately; the media is a conversation with the user, not a delete decision you
|
|---|
| 140 | make alone.
|
|---|
| 141 |
|
|---|
| 142 | ---
|
|---|
| 143 |
|
|---|
| 144 | ## 5. What you are actually holding
|
|---|
| 145 |
|
|---|
| 146 | This is the section people skip. Do not.
|
|---|
| 147 |
|
|---|
| 148 | Each instance's data directory contains that person's database: their posts,
|
|---|
| 149 | their private messages, who they follow, and — if they are a ward or a guardian —
|
|---|
| 150 | their guardianship relationships. It also contains **the private key of their
|
|---|
| 151 | fediverse actor**.
|
|---|
| 152 |
|
|---|
| 153 | That last one is not a privacy nuance. Whoever has that key can post as that
|
|---|
| 154 | person, follow as that person, and send messages as that person, and the rest of
|
|---|
| 155 | the fediverse has no way to tell. You have it because you have the machine. There
|
|---|
| 156 | is no configuration that takes it away.
|
|---|
| 157 |
|
|---|
| 158 | So:
|
|---|
| 159 |
|
|---|
| 160 | - **Say so.** Tell the people you host, in plain words, that you can technically
|
|---|
| 161 | read and impersonate. It is better coming from you than discovered later.
|
|---|
| 162 | - **Do not build tooling that makes it easy.** Never export or display actor keys
|
|---|
| 163 | from an admin panel. It prevents nothing, but a tool that offers it invites it.
|
|---|
| 164 | - **Guardianship data deserves more care than the rest.** A ward is often a
|
|---|
| 165 | minor, and a 🛟 help request is a distress signal. That a guardianship exists
|
|---|
| 166 | may be visible to you for support. What is in it is not yours to read.
|
|---|
| 167 |
|
|---|
| 168 | ### The legal shape
|
|---|
| 169 |
|
|---|
| 170 | Under the GDPR you are a **processor**: you handle personal data on behalf of
|
|---|
| 171 | someone else, who is the controller. That relationship needs a written agreement
|
|---|
| 172 | (Art. 28). This is true even if you host for free, and even for one friend.
|
|---|
| 173 |
|
|---|
| 174 | If you also use the data for your own purposes — statistics across instances,
|
|---|
| 175 | moderating what people post, backups you keep for your own reasons — you are no
|
|---|
| 176 | longer only a processor, and the bar is higher.
|
|---|
| 177 |
|
|---|
| 178 | The single-user design helps you here more than you would expect. A request to
|
|---|
| 179 | see or delete everything about one person is *one instance*, not a query across
|
|---|
| 180 | shared tables. You can answer it honestly, and prove it.
|
|---|
| 181 |
|
|---|
| 182 | ---
|
|---|
| 183 |
|
|---|
| 184 | ## 6. Letting someone leave
|
|---|
| 185 |
|
|---|
| 186 | A hoster who cannot be left is not a hoster. Klonkt has a portable content
|
|---|
| 187 | archive; see [../docs/EXPORT-FORMAT.md](../docs/EXPORT-FORMAT.md).
|
|---|
| 188 |
|
|---|
| 189 | ```bash
|
|---|
| 190 | cd /opt/klonkt
|
|---|
| 191 | node scripts/export-archive.mjs <slug> --out /tmp/<slug>-archive.zip
|
|---|
| 192 | ```
|
|---|
| 193 |
|
|---|
| 194 | It contains their posts, their media, and the replies underneath as a read-only
|
|---|
| 195 | record. No credentials, no keys. Hand it over and it can be imported into another
|
|---|
| 196 | Klonkt.
|
|---|
| 197 |
|
|---|
| 198 | Two things to know before you hand it over:
|
|---|
| 199 |
|
|---|
| 200 | - If the site has **paid posts**, the archive contains their full text. Treat the
|
|---|
| 201 | file like the content itself.
|
|---|
| 202 | - The **ActivityPub ids survive** only if the new home has the same domain.
|
|---|
| 203 | Moving to a different domain means new ids, and the boosts and replies that
|
|---|
| 204 | point at the old ones do not follow. That is a property of the fediverse, not
|
|---|
| 205 | of the export.
|
|---|
| 206 |
|
|---|
| 207 | Then remove the instance ([MULTI-INSTANCE.md](MULTI-INSTANCE.md) §Removing an
|
|---|
| 208 | instance) — and only after they confirm the archive opens.
|
|---|
| 209 |
|
|---|
| 210 | ---
|
|---|
| 211 |
|
|---|
| 212 | ## 7. Things not to do
|
|---|
| 213 |
|
|---|
| 214 | - **Do not host for people you would not tell about §5.** If you would rather
|
|---|
| 215 | they did not know what you can see, you should not be holding it.
|
|---|
| 216 | - **Do not update to fix one instance.** It restarts all of them.
|
|---|
| 217 | - **Do not put security updates behind anything.** If you ever charge for
|
|---|
| 218 | hosting, charge for the convenience — scheduled, all at once, with a way back
|
|---|
| 219 | — never for the update itself. An unpatched fediverse server is a problem for
|
|---|
| 220 | everyone it talks to, not only for you.
|
|---|
| 221 | - **Do not keep backups you have never restored.** See §1.
|
|---|
| 222 | - **Do not delete someone's instance the same day they ask.** Export first,
|
|---|
| 223 | confirm they can open it, then remove.
|
|---|