# anacrolix/dms: a terminal UPnP DLNA server in Go with optional ffmpeg transcoding

> dms serves media straight from a directory over UPnP/DLNA, adds transcoded streams and thumbnails when ffmpeg tools are on the PATH, and ships a Dockerfile and a FreeBSD service file. It is a small, single-binary answer for people who want a DLNA server they can read and start from a shell.

**anacrolix/dms** — A UPnP DLNA Digital Media Server that includes basic video transcoding. Tested on a Panasonic Viera television, several Android UPnP apps, and Chromecast.

- Repository: https://github.com/anacrolix/dms
- Stars: 750 · Forks: 116
- Language: Go
- License: BSD-3-Clause
- Published: 2026-08-08 · Updated: 2026-08-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/anacrolix-dms

## What dms is for, and who it is for

dms is a UPnP DLNA Digital Media Server that runs from the terminal. It serves content directly from the filesystem, either from the working directory or from a path you pass on the command line. The README describes it as advertising and serving raw files, plus alternate transcoded streams when it can produce them, such as mpeg2 PAL-DVD and WebM for the Chromecast, and thumbnails where possible.

The intended user is someone with a media directory and a DLNA-capable client, who would rather start one process than configure a library application. The README names the clients it was tested against: a Panasonic Viera television, several Android UPnP apps, and Chromecast. That list is useful because DLNA clients differ in which profiles and containers they accept, and a server that has been exercised against a Viera set and Android apps is likely to behave on similar hardware.

What dms is not is a media manager. There is no mention of a database, a web interface, user accounts, or metadata scraping. The directory tree is the library. If your media is already organised into folders that a television can browse, that is the whole setup.

## How dms builds its responses: SSDP, SOAP and the transcoding path

The repository layout shows the moving parts: ssdp/ for discovery, soap/ and upnp/ for the control protocol, upnpav/ for the AV-specific service definitions, dlna/ for the DLNA extensions, transcode/ for the ffmpeg pipeline, rrcache/ for a round-robin cache, and play/ and data/ for playback and metadata handling. main.go wires them together.

The README states that the SSDP component broadcasts and responds to requests on all available network interfaces. That is the discovery half: a client on the LAN sends a search, dms answers, and the client then talks SOAP to the ContentDirectory service. The justfile in the repository shows exactly that call being made by hand against a running instance, posting a Browse action with the SOAPAction header set to urn:schemas-upnp-org:service:ContentDirectory:1#Browse. Being able to issue that request with curl is the fastest way to confirm the server is alive without involving a television.

For media data, dms shells out. The README says it uses ffprobe or avprobe to get information such as bitrate and duration, ffmpeg or avconv for video transcoding, and ffmpegthumbnailer for thumbnails when browsing. The important consequence is that these are not optional libraries linked into the binary. They are external commands that must be in the PATH given to dms, and the README is explicit that features requiring them are disabled if they are missing. A dms started from a shell with a trimmed PATH will still serve raw files, but the transcoded alternate streams and the thumbnails will simply not appear. That is a silent degradation, not an error, which is worth knowing before you conclude that transcoding is broken.

The README also mentions dynamic streams, such as a live RTSP stream, generated on the fly with the help of an external application like ffmpeg. So the transcode layer is not limited to converting files on disk; it can be pointed at a source that produces bytes continuously.

## Installing dms and running a first browse

The README assumes Go and GOPATH are already configured, and gives a single install command:

```bash
go install github.com/anacrolix/dms@latest
```

After that, the binary lands in $GOPATH/bin, and the README runs it as:

```bash
"$GOPATH"/bin/dms
```

Started with no argument, dms serves the working directory, so the practical first run is to change into the media folder and launch it from there. If you want transcoding and thumbnails, make sure ffmpeg or avconv and ffmpegthumbnailer are on the PATH before you start it; otherwise those features are disabled.

The repository also carries a Dockerfile, which is the cleaner route on a machine you do not want to install Go on. It builds from docker.io/alpine:edge, installs ffmpeg, ffmpegthumbnailer and mailcap in the runtime stage, declares /dmsdir as a volume, and runs as an unprivileged user. That means the container already has the external tools the transcoding features need. Mount your media at /dmsdir and the entrypoint serves it.

To check that the server is answering control requests before you touch a television, the justfile shows the Browse call, aimed at localhost:1338:

```bash
curl -s -X POST http://localhost:1338/ctl \
    -H "Content-Type: text/xml" \
    -H 'SOAPAction: "urn:schemas-upnp-org:service:ContentDirectory:1#Browse"' \
    --data-binary @testdata/browse-root.xml
```

A SOAP response listing the root container tells you the server is up. If curl cannot connect, the problem is on the host, not on the client.

## Running dms as a service, and where the deployment story is thin

The README documents one service integration in detail: FreeBSD. You install the provided file from helpers/bsd/dms into /etc/rc.d or /usr/local/etc/rc.d, then add dms_enable="YES" to /etc/rc.conf, optionally with dms_root="/path/to/my/media" and dms_user="myuser". That is a complete, concrete recipe with three knobs, and it is the only one the README gives.

Linux users get no equivalent. There is no systemd unit in the top-level repository entries, and the README is silent on how to supervise dms on a Linux host. You can write your own unit, or run the container, but neither is documented as the intended path. Given that the project ships a Dockerfile and a FreeBSD service file, the omission of a systemd unit is a gap rather than a philosophical choice, and it means the deployment advice on Linux is left to the reader.

The same is true of configuration in general. There is no config file described. Behaviour is controlled by the path argument and by environment, and the justfile's run recipe sets GOPPROF=http, which is a debugging convenience rather than a documented option. If you need per-client profiles or access restrictions, the README does not describe any.

## Where dms is the wrong tool

The clearest limitation is the dependency on external binaries for anything beyond raw file serving. Transcoding, duration and bitrate probing, and thumbnails all depend on ffmpeg, ffprobe or avprobe, and ffmpegthumbnailer being present in the PATH. The README states plainly that features requiring them are disabled when they are absent. On a minimal host, or inside a container you built yourself without those packages, dms becomes a plain file server, and the WebM and mpeg2 PAL-DVD streams the README mentions will not be offered.

A second limitation follows from the design: dms serves the filesystem. There is no described mechanism for hiding part of a tree, restricting which client sees which folder, or authenticating a user. If your media directory contains anything you would not want every device on the LAN to browse, that is a reason to point dms at a narrower path rather than to expect the server to filter.

A third is the SSDP behaviour. The README says dms broadcasts and responds on all available network interfaces. On a machine with a management interface, a container bridge, or a VPN interface, that is broader than some operators want, and the README does not describe a flag to limit it. If you need discovery pinned to one interface, this is the wrong shape of tool.

Finally, dms is a UPnP/DLNA server. If your clients are modern apps that expect an HTTP API or a web UI, DLNA compatibility is not the same thing, and the README describes no other interface.

## How dms compares with Gerbera and SimpleDLNA

Gerbera is the natural comparison point, and the difference is architectural. Gerbera is a full media server application with its own configuration model and a database-backed library; it is the kind of project you install as a package and configure through a file. dms is a Go program that you start against a directory, with the filesystem as the library and no database in the repository layout. If you want to curate metadata, define virtual containers, or manage a large library through a config file, Gerbera is built for that and dms is not.

SimpleDLNA occupies the other end: a deliberately minimal DLNA server, also aiming at serving files without a library layer. The distinction against dms is the transcoding and thumbnail path. dms documents ffmpeg-based alternate streams, including WebM for Chromecast and mpeg2 PAL-DVD, plus ffmpegthumbnailer thumbnails, and it documents dynamic streams such as a live RTSP feed generated on the fly. That is more than plain file advertisement, and it is the reason to pick dms over a purely static server when your client cannot play the source format.

Neither comparison is a verdict. If your television plays your files as they are, a minimal server is enough. dms earns its place when the client needs a different container or a thumbnail grid, and you are willing to keep ffmpeg on the PATH to get it.

## Licence, maintenance and upgrade cost

dms is licensed under BSD-3-Clause. That is a permissive licence, and the practical implication for most users is that embedding or redistributing the binary carries few obligations beyond retaining the copyright notice and licence text. The repository also contains a LICENSE file, which is the authoritative copy; read it rather than this summary, and treat any question about your own distribution as a matter for your legal team rather than for an article.

On maintenance, the facts are narrow. The repository is not archived, and the last push was on 2026-07-28, which is also the date of the v1.8.0 release. The release history shows v1.6.0 in May 2023, v1.7.2 in July 2025, and v1.8.0 in July 2026. That is a slow but real cadence: roughly one notable release a year, with long gaps in between. It is not a project that ships weekly, and you should not expect fixes to land the same day you report them.

The upgrade surface is small, which keeps the cost down. The go.mod targets Go 1.24.0 and pulls in only four direct dependencies: anacrolix/ffprobe, nfnt/resize, golang.org/x/net and golang.org/x/sys. There is no database to migrate and no config schema to update. Upgrading means replacing the binary and restarting it. The one thing to re-check after an upgrade is the external tool set: the Dockerfile pins the Alpine base as edge and installs ffmpeg, ffmpegthumbnailer and mailcap, so a change there is what would affect transcoding behaviour, not the Go code alone.

The README opens with a funding note pointing to the sponsors page and the issues list. That is worth reading as a signal about the project's capacity rather than as a request, since the release cadence is consistent with a maintainer working on it when time allows.

## Conclusion

Adopt dms if you want a small Go binary that serves a directory over UPnP/DLNA from a terminal, and you are willing to put ffmpeg, ffprobe and ffmpegthumbnailer on its PATH to get transcoding and thumbnails. Skip it if you need a web UI, a database-backed library, or per-user access control: the README describes none of these, and the server exposes whatever is under the path you give it. Before deploying, verify the three external binaries resolve inside the same PATH the process gets, and confirm the SSDP behaviour on a host with several network interfaces, because the README states dms broadcasts and responds on all available interfaces.

## FAQ

### Is anacrolix/dms free to use?

Yes. It is published under BSD-3-Clause, and the repository includes a LICENSE file. The README also notes that the project is looking for funding through the sponsors page, which is separate from the licence terms.

### Does anacrolix/dms need UPnP to work?

dms is a UPnP DLNA server, so UPnP is the protocol it speaks. The repository separates the SSDP discovery component from the SOAP control layer and the upnpav service definitions, and the README states that SSDP broadcasts and responds on all available network interfaces.

### How do I connect a client to anacrolix/dms?

Start dms, then let the client discover it over SSDP on the local network. To confirm the server is answering before involving a television, the justfile issues a Browse action with curl against localhost:1338, posting to the /ctl endpoint with the ContentDirectory SOAPAction header.

### Is DLNA still relevant for a server like anacrolix/dms?

The README lists a Panasonic Viera television, several Android UPnP apps and Chromecast as the clients dms was tested against, so DLNA remains a working path to those devices. Whether it fits you depends on whether your clients speak DLNA rather than a web API.

## Sources

- [Official README](https://github.com/anacrolix/dms#readme)
- [Project repository](https://github.com/anacrolix/dms)
- [Release notes](https://github.com/anacrolix/dms/releases)

---

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