Serving the interwebz since
Warning! If you can see this text, your browser is too old to load some of the CSS styles.

FUZE Mediaboard

Version 0.2
View: Git, Documentation, Overview

Fuze Mediaboard is a self-hosted multimedia messaging platform, running on the FuzeHttp framework. It is written for humans, by humans.

Features include:

Supported OS: FreeBSD, Linux, MacOS. Windows support coming soon.

Getting started

Running a chat server may seem daunting, but hosting a basic instance is actually simple. As the tutorial progresses, you will start with running a local text-only server, which will evolve into a fully-featured online platform.

Compiling from source

Prerequisites: Git, CMake (>= 3.28), Boost (>= 1.88), SQLite OR PostgreSQL.

First ensure that submodules are downloaded. Use this command:
git submodule update --init --recursive
Now, to compile the server:
cmake -B build -G Ninja -D WITH_WEBRTC=OFF -D WITH_MAGICK=OFF
cmake --build build
cmake --install build --prefix install
Compiling is known to work with clang-19, but not GCC 14.

Running the server

The --create_owner flag is required on first boot. When the server starts, an invitation link will appear in the command-line output.
Registration link
Invitation link to create owner account.
Accepting the invitation
A registration form is shown when invitation is opened
After registering the owner account, you can now interact with the server.
If you ever forget the password, you can simply run the create_owner command again. Note that it will not be the same account.

Making it public

Fuze mediaboard requires HTTPS for secure remote authentication. It is recommended to use a reverse proxy like NGINX. SSL certificates (required for HTTPS) can be obtained for free using Certbot.
Example NGINX config.

Ensure your IP is accessible to the outside world, using port forwarding if necessary.

Permissions

By default, only the owner can read and write messages.

  1. After logging in, click on the "Manage server" tab in the toolbar as an administrator.
  2. In the Manage permissions tab, click "Add group" and select "Public".
  3. Change setting to Allow for the permissions you want to grant.
Public permissions set in the Manage Server page
Granted read/write permissions to Public
Permissions can also be set on boards, which inherit from server-level settings, and threads, which inherit from boards.

Leaving a setting on Inherit means the permission will be searched by traversing up the inheritance tree (if applicable), and cascading down the group heirarchy until a non-inherited setting is found. If no permission setting is found by the time inheritance passes the server-level setting for Public, permission is denied.

If both a user and group permission are set on an object, the user setting takes priority.
Manage Users tab
Adding groups to a user on the Manage users page.
Manage Groups tab
In Manage groups you can add/delete groups, change their heirarchy, and dismiss members.

Configuration

Changes made to config.ini are read when the server starts. These options can also be passed directly in the command line, which will override what is set in the config file.

Secret is used for registration, but is not strictly necessary.
config.ini
server_portServes http://localhost:8300 by default. Change this if running multiple Mediaboard instances.
threadsNumber of async threads. Values greater than 1 should be used for testing only.
file_size_limit_mbFor limiting the maximum size of user-uploaded files and to prevent abuse.
favicon_url
site_name
Cosmetic settings.
strip_metadataRemoves metadata from uploaded images (except SVG files).
thumbnail_file_exension
thumbnail_size
Format must be supported by ImageMagick. Please note that any change in this setting will not apply to existing thumbnails - those will have to be converted manually.
avif_thumbnails
heic_thumbnails
svg_thumbnails
webp_thumbnails
mp4_thumbnails
webm_thumbnails
Requires the respective formats to be installed in the instance of ImageMagick used - Use magick -list format to see if they are supported.
Video formats require ffmpeg.
sqlite_database_filePath to SQLite database file. Ignored when compiled with the PostgreSQL interface.
postgresql_host
postgresql_port
postgresql_user
postgresql_database_name
PostgreSQL database connection parameters. Only used when compiled with the PostgreSQL interface.
environment_variable_for_secretIf secret_required=true, this environment variable must be visible to the server
secret_requiredControls whether environment_variable_for_secret must be found

Embedding into a webpage

Fuze Mediaboard can be embedded inside of a page by using an iframe:
<iframe src="http://localhost:8300/"></iframe>

Using Fuze Mediaboard inside of an iframe
It can be shown with controls hidden by adding display=embed as a URL parameter:
<iframe src="http://localhost:8300/?display=embed"></iframe>
Iframe with display=embed
display=embed also works with individual threads - just add &thread=0 (with a valid thread ID) to the path. Embedding threads has a number of potential uses, for example adding comment sections on blog posts, or an artist uploading his/her latest work.

Optional: ImageMagick support

In order for thumbnails to work, the software needs to be compiled with ImageMagick. The dependency is not included as a submodule; it must be installed seperately.

Getting ImageMagick

Clone and configure Imagemagick with the delegates for JPEG, PNG, WEBP, XML, and JPEG-XL.
You may need to install dependencies first. Usually a custom build of ImageMagick is preferred, to ensure all required delegates are installed. FreeBSD's package is sufficient so you can install that via pkg, but Debian's apt package is not. On Debian, you should apt install libxml2-dev and libjxl-dev
Change to the ImageMagick directory, and configure:
./configure --with-jpeg --with-jxl --with-png --with-xml
Ensure the configure output ends with all the delegates listed:
DELEGATES = jng jpeg jxl lcms png xml zlib
Then install:
make
sudo make install

Compiling Fuze Mediaboard with ImageMagick

Configure with -DWITH_MAGICK=ON.
Note: To build without ImageMagick, add -D WITH_MAGICK=OFF instead to the CMake -B command.

ImageMagick may use significant amounts of memory, which can crash the program if system memory runs out. To set memory limits add these environment variables:
MAGICK_MEMORY_LIMIT=512MiB
MAGICK_MAP_LIMIT=1GiB
MAGICK_DISK_LIMIT=2GiB

Optional: WebRTC Live Rooms

Live Rooms are similar to Discord's voice channels. Users can share and receive live video and audio, from the desktop, microphone, and webcam. The main difference is Live Rooms are created and closed on-demand, whereas a Discord server has a set number of voice channels created by the server administrator(s).

When this feature is enabled, each Board gets a "Live" page, which will appear in the top navigation bar within each Board.

Compiling Fuze Mediaboard with WebRTC features

The dependencies for this are included as git submodules. The libdatachannel library is used by the server.
Configure with -DWITH_WEBRTC=ON.

ICE servers

On the Manage Server page, there is a tab to configure WebRTC features. There will be a table with columns for "Type", "Hostname", "Port", "Transport", and "Shared secret". ICE servers are often needed to connect remote peers in live rooms, where they might not have a unique public IP, thanks to CGNAT.
The "Transport" and "Shared secret" values are only used for TURN.

ICE servers config table
"Add server" to add a new entry, "Clear" to remove an entry, and "Submit" to update the list stored on the server.

Optional: Using PostgreSQL as the database

Alternatively, you can build with the PostgreSQL interface instead:
cmake -B build -D FUZEDBI_USE_POSTGRES=ON

Set the following options in config.ini to correspond to the database: postgresql_host, postgresql_port, postgresql_user, and postgresql_database_name.

Start cluster

This may be skipped on certain Linux distros such as Debian. Check if the server is already running with systemctl status postgresql or service postgresql status
initdb -D /var/db/postgres/18/main/
pg_ctl -D /var/db/postgres/18/main start

Create database

su -
su postgres
createdb fuze_mediaboard
psql -d fuze_mediaboard
fuze_mediaboard=# CREATE USER mediaboard_server WITH PASSWORD '';
fuze_mediaboard=# GRANT ALL ON SCHEMA public TO mediaboard_server;
fuze_mediaboard=# \q
To import the database template, go back to your user account and run:
psql -U postgres fuze_mediaboard < database_template.sql
Add the following line to pg_hba.conf[documentation]. Insert it at the top of the table so that it won't be overridden by other settings:

local      fuze_mediaboard    mediaboard_server           password

mediaboard_server is the PostgreSQL user which interacts with the database named fuze_mediaboard.\ Set the environment variable FUZE_MEDIABOARD_PASSWORD with the same password used in the CREATE_USER statement earlier. Open a new terminal window or reboot your system to apply the change.

Developer's section

Contributions from any human are welcome. You are invited to use Fuze.page Mediaboard for any questions/discussion, or to e-mail me privately at mash@fuze.page.

AI policy

AI usage is not principally rejected, but any generated code must be marked with comments indicating the start and end of each AI-assisted section.

Example from CMakeLists.txt
elseif (file MATCHES "\.template\.[^\\\/]+$")
    message("----is template")
    set(frontend_definitions "")
    if (WITH_WEBRTC)
      set(frontend_definitions "-DWITH_WEBRTC=1")
    endif()
    # [AI glasnost] this section assisted by Claude Sonnet 5
    set(qualified_source ${FRONTEND_SOURCE_DIR}/${file})
    set(qualified_destination ${CMAKE_BINARY_DIR}/share/FuzeMediaboard/frontend/${file})
    set(depfile ${CMAKE_BINARY_DIR}/frontend_deps/${file}.d)

    get_filename_component(destination_dir ${qualified_destination} DIRECTORY)
    get_filename_component(depfile_dir ${depfile} DIRECTORY)
    file(MAKE_DIRECTORY ${destination_dir})
    file(MAKE_DIRECTORY ${depfile_dir})

    # Extract template name without .template.* suffix
    string(REGEX REPLACE "\.template\.[^\\\/]+$" "" template_basename "${file}")
    # Convert to uppercase token: index.html → INDEX
    string(TOUPPER "${template_basename}" template_token)
    string(REGEX REPLACE "[^A-Z0-9_]" "_" template_token "${template_token}")

    add_custom_command(
      OUTPUT ${qualified_destination}
      COMMAND ${CMAKE_C_COMPILER} # runs C preprocessor
              -E -P -CC -undef -nostdinc -x c -Wno-trigraphs -Wno-c23-extensions
              -D${template_token} ${frontend_definitions}
              -I ${FRONTEND_SOURCE_DIR} -I ${FRONTEND_SOURCE_DIR}/include
              -MMD -MF ${depfile} -MT ${qualified_destination}
              ${qualified_source} -o ${qualified_destination}
      DEPENDS ${qualified_source}
      DEPFILE ${depfile}
      COMMENT "Preprocessing ${file} :: ${template_token}"
      VERBATIM
    )
    list(APPEND frontend_list ${qualified_destination})
    # [AI glasnost] end AI-assisted section
  else()

AI should not be used to make media assets (icons, sounds etc), period. Neither should it be used to generate documentation. Aside from that, feel free to use AI to help understand the code, find bugs, and receive guidance on solutions. Refer to the Fuze Human-oriented License for more info.

Creating an AppImage

To create Appdir required by AppImage, run:
cmake --install build --prefix AppDir/usr
Then to bundle the dependencies, use Linuxdeploy:
./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage

Other useful commands

Update submodules to the latest commit:
git submodule update --remote
Dump PostgreSQL database:
pg_dump fuze_mediaboard > mediaboard_dump.sql
Restore PostgreSQL database backup:
psql -X --set ON_ERROR_STOP=on fuze_mediaboard < mediaboard_dump.sql

Here be photons