diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml
new file mode 100644
index 000000000..055615c56
--- /dev/null
+++ b/.github/workflows/web.yml
@@ -0,0 +1,99 @@
+# Workflow to build your docs with oranda (and mdbook)
+# and deploy them to Github Pages
+name: Web
+
+# We're going to push to the gh-pages branch, so we need that permission
+permissions:
+ contents: write
+
+# What situations do we want to build docs in?
+# All of these work independently and can be removed / commented out
+# if you don't want oranda/mdbook running in that situation
+on:
+ # Check that a PR didn't break docs!
+ #
+ # Note that the "Deploy to Github Pages" step won't run in this mode,
+ # so this won't have any side-effects. But it will tell you if a PR
+ # completely broke oranda/mdbook. Sadly we don't provide previews (yet)!
+ pull_request:
+
+ # Whenever something gets pushed to main, update the docs!
+ # This is great for getting docs changes live without cutting a full release.
+ #
+ # Note that if you're using cargo-dist, this will "race" the Release workflow
+ # that actually builds the Github Release that oranda tries to read (and
+ # this will almost certainly complete first). As a result you will publish
+ # docs for the latest commit but the oranda landing page won't know about
+ # the latest release. The workflow_run trigger below will properly wait for
+ # cargo-dist, and so this half-published state will only last for ~10 minutes.
+ #
+ # If you only want docs to update with releases, disable this, or change it to
+ # a "release" branch. You can, of course, also manually trigger a workflow run
+ # when you want the docs to update.
+ push:
+ branches:
+ - main
+
+ # Whenever a workflow called "Release" completes, update the docs!
+ #
+ # If you're using cargo-dist, this is recommended, as it will ensure that
+ # oranda always sees the latest release right when it's available. Note
+ # however that Github's UI is wonky when you use workflow_run, and won't
+ # show this workflow as part of any commit. You have to go to the "actions"
+ # tab for your repo to see this one running (the gh-pages deploy will also
+ # only show up there).
+ workflow_run:
+ workflows: [ "Release" ]
+ types:
+ - completed
+
+# Alright, let's do it!
+jobs:
+ web:
+ name: Build and deploy site and docs
+ runs-on: ubuntu-latest
+ steps:
+ # Setup
+ - uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ - uses: dtolnay/rust-toolchain@stable
+ - uses: swatinem/rust-cache@v2
+
+ # If you use any mdbook plugins, here's the place to install them!
+
+ # Install and run oranda (and mdbook)
+ # This will write all output to ./public/ (including copying mdbook's output to there)
+ - name: Install and run oranda
+ run: |
+ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/axodotdev/oranda/releases/latest/download/oranda-installer.sh | sh
+ oranda build
+
+ - name: Prepare HTML for link checking
+ # untitaker/hyperlink supports no site prefixes, move entire site into
+ # a subfolder
+ run: mkdir /tmp/public/ && cp -R public /tmp/public/oranda
+
+ - name: Check HTML for broken internal links
+ uses: untitaker/hyperlink@0.1.29
+ with:
+ args: /tmp/public/
+
+ # Deploy to our gh-pages branch (creating it if it doesn't exist)
+ # the "public" dir that oranda made above will become the root dir
+ # of this branch.
+ #
+ # Note that once the gh-pages branch exists, you must
+ # go into repo's settings > pages and set "deploy from branch: gh-pages"
+ # the other defaults work fine.
+ - name: Deploy to Github Pages
+ uses: JamesIves/github-pages-deploy-action@v4.4.1
+ # ONLY if we're on main (so no PRs or feature branches allowed!)
+ if: ${{ github.ref == 'refs/heads/main' }}
+ with:
+ repository-name: "kitsune-soc/kitsune-soc.github.io"
+ branch: gh-pages
+ # Gotta tell the action where to find oranda's output
+ folder: public
+ token: ${{ secrets.GITHUB_TOKEN }}
+ single-commit: true
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 3c983c153..53f1832c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,7 @@
+# Documentation builds
+/dist
+/docs/book
+
# Rust target directories
target
target-analyzer
diff --git a/README.md b/README.md
index 29304f6c5..a3bcd42fd 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,11 @@
+
+
# kitsune
+
+
![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/kitsune-soc/kitsune/rust.yml?style=for-the-badge)
[![dependency status](https://deps.rs/repo/github/kitsune-soc/kitsune/status.svg?style=for-the-badge)](https://deps.rs/repo/github/kitsune-soc/kitsune)
diff --git a/docs/book.toml b/docs/book.toml
new file mode 100644
index 000000000..6afd543cd
--- /dev/null
+++ b/docs/book.toml
@@ -0,0 +1,6 @@
+[book]
+authors = ["aumetra"]
+language = "en"
+multilingual = false
+src = "src"
+title = "Kitsune documentation"
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
new file mode 100644
index 000000000..574b80c48
--- /dev/null
+++ b/docs/src/SUMMARY.md
@@ -0,0 +1,24 @@
+# Summary
+
+- [Introduction](./introduction.md)
+- [Running]()
+ - [Installation](./running/installation.md)
+ - [Basic configuration](./running/basic-configuration.md)
+- [Configuring]()
+ - [Cache](./configuring/cache.md)
+ - [Captcha](./configuring/captcha.md)
+ - [Clacks Overhead](./configuring/clacks-overhead.md)
+ - [Database](./configuring/database.md)
+ - [Emailing](./configuring/email.md)
+ - [Federation filter](./configuring/federation-filter.md)
+ - [Instance](./configuring/instance.md)
+ - [Job Scheduler](./configuring/job-scheduler.md)
+ - [Link embedding](./configuring/link-embedding.md)
+ - [Messaging](./configuring/messaging.md)
+ - [OIDC (OpenID Connect)](./configuring/oidc.md)
+ - [OpenTelemetry](./configuring/opentelemetry.md)
+ - [Search](./configuring/search.md)
+ - [Storage](./configuring/storage.md)
+- [Specification]()
+ - [HTTP signatures](./spec/http-signatures.md)
+ - [Webfinger](./spec/webfinger.md)
diff --git a/docs/src/configuring/cache.md b/docs/src/configuring/cache.md
new file mode 100644
index 000000000..b96989d05
--- /dev/null
+++ b/docs/src/configuring/cache.md
@@ -0,0 +1,34 @@
+# Cache
+
+Computing things from scratch can be pretty expensive, that's where caching comes in.
+To best fit for your specific setup, Kitsune has multiple caching backends:
+
+## No Cache
+
+```toml
+[cache]
+type = "none"
+```
+
+This is the simplest of all caching modes. It just doesn't cache anything at all and utilises Kitsune's no-op cache.
+Pretty much only desirable if you are debugging other caches for invalidation issues (or if you have *heavy* memory constraints and no way to get your hands on a Redis instance).
+
+## In-Memory Cache
+
+```toml
+[cache]
+type = "in-memory"
+```
+
+This tells Kitsune to cache data directly into its memory. The cache is bounded so it doesn't make you run out of memory.
+
+## Redis Cache
+
+```toml
+[cache]
+type = "redis"
+redis-url = "redis://[Your Redis instance]"
+```
+
+This tells Kitsune to cache data via expiring keys into the configured Redis instance.
+This is the optimal configuration for setups where you have multiple Kitsune nodes running at the same time.
diff --git a/docs/src/configuring/captcha.md b/docs/src/configuring/captcha.md
new file mode 100644
index 000000000..c36d8ef80
--- /dev/null
+++ b/docs/src/configuring/captcha.md
@@ -0,0 +1,35 @@
+# Captcha
+
+Kitsune offers the ability to require captchas on sign-up to protect your service against spam waves.
+
+We offer different implementations to fit your specific needs
+
+## hCaptcha
+
+The rather well-known [hCaptcha service](https://www.hcaptcha.com/) advertises itself as a more privacy-oriented alternative to Google's reCaptcha.
+
+To use it to protect your instance, add the following to your configuration:
+
+```toml
+[captcha]
+type = "hcaptcha"
+verify-url = "[Verify URL]"
+site-key = "[Your site key]"
+secret-key = "[Your secret key]"
+```
+
+## mCaptcha
+
+[mCaptcha](https://mcaptcha.org/) is a lesser known open-source self-hostable captcha service.
+Technically it isn't a "captcha" and more of a "proof-of-work verification system", but it should defend your service against large spam attacks.
+
+To use mCaptcha, add the following to your configuration:
+
+```toml
+[captcha]
+type = "mcaptcha"
+widget-link = "[Widget link]"
+site-key = "[Your site key]"
+secret-key = "[Your secret key]"
+verify-url = "[Verify URL]"
+```
diff --git a/docs/src/configuring/clacks-overhead.md b/docs/src/configuring/clacks-overhead.md
new file mode 100644
index 000000000..8373c35db
--- /dev/null
+++ b/docs/src/configuring/clacks-overhead.md
@@ -0,0 +1,24 @@
+# Clacks Overhead
+
+Clacks Overhead is a non-standard HTTP header used for as something like a silent memorial.
+The header is appended to each response via a middleware.
+
+The header looks something like this:
+
+```
+X-Clacks-Overhead: GNU [Name 1 here], [Name 2 here]
+```
+
+[More info about this header](https://xclacksoverhead.org/home/about)
+
+---
+
+The names for the header can be configured like so:
+
+```toml
+[server]
+clacks-overhead = [
+ "Natalie Nguyen",
+ "John \"Soap\" MacTavish"
+]
+```
\ No newline at end of file
diff --git a/docs/src/configuring/database.md b/docs/src/configuring/database.md
new file mode 100644
index 000000000..0cc439c20
--- /dev/null
+++ b/docs/src/configuring/database.md
@@ -0,0 +1,25 @@
+# Database
+
+Kitsune requires a PostgreSQL installation that it can connect to since we make usage of Postgres-specific features, such as their full-text search.
+
+You can find instructions on creating a database (along with password-protected user) [here](https://medium.com/coding-blocks/creating-user-database-and-adding-access-on-postgresql-8bfcd2f4a91e).
+
+> We supported SQLite in the past (before v0.0.1-pre.1), but the support has been dropped due to a high maintenance burden and rather little expected usage.
+
+## Database URL structure
+
+```
+postgres://[Username]:[Password]@[DBMS host]:[Port]/[Database name]
+```
+### Example URL
+
+```
+postgres://database-user:password-here@localhost:5432/db-name-here
+```
+
+## Maximum connections
+
+The `max-connections` setting defines how many connections the globally shared connection pool will open to the database server *at maximum*.
+What you should set this value to depends on many factors.
+
+> We currently do not report any pool metrics via the Prometheus endpoint. This might be added in the future.
diff --git a/docs/src/configuring/email.md b/docs/src/configuring/email.md
new file mode 100644
index 000000000..5a6b48efc
--- /dev/null
+++ b/docs/src/configuring/email.md
@@ -0,0 +1,49 @@
+# Emailing
+
+Configuring an Email server for Kitsune automatically enables account confirmation via Email.
+
+The mailer currently only supports SMTP, no provider-specific REST APIs.
+
+## Example
+
+```toml
+[email]
+from-address = "kitsunemailer@joinkitsune.org"
+host = "your.smtp.host"
+username = "admin"
+password = "password"
+starttls = false
+```
+
+There is also an option config you can place in front of "from_address" if your email service provider does not do TLS over 465 and instead uses 587 (STARTTLS).
+
+Here is an example configuration utilizing STARTTLS:
+
+```toml
+[email]
+from_address = "kitsunemailer@joinkitsune.org"
+host = "your.smtp-host.example"
+username = "admin"
+password = "password"
+starttls = true
+```
+
+## Parameters
+
+```starttls``` :
+
+By default Kitsune users the port 465 to send mail.
+
+Most service providers use this port, but some (for example Postmark) need to have their TLS usage bootstrapped via STARTTLS over port 587.
+
+```from-address``` :
+
+This is the address Kitsune puts into the `From` field of the Email
+
+```host``` :
+
+This is the domain that your SMTP server is reachable under.
+
+```username, password``` :
+
+The credentials to your SMTP server. Which values to put here vary from provider to provider.
diff --git a/docs/src/configuring/federation-filter.md b/docs/src/configuring/federation-filter.md
new file mode 100644
index 000000000..f3cd4524d
--- /dev/null
+++ b/docs/src/configuring/federation-filter.md
@@ -0,0 +1,33 @@
+# Federation filter
+
+Kitsune has a basic federation filter. It has two main modes of operation:
+
+- Allowlist-based
+- Denylist-based
+
+The domain list supports [globbing](https://en.wikipedia.org/wiki/Glob_(programming)), so can, among other things, define wildcard blocks.
+
+## Allowlist
+
+As the name might suggests, this mode allows instance administrators to define a set list of domains the server is allowed to interact with.
+Federation attempts from any other server are rejected.
+
+### Configuration example
+
+```toml
+[instance.federation-filter]
+type = "allow"
+domains = ["*.myfriends.com", "cool-instan.ce"]
+```
+
+## Denylist
+
+This is the opposite of the allowlist-based federation. In this mode, Kitsune generally accepts federation attempts from any instance *except* the ones defined in the domain list.
+
+### Configuration example
+
+```toml
+[instance.federation-filter]
+type = "deny"
+domains = ["*.badstuff.com", "mean-people.biz"]
+```
diff --git a/docs/src/configuring/instance.md b/docs/src/configuring/instance.md
new file mode 100644
index 000000000..4f2654bae
--- /dev/null
+++ b/docs/src/configuring/instance.md
@@ -0,0 +1,40 @@
+# Instance
+
+Kitsune has a number of configurations that change how your instance works.
+
+```toml
+[instance]
+name = "Kitsune"
+description = "https://www.youtube.com/watch?v=6lnnPnr_0SU"
+character-limit = 5000
+registrations-open = true
+```
+
+## `name`
+
+This changes the name of the instance displayed on the landing page and returned via instance metadata endpoints (such as Mastodon's `/api/v1/instance`).
+
+## `description`
+
+Similar to `name`, this setting adjusts the description on the landing page and the one returned via the metadata endpoints.
+
+> **Note**: This field is interpreted as raw HTML
+
+## `character-limit`
+
+This setting sets the character limit specific to your instance.
+
+## `registrations-open`
+
+Determines whether your instance accepts new users or not. When set to `false`, the registration APIs will return a failure code.
+
+## `webfinger-domain`
+
+This enables you to host your `.well-known/webfinger` resource on your main domain (i.e. `example.com`) and the web UI and inboxes on a subdomain (i.e. `kitsune.example.com`).
+The advantage of this configuration is that your handle can be `@me@example.com`, while the account is hosted on `fedi.example.com`.
+
+### Example value
+
+```toml
+webfinger-domain = "example.com"
+```
diff --git a/docs/src/configuring/job-scheduler.md b/docs/src/configuring/job-scheduler.md
new file mode 100644
index 000000000..c6877f1d9
--- /dev/null
+++ b/docs/src/configuring/job-scheduler.md
@@ -0,0 +1,25 @@
+# Job Scheduler
+
+Kitsune uses the database to store and retrieve jobs that have to be run.
+There are options to tune the job scheduler to your specific needs.
+
+```toml
+[job-queue]
+redis-url = "redis://localhost"
+num-workers = 20
+```
+
+## `redis-url`
+
+This option configures the Redis instance that the jobs are put on.
+
+We utilize Redis streams and transactional Lua scripting to ensure no jobs are lost even in the case of a crash.
+
+## `job-workers`
+
+This option configures how many jobs are run concurrently at the same time.
+
+Each job is a lightweight task inside Kitsune's async runtime, so you can raise this well above what you'd raise a thread limit to.
+
+> **Caution**: Each activity delivery is a job, and each of the delivery jobs run multiple connections concurrently.
+> Raising this job worker limit too high without also increasing the maximum file descriptors might lead to weird issues.
diff --git a/docs/src/configuring/link-embedding.md b/docs/src/configuring/link-embedding.md
new file mode 100644
index 000000000..e6e46e4d4
--- /dev/null
+++ b/docs/src/configuring/link-embedding.md
@@ -0,0 +1,11 @@
+# Link embedding
+
+Kitsune has the ability to show link previews as so-called "embed cards".
+We use [Lantern Chat's `embed-service`](https://github.com/Lantern-chat/embed-service/) to provide this functionality.
+
+To use it with Kitsune, run the `embed-service` and add the following configuration to Kitsune's configuration file:
+
+```toml
+[embed]
+service-url = "[URL to the embed service]"
+```
diff --git a/docs/src/configuring/messaging.md b/docs/src/configuring/messaging.md
new file mode 100644
index 000000000..4686886df
--- /dev/null
+++ b/docs/src/configuring/messaging.md
@@ -0,0 +1,26 @@
+# Messaging
+
+Kitsune uses messaging services to exchange events for cache invalidation, notification delivery, etc.
+To offer flexibility and to make self-hosting as easy as possible, we have multiple such backends.
+
+## Redis backend
+
+This is backend you should choose when running multiple nodes in parallel. This then uses Redis' PubSub feature to exchange messages.
+
+### Configuration example
+
+```toml
+[messaging]
+type = "redis"
+redis-url = "redis://localhost:6379"
+```
+
+## In-process
+
+This backend is optimal for small self-contained installations. It uses Tokio's broadcast channel internally.
+
+### Configuration example
+
+```toml
+[messaging]
+type = "in-process"
diff --git a/docs/src/configuring/oidc.md b/docs/src/configuring/oidc.md
new file mode 100644
index 000000000..a136fd959
--- /dev/null
+++ b/docs/src/configuring/oidc.md
@@ -0,0 +1,50 @@
+# OIDC (OpenID Connect)
+
+> This feature is gated behind the `oidc` compile-time feature
+
+OpenID Connect (OIDC) is a technology to provide Single Sign-On (SSO) that it shared across multiple services.
+This is useful if you, for example, want to run Kitsune together with a bunch of other services and don't want to maintain multiple logins.
+
+In order to enable OIDC for your Kitsune instance, find the `oidc` parameter inside the `server` configuration section.
+Set this parameter to the following value:
+
+```toml
+[server.oidc]
+server-url = "[Issuer URL]"
+client-id = "[Kitsune's Client ID]"
+client-secret = "[Kitsune's Client Secret]"
+
+[server.oidc.store]
+type = "in-memory" # "in-memory" or "redis"
+#url = "redis://localhost" # If the configured type is "redis"
+```
+
+## Server URL
+
+This is the URL of the issuer; this setting differs between OIDC solutions. Don't worry, Kitsune won't start up if this value is invalid.
+
+## Client ID and Secret
+
+These values are created on the dashboard of the OIDC solution you are using.
+Kitsune needs these to obtain an access token from the OIDC server to do introspection and obtain some information about the user.
+
+## Store
+
+The store is where the login state is stored in temporarily until the sign-in has completed.
+
+### Supported backends
+
+- `in-memory`: The state is stored in an in-memory LRU structure
+- `redis`: The state is stored in a Redis instance
+
+If you run multiple nodes, you should use Redis. Otherwise sign-ins can randomly fail.
+
+## Kitsune-specific OIDC requirements
+
+The OIDC server **must** return the following values in the claim:
+
+- `preferred_username`
+- `email`
+
+> Keep the preferred username field unique. The username is used to identify the user inside Kitsune's database that's getting registered.
+> This might change in the future.
diff --git a/docs/src/configuring/opentelemetry.md b/docs/src/configuring/opentelemetry.md
new file mode 100644
index 000000000..1111eec36
--- /dev/null
+++ b/docs/src/configuring/opentelemetry.md
@@ -0,0 +1,15 @@
+# OpenTelemetry
+
+Kitsune can export its traces and metrics via the OpenTelemetry Protocol (or OTLP, for short).
+
+To push the data to an endpoint, add the following to your configuration:
+
+```toml
+[opentelemetry]
+# Where Kitsune pushes metrics (eg. Prometheus)
+metrics-transport = "http" # "http" or "grpc"
+metrics-endpoint = "https://localhost:5050/metrics-endpoint"
+# Where Kitsune pushes traces (eg. Jaeger)
+tracing-transport = "http" # "http" or "grpc"
+tracing-endpoint = "https://localhost:5050/tracing-endpoint"
+```
diff --git a/docs/src/configuring/search.md b/docs/src/configuring/search.md
new file mode 100644
index 000000000..58dd16e23
--- /dev/null
+++ b/docs/src/configuring/search.md
@@ -0,0 +1,36 @@
+# Search
+
+Kitsune has a number of search backends, each different from the other, to best fit your specific needs.
+We want to give you a brief overview over the available backends.
+
+## No Search
+
+```toml
+[search]
+type = "none"
+```
+
+This completely disables the search on your instance. Finding posts and accounts is now only possible via direct links and handles.
+
+## SQL-based Search
+
+```toml
+[search]
+type = "sql"
+```
+
+This runs searches on your database directly. The quality is actually not too bad and uses automatic language detection to make full-text searches relevant.
+
+## Meilisearch
+
+> You need to compile Kitsune with the `meilisearch` feature flag to enable this feature
+
+```toml
+[search]
+type = "meilisearch"
+instance-url = "[URL of your Meilisearch instance]"
+api-key = "[API key to access your Meilisearch instance]"
+```
+
+This instructs Kitsune to use [Meilisearch](https://www.meilisearch.com/) as the search engine. Meilisearch provides incredibly fast, high-quality full-text search.
+Meilisearch also has a cloud offering, making this the easiest high-quality search to use with Kitsune.
diff --git a/docs/src/configuring/storage.md b/docs/src/configuring/storage.md
new file mode 100644
index 000000000..3f13d1f0c
--- /dev/null
+++ b/docs/src/configuring/storage.md
@@ -0,0 +1,71 @@
+# Storage
+
+As a microblogging platform, Kitsune also offers users the ability to attach images, videos, and audio to their posts.
+We offer multiple different storage backends to store the attachments to.
+
+> **Note**: You might want to increase the upload limit by tweaking the `max-upload-size` parameter in your configuration; the number is the upload limit in bytes.
+> The default set by the example configuration is 5MiB.
+
+## File System
+
+This is recommended for small instances.
+Kitsune simply stores the media inside a user-defined directory on the local file system.
+
+In order to enable this, add this to your configuration:
+
+```toml
+[storage]
+type = "fs"
+upload-dir = "path/to/upload/directory"
+```
+
+This will then place all the uploads into the specified directory.
+
+## S3-compatible storage
+
+When your user count increases (or your requirements change), you might want to consider using an S3-compatible storage solution to store all your media attachments.
+
+In order to make this happen, add this to your configuration:
+
+```toml
+[storage]
+type = "s3"
+bucket-name = "[Name of your bucket]"
+endpoint-url = "[Name of the endpoint]"
+region = "[Region of your S3 storage]"
+force-path-style = false
+access-key = "[Access key]"
+secret-access-key = "[Secret access key]"
+```
+
+### Bucket Name
+
+This setting is pretty self-explanatory. It's the name of the bucket you created and want your attachments to be put in.
+
+### Endpoint URL
+
+The URL of the S3 endpoint. You can either get this from your storage provider's dashboard or documentation; really depends on the provider.
+
+### Region
+
+The S3 region in which you created the bucket. The value of this might be different from provider to provider.
+
+### Force Path Style
+
+Some S3 storage providers don't support the virtual-hosted request style. If your provider is one of those, set this setting to `true` to instruct Kitsune to use the legacy path style.
+
+### (Secret) Access Key
+
+These keys are given to you when creating your bucket. Make sure you keep these private!
+
+### Notes on "get_object" requests
+
+Currently Kitsune proxies all the S3 accesses, meaning each media access results in a "get object" request.
+For example, Cloudflare R2 has a "no egress fee policy" which, due to this implementation detail, doesn't apply to Kitsune.
+
+> This is not final, we might change how S3 uploads are handled
+
+### Migrating from file-system storage to S3
+
+The migration is pretty simple. Upload all the files from your upload directory into the S3 bucket (while preserving the same file hirearchy) and change the configuration.
+Kitsune should then serve the files without any problems.
diff --git a/docs/src/introduction.md b/docs/src/introduction.md
new file mode 100644
index 000000000..42e558112
--- /dev/null
+++ b/docs/src/introduction.md
@@ -0,0 +1,17 @@
+# Introduction
+
+Kitsune is a decentralised microblogging platform built on the ActivityPub protocol.
+This means that anyone can run their own Kitsune on their own hardware and seamlessly interact with each other.
+
+Of course you can also sign up on an existing instance to try it out, no strings attached.
+If you are interested in running your own instance, head over to our installation guide.
+
+## Chat
+
+Feel free to join our chat if you have any problems or if you want to contribute.
+We have channels on Matrix and Discord which are bridged with each other, so join whichever you are more comfortable with.
+
+[![Matrix](https://img.shields.io/matrix/kitsune-space:matrix.org?label=Matrix%20chat&style=for-the-badge)](https://matrix.to/#/#kitsune-space:matrix.org)
+[![Discord](https://img.shields.io/discord/1118538521423138856?label=Discord%20chat&style=for-the-badge)](https://discord.gg/YGAtX7nfrG)
+
+(The side-panel links to the Matrix room since Matrix is the more open and privacy-respecting solution out of the both)
diff --git a/docs/src/running/basic-configuration.md b/docs/src/running/basic-configuration.md
new file mode 100644
index 000000000..b89966a02
--- /dev/null
+++ b/docs/src/running/basic-configuration.md
@@ -0,0 +1,80 @@
+# Basic configuration
+
+Kitsune is using the [TOML configuration format](https://toml.io) to configure the main application and the job runner.
+The syntax itself is easy to grasp and is essentially and extended INI format.
+
+> The auxiliary services/CLI tools are using environment variables at the moment.
+> Note that this might change in the future.
+
+> Example configurations for external programs can be found in `kitsune/contrib`.
+
+> The example config for Kitsune can be found in the root directory titled "config.example.toml", move it wherever you like, and feel free to rename it.
+
+The simplest Kitsune configuration looks like this:
+
+```toml
+[cache]
+type = "in-memory"
+
+[database]
+url = "postgres://localhost/kitsune"
+max-connections = 20
+
+[instance]
+name = "Kitsune"
+description = "https://www.youtube.com/watch?v=6lnnPnr_0SU"
+character-limit = 5000
+registrations-open = true
+
+[instance.federation-filter]
+type = "deny"
+domains = []
+
+[job-queue]
+redis-url = "redis://localhost"
+num-workers = 20
+
+[messaging]
+type = "in-process"
+
+[server]
+frontend-dir = "./kitsune-fe/dist"
+max-upload-size = 20242880 # 5MB
+media-proxy-enabled = false
+port = 5000
+request-timeout-secs = 60
+
+[search]
+type = "sql"
+
+[storage]
+type = "fs"
+upload-dir = "./uploads"
+
+[url]
+scheme = "https"
+domain = "kitsune.example.com"
+```
+
+To successfully deploy the application, make sure you **at least** change the following sections to your own:
+
+- `domain`
+
+ - Domain of your instance. Used to build the URLs of your activities.
+ - This is a *very important* setting and **cannot** be changed after the first setup.
+
+- `database`
+
+ - Specifically the `url` parameter. Refer to [database section](../configuring/database) page for the expected format.
+
+- `job-queue`
+
+ - Specifically the `redis-url` parameter. Refer to the [job scheduler](../configuring/job-scheduler) page for the expected format.
+
+To run the application use the following command:
+
+```bash
+./kitsune -c [path-to-config-file]
+```
+
+In order to read up on all the possible configurations, check out the "Configuration" section.
diff --git a/docs/src/running/installation.md b/docs/src/running/installation.md
new file mode 100644
index 000000000..51006a0f1
--- /dev/null
+++ b/docs/src/running/installation.md
@@ -0,0 +1,65 @@
+# Installation
+
+At the moment, the only way to install Kitsune is to compile it from source.
+Don't worry, that sounds way more scary than it actually is. In this guide we will step you through it.
+
+## Dependencies
+
+In order to build Kitsune, need a few dependencies. These are:
+
+1. The Rust toolchain ([recommended installation](https://rustup.rs/))
+2. PostgreSQL as a dedicated DBMS
+3. Redis for the job queue
+4. [NodeJS](https://nodejs.org/en) v16+
+5. [Yarn](https://classic.yarnpkg.com/en/docs/install)
+6. Reverse Proxy (recommended: [Caddy](https://caddyserver.com/docs/install))
+
+Yes, that's really it. We don't need more. Kitsune is designed to use as few native dependencies as possible to make building from source easy!
+
+### Note on C/C++ compiler requirement
+
+Rust needs a C/C++ compiler to invoke the linker and potentially build some native libraries to statically link to, so make sure you have one installed.
+
+To install it under Debian and Ubuntu, run the following command:
+
+```bash
+sudo apt install build-essential
+```
+
+The name of the package(s) containing these tools might differ between distributions.
+
+## Building
+
+First, grab yourself a copy of the source code. You can either download the [main branch ZIP archive](https://github.com/kitsune-soc/kitsune/archive/refs/heads/main.zip) or clone it via Git. Both ways will work just fine.
+
+> The recommended way to download the source is via Git since it makes updating and doing a rollback way easier.
+
+To download a Git repository, just run the following command (this assumes you have [Git](https://git-scm.com/) installed):
+
+```bash
+git clone https://github.com/kitsune-soc/kitsune.git
+```
+
+> If you downloaded the ZIP, just unzip the archive
+
+Next, move into the newly created directory and then into the `kitsune-fe` directory and build the frontend.
+To do this run:
+
+```bash
+yarn install && yarn build
+```
+
+Now move out of the directory and back into the main one. Then build the binaries in release mode.
+To do this run the following command:
+
+```bash
+cargo build --release
+```
+
+After the command finished there should be the following three binaries inside the `target/release` directory:
+
+- `kitsune`: The main Kitsune application. This is the heart of the whole application.
+- `kitsune-cli`: The Kitsune CLI utility. Used to give users roles and clear the job scheduler table.
+- `kitsune-job-runner`: The dedicated Kitsune job runner
+
+That's it for the building part but before we can actually run our instance, we need to configure it first.
diff --git a/docs/src/spec/http-signatures.md b/docs/src/spec/http-signatures.md
new file mode 100644
index 000000000..9d2e94488
--- /dev/null
+++ b/docs/src/spec/http-signatures.md
@@ -0,0 +1,19 @@
+# HTTP signatures
+
+HTTP signatures are used by Kitsune to validate that the Activity/Object actually originates from the user it claims to.
+We implement a subset of [`draft-cavage-http-signatures-12`](https://datatracker.ietf.org/doc/html/draft-cavage-http-signatures-12) to do this.
+
+Only asymmetric cryptographic algorithms are implemented since the symmetric ones:
+
+1. Could lead to potential key-confusion attacks
+2. Aren't useful in the context of ActivityPub
+
+We make use of the `keyId` field by looking up the public key material via this ID. The ID is sourced from the ActivityPub actor.
+The signature scheme used is inferred by the OID embedded in the public key material. The material is expected to be an X.509 SPKI structure.
+
+At the moment, Kitsune uses RSA keys but has support for implementations that use Ed25519 for signatures.
+
+> We use RSA because Mastodon doesn't support anything else. So if you want compatibility with Mastodon, you have to use RSA.
+> As soon as a mainline Mastodon release gets support for Ed25519 signatures, we will release an update that allows to rekey all the users.
+
+But if you are happy to just federate with Kitsune users, you can use Ed25519!
diff --git a/docs/src/spec/webfinger.md b/docs/src/spec/webfinger.md
new file mode 100644
index 000000000..4bcb1890b
--- /dev/null
+++ b/docs/src/spec/webfinger.md
@@ -0,0 +1,21 @@
+# Webfinger
+
+Kitsune uses Webfinger for resolving mentions and such. For example, when mentioning a user in a post in the form `@user@instance.org`, the mention is interpreted as a Webfinger `acct` query.
+We then connect to the remote server and send an HTTP GET request on the path `/.well-known/webfinger` with the query parameter `resource` set to `acct:user@instance.org`.
+
+The server is then expected to return a Webfinger resource containing a link with the `rel` property set to `self` and the `href` attribute pointing to the ActivityPub actor.
+
+Example Webfinger resource:
+
+```json
+{
+ "subject": "acct:user@instance.org",
+ "aliases": [],
+ "links": [
+ {
+ "rel": "self",
+ "href": "https://instance.org/users/user"
+ }
+ ]
+}
+```
diff --git a/oranda.json b/oranda.json
new file mode 100644
index 000000000..276d59b2b
--- /dev/null
+++ b/oranda.json
@@ -0,0 +1,21 @@
+{
+ "build": {
+ "dist_dir": "dist"
+ },
+ "components": {
+ "artifacts": {
+ "cargo_dist": true
+ },
+ "changelog": {
+ "read_changelog_file": false
+ }
+ },
+ "project": {
+ "name": "Kitsune",
+ "license": "MIT",
+ "repository": "https://github.com/kitsune-soc/kitsune"
+ },
+ "styles": {
+ "theme": "hacker"
+ }
+}
\ No newline at end of file