CLI tool
vdsm/virtual-dsm avatar
vdsm/virtual-dsm

virtual-dsm puts Synology DSM in a container, and the image borrows its root filesystem

vdsm/virtual-dsm is an open-source project for practical engineering and operations.

4,033 stars494 forksShellMIT

At a glance

What is it?
virtual-dsm packages the Synology NAS operating system as a container that runs on KVM, reachable on a web port, with disk, CPU and memory controlled by environment variables and four documented ways to start it. The container file is unusual in a way worth knowing before you build it: the image starts from an empty base and copies an entire root filesystem out of a published virtualisation image, then downloads a third party script at build time.
Who is it for?
virtual-dsm suits someone who wants to try the NAS operating system, or to script against it, on a Linux host that has hardware virtualisation available. It does not suit a laptop running the desktop container runtime on an operating system where that runtime hides the virtualisation device, since the project says so explicitly.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Shell, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • vdsm/virtual-dsm4,033 ★ · +97
Star history
Repository2026-08-012026-11-14
vdsm/virtual-dsm3.9k4k

97 Stars in the last 105 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The image is an empty base plus a copied root filesystem

The container file is the most interesting document in the repository and it is worth reading in order. It declares the modern build syntax, then starts from an empty base and immediately copies everything out of a published virtual machine image into it, which is how a container ends up with an operating system inside an operating system. After that it installs a small set of packages: a file ownership faker, two Python bindings for serialising structures and for a cryptography library, and one Python package for parsing binary structures, installed with the flags that let it write to the system directories. The version string is written to a file at build time. Two directories are then copied in, one for the startup scripts and one that becomes the web root, along with the web server configuration and a host binary copied from a second published image.

Two artefacts arrive from the network at build time

Two details make this image different from a normal application image, and both are visible in the container file rather than in the documentation. The first is the copy from a published virtual machine image, which means the entire userland of the container is whatever that image published on the day your build ran, not something this project assembles. The second is a line that downloads a Python script from a raw URL belonging to a different repository and places it in the startup directory, which is how the installation files get extracted once the container starts. Neither is a criticism so much as a fact to record: the reproducibility of a self built image depends on artefacts the project does not control, and the published image is the version you can pin. The rest of the file is conventional: a volume for storage, two exposed ports including the file sharing one, four environment defaults, a health check that starts generous and retries twice, and a small init process as the entry point.

Four ways to start it, and only two need a compose file

The usage section documents four routes and that is most of the onboarding. The compose file is the reference:

yaml
services:
  dsm:
    container_name: dsm
    image: vdsm/virtual-dsm
    environment:
      DISK_SIZE: "256G"
    devices:
      - /dev/kvm
      - /dev/net/tun
    cap_add:
      - NET_ADMIN
    ports:
      - 5000:5000
    volumes:
      - ./dsm:/storage
    restart: always
    stop_grace_period: 2m

That is one service, the image, a disk size variable, two device mappings for virtualisation and the tun device, one added capability for network administration, a port mapping, a storage bind mount, a restart policy and a two minute stop grace period. The command line equivalent is a single run invocation with the same ingredients written as flags, including a stop timeout. For Kubernetes there is one command that applies a manifest from the repository over a network fetch, which is the shortest path of all. And there is a Codespaces badge, which means the project is aware that a hosted development environment with nested virtualisation is now a plausible place to try a NAS. The four routes share the same defaults, so the compose file is the one to read if you want to know what the image expects.

The desktop container runtime is excluded on three platforms

The requirements section is short and one note dominates it. A Linux host needs a container runtime and hardware virtualisation support, and Windows 11 can work through the desktop runtime provided nested virtualisation is enabled. Everything else is resource floors: at least a gigabyte of memory available and at least sixteen gigabytes of free disk, which tells you the install downloads a full operating system image. Then the note: the desktop container runtime on Linux, on macOS and on Windows 10 does not currently give containers access to the virtualisation device, and is therefore not supported. That is a hardware path restriction rather than a bug, and it is the single most useful line in the readme for someone who tried this on a laptop and got a container that would not boot.

Disk sizing is one variable, and growing an existing disk is supported

Storage is configured with environment variables rather than image sizes, which is what lets the operating system format the disk itself. A single disk starts at two hundred and fifty six gigabytes and is set by one variable, and there is a tip attached to it: the same variable resizes an existing disk to a larger capacity with no data loss, which is the opposite of what an image layer does. Extra disks use the same pattern with incremented variable names and a matching storage path, and the repository shows three. Passing a real host disk through is a different mechanism again, using a device mapping rather than a volume, and it carries a condition the readme is emphatic about: the device has to be completely empty, with no filesystem on it, otherwise the operating system inside may refuse to format it as a volume.

macvlan buys a real address and costs you host access

By default the container shares the host's bridge network, so the web interface is reached through a published port. To give the container an address on your own network instead, the readme walks through creating a macvlan network with a subnet, a gateway, an address range and a parent interface, then referencing it from the compose file and pinning an address. The benefit is stated plainly: every port is exposed by default, so no port mapping is needed. The cost is stated just as plainly in an important note, because it is the part people forget: the container will not be reachable from the host itself, since macvlan does not permit communication between the two, and the readme links a second network as the workaround. A follow up question covers the common case of wanting the NAS to look like any other device, answered by a DHCP flag plus the network device and a permissive cgroup rule.

GPU support has two paths and neither one transcodes video

Hardware acceleration is one flag for the integrated path and a documented set-up for the dedicated one. For an Intel or AMD device you set the flag and map the render device node, and the readme's closing sentence says what that buys you: it can enable the facial recognition function in the photo application. For a discrete NVIDIA card the host needs the vendor's container toolkit installed, the capabilities variable has to allow all capabilities, and a deployment reservation has to request the device. The same closing sentence applies to both, and it is the limit worth remembering: hardware video transcoding is not provided yet. So the feature is a photo application extra rather than a media server speedup, and anyone expecting the second will be disappointed.

Guest sizing defaults live in the image, and ballooning is opt in

The resource defaults are split across two places, and the readme is honest about the consequence. The guest is allowed two processor cores and two gigabytes of memory by default, and both are set with environment variables that override those defaults. Memory allocation is otherwise static: the guest is given the full configured amount for its entire lifetime, which is simple and predictable and wasteful on a busy host. A linked option changes that. Memory ballooning lets the container reclaim guest memory that is not in use, based on pressure on the host, and the readme presents it as something you enable rather than something you get. The version story works the same way: the default installation is version 7.2 of the operating system, and an older one is selected by putting the download address of its installation file into a variable.

Editorial conclusion

virtual-dsm suits someone who wants to try the NAS operating system, or to script against it, on a Linux host that has hardware virtualisation available. It does not suit a laptop running the desktop container runtime on an operating system where that runtime hides the virtualisation device, since the project says so explicitly. Before deploying, read the requirements list rather than the feature list, and if you build the image yourself, note that it pulls its root filesystem and one script from elsewhere at build time, which is the part of the supply chain you are trusting.

Frequently asked questions

What is virtual-dsm?

An open source project that runs the Synology NAS operating system inside a Docker container, with the installation files downloaded automatically and access through a web browser on port 5000. The container is started with hardware virtualisation enabled, and CPU, memory and storage sizes are set with environment variables.

How do I install virtual-dsm?

With a container file, a one line run command, a single apply of a Kubernetes manifest fetched over the network, or a hosted development environment badge. The compose file is the reference: it maps the virtualisation and tun devices, adds the network capability, publishes port 5000, mounts a storage folder and sets a two minute stop grace period.

Can I run Synology DSM on a virtual machine?

That is what this project automates: it runs the operating system inside a container using hardware virtualisation, with near-native performance claimed as a feature. It needs a Linux host with virtualisation support and at least a gigabyte of memory and sixteen gigabytes of free disk, and the desktop container runtime is not supported on Linux, macOS or Windows 10 because it does not expose the device to containers.

Official sources

  1. Official README
  2. Project repository
  3. Release notes
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/vdsm-virtual-dsm.svg)](https://hysenlabs.com/projects/vdsm-virtual-dsm)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/vdsm-virtual-dsm.svg)](https://hysenlabs.com/projects/vdsm-virtual-dsm)

Was this useful?