# jfa-go: invite based accounts, expiry and bulk management for Jellyfin

> jfa-go is a Go application that puts a user management layer in front of a Jellyfin server, with invite links that carry profiles, self service password resets, user expiry, bulk operations and contact through Discord, Telegram or Matrix, and it reaches the server through the Jellyfin API rather than replacing it. It suits a media server operator who wants sign up without handing out passwords by hand, and the project describes its own maintenance level as active-ish.

**hrfee/jfa-go** — a bit-of-everything user management app for Jellyfin

- Repository: https://github.com/hrfee/jfa-go
- Website: https://jfa-go.com
- Stars: 1,185 · Forks: 72
- Language: Go
- License: NOASSERTION
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/hrfee-jfa-go

## What jfa-go adds to a Jellyfin server

jfa-go is a user management app for Jellyfin, with Emby described as a second class citizen, and it provides invite-based account creation along with other features that make an instance easier to manage.

The framing matters. It is not a fork of Jellyfin and it does not replace the media server. It sits in front of it, talks to the Jellyfin API, and does the administrative work that a server owner would otherwise do by hand: creating accounts, applying library access, expiring accounts, resetting passwords and telling people when something changes.

The feature list is the clearest description of the scope. Invites are links sent to new users so they can sign up without relying on you, and an invite can be customised with profiles that apply Jellyfin settings, library access and transcoding options at sign-up, with a different profile per user type. Invites can be limited by time or by number of uses, and the system can enforce strong passwords and require a CAPTCHA.

Password resets are delegated to the user, working with the Jellyfin Forgot Password feature or through the My Account page, with the options in the wiki.

Contact is a first class concept. jfa-go collects email addresses and Discord, Telegram or Matrix details when a user signs up or later, and it can contact them when needed, for instance on or before account expiry, when disabling or enabling an account, when deleting one, or whenever you want to send a Markdown announcement. Confirming the email is optional, while confirming the Discord, Telegram or Matrix contact is required.

The My Account page lets users change their own password and contact details and shows them relevant information. Referrals give a user a special, limited invite to pass to friends or family. Advanced user management shows all users at once and offers bulk enable, disable, delete, Markdown announcements and profile application. User expiry can be set on an invite, so new accounts are valid for a fixed period, after which the account is disabled, deleted, or disabled and then deleted.

There is integration with Ombi and Jellyseerr, syncing usernames, passwords and contact details between the services. Everything the user sees, the messages, the invites and the My Account page, is customisable with full Markdown support.

## The project status, stated unusually plainly

There is a section of the README titled Project Status, and it is worth quoting the substance because it sets expectations that no marketing copy would.

The status is Active-ish. The reason given is that studies mean the author cannot work on the project much outside of breaks, and the hope is to fit in general support and things like bug fixes into the available time. New features are likely to come in short bursts throughout the year, if they do at all.

Then there is a section titled Does it still work, and the answer is that jfa-go currently works on Jellyfin 10.11.0, the latest version as of 21/10/25, and the author should be able to maintain compatibility in the future unless big changes occur.

That is a candid and specific commitment, and the specificity is what makes it useful. It tells you the project tracks the current Jellyfin release, that a Jellyfin update is the thing that could break it, and that a bug report will be answered by one person who is a student.

There is also an Alternatives section, which is unusual and welcome. If you want a bit more guarantee of support, the README points at Wizarr, saying it is popular and seems very polished, and that it supports multiple media servers, lots of customization and invitation through Discord.

That comparison is the clearest statement of the difference between the two projects. Wizarr is the broader option, pitched for more guarantee of support. jfa-go is the deeper, more Jellyfin specific one, and the trade is support against focus.

The last push to the repository was on 2026-10-10, and the recent releases are v0.6.0 in November 2025, v0.5.1 in December 2023 and v0.5.0 in September 2023.

## Installing it, and the build variants

There are more installation routes than most projects of this size, and they are worth reading in full because the variants matter.

Docker is the primary route, with the image on Docker Hub.

```sh
docker create \
             --name "jfa-go" \
            -p 8056:8056 \
            -v /path/to/.config/jfa-go:/data \
            -v /path/to/jellyfin:/jf \
            -v /etc/localtime:/etc/localtime:ro \
            hrfee/jfa-go
```

Three things in that command are load bearing. The data volume holds the config file and other data. The Jellyfin volume is only needed for password resets through Jellyfin and is to be ignored for Emby. And the localtime mount keeps the time correct. A second port, 8057, is for TLS.

Debian and Ubuntu are served from an apt repository, with a stable and an unstable suite, and there are two packages. The plain jfa-go package is for servers, and jfa-go-tray is for desktops and servers with a GUI, which may pull in a lot of dependencies. The tray builds add a tray icon to start, stop and restart the app, and an option to start it automatically when you log in.

Arch is on the AUR in three flavours, a stable package, a pre-compiled binary package and a nightly one tracking git.

Other platforms get precompiled binaries from the releases section for stable versions and from dl.jfa-go.com for nightlies, unzip the executable, and for Unix and macOS make it executable and put it on the PATH.

Then there are the build tags, which explain the variants. The Makefile has flags for internal assets, a tray icon, end-to-end encryption for the Matrix bot, and the updater. The Matrix end-to-end encryption builds, and the Linux tray builds, require the libolm dependency, which the package files list and the Docker images include.

## Running it: the setup wizard, the daemon commands and the config

Running the application starts a setup wizard on localhost:8056, or on whatever address you specify, and you refresh the page once it completes.

The command line surface is small and is printed by the binary itself.

```
Usage of jfa-go:
  start
	start jfa-go as a daemon and run in the background.
  stop
	stop a daemonized instance of jfa-go.
  systemd
	generate a systemd .service file.

  -config, -c string
    	alternate path to config file. (default "/home/hrfee/.config/jfa-go/config.ini")
  -data, -d string
    	alternate path to data directory.
```

The daemon commands matter for the deployment story. The systemd subcommand generates a service file, and the repository carries a jfa-go.service file, so running as a service on a server is the intended path rather than an afterthought.

The two flags are for the cases where the defaults do not fit. The config file is an ini file in a per user configuration directory, and the data directory is separate, which is what lets you mount one as a volume in Docker and leave the other wherever the platform puts it.

The Docker image itself is built in two stages. The build stage runs goreleaser for a snapshot build and then rewrites the setup page, disabling the password reset watch directory and pointing it at the mounted Jellyfin path. The final image is distroless base, with the built binary and the static data copied in, the two ports exposed and the entry point running the binary with the data directory flag.

The choice of a distroless final image is a deliberate one for a tool that sits in front of a media server, since it ships without a shell or a package manager.

## How the codebase is put together

The repository layout tells you this is a multi-module Go project with a TypeScript front end, which is not what most people expect from a small self hosted tool.

The Go side is split by concern at the top level, with a file per API area, api-activities.go, api-backups.go, api-invites.go, api-jellyseerr.go, api-messages.go, api-ombi.go, api-profiles.go, api-userpage.go and api-users.go, plus the supporting pieces like auth.go, email.go, discord.go, config.go, backups.go and log.go.

The module setup is unusual and worth noting, because the go.mod contains a series of replace directives pointing the project's own submodules at local directories, for the common, docs, ombi, logger, logmessages, linecache, api, easyproxy and jellyseerr modules. That means those are separate Go modules developed in the same repository, and the main module consumes them from the working tree rather than from a published version. There is a commented out replace for the mediabrowser module, which is the Jellyfin API client, and it points at a sibling directory, so the client library is expected to sit next to the project on disk during development.

The front end is a separate build. The package.json says outright that it is only used for grabbing scss build dependencies and is not a real package, and its dependency list is the toolchain for the styles: tailwindcss, postcss, mjml for email markup, nightwind, cheerio for the markdown pipeline, highlight.js, uncss, jsdom and the markdown libraries.

The Makefile drives the whole build, with the version, commit, build time and the build host injected into the binary through linker flags, and a separate variable for the CSS version that is derived from the latest git tag. There are also development containers, a Woodpecker CI configuration, a goreleaser configuration, and a Weblate instance for the translations, with the translation status badge in the README header.

## Conclusion

Adopt jfa-go if you run a Jellyfin server for other people and want sign up to happen through invites with library access applied automatically, because that is the workflow it automates and the part a hand made script does badly. Do not adopt it for a server where every user is a member of your household, and do not treat it as a supported product, since the project status is stated as active-ish and the author says features arrive in short bursts. Before you install, check your Jellyfin version, because the project tracks the current release and states compatibility with 10.11.0.

## FAQ

### What does jfa-go do for a Jellyfin server?

It is a user management app that adds invite based account creation, invite profiles that apply Jellyfin library and transcoding settings at sign up, self service password resets, user expiry, bulk management of accounts, and contact through email, Discord, Telegram or Matrix, with Markdown support for the messages users see.

### Which Jellyfin versions does jfa-go work with?

The README states that jfa-go currently works on Jellyfin 10.11.0, the latest version as of 21/10/25, and that the author should be able to maintain compatibility in the future unless big changes occur. Emby is supported as a second class citizen.

### How do I run jfa-go with Docker?

The image is hrfee/jfa-go on Docker Hub. You create a container with port 8056 published, a volume for the configuration and data directory, a volume for the Jellyfin directory if you want password resets through Jellyfin, and a localtime mount. A second port, 8057, is for TLS.

### How active is the jfa-go project?

The README calls the status Active-ish, explaining that studies limit the author's time and that new features are likely to come in short bursts throughout the year, if at all, with general support and bug fixes fitted in between. For a better supported alternative it points at Wizarr, which supports multiple media servers and invitation through Discord.

## Sources

- [hrfee/jfa-go on GitHub](https://github.com/hrfee/jfa-go)
- [Issues](https://github.com/hrfee/jfa-go/issues)
- [Project website](https://jfa-go.com)
- [README](https://github.com/hrfee/jfa-go/blob/main/README.md)
- [Releases](https://github.com/hrfee/jfa-go/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/hrfee-jfa-go
