Introduction
Welcome to the gomuks docs!
Discussion
Matrix room: #gomuks:maunium.net
Installation
There is a demo instance of gomuks web compiled to wasm available at https://demo.gomuks.app. However, the performance is significantly worse than with a native backend, so the demo is only meant for testing with a small account.
An Electron wrapper is also available, which includes the backend. The setup steps below can be ignored when using the desktop app. Just install the app and open it.
The Android wrapper does not currently come with the backend, which means you have to run the backend elsewhere. Something like a Raspberry Pi plus Tailscale (or another Wireguard solution) for external connectivity usually works nicely.
New gomuks terminal currently requires the backend to be running separately. An embedded backend mode will be added later. It also doesn't support Matrix login yet, so the backend must be set up using the web frontend before the terminal frontend can be used.
Setup steps
- Acquire a binary using the instructions below (either installing a package or compiling from source)
- Run the binary. It'll prompt you to create basic auth credentials on the first run. They're not your Matrix credentials.
- Open the web interface (at http://localhost:29325 by default)
If you want to have gomuks behind a reverse proxy, you'll need to adjust
listen_address and origin_patterns in the config file.
Installing a package
Prebuilt binaries can be found in GitHub releases or GitLab CI where every commit is built.
The release and CI binaries for Linux are statically built and have no
hard dependencies. The binaries for macOS require installing libolm, either
with brew install libolm or by placing libolm.3.dylib from the CI in the
same directory as the gomuks binary.
The gomuks backend requires having ffmpeg and ffprobe in $PATH to generate
metadata when sending video files.
Direct links to latest CI binaries:
- gomuks backend (includes web frontend): linux/amd64, linux/arm64, linux/arm, macos/arm64, windows/amd64
- gomuks terminal (frontend only): linux/amd64, linux/arm64, linux/arm, macos/arm64
- gomuks android (currently frontend wrapper only): arm64-v8a.apk, x86_64.apk
- gomuks desktop: debian/amd64, debian/arm64, linux/amd64 (zip), linux/arm64 (zip), macos/arm64, windows/amd64
There are also some community-maintained distro packages. If you've made a new package, please add it to the list below.
- Void Linux: gomuks
Compiling from source
- Install Go 1.25 or higher.
- Compiling the frontend for gomuks web also requires the latest LTS of Node.js or higher (currently v24).
libolm-devmust also be installed for end-to-end encryption, unless you opt to use goolm.
- Clone the repo:
git clone https://github.com/gomuks/gomuks.git && cd gomuks - Build:
./build.sh(build.sh will build the frontend with npm, followed by running go build with some additional flags).- To add custom build tags, such as
goolm, set them in theGO_BUILD_TAGSenvironment variable, which the build script will read.
- To add custom build tags, such as
Simply pull changes (git pull) and run ./build.sh again to update.
To build the terminal frontend, use ./build-terminal.sh. The backend and
terminal frontend are separate binaries for now.
Common compilation issues
fatal error: olm/olm.h: No such file or directorymeans you forgot to install libolm-dev, or that you installed it in a weird place which isn't in your default library lookup path.- In the latter case, set the
LIBRARY_PATHandCPATHenvironment variables, e.g.export LIBRARY_PATH=/usr/local/lib CPATH=/usr/local/include. - Alternatively, build with goolm to avoid the libolm dependency entirely.
- In the latter case, set the
cgo: C compiler "gcc" not found: exec: "gcc": executable file not found in $PATHmeans you forgot to install C/C++ compilers.//go:build comment without // +build commentmeans your Go version is slightly outdated.cannot load embed: malformed module path "embed"orpackage embed is not in GOROOTmeans your Go version is very outdated.cannot find package "maunium.net/go/gomuks/..." in any of:usually means your Go version is extremely outdated.
Docker (gomuks web)
The backend for gomuks web can also run in Docker. Docker images are available
at dock.mau.dev/gomuks/gomuks.
On first run, gomuks will interactively ask for basic auth credentials, so you
have to either run it with the -it flags, or create the config file yourself.
You'll likely also have to follow the instructions for connecting to a remote
backend in the FAQ.
The docker image defaults to GOMUKS_ROOT=/data, so remember to persist /data
appropriately (e.g. by mounting a host directory there).
Keep in mind that the backend has all your encryption keys, which means it must be ran in a secure location.
FAQ
Can I connect to a remote gomuks backend?
Yes, the recommended way to do it is to run the backend behind a reverse proxy (see entry below). It is possible to connect directly without a reverse proxy, but LANs are dangerous, so using TLS is recommended, which requires a reverse proxy.
If you really don't want to use TLS, you'll have to set insecure_cookies in
the config to allow connecting from an insecure context. By default, the auth
cookie will only work on localhost and https sites.
listen_address and origin_patterns have to be changed to allow connecting
from non-localhost addresses. 0.0.0.0:port is the way to listen on all
interfaces, which is what you likely want on Docker. origin_patterns should
include the URL you enter in your browser, including explicit ports, but
excluding the protocol (https://).
Can I run the backend behind a reverse proxy?
Yes, origin_patterns just needs to be changed to match what the client will
use to connect to. listen_address may also need to be changed if using
something like Docker where the reverse proxy can't connect using localhost.
If you want to use custom auth instead of the standard basic auth, you can either have your reverse proxy inject it, or use the secret config option to disable auth entirely in the backend. When disabling auth, you need to be extra careful not to allow untrusted requests to the backend.
Can I use gomuks with multiple accounts?
gomuks currently only supports one account at a time, but you can run multiple instances of gomuks with different data directories. See the entry below for details.
When using the Electron wrapper, you can have the wrapper run multiple backends internally and display an in-app switcher for them. Use the backend manager tab in settings to add more backends.
If you aren't using a reverse proxy, you'll have to use different ports and
localhosts to access the gomukses to avoid cookie conflicts. The port can be
changed in the config. All modern browsers should force anything.localhost
to connect to localhost, so you could use http://main.localhost:8000 and
http://anotheraccount.localhost:8001 for example.
Where does gomuks store data?
By default, data is stored in the default config/cache/data directories using
OS-specific conventions. To store all gomuks data in a custom directory, use
the GOMUKS_ROOT environment variable.
You can also override individual directories using GOMUKS_THING_HOME (where
THING is CONFIG, DATA or CACHE).
- Config contains the config file with things like listen address, basic auth credentials and log config.
- Data contains all persistent data (messages, encryption keys, etc). Deleting the data directory will log you out.
- Cache contains media and can be safely deleted at any time. The cache is content-addressed, so it can also be shared between multiple gomuks instances.
GOMUKS_LOGS_HOME can also be used to redirect logs, but the variable is only
read on first startup and then baked into the config file.
Electron wrapper
The Electron gomuks desktop stores backend data under the default Electron
session data directory, which means ~/.config/gomuks-desktop on Linux and
~/Library/Application Support/gomuks-desktop on macOS.
The config for the Electron side is in gomuks-desktop.json, which is where
backends are defined. All backend entries must have type (embedded or
remote) and a unique name. Remote backends must also have address
and optionally username and password. All backends can have displayname
to use in the account picker.
Each embedded backend has its own subdirectory named after the name field in
the config. The media cache is shared by all backends and will be in the
gomuks-cache subdirectory.
System-specific defaults
These are the base directories for each OS, data will be stored in the gomuks
directory inside each base directory.
*nix
- Config:
$XDG_CONFIG_HOMEor$HOME/.config - Cache:
$XDG_CACHE_HOMEor$HOME/.cache - Data:
$XDG_DATA_HOMEor$HOME/.local/share - Logs:
$XDG_STATE_HOMEor$HOME/.local/state
macOS
- Config & Data:
$HOME/Library/Application Support - Cache:
$HOME/Library/Caches - Logs:
$HOME/Library/Logs
Windows
- Config & Data:
%AppData% - Cache:
%LocalAppData% - Logs:
%LocalAppData%
How do I use a proxy?
Go's HTTP library reads the https_proxy environment variable by default
(see https://pkg.go.dev/net/http#ProxyFromEnvironment for more info).
Where are the legacy gomuks docs
Legacy gomuks is no longer supported. You can find the old docs in the git history of the mautrix/docs repo: https://github.com/mautrix/docs/tree/a904952822e967c3f71c2a75d1e2bf904f167db2/gomuks
RPC API ↗
HTTP API ↗
C FFI
In addition to the HTTP and Go interfaces, the gomuks backend can be used through C function calls. The interface is mostly documented in the header file: https://github.com/gomuks/gomuks/blob/main/pkg/ffi/gomuksffi.h.
The C functions are just light wrapping to access the RPC API,
so almost everything happens through the GomuksSubmitCommand function and the
event callback passed to GomuksStart. There are some extra methods which can
optionally be used for more advanced media features (like upload progress and
download streaming).
Building
The easiest way to build the .so file is to use ./pkg/ffi/build.sh in the
gomuks repo, which ends up calling go build with a bunch of flags.
If you want to cross-compile using the build script, use TARGET_GOOS and
TARGET_GOARCH instead of GOOS and GOARCH respectively. Trying to set the
plain variables will make go tool compile maubuild for the target instead of
the host and then fail to execute it.
Additional build tags (like goolm) can be set in the GO_BUILD_TAGS environment
variable. If you want a static archive (.a) instead of a dynamic library, set
MAU_STATIC_BUILD=true in environment.
Building manually
You can also ignore the helper script and call go build manually.
The details to note when doing that are:
- The main package is
./pkg/ffi. -buildmode=c-sharedmakes dynamic libraries and-buildmode=c-archivemakes static ones. You also usually need-linkmode external -extldflags '-static'for static builds.-tags sqlite_fts5is mandatory for all gomuks builds.- Building in version info is strongly recommended. It's done by setting some
variables using the
-Xflag. Specifically, thego.mau.fi/gomuks/versionpackage hasCommit(full git commit hash),BuildTime(RFC3339 timestamp with second precision) andTag(git tag only if building an exact tag). Additionally,maunium.net/go/mautrixhasGoModVersionwhich is the raw version extracted from the go.mod file.
Contributing guidelines
These guidelines apply to all mautrix bridges, as well as other associated projects like the mautrix libraries, whatsmeow, meowlnir, and gomuks.
Making pull requests
For any non-trivial changes (more than a few lines), you should join the Matrix room linked in the project readme and briefly explain your plan to confirm that it makes sense and is wanted. Failure to do so may result the PRs in being ignored and/or closed without further comment. The Matrix room is also preferred in case discussion about the contribution beyond basic code review is necessary.
Updating the changelog file is not necessary when making a pull request. That will be done separately when a release is being made.
Pull requests may be missed and/or forgotten for extended periods of time, especially if they involve more complicated changes. Feel free to remind us in the appropriate Matrix room if it seems like nothing is happening. Pinging on GitHub is not recommended.
In case a PR has too many things to fix, it may be rewritten instead of reviewed. If that is something which would offend you, please don't open a PR.
Use of AI
In general, you can use AI to help with contributions. However, AI slop is not accepted.
The author is accountable for the code. You must understand all changes that were made. Authors are also expected to test their changes (if applicable), and understanding changes generally means testing them yourself, not asking AI to do it. All PRs are held to the same (relatively high) standards for code quality, architecture, etc regardless of whether AI is used.
AI should not be used for communicating with humans. This means things like issues, pull request descriptions and comments should be written by yourself, not an AI.
Development instructions
The latest version of Go is recommended, but using the previous version is fine too. Go only supports the last two releases, so anything older than that is EOL and will not work.
Since the bridges use cgo, you'll also need a C compiler and libolm-dev installed
(though libolm-dev can be bypassed by using -tags goolm). For Signal, you can
either install Rust, or just download libsignal_ffi.a from the CI to avoid the
Rust dependency (see normal Signal setup instructions for that).
You should install pre-commit and run pre-commit install in the repo before
committing to have linters run automatically. You can also run pre-commit run -a
before pushing to lint everything. Finally, you can let GitHub actions run the
linters for you after pushing, but it's usually more effort to go back and fix
things at that point.
Using Linux or macOS is recommended for development. Windows is generally not a supported environment for anything, so WSL is likely necessary if you're running Windows.
A local Synapse instance is useful for testing bridges. Alternatively, you can
sign up for Beeper and use bridge-manager to run local bridges against the
Beeper servers (there's a convenient --local-dev flag for bbctl run).
Code style
See https://beeper.notion.site/Beeper-Go-Guidelines-ae943532d96f4ad6a614baf836c073eb
Release schedule
When software is being actively developed, releases are effectively always outdated. The main branch is generally stable and safe to use in production, although automatic unattended upgrades are not recommended. The CI builds binaries and docker images for every commit, so you don't need to compile yourself to use the main branch (see the setup docs for details). Bugs should only be reported on the main branch.
The standard release day is the 16th of each month. New releases may be skipped if there's something blocking the release, or if nothing relevant has changed since the last release. Releases outside the standard cycle only happen if there are severe security issues that must be fixed immediately, or if there's a major breaking change externally that breaks the latest release completely.
Scheduled releases are accompanied by a blog post on mau.blog with the list of releases and highlights of the changes.
Anything older than the latest release is completely unsupported and there won't be any patches even for security issues.
The standard release cycle applies to:
- all mautrix bridges
- mautrix-go and go-util
- Meowlnir
- gomuks
All other projects do not have a release cycle and will be released at random. This includes:
- mautrix-python
- maubot and official plugins
- whatsmeow