Hard board.
Find a file
2026-09-29 10:57:00 +02:00
src fix 2026-09-28 18:44:30 +02:00
.envrc Initial commit 2026-04-05 21:17:37 +02:00
.gitignore move webname to plank.txt 2026-09-11 03:31:45 +02:00
Cargo.lock display date 2026-04-08 17:11:00 +02:00
Cargo.toml display date 2026-04-08 17:11:00 +02:00
format.md document plankdata format 2026-09-11 11:45:10 +02:00
LICENSE Update LICENSE 2026-09-29 10:57:00 +02:00
README.md change plankauth failure mode 2026-09-25 17:46:20 +02:00
shell.nix Initial commit 2026-04-05 21:17:37 +02:00

Plank

A hard, imageless board.

Inspired by the function of bulletin boards and forums, and the simplicity of imageboards; Hardened with hatred and spite.

Everything is a file. Plank is unix-compliant.

Sample instance & Discussion

Setup

First, ensure you have argon2, sha512sum, and xxd (tinyxxd) installd.

For setup with a personal account

  1. Run the binary in an empty directory. (no args or <listen ip> <listen port>)
  2. Log in with root:init
  3. Create an account with your root invite
  4. Log back into root and delete it as specified on the login page
  5. Log in with the account you created again

You can also skip the own account step if you change the root password instead of deleting the account:

  1. Run the binary in an empty directory. (no args or <listen ip> <listen port>)
  2. Log in with root:init
  3. Change its password

You may change some config values in plank.txt.

Moderation

To delete an account, all of its posts, and every account that was invited by them, delete the folder of the account (e.g. ./root/tudbut). This essentially undoes their whole existence.

To disable someone's invite link, you can remove the ./invites file associated with it. To discover which to remove, check their account.txt

Format

For file format, see format.md

Authentication service

(Disabled by default)

Plank supports being used as an authentication service for other services. To authenticate a client, redirect it to /auth?<endpoint> (endpoint is urlencoded), after which it will be redirected to <endpoint>?plankauth=<token> where token is the following:

USERNAME = the username that was authenticated
ENDPOINT = the decoded endpoint supplied to plank
TIMESTAMP = unix millis when the authentication happened
PSK = taken from plank.txt

SIGNATURE = sha512(PSK ' ' USERNAME ' ' TIMESTAMP ' ' ENDPOINT)
token = USERNAME ':' TIMESTAMP ':' SIGNATURE

To verify, parse the username and timestamp back out of the token, then derive the same signature using the pre-shared-key, the username, the timestamp, and the endpoint in use. The intended endpoint is included in the signature to ensure no attacker can trick a user into authenticating a malicious server and then re-using the token to trick other servers.

If the authentication failed (i.e. the user is not logged into plank), the plankauth parameter in the redirection will be "fail".

Example (psk is init):

  1. thing.tudbut.de wants plank auth from plank.tudbut.de and receive the token on thing.tudbut.de/callback
  2. thing.tudbut.de redirects user to https://plank.tudbut.de/auth?https%3A%2F%2Fthing.tudbut.de%2Fcallback
  3. plank.tudbut.de redirects user to https://thing.tudbut.de/callback?plankauth=root%3A1789156906420%3A60603ed6afca5dfd22216a55a9690a8e4ededcb1d9a05999a87cc253673ad4e63305964355e4441c7b2f9b0dc587e2f016851d5011149e68ff8ad8272b50e290
  4. thing.tudbut.de receives this, knows username is root, timestamp is 1789156906420, and its own endpoint is https://thing.tudbut.de/callback.
  5. thing.tudbut.de computes the sha512 hash for init root 1789156906420 https://thing.tudbut.de/callback (try it: echo -n "init root 1789156906420 https://thing.tudbut.de/callback" | sha512sum)
  6. thing.tudbut.de considers the authentication successful because the computed hash (60603ed...) matches the one in the token.