Powerful, configurable and modular federated server using the Versia Protocol
Find a file
2023-11-28 12:07:26 -10:00
.github Fix failing builds 2023-11-28 11:39:30 -10:00
benchmarks Fix ESLint errors 2023-11-19 16:25:41 -10:00
classes Enable verbatim module syntax + more API routes 2023-11-22 18:10:37 -10:00
config Add working Dockerfile 2023-11-26 19:30:57 -10:00
database Fix Redis connection 2023-11-26 19:53:13 -10:00
pages Rename project to Lysand 2023-09-14 19:08:59 -10:00
plugins Enable verbatim module syntax + more API routes 2023-11-22 18:10:37 -10:00
prisma Work on federation 2023-11-26 15:40:44 -10:00
server/api Add favourites endpoint 2023-11-26 15:01:07 -10:00
tests Add status pinning and unpinning, fix bugs 2023-11-26 14:56:16 -10:00
types Enable verbatim module syntax + more API routes 2023-11-22 18:10:37 -10:00
utils Add working Dockerfile 2023-11-26 19:30:57 -10:00
.dockerignore Add working Dockerfile 2023-11-26 19:30:57 -10:00
.eslintrc.cjs Enable verbatim module syntax + more API routes 2023-11-22 18:10:37 -10:00
.gitignore Add more cases for media backend 2023-10-17 14:57:47 -10:00
.prettierrc Add stricter ESLint rules 2023-09-12 14:29:13 -10:00
bun.lockb Update packages 2023-11-28 12:04:18 -10:00
cli.ts Fix user creation message formatting 2023-11-20 14:02:20 -10:00
CODE_OF_CONDUCT.md Add more contribution help 2023-10-22 14:23:15 -10:00
CONTRIBUTING.md Clarify Copilot usage for writing tests 2023-11-23 09:19:55 -10:00
docker-compose.yml Add more instructions for running in Docker 2023-11-27 15:42:52 -10:00
Dockerfile Fix Dockerfile 2023-11-27 15:47:39 -10:00
index.ts Fix SIGSEGV bug!! 2023-11-26 11:54:20 -10:00
LICENSE Add better README 2023-09-14 15:42:56 -10:00
package.json Update packages 2023-11-28 12:04:18 -10:00
Postgres.Dockerfile Add media upload functionality and create uploads 2023-11-19 10:36:54 -10:00
prisma.ts Add prisma script to remove env files 2023-11-28 11:14:31 -10:00
README.md Add prisma script to remove env files 2023-11-28 11:14:31 -10:00
SECURITY.md Add security policy 2023-11-19 16:34:59 -10:00
tsconfig.json Enable verbatim module syntax + more API routes 2023-11-22 18:10:37 -10:00
uno.config.ts guh 2023-09-14 15:22:27 -10:00

Lysand Logo

Postgres Bun VS Code Insiders TypeScript Linux Docker ESLint Contributor Covenant

What is this?

This is a project to create a federated social network based on the Lysand protocol. It is currently in alpha phase, with basic federation and API support.

This project aims to be a fully featured social network, with a focus on privacy and security. It will implement the Mastodon API for support with clients that already support Mastodon or Pleroma.

Note: This project is not affiliated with Mastodon or Pleroma, and is not a fork of either project. It is a new project built from the ground up.

Features

  • Inbound federation
  • S3 or local media storage
  • Deduplication of uploaded files
  • Federation limits
  • Configurable defaults
  • Full regex-based filters for posts, users and media
  • Custom emoji support
  • Automatic image conversion to WebP or other formats
  • Moderation tools
  • Full Mastodon API support
  • Outbound federation

How do I run it?

Requirements

  • The Bun Runtime, version 1.0.5 or later (usage of the latest version is recommended)
  • A PostgreSQL database
  • (Optional but recommended) A Linux-based operating system

Note

: We will not be offerring support to Windows or MacOS users. If you are using one of these operating systems, please use a virtual machine or container to run Lysand.

Installation

  1. Clone this repository
git clone https://github.com/lysand-org/lysand.git
  1. Install the dependencies
bun install
  1. Set up a PostgreSQL database, using the pg_uuidv7 extension

You may use the following Dockerfile to set it up:

# Use the latest Postgres Docker image based on Alpine
FROM postgres:alpine

# Set working directory
WORKDIR /usr/src/app

# Install curl
RUN apk add --no-cache curl

RUN cd "$(mktemp -d)" \
        && curl -LO "https://github.com/fboulnois/pg_uuidv7/releases/download/v1.3.0/{pg_uuidv7.tar.gz,SHA256SUMS}" \
        && tar xf pg_uuidv7.tar.gz \
        && sha256sum -c SHA256SUMS \
        && PG_MAJOR=$(pg_config --version | sed 's/^.* \([0-9]\{1,\}\).*$/\1/') \
        && cp "$PG_MAJOR/pg_uuidv7.so" "$(pg_config --pkglibdir)" \
        && cp sql/pg_uuidv7--1.3.sql pg_uuidv7.control "$(pg_config --sharedir)/extension"
# Add a script to run the CREATE EXTENSION command
RUN echo '#!/bin/sh\npsql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE EXTENSION pg_uuidv7;"' > /docker-entrypoint-initdb.d/init.sh

# Make the entrypoint script executable
RUN chmod +x /docker-entrypoint-initdb.d/init.sh
  1. Copy the config.toml.example file to config.toml and fill in the values (you can leave most things to the default, but you will need to configure things such as the database connection)

  2. Run migrations:

bun migrate

Running

To run the server, simply run the following command:

bun start

Using the CLI

Lysand includes a built-in CLI for managing the server. To use it, simply run the following command:

bun cli

You can use the help command to see a list of available commands. These include creating users, deleting users and more.

Using Database Commands

The bun prisma commands allows you to use Prisma commands without needing to add in environment variables for the database config. Just run Prisma commands as you would normally, replacing bunx prisma with bun prisma.

With Docker

Note

: Docker is currently broken, as Bun with Prisma does not work well with Docker yet for unknown reasons. The following instructions are for when this is fixed.

These instructions will probably also work with Podman and other container runtimes.

You can also run Lysand using Docker. To do so, you can:

  1. Acquire the Postgres Dockerfile from above
  2. Use this repository's docker-compose.yml file
  3. Create the lysand-net docker network:
docker network create lysand-net
  1. Fill in the config file (see Installation)
  2. Run the following command:
docker-compose up -d

You may need root privileges to run Docker commands.

Running CLI commands inside Docker

You can run CLI commands inside Docker using the following command:

sudo docker exec -it lysand bun cli ...

Running migrations inside Docker

You can run migrations inside Docker using the following command (if needed):

sudo docker exec -it lysand bun migrate

Contributing

Contributions are welcome! Please see the CONTRIBUTING.md file for more information.

Planned Extra Features

  • Send notifications to moderators when a report is received
  • Email notifications on certain actions

Federation

Warning

: Federation has not been tested outside of automated tests. It is not recommended to use this software in production.

The following extensions are currently supported or being worked on:

  • org.lysand:custom_emojis: Custom emojis

API

Lysand implements the Mastodon API, with some extensions. The API is currently in early alpha, and is not recommended for use in production.

Working endpoints are:

  • /api/v1/accounts
  • /api/v1/accounts/:id
  • /api/v1/accounts/:id/statuses
  • /api/v1/accounts/:id/follow
  • /api/v1/accounts/:id/unfollow
  • /api/v1/accounts/:id/block
  • /api/v1/accounts/:id/unblock
  • /api/v1/accounts/:id/mute
  • /api/v1/accounts/:id/unmute
  • /api/v1/accounts/:id/pin
  • /api/v1/accounts/:id/unpin
  • /api/v1/accounts/:id/note
  • /api/v1/accounts/:id/remove_from_followers
  • /api/v1/accounts/relationships
  • /api/v1/accounts/update_credentials
  • /api/v1/accounts/verify_credentials
  • /api/v1/accounts/familiar_followers
  • /api/v1/profile/avatar (DELETE)
  • /api/v1/profile/header (DELETE)
  • /api/v1/statuses/:id (GET, DELETE)
  • /api/v1/statuses/:id/context
  • /api/v1/statuses/:id/favourite
  • /api/v1/statuses/:id/unfavourite
  • /api/v1/statuses/:id/favourited_by
  • /api/v1/statuses/:id/reblogged_by
  • /api/v1/statuses/:id/reblog
  • /api/v1/statuses/:id/unreblog
  • /api/v1/statuses/:id/pin
  • /api/v1/statuses/:id/unpin
  • /api/v1/statuses
  • /api/v1/timelines/public
  • /api/v1/timelines/home
  • /api/v1/apps
  • /api/v1/instance
  • /api/v1/custom_emojis
  • /api/v1/apps/verify_credentials
  • /oauth/authorize
  • /oauth/token
  • /api/v1/blocks
  • /api/v1/mutes
  • /api/v2/media

Tests needed but completed:

  • /api/v1/media/:id
  • /api/v1/favourites

Endpoints left:

  • /api/v1/reports
  • /api/v1/accounts/:id/lists
  • /api/v1/accounts/:id/following
  • /api/v1/follow_requests
  • /api/v1/follow_requests/:account_id/authorize
  • /api/v1/follow_requests/:account_id/reject
  • /api/v1/follow_suggestions
  • /api/v1/domain_blocks (GET, POST, DELETE)
  • /api/v2/filters (GET, POST)
  • /api/v2/filters/:id (GET, PUT, DELETE)
  • /api/v2/filters/:filter_id/keywords (GET, POST)
  • /api/v2/filters/keywords/:id (GET, PUT, DELETE)
  • /api/v2/filters/:filter_id/statuses (GET, POST)
  • /api/v2/filters/statuses/:id (GET, DELETE)
  • /api/v1/endorsements
  • /api/v1/featured_tags (GET, POST)
  • /api/v1/featured_tags/:id (DELETE)
  • /api/v1/featured_tags/suggestions
  • /api/v1/preferences
  • /api/v1/followed_tags
  • /api/v2/suggestions
  • /api/v1/suggestions/:account_id (DELETE)
  • /api/v1/tags/:id
  • /api/v1/tags/:id/follow
  • /api/v1/tags/:id/unfollow
  • /api/v1/statuses/:id/translate
  • /api/v1/statuses/:id/bookmark
  • /api/v1/statuses/:id/unbookmark
  • /api/v1/statuses/:id/mute
  • /api/v1/statuses/:id/unmute
  • /api/v1/statuses/:id (PUT)
  • /api/v1/statuses/:id/history
  • /api/v1/statuses/:id/source
  • /api/v1/polls/:id
  • /api/v1/polls/:id/votes
  • /api/v1/scheduled_statuses
  • /api/v1/scheduled_statuses/:id (GET, PUT, DELETE)
  • /api/v1/timelines/tag/:hashtag
  • /api/v1/timelines/list/:list_id
  • /api/v1/conversations
  • /api/v1/conversations/:id
  • /api/v1/conversations/:id/read
  • /api/v1/lists (GET, POST)
  • /api/v1/lists/:id (GET, PUT, DELETE)
  • /api/v1/markers (GET, POST)
  • /api/v1/lists/:id/accounts (GET, POST, DELETE)
  • /api/v1/notifications
  • /api/v1/notifications/:id
  • /api/v1/notifications/clear
  • /api/v1/notifications/:id/dismiss
  • /api/v2/search
  • /api/v2/instance
  • /api/v1/instance/peers
  • /api/v1/instance/activity
  • /api/v1/instance/rules
  • /api/v1/instance/domain_blocks
  • /api/v1/instance/extended_description
  • /api/v1/directory
  • /api/v1/trends/tags
  • /api/v1/trends/statuses
  • /api/v1/trends/links
  • /api/v1/announcements
  • /api/v1/announcements/:id/dismiss
  • /api/v1/announcements/:id/reactions/:name (PUT, DELETE)
  • Admin API

WebSocket Streaming API also needed to be added (and push notifications)

Configuration Values

Configuration can be found inside the config.toml file. The following values are available:

Database

  • host: The hostname or IP address of the database server. Example: "localhost"
  • port: The port number to use for the database connection. Example: 48654
  • username: The username to use for the database connection. Example: "lysand"
  • password: The password to use for the database connection. Example: "mycoolpassword"
  • database: The name of the database to use. Example: "lysand"

HTTP

  • base_url: The base URL for the HTTP server. Example: "https://lysand.social"
  • bind: The hostname or IP address to bind the HTTP server to. Example: "http://localhost"
  • bind_port: The port number to bind the HTTP server to. Example: "8080"

Security

  • banned_ips: An array of strings representing banned IPv4 or IPv6 IPs. Wildcards, networks and ranges are supported. Example: [ "192.168.0.*" ] (empty array)

Media

  • backend: Specifies the backend to use for media storage. Can be "local" or "s3", "local" uploads the file to the local filesystem.
  • deduplicate_media: When set to true, the hash of media is checked when uploading to avoid duplication.

Conversion

  • convert_images: Whether to convert uploaded images to another format. Example: true
  • convert_to: The format to convert uploaded images to. Example: "webp". Can be "jxl", "webp", "avif", "png", "jpg" or "gif".

S3

  • endpoint: The endpoint to use for the S3 server. Example: "https://s3.example.com"
  • access_key: Access key to use for S3
  • secret_access_key: Secret access key to use for S3
  • bucket_name: The bucket to use for S3 (can be left empty)
  • region: The region to use for S3 (can be left empty)
  • public_url: The public URL to access uploaded media. Example: "https://cdn.example.com"

SMTP

  • server: The SMTP server to use for sending emails. Example: "smtp.example.com"
  • port: The port number to use for the SMTP server. Example: 465
  • username: The username to use for the SMTP server. Example: "test@example.com"
  • password: The password to use for the SMTP server. Example: "password123"
  • tls: Whether to use TLS for the SMTP server. Example: true

Email

  • send_on_report: Whether to send an email to moderators when a report is received. Example: false
  • send_on_suspend: Whether to send an email to moderators when a user is suspended. Example: true
  • send_on_unsuspend: Whether to send an email to moderators when a user is unsuspended. Example: false

Validation

  • max_displayname_size: The maximum size of a user's display name, in characters. Example: 30
  • max_bio_size: The maximum size of a user's bio, in characters. Example: 160
  • max_note_size: The maximum size of a user's note, in characters. Example: 500
  • max_avatar_size: The maximum size of a user's avatar image, in bytes. Example: 1048576 (1 MB)
  • max_header_size: The maximum size of a user's header image, in bytes. Example: 2097152 (2 MB)
  • max_media_size: The maximum size of a media attachment, in bytes. Example: 5242880 (5 MB)
  • max_media_attachments: The maximum number of media attachments allowed per post. Example: 4
  • max_media_description_size: The maximum size of a media attachment's description, in characters. Example: 100
  • max_username_size: The maximum size of a user's username, in characters. Example: 20
  • username_blacklist: An array of strings representing usernames that are not allowed to be used by users. Defaults are from Akkoma. Example: ["admin", "moderator"]
  • blacklist_tempmail: Whether to blacklist known temporary email providers. Example: true
  • email_blacklist: Additional email providers to blacklist. Example: ["example.com", "test.com"]
  • url_scheme_whitelist: An array of strings representing valid URL schemes. URLs that do not use one of these schemes will be parsed as text. Example: ["http", "https"]
  • allowed_mime_types: An array of strings representing allowed MIME types for media attachments. Example: ["image/jpeg", "image/png", "video/mp4"]

Defaults

  • visibility: The default visibility for new notes. Example: "public"
  • language: The default language for new notes. Example: "en"
  • avatar: The default avatar URL. Example: "" (empty string)
  • header: The default header URL. Example: "" (empty string)

ActivityPub

Note

: These options do nothing and date back to when Lysand had ActivityPub support. They will be removed in a future version.

  • use_tombstones: Whether to use ActivityPub Tombstones instead of deleting objects. Example: true
  • fetch_all_collection_members: Whether to fetch all members of collections (followers, following, etc) when receiving them. Example: false
  • reject_activities: An array of instance domain names without "https" or glob patterns. Rejects all activities from these instances, simply doesn't save them at all. Example: [ "mastodon.social" ]
  • force_followers_only: An array of instance domain names without "https" or glob patterns. Force posts from this instance to be followers only. Example: [ "mastodon.social" ]
  • discard_reports: An array of instance domain names without "https" or glob patterns. Discard all reports from these instances. Example: [ "mastodon.social" ]
  • discard_deletes: An array of instance domain names without "https" or glob patterns. Discard all deletes from these instances. Example: [ "mastodon.social" ]
  • discard_updates: An array of instance domain names without "https" or glob patterns. Discard all updates (edits) from these instances. Example: []
  • discard_banners: An array of instance domain names without "https" or glob patterns. Discard all banners from these instances. Example: [ "mastodon.social" ]
  • discard_avatars: An array of instance domain names without "https" or glob patterns. Discard all avatars from these instances. Example: [ "mastodon.social" ]
  • discard_follows: An array of instance domain names without "https" or glob patterns. Discard all follow requests from these instances. Example: []
  • force_sensitive: An array of instance domain names without "https" or glob patterns. Force set these instances' media as sensitive. Example: [ "mastodon.social" ]
  • remove_media: An array of instance domain names without "https" or glob patterns. Remove these instances' media. Example: [ "mastodon.social" ]

Filters

  • note_filters: An array of regex filters to drop notes from new activities. Example: ["(https?://)?(www\\.)?youtube\\.com/watch\\?v=[a-zA-Z0-9_-]+", "(https?://)?(www\\.)?youtu\\.be/[a-zA-Z0-9_-]+"]
  • username_filters: An array of regex filters to drop users from new activities based on their username. Example: [ "^spammer-[a-z]" ]
  • displayname_filters: An array of regex filters to drop users from new activities based on their display name. Example: [ "^spammer-[a-z]" ]
  • bio_filters: An array of regex filters to drop users from new activities based on their bio. Example: [ "badword" ]
  • emoji_filters: An array of regex filters to drop users from new activities based on their emoji usage. Example: [ ":bademoji:" ]

Logging

  • log_requests: Whether to log all requests. Example: true
  • log_requests_verbose: Whether to log request and their contents. Example: false
  • log_filters: Whether to log all filtered objects. Example: true

Ratelimits

  • duration_coeff: The amount to multiply every route's duration by. Example: 1.0
  • max_coeff: The amount to multiply every route's max by. Example: 1.0

Custom Ratelimits

  • "/api/v1/timelines/public": An object representing a custom ratelimit for the specified API route. Example: { duration = 60, max = 200 }

License

This project is licensed under the AGPL-3.0.