# Table of Contents - [Mutagen | Cloud-based development using your local tools ](#mutagen-cloud-based-development-using-your-local-tools-) - [Overview | Mutagen ](#overview-mutagen-) - [Installation | Mutagen ](#installation-mutagen-) - [Getting started | Mutagen ](#getting-started-mutagen-) - [Blog | Mutagen ](#blog-mutagen-) - [Names, labels, and identifiers | Mutagen ](#names-labels-and-identifiers-mutagen-) - [Configuration | Mutagen ](#configuration-mutagen-) - [Docker® containers | Mutagen ](#docker-containers-mutagen-) - [Daemon | Mutagen ](#daemon-mutagen-) - [Local | Mutagen ](#local-mutagen-) - [File synchronization | Mutagen ](#file-synchronization-mutagen-) - [Ignores | Mutagen ](#ignores-mutagen-) - [Transports | Mutagen ](#transports-mutagen-) - [Licenses | Mutagen ](#licenses-mutagen-) - [Third-party trademarks | Mutagen ](#third-party-trademarks-mutagen-) - [Symbolic links | Mutagen ](#symbolic-links-mutagen-) - [SSH | Mutagen ](#ssh-mutagen-) - [Version control systems | Mutagen ](#version-control-systems-mutagen-) - [Permissions | Mutagen ](#permissions-mutagen-) - [Staging | Mutagen ](#staging-mutagen-) - [Probing and scanning | Mutagen ](#probing-and-scanning-mutagen-) - [Size limits | Mutagen ](#size-limits-mutagen-) - [Network forwarding | Mutagen ](#network-forwarding-mutagen-) - [Safety mechanisms | Mutagen ](#safety-mechanisms-mutagen-) - [TCP sockets | Mutagen ](#tcp-sockets-mutagen-) - [Watching | Mutagen ](#watching-mutagen-) - [Windows named pipes | Mutagen ](#windows-named-pipes-mutagen-) - [Mutagen Compose | Mutagen ](#mutagen-compose-mutagen-) - [Unix domain sockets | Mutagen ](#unix-domain-sockets-mutagen-) - [Tooling Integration | Mutagen ](#tooling-integration-mutagen-) - [Projects | Mutagen ](#projects-mutagen-) - [Mutagen Extension for Docker Desktop | Mutagen ](#mutagen-extension-for-docker-desktop-mutagen-) - [Docker Privacy | Docker](#docker-privacy-docker) - [Docker Privacy | Docker](#docker-privacy-docker) - [Docker Terms of Service | Docker](#docker-terms-of-service-docker) - [SSH Tips for Remote Development | Mutagen ](#ssh-tips-for-remote-development-mutagen-) - [Building a Robust Future for Mutagen | Mutagen ](#building-a-robust-future-for-mutagen-mutagen-) - [General | Mutagen ](#general-mutagen-) - [Docker Acquires Mutagen to Invest in Docker Desktop | Docker](#docker-acquires-mutagen-to-invest-in-docker-desktop-docker) - [Legal | Docker](#legal-docker) --- # Mutagen | Cloud-based development using your local tools Cloud-based development using your local tools ============================================== Mutagen provides real-time file synchronization and flexible network forwarding for developers, extending the reach of local development tools to cloud-based containers and infrastructure. [Learn more →](https://mutagen.io/documentation/introduction/) ![Docker logo](https://mutagen.io/img/docker.svg) **Docker Acquires Cloud-Development Startup Mutagen** As part of its continued investment in the performance and capabilities of Docker Desktop, **[Docker has acquired Mutagen](https://www.docker.com/blog/mutagen-acquisition/) **, a startup focused on high-performance local and cloud-based development. ![](https://mutagen.io/img/landing/icon_dish.svg) ##### Flexible transports Mutagen works across local, server, and container infrastructure, including Docker® containers. [Transports →](https://mutagen.io/documentation/transports/) ![](https://mutagen.io/img/landing/icon_computer.svg) ##### Cross-platform Mutagen supports a broad range of platforms, handling their idiosyncrasies automatically while offering users full control. [Install →](https://mutagen.io/documentation/introduction/installation/) ![](https://mutagen.io/img/landing/icon_open_source.svg) ##### Open-source Mutagen is an open-source tool that gives your full control over your data, how it's transmitted, and where it's stored. [Source code →](https://github.com/mutagen-io/mutagen) Fill in the gaps of remote development -------------------------------------- Running containers in the cloud is easy, but editing code and accessing applications there is hard. Mutagen bridges the gap between your local development tools and code in the cloud. ##### Synchronize code Move code in real-time with fast two-way file synchronization ------------------------------------------------------------- Mutagen syncs files between arbitrary locations using a custom algorithm designed specifically for code and build products. [Learn more →](https://mutagen.io/documentation/synchronization/) ![](https://mutagen.io/img/landing/icon_tachymeter.svg) ###### Performant Low-latency [filesystem watching](https://mutagen.io/documentation/synchronization/watching/) and differential file transfers propagate code changes almost instantly. ![](https://mutagen.io/img/landing/icon_terminal.svg) ###### Configurable Settings for [bidirectionality](https://mutagen.io/documentation/synchronization/#modes) , [permissions](https://mutagen.io/documentation/synchronization/permissions/) , [ignores](https://mutagen.io/documentation/synchronization/ignores/) , [symlinks](https://mutagen.io/documentation/synchronization/symbolic-links/) , and more are available for developers. ![](https://mutagen.io/img/landing/skeleton_editor.svg) ![](https://mutagen.io/img/landing/skeleton_browser.svg) ##### Forward traffic Connect to remote applications with powerful network forwarding --------------------------------------------------------------- Mutagen supports forwarding TCP traffic, Unix domain sockets, and Windows named pipes between arbitrary endpoints. [Learn more →](https://mutagen.io/documentation/forwarding/) ![](https://mutagen.io/img/landing/icon_topology.svg) ###### Flexible Mutagen's architecture allows arbitrary traffic flows, including remote-to-remote. ![](https://mutagen.io/img/landing/icon_forwarding.svg) ###### Adaptable Mutagen can mix and match transport layer protocols, making it easy to connect disparate components. ##### Develop remotely Unlock the full power of cloud-based development by making it feel local ------------------------------------------------------------------------ With Mutagen, you can shift the workload from your laptop to cloud-based servers and containers. [Learn more →](https://mutagen.io/documentation/orchestration/) ![](https://mutagen.io/img/landing/icon_containers.svg) ###### Container-ready Mutagen can connect directly to [Docker® containers](https://mutagen.io/documentation/transports/docker/) or work with Compose projects via its [Compose integration](https://mutagen.io/documentation/orchestration/compose/) . ![](https://mutagen.io/img/landing/icon_yaml.svg) ###### Orchestration-friendly Simply [annotate your Compose YAML](https://mutagen.io/documentation/orchestration/compose/) or use Mutagen's [project functionality](https://mutagen.io/documentation/orchestration/projects/) for easy integration. ![](https://mutagen.io/img/landing/skeleton_terminal.svg) ### Get started Read more about Mutagen ======================= You can find more information about how to install and use Mutagen in the documentation. [Documentation →](https://mutagen.io/documentation/introduction/) --- # Overview | Mutagen Contents Overview ======== Mutagen is a development utility that lets you use your existing local tools (such as your text editor/IDE, browser, and terminal) to work in remote environments like cloud servers and containers. It does this by providing high-performance file synchronization and flexible network forwarding, allowing you to develop applications in a way that _looks_ local but runs on remote hardware. Mutagen is completely [free and open-source](https://github.com/mutagen-io/mutagen) and works directly between your local system and the remote infrastructure that you need to access. Design ------ Unlike most other remote development solutions, Mutagen isn’t a plug-in or a wrapper, so it works with essentially any tool. It also doesn’t require manual installation on remote endpoints, instead using copy mechanisms like `scp` and `docker cp` to inject small “agent” binaries into remote environments and commands like `ssh` or `docker exec` as transports for communication. Mutagen’s [synchronization](https://mutagen.io/documentation/synchronization/) and [forwarding](https://mutagen.io/documentation/forwarding/) facilities are designed to be extremely flexible, operating between arbitrary pairs of endpoints using any combination of [transports](https://mutagen.io/documentation/transports/) . This includes cases where both endpoints are remote, allowing for synchronization and forwarding that’s simply proxied through your local system. In addition to manual and scripted management of synchronization and forwarding, tooling is available to help automate and integrate this functionality with your existing development workflows. Mutagen offers a [Docker Desktop extension](https://mutagen.io/documentation/docker-desktop-extension/) as well as [a Mutagen-aware Compose implementation](https://mutagen.io/documentation/orchestration/compose/) . For non-Docker projects, Mutagen offers a generic [project format](https://mutagen.io/documentation/orchestration/projects/) for automation. File synchronization -------------------- Mutagen’s file synchronization is designed to facilitate real-time remote code editing with your existing text editor or IDE, allowing you to quickly test code changes in a remote environment without having to re-deploy. It has rsync-like performance, coupled with low-latency filesystem watching and the ability to operate in both unidirectional and bidirectional modes. In addition to code, it can easily handle build artifacts, analysis outputs, or even your coding music collection. Since Mutagen is development-focused, it gives users granular control over behaviors like conflict resolution, ignores, symbolic link handling, permission propagation, and more. It’s also aggressively cross-platform, meaning that platform-specific quirks are handled automatically and Windows-to-POSIX development isn’t a problem. Network forwarding ------------------ Mutagen’s network forwarding is designed to let you access remote applications without exposing ports publicly, as well as link application components that might exist in separate locations. Mutagen currently supports forwarding IPv4/v6 TCP traffic as well as Unix domain sockets and Windows named pipes. Mutagen can even mix transport layer protocols, for example mapping a local Unix domain socket to a remote TCP listener. Getting started --------------- To learn more about Mutagen and get a basic understanding of how it works, check out the [Getting started](https://mutagen.io/documentation/introduction/getting-started/) guide. --- # Installation | Mutagen Contents Installation ============ Mutagen can be installed in two ways: manually or via [Homebrew](https://brew.sh/) . Work is underway to bring packaging to other platforms, so please check back regularly. **Note:** A Mutagen installation is **not** required to use the [Mutagen extension for Docker Desktop](https://mutagen.io/documentation/docker-desktop-extension/) . The extension is [installed separately](https://mutagen.io/documentation/docker-desktop-extension/#installation) . Homebrew -------- Homebrew users (on both macOS and Linux®) can install Mutagen using the following command: # Subscribe to the stable release channel brew install mutagen-io/mutagen/mutagen Other platforms --------------- On other platforms, Mutagen can be installed by [downloading](https://github.com/mutagen-io/mutagen/releases/latest) the appropriate release and adding its contents to your path. Development channels -------------------- There are two development release channels that allow Homebrew users to experiment with new features before they hit the stable release channel: beta and edge. Neither of these channels is officially supported, but testing and feedback for the releases in them is essential to ensuring stable, correct, and performant final releases. Beta channel releases are fairly stable and can be thought of as something akin to release candidates. Beta channel releases can be installed using: # Subscribe to the beta release channel brew install mutagen-io/mutagen/mutagen-beta Edge channel releases should be considered unstable and shouldn’t be the default for _any_ user. These are essentially nightly/alpha builds. Features may appear and then disappear in edge channel releases, depending on how their development progresses. # Subscribe to the edge release channel (NOT RECOMMENDED!) brew install mutagen-io/mutagen/mutagen-edge The synchronization and forwarding sessions created with beta and edge channel releases may not be forward-compatible with final release versions of Mutagen (which do maintain compatibility across versions). --- # Getting started | Mutagen Contents Getting started =============== This guide aims to provide a basic introduction to Mutagen’s design and usage, providing links along the way to more advanced topics and features. It focuses on manual usage, though the topics introduced here are a prerequisite for understanding Mutagen’s higher-level [orchestration features](https://mutagen.io/documentation/orchestration/) . Design ------ Mutagen is designed and operated around the concept of individual synchronization and forwarding _**sessions**_. Each session operates between two _**endpoints**_. In the case of synchronization, these endpoints are file system locations, and in the case of forwarding, these endpoints are network endpoints. What makes Mutagen uniquely powerful is that sessions can combine any pair of endpoints, regardless of their location or access mechanism. Common usage scenarios include synchronizing source code from your laptop to a remote server or container, or forwarding requests from local TCP endpoints to remote web servers. But Mutagen can also do things like synchronize files between two remote filesystems using the local system as a proxy, or perform reverse tunneling from a remote system to a service running on your laptop. If you have a problem where you need to synchronize files efficiently or forward network traffic flexibly, then Mutagen can most likely be used to solve it. Mutagen can manage any number of concurrent sessions, each of which can be as ephemeral or permanent as necessary. The `mutagen` command itself is designed entirely around managing session lifecycles. The following sections provide an outline of the Mutagen session lifecycle by demonstrating their creation, management, and termination. This guide doesn’t aim to be an exhaustive exploration of the `mutagen` command, and many other options can be discovered in other parts of the documentation and via the command’s built-in help information: # Show general help. mutagen --help # Show help for a specific command. mutagen --help ### Daemon Before getting into the session management commands, it’s worth mentioning the Mutagen daemon. The daemon is the core of the Mutagen architecture. It runs in the background as a per-user process, hosting and managing synchronization sessions. While most of the daemon’s lifecycle is automatic, and you don’t need to know anything about it to read this guide, it is important to know about in general. More information can be found in the about the daemon in a [later section](https://mutagen.io/documentation/introduction/daemon/) . Session management ------------------ Mutagen provides two sets of session management commands: one for synchronization sessions (`mutagen sync`) and one for forwarding sessions (`mutagen forward`). They have approximately the same structure, with only a few minor differences to account for their different purposes. ### Creating sessions To create synchronization and forwarding sessions, you use the `mutagen sync create` and `mutagen forward create` commands, respectively. Creating a session in Mutagen is as simple as invoking a creation command with two endpoint URLs, for example: # Create a synchronization session named "web-app-code" between the local path # ~/project and an SSH-accessible endpoint. mutagen sync create --name=web-app-code ~/project user@example.org:~/project or # Create a forwarding session named "web-app" between port 8080 on localhost and # port 1313 inside a Docker container. mutagen forward create --name=web-app tcp:localhost:8080 docker://devcontainer:tcp:localhost:1313 The `create` commands each take two endpoint specifications and create a session between them. The format for each endpoint specification depends on the desired [transport](https://mutagen.io/documentation/transports/) . For SSH-accessible endpoints, Mutagen uses OpenSSH under the hood, so all of your settings, keys, and aliases will be automatically available. For Docker® containers, Mutagen shells out directly to the `docker` command, so `DOCKER_HOST` and other settings are respected (and stored) when the session is created. If confirmation or authentication is required to connect to a remote endpoint, then the `create` command will prompt accordingly. The exact format for the endpoint specifications and meaning of their order depends on whether the session is a [synchronization](https://mutagen.io/documentation/synchronization/) or [forwarding](https://mutagen.io/documentation/forwarding/) session. Both `create` commands also take a large number of [configuration](https://mutagen.io/documentation/introduction/configuration/) options, all of which are documented in later sections. ### Session identification Once created, each Mutagen session can be addressed in three different ways: by name, by label, or by session identifier. Names are optional user-friendly identifiers that can be used to identify sessions to other commands. Labels are optional key-value pairs that can be attached to sessions and queried to perform more complex session selection. Session identifiers are unique strings that Mutagen generates automatically, allowing for unambiguous session specification. Session identifiers are printed out when a session is created and are also available via the `list` commands described in the next section. More information about each of these can be found in the guide on [names, labels, and identifiers](https://mutagen.io/documentation/introduction/names-labels-identifiers/) . ### Listing sessions The `mutagen sync list` and `mutagen forward list` commands show the current status of synchronization and forwarding sessions, respectively, for example: $ mutagen sync list Name: web-app-code Identifier: sync_rJA9OdPDEtIVcqwhOMlBw2BvMgpctZXUsEr4Jl3kUd7 Labels: None Alpha: URL: /home/user/project Connection state: Connected Beta: URL: user@example.org:~/project Connection state: Connected Status: Watching for changes or $ mutagen forward list Name: web-app Identifier: fwrd_6mkwS3yuAZyD1VmDtUvCgn3pwqMQf28V4EbxLLvm8OI Labels: None Source: URL: tcp:localhost:8080 Connection state: Connected Destination: URL: docker://devcontainer:tcp:localhost:1313 Connection state: Connected Status: Forwarding connections In the case of synchronization, this output will include any conflicts or problems that have arisen in the propagation of changes between endpoints. If no sessions or label selectors are specified to the `list` commands, they will simply print all sessions. More detailed listing output is available through the `-l/--long` flag. ### Monitoring a session The `monitor` command shows live monitoring information for a session, for example: $ mutagen sync monitor web-app-code Name: web-app-code Identifier: sync_rJA9OdPDEtIVcqwhOMlBw2BvMgpctZXUsEr4Jl3kUd7 Labels: None Alpha: /home/user/project Beta: user@example.org:~/project Status: Staging files on beta: 75% (8942/11782) or $ mutagen forward monitor web-app Name: web-app Identifier: fwrd_6mkwS3yuAZyD1VmDtUvCgn3pwqMQf28V4EbxLLvm8OI Labels: None Source: tcp:localhost:8080 Destination: docker://devcontainer:tcp:localhost:1313 Status: Forwarding connections: 4 active, 4 total If no session is specified, the `monitor` commands will show information for the most recently created session of the relevant type. ### Pausing sessions Synchronization or forwarding can be temporarily halted for a session using the `pause` commands, for example: # Pause the synchronization session named "web-app-code". mutagen sync pause web-app-code or # Pause the forwarding session named "web-app". mutagen forward pause web-app A session will remain paused until manually resumed. ### Resuming sessions Sessions can be resumed using the `resume` commands, for example: # Pause the synchronization session named "web-app-code". mutagen sync resume web-app-code or # Resume the forwarding session named "web-app". mutagen forward resume web-app These commands will ensure that the specified sessions are unpaused and attempting to synchronize or forward. They can also be used to provide user input (for example, a password) in cases where the daemon can’t automatically reconnect to an endpoint in the background because confirmation or authentication is required. Finally, the `mutagen sync resume` command can be used to resume synchronization when Mutagen’s [safety mechanisms](https://mutagen.io/documentation/synchronization/safety-mechanisms/) detect a synchronization anomaly and halt synchronization. ### Flushing sessions Synchronization cycles can be manually triggered for synchronization sessions using the `mutagen sync flush` command, for example: # Flush the synchronization session named "web-app-code". mutagen sync flush web-app-code This command will manually trigger a synchronization cycle for the session. This is particularly useful when combined with the [`no-watch` filesystem watching mode](https://mutagen.io/documentation/synchronization/watching/#modes) , allowing users to manually control when synchronization occurs or to integrate with external filesystem watching tools (such as [Watchman](https://facebook.github.io/watchman/) ). ### Resetting sessions Synchronization sessions can have their histories cleared (causing them to behave like newly created sessions with the same configuration) using the `mutagen sync reset` command, for example: # Reset the synchronization session named "web-app-code". mutagen sync reset web-app-code This command is mostly useful in cases where one of [Mutagen’s safety mechanisms](https://mutagen.io/documentation/synchronization/safety-mechanisms/) engages. It can also be helpful when recreating containerized infrastructure where the filesystem isn’t persistent. ### Terminating sessions Synchronization or forwarding can be permanently halted (and the session deleted) using the `terminate` commands, for example: # Terminate the synchronization session named "web-app-code". mutagen sync terminate web-app-code or # Terminate the forwarding session named "web-app". mutagen forward terminate web-app For synchronization sessions, this will not delete files at either endpoint (but should be done before manually deleting files on either endpoint to avoid propagating any deletions). --- # Blog | Mutagen [Blog](https://mutagen.io/blog) › Recent posts * * * [![](https://mutagen.io/img/social/twitter_blue.svg) Follow on Twitter](https://twitter.com/mutagen_io) [Blog](https://mutagen.io/blog) › Recent posts * * * [![](https://mutagen.io/img/social/twitter_blue.svg) Follow on Twitter](https://twitter.com/mutagen_io) [Docker Acquires Mutagen for Continued Investment in Performance and Flexibility of Docker Desktop\ =================================================================================================](https://mutagen.io/blog/mutagen-is-joining-docker/) ![Justin Cormack](https://mutagen.io/img/authors/justin-cormack.png) [Justin Cormack](https://www.docker.com/author/justin-cormack/) in [General](https://mutagen.io/blog/category/general) 27 June 2023 I’m excited to announce that Docker, voted the most-used and most-desired tool in Stack Overflow’s [2023 Developer Survey](https://survey.stackoverflow.co/2023/#section-most-popular-technologies-other-tools) , has acquired [Mutagen IO, Inc](https://mutagen.io/) , the company behind the open source Mutagen file synchronization and networking technologies that enable high-performance remote development. [Read more →](https://mutagen.io/blog/mutagen-is-joining-docker/) [Building a Robust Future for Mutagen\ ====================================](https://mutagen.io/blog/building-a-robust-future-for-mutagen/) ![Jacob Howard](https://mutagen.io/img/authors/jacob-howard.png) [Jacob Howard](https://twitter.com/xenoscopic) in [General](https://mutagen.io/blog/category/general) 21 February 2023 [Mutagen v0.17](https://github.com/mutagen-io/mutagen/releases/tag/v0.17.0) is bringing some fundamental changes to Mutagen’s licensing and monetization model, but not its commitment to open-source and sustainability. I wanted to give users an overview of Mutagen’s roadmap and hopefully address any concerns that might arise due to these changes. [Read more →](https://mutagen.io/blog/building-a-robust-future-for-mutagen/) [SSH Tips for Remote Development\ ===============================](https://mutagen.io/blog/ssh-tips-for-remote-development/) ![Jacob Howard](https://mutagen.io/img/authors/jacob-howard.png) [Jacob Howard](https://twitter.com/xenoscopic) in [General](https://mutagen.io/blog/category/general) 8 January 2020 SSH is undoubtedly one of the most powerful tools for enabling remote development. Over a history spanning decades, SSH has proven itself to be reliable, security-focused, and flexible. Since SSH is one of Mutagen’s core transports, I felt that it would be useful to share a handful of simple but powerful features that I use on a daily basis to drastically improve my SSH experience and remote development workflows. [Read more →](https://mutagen.io/blog/ssh-tips-for-remote-development/) --- # Names, labels, and identifiers | Mutagen Contents Names, labels, and identifiers ============================== Mutagen provides three mechanisms for identifying and selecting sessions: **names**, **labels**, and session **identifiers**. These mechanisms can be used to identify sessions in listings and to select sessions when using session management commands. Names ----- Names are user-provided identifiers that can be attached to sessions. Names are optional and aren’t guaranteed to be unique. Each session can have only a single name. Names are particularly useful for manual usage, where a simple identifier for selecting sessions is desirable and the chance of name collisions is low. Names can currently contain any Unicode letter (Unicode category L), number (Unicode category N), or a dash (`-`), though they must start with a letter. Names, if provided, must also be non-empty and must not be “defaults”. Names can be provided to session management commands as arguments, in which case all sessions with a matching name will be selected. Labels ------ Labels are user-provided key/value pairs that are attached to sessions, allowing sessions to be selected via a query. Mutagen re-uses the Kubernetes label and selector implementation and thus shares the same [syntax/semantics](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set) and [selector format](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors) . Label selectors can be provided to session management commands using the `--label-selector` flag, in which case all sessions with labels matching the selector will be selected. Identifiers ----------- Each Mutagen session is also assigned a unique identifier that allows it to be addressed unambiguously. These values are printed at session creation time and can also be found via the `mutagen sync list` and `mutagen forward list` commands. Session identifiers can be provided to session management commands as arguments, providing the most reliable way to uniquely identify sessions. --- # Configuration | Mutagen Contents Configuration ============= Mutagen has multiple levels of configuration that are merged together and locked-in at session creation time. These include built-in defaults, the global configuration file, command line configuration, and other configuration files. Once the configuration for a session is locked-in, it can’t be changed (without recreating the session). The purpose of this design is to prevent unintended behavioral changes from occuring for existing sessions when configuration files are updated. When configuration levels are merged, more specific configuration levels take precedence. For example, configuration parameters provided on the command line take precedence over those provided in the global configuration file. For certain configuration parameters (specifically ignore specification lists), merging means appending lists, with the more specific list being appended to the end of the less specific list to allow for overrides. Some parameters also permit endpoint-specific specifications that take precedence over the core merged session configuration. This guide aims to give an outline of the configuration hierarchy, with individual configuration parameters described in their respective documentation. Built-in defaults ----------------- Every configuration parameter has a default value. Mutagen’s built-in defaults are designed to be safe and portable. The value for each of these defaults can be found in the relevant documentation for a given parameter. Global configuration -------------------- Mutagen’s global configuration is stored at `~/.mutagen.yml`. If it exists, this file will be merged into the session configuration, taking precedence over built-in defaults. This configuration is loaded and applied automatically to all sessions, including those created using Mutagen’s orchestration infrastructure, unless the `--no-global-configuration` flag is passed to the relevant session creation command (`mutagen sync create`, `mutagen forward create`, or `mutagen project start`). ### Format All of Mutagen’s configuration files share the same YAML-based format. The global configuration permits only a subset of this format, namely session defaults. The complete format for this file is as follows: sync: defaults: mode: ... maxEntryCount: ... maxStagingFileSize: ... probeMode: ... scanMode: ... stageMode: ... symlink: mode: ... watch: mode: ... pollingInterval: ... ignore: paths: - ... - ... vcs: ... permissions: defaultFileMode: ... defaultDirectoryMode: ... defaultOwner: ... defaultGroup: ... forward: defaults: socket: overwriteMode: ... owner: ... group: ... permissionMode: ... The `...` values in this case represent the values that can be used for each configuration parameter. These values are documented in their respective sections throughout the documentation. All parameters are optional. Configuration files ------------------- An additional configuration file, with the same format as the global configuration, can be specified to `mutagen sync create` and `mutagen forward create` using the `-c/--configuration-file` flag. If provided, this file will be merged into the session configuration, taking precedence over the global configuration (if any) and built-in defaults. Command line configuration -------------------------- Both the `mutagen sync create` and `mutagen forward create` commands permit the specification of any session configuration parameter. If provided, these parameters are merged into the session configuration, taking precedence over specifications from any other source. These commands also permit endpoint-specific overrides for certain configuration parameters. --- # Docker® containers | Mutagen Contents Docker® container endpoints =========================== Mutagen has support for synchronizing files and forwarding network traffic to and from Docker® containers. This support extends to all Docker client platforms (Linux®, macOS, Windows, etc.), Docker daemon setups (local, remote, VM, Hyper-V, etc.), and Docker container types (both Linux and Windows containers are supported). **Tip:** This page describes Mutagen’s low-level Docker transport. This transport is useful if you want to integrate Mutagen into a script or tool that targets Docker containers. For turnkey containerized development options, check out the [Mutagen extension for Docker Desktop](https://mutagen.io/documentation/docker-desktop-extension/) and/or [Mutagen Compose](https://mutagen.io/documentation/orchestration/compose/) . **Caution:** Mutagen assumes that the transport from the `docker` command to the Docker daemon is secure, and thus Mutagen provides no encryption on top of this transport. For information about securing the Docker daemon, please see the [relevant documentation](https://docs.docker.com/engine/security/https/) . Requirements ------------ Mutagen requires the `docker` command to be in the user’s path. Due to its use of the `-w/--workdir` flag with the `docker exec` command, Mutagen requires a Docker client and daemon supporting API 1.35+. You can check the API version support of your Docker client and daemon by using the `docker version` command. Synchronization --------------- Docker container filesystem endpoints can be specified to the `mutagen sync create` command using URLs of the form: docker://[@] These URLs support Unicode names and paths and neither require nor support URL escape encoding (i.e. just type “ö”, not “%C3%B6”, etc.). The `` component is optional and tells Mutagen to run as the specified user inside the container. If unspecified, Mutagen operates as the default container user (usually `root` for Linux containers or `ContainerAdministrator` for Windows containers). In either case, the user should be chosen in such a way as to allow access permissions to the target path and to generate files with the correct permissions. Using an administrative user (such as `root`) for access and [setting permissions explicitly](https://mutagen.io/documentation/synchronization/permissions/) is often the most robust strategy with containers. The `` component can specify any type of container identifier understood by `docker cp` and `docker exec` (for example, a container name or hexidecimal identifier). The `` component must be non-empty and must start with a `/`. It can take one of four forms: an absolute path, a home-directory-relative path, a home-directory-relative path for an alternate user, or a Windows absolute path. In the case of a Windows path, the `/` character is still requird at the start of the path. Docker containers must be running to create synchronization sessions and to allow synchronization to run. Example Docker container synchronization URLs * `docker://project_container_1/var/www` Target an absolute path in the container named `project_container_1`. * `docker://9ba4bcda42fe/~/project` Target a path relative to the default container user's home directory in the container with the ID `9ba4bcda42fe`. * `docker://george@9ba4bcda42fe/~/project` Target a path relative to the `george` user's home directory in the container with the ID `9ba4bcda42fe`. * `docker://project_container_1/~otheruser/project` Target a path relative to a specific user's home directory in the container named `project_container_1`. * `docker://windows_container_1/C:\path` Target an absolute path in a Windows container named `windows_container_1`. Note that, in POSIX shells, the backslash character will require quoting or escaping. Forwarding ---------- Docker container network endpoints can be specified to the `mutagen forward create` command using URLs of the form: docker://[@]: The `` and `` components of this URL are the same those in the synchronization URL format described above, while the `` component is described in the [forwarding documentation](https://mutagen.io/documentation/forwarding/#endpoint-urls) . As with synchronization, the `` component (or absence thereof) should be chosen to ensure the necessary in-container capabilities (e.g. binding to privileged ports). In the case of relative Unix domain socket paths in network endpoints, path resolution will be performed relative to the home directory of the container user (i.e. the user specified in the URL or the default container user if none is specified in the URL). Docker containers must be running to create forwarding sessions and to allow forwarding to run. Example Docker container forwarding URLs * `docker://project_container_1:tcp::8080` Bind to all network interfaces on port `8080` in the container named `project_container_1`. * `docker://george@project_container_1:tcp:localhost:8080` Bind to or target the loopback interface on port `8080` as the user `george` in the container named `project_container_1`. * `docker://project_container_1:tcp6:localhost:8080` Bind to or target the IPv6 loopback interface on port `8080` in the container named `project_container_1`. * `docker://george@project_container_1:tcp:10.0.1.25:6060` Bind to or target `10.0.1.25` on port `6060` as the user `geroge` in the container named `project_container_1`. * `docker://9ba4bcda42fe:unix:/path/to/socket.sock` Bind to or target a Unix domain socket using an absolute path in the container with the ID `9ba4bcda42fe`. * `docker://project_container_1:unix:path/to/socket.sock` Bind to or target a Unix domain socket using a relative path in the container named `project_container_1`. Path resolution in this case is relative to the home directory of the default container user. * `docker://project_container_1:unix:~/path/to/socket.sock` Bind to or target a Unix domain socket relative to the default container user's home directory in the container named `project_container_1`. * `docker://project_container_1:unix:~otheruser/path/to/socket.sock` Bind to or target a Unix domain socket relative to a specific user's home directory in the container named `project_container_1`. Environment variables --------------------- The Docker client’s behavior is controlled by several environment variables: * `DOCKER_HOST` * `DOCKER_TLS_VERIFY` * `DOCKER_CERT_PATH` * `DOCKER_API_VERSION` * `DOCKER_CONTEXT` (in Mutagen v0.12+) Mutagen is aware of these environment variables and will lock them in at session creation time (as seen by the `mutagen sync create` and `mutagen forward create` commands), including locking in absent or empty values. These locked in values will then be forwarded to any `docker` commands executed by Mutagen. If required, endpoint-specific versions of these variables (prefixed with `MUTAGEN_ALPHA_`/`MUTAGEN_BETA_` for synchronization sessions and `MUTAGEN_SOURCE_`/`MUTAGEN_DESTINATION_` for forwarding sessions) can be used to override their values on a per-endpoint basis. This would be necessary to, for example, create a synchronization session between two Docker containers hosted on different Docker daemons. In that case, single global values for `DOCKER_*` environment variables can’t be used (since it would apply to both endpoint URLs), and endpoint-specific variables such as `MUTAGEN_ALPHA_DOCKER_HOST` or `MUTAGEN_BETA_DOCKER_TLS_VERIFY` would need to be used when invoking `mutagen sync create`. Implementation -------------- Mutagen’s support for Docker containers is provided by the Docker client executable on your system. Mutagen uses the `docker cp` command to copy agent binaries into containers and the `docker exec` command to run and communicate with the agent binaries over standard input/output streams. ### Windows containers Docker Windows containers are run using Microsoft’s Hyper-V hypervisor, which unfortunately does not allow `docker cp` operations to copy files into running containers. This means that Mutagen has to stop and restart Windows containers in order to copy its agent executables. Mutagen will prompt the user if this is necessary and allow the user to abort or proceed. If the user decides to proceed, the stop and restart will be automatically performed by Mutagen. This is only necessary if a compatible agent binary doesn’t already exist in the container, so it won’t be necessary on subsequent connection operations. This restriction does not apply to Linux containers. Docker search path ------------------ Mutagen uses the first `docker` executable found in the user’s path (and on macOS includes a few other well-known search paths). This search strategy can be overridden by setting the `MUTAGEN_DOCKER_PATH` environment variable (for the Mutagen daemon) to a path containing the desired Docker client executable. Windows and Chocolatey ---------------------- If you’re using [Chocolatey](https://chocolatey.org/) to install the Docker CLI on Windows, please be aware that Chocolatey generates shim executables that break the standard input/output streaming that Mutagen uses. Fortunately, you can point Mutagen to the unshimmed executables to avoid this breakage by setting the `MUTAGEN_DOCKER_PATH` environment variable. This setting should look like: MUTAGEN_DOCKER_PATH=C:\ProgramData\chocolatey\lib\docker-cli\tools You may need to adjust this path depending on your Chocolatey installation. You can also use the `%ChocolateyInstall%` environment variable as part of this definition, for example: MUTAGEN_DOCKER_PATH=%ChocolateyInstall%\lib\docker-cli\tools --- # Daemon | Mutagen Contents Daemon ====== At the core of Mutagen’s architecture is the Mutagen daemon. The Mutagen daemon is a per-user process that runs in the background, hosting and managing Mutagen’s synchronization and forwarding sessions. All of Mutagen’s session management commands actually dispatch their operations to the daemon and simply output its feedback. Although it’s not a user-facing component, understanding the behavior and lifecycle of the daemon is critical to using Mutagen effectively. Lifecycle --------- The daemon is designed to operate on a per-user basis. Only a single instance of the daemon is allowed to run for a particular user at any given time. The lifecycle of this instance can be managed in three different ways: automatically, manually, or by the system. All three of these mechanisms can be used in conjunction with one another (for example, you can manually stop a daemon that was automatically started). ### Automatic management If it’s not already running, the daemon will be started automatically when any session management command is invoked. At system shutdown time, the daemon will terminate gracefully. If you wish to disable automatic daemon startup, you can set the environment variable `MUTAGEN_DISABLE_AUTOSTART=1`. ### Manual management The daemon can be started manually using the `mutagen daemon start` command. This command is fast and idempotent, so it can safely be added to your shell initialization script (for example `.bashrc` or `.profile`) if you want the daemon to start automatically when you open a shell. The daemon can also be stopped manually using the `mutagen daemon stop` command. ### System management If you wish to have the daemon start automatically without any intervention, experimental support for registering the daemon to start automatically on login is available for macOS and Windows via the `mutagen daemon register` command. Upgrading --------- The API that session management commands use to communicate with the daemon isn’t currently stable, so the daemon needs to be restarted when upgrading Mutagen: $ mutagen daemon stop $ mutagen daemon start If you forget, don’t worry, Mutagen will simply print a warning message the next time you try to invoke a session management command. Embedding --------- Experimental support is available for embedding Mutagen and its daemon into other applications. There are two steps to this process: changing the Mutagen data directory to create an isolated daemon instance and (optionally) hosting the daemon process directly. Mutagen’s data directory stores session configurations, synchronization archives, and more. It’s also the location of the Mutagen daemon IPC endpoint and lock. Its default location is `~/.mutagen`, but this can be changed by setting the `MUTAGEN_DATA_DIRECTORY` environment variable. If specified at daemon startup, this environment variable will tell the daemon to store its data and IPC endpoint in an alternate location. The same environment variable can then be used to tell session management commands where to find that isolated daemon’s IPC endpoint. This variable should be set to an absolute path. If desired, the daemon can also be hosted by the embedding process by invoking its entry point directly using the hidden `mutagen daemon run` command. Unlike the `mutagen daemon start` command, this will avoid starting the daemon process in the background. The child process can then be terminated directly by the hosting process. --- # Local | Mutagen Contents Local endpoints =============== Mutagen’s local transport provides support for synchronizing and forwarding to and from local filesystem locations and network endpoints, respectively. Synchronization --------------- Local filesystem endpoints can be specified to the `mutagen sync create` command using their local path in either an absolute or relative format. If a relative path is specified, then it will be resolved relative to the working directory in which the `mutagen sync create` command is issued. Forwarding ---------- Local forwarding endpoints can be specified to the `mutagen forward create` command as raw network endpoints. For a description of the network endpoint format, please see the [forwarding documentation](https://mutagen.io/documentation/forwarding/#endpoint-urls) . In the case of relative Unix domain socket paths, path resolution will be performed relative to the directory in which the `mutagen forward create` command is issued. --- # File synchronization | Mutagen Contents File synchronization ==================== Mutagen’s file synchronization uses a novel algorithm that combines the performance of the [rsync algorithm](https://www.samba.org/~tridge/phd_thesis.pdf) with bidirectionality and low-latency filesystem watching. It can be used (for example) to synchronize code between your laptop and a remote container in effective real-time, allowing you to edit code with your editor of choice and have it pushed to the remote environment almost instantly. Because it uses differential transfers, Mutagen’s synchronization also works effectively for transferring large binary files such as images or build artifacts. Design and architecture ----------------------- Mutagen’s synchronization sessions each operate between an arbitrary pair of endpoints, termed **alpha** and **beta**. The reason that these endpoints aren’t termed “source” and “destination” is that Mutagen has multiple synchronization modes, including bidirectional modes, where these terms don’t necessarily apply. Thus, the order of endpoints provided to the `mutagen sync create` command simply establishes these _identities_ (with the first endpoint being alpha and the second being beta), whereas the _roles_ of these endpoints are determined by the [synchronization mode](https://mutagen.io/documentation/synchronization/#modes) . Synchronization sessions are extremely flexible, allowing both endpoints to be local, one to be local and one to be remote, or both to be remote (in which case the local system is simply used as a proxy and controller for synchronization). This flexible topology, combined with the myriad [synchronization configuration](https://mutagen.io/documentation/synchronization/#configuration) options, allows users to create arbitrarily complex synchronization topologies. Internally, the synchronization algorithm uses a three-way merge to reconcile changes from both endpoints in a safe and controlled fashion. This means that synchronization sessions track the most-recently agreed-upon content and use that information to detect the changes that each endpoint has made, as well as any conflicts. This algorithm operates in short cycles, with every filesystem change triggering a cycle. Each cycle consists of a scan of both endpoints, a reconciliation of endpoint contents, staging of updated contents from one endpoint to another, and application of changes. These cycles are designed to be extremely efficient, to the point of being imperceptibly fast for most content and changes. Modes ----- Mutagen provides four different synchronization modes: * **`two-way-safe` (Default)**: In this bidirectional synchronization mode, both endpoints are treated with equal precedence, and conflicts are only automatically resolved if they don’t result in data loss (for example, modifications on one endpoint can can overwrite deletions of the corresponding content on the other endpoint). If conflicts can’t be automatically resolved, they are stored in the session state (and can be enumerated with the `mutagen sync list` command). * **`two-way-resolved`**: This is the same as `two-way-safe`, except that the alpha endpoint automatically wins all conflicts, including cases where alpha’s deletions would overwrite beta’s modifications or creations. No conflicts can occur in this synchronization mode. * **`one-way-safe`**: In this unidirectional synchronization mode, changes are only allowed to propagate from alpha to beta. Deletions on beta are overwritten by content from alpha (i.e. the content comes right back), but modifications and creations on beta can’t be overwritten by alpha (unless both endpoints have made the same modifications or created the same content). Conflicting contents on beta that can’t be overwritten will be recorded to the session state (and can be enumerated with the `mutagen sync list` command). Extra content on beta that doesn’t conflict with contents on alpha is simply ignored. * **`one-way-replica`**: In this unidirectional synchronization mode, beta becomes an exact replica of alpha. Any modifications or additional content on beta are instantly overwritten or removed, respectively. No conflicts can occur in this synchronization mode. You can think of these modes as existing in a table: | | Safe | Auto-resolved | | --- | --- | --- | | Bidirectional | `two-way-safe` | `two-way-resolved` | | Unidirectional | `one-way-safe` | `one-way-replica` | “Safe” in this case means that conflicts are only automatically resolved if they don’t result in the loss of unsynchronized data. “Auto-resolved” means that the alpha endpoint wins any conflict, even if it involves deleting additional unsynchronized content from beta. These modes can be specified on a per-session basis by passing the `-m/--sync-mode=` flag to the `mutagen sync create` command. These modes can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: mode: "" ### Conflict resolution Conflicts (which can occur in `two-way-safe` and `one-way-safe` modes) can be resolved manually by deleting the content on the endpoint which you wish to have lose the conflict. Once deleted, the conflict will no longer exist since deletions can be overwritten. Endpoint URLs ------------- Synchronization endpoint URLs are nothing more than pointers to local or remote filesystem locations. The exact format for forwarding endpoint URLs is [transport-dependent](https://mutagen.io/documentation/transports/) , but each contains a path component identifying the filesystem location to be synchronized. Filesystem locations can be directory hierarchies or individual files — Mutagen can synchronize either. Mutagen only applies a few restrictions to synchronization endpoints: * Symbolic links aren’t allowed as synchronization roots, though they can exist as part of the parent path of a synchronization roots, and of course are allowed to exist inside of synchronization roots. * Synchronization of directory hierarchies that span filesystem boundaries is not allowed. In both cases, Mutagen will detect and warn about the condition. Configuration ------------- Synchronization configuration is extensive, with configuration options controlling: * [Synchronization modes](https://mutagen.io/documentation/synchronization/#modes) * [Ignores](https://mutagen.io/documentation/synchronization/ignores/) * [Permissions](https://mutagen.io/documentation/synchronization/permissions/) * [Symbolic links](https://mutagen.io/documentation/synchronization/symbolic-links/) * [Filesystem watching](https://mutagen.io/documentation/synchronization/watching/) * [Filesystem probing and scanning](https://mutagen.io/documentation/synchronization/probing-and-scanning/) * [File staging](https://mutagen.io/documentation/synchronization/staging/) * [Size limits](https://mutagen.io/documentation/synchronization/size-limits/) Session management ------------------ Synchronization sessions are managed using the `mutagen sync` commands, namely `create`, `list`, `monitor`, `flush`, `pause`, `resume`, and `terminate`. Example usage for these commands can be found in the [Getting started](https://mutagen.io/documentation/introduction/getting-started/) guide. The `create` command comes with a number of flags that control the configuration of the sessions that it creates, and the other synchronization session management commands all include flags that control their behavior. For more information about a particular command, use: # Show help about a particular synchronization session management command. mutagen sync --help --- # Ignores | Mutagen Contents Ignores ======= By default, Mutagen attempts to propagate all files that it sees within a synchronization root. This isn’t always desirable, so Mutagen supports ignoring paths within a synchronization root and excluding them from synchronization. When a path is ignored, it won’t be scanned, it won’t be propagated, and it won’t be deleted. Mutagen allows ignores to be specified on both a default and per-session basis. It supports a rich syntax for specifying ignores, which should be familiar to Git users. In fact, the syntax and behavior is almost identical to Git’s (with a few helpful extensions), so the [`gitignore`](https://git-scm.com/docs/gitignore) documentation is another useful reference for understanding ignore behavior and strategies. Finally, Mutagen provides utilities for ignoring certain kinds of common directories, such as data directories from version control systems. Global ignores -------------- Global ignores affect all newly created sessions. These should be used for files that should always be ignored (for example, those pesky `.DS_Store` files on macOS). When a new session is created, global ignores are “locked in” to the session configuration, meaning that subsequent changes to global ignores will only be reflected in subsequently created sessions. This is for simplicity (no need to think through the effects of changing ignores in one place) and safety (no files will suddenly become unignored and propagated (causing conflicts or security risks) or silently ignored). Global ignores are specified in the `~/.mutagen.yml` file as follows: sync: defaults: ignore: paths: - "" - "" - ... The format of ignore specifications is outline below. Per-session ignores ------------------- Per-session ignores only affect the session to which they are attached. They are processed after global ignores, meaning that they can extend or cancel out global ignores. To specify ignores on a per-session basis, use the `-i/--ignore` flag of the `mutagen sync create` command. Multiple ignores can be specified using repeated `-i/--ignore` flags, for example: mutagen sync create -i -i ... or using comma-separated values, for example: mutagen sync create --ignore=, ... Ignore groups ------------- Mutagen provides ignore “groups” that provide a pre-defined set of ignores that can be used for sessions. At the moment, only one ignore group is defined in Mutagen, which ignores VCS directories (for example, `.git`, `.svn`, etc.), though additional ignore groups (for example, for Python object code files, `node_modules` directories, etc.) will be coming in future versions. Ignore groups are processed before both global and per-session ignores, so they can be extended or cancelled out by global and per-session ignores. ### Version control systems Version control system (VCS) directories can be ignored on a per-session basis by passing the `--ignore-vcs` flag to the `create` command and on a default basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: ignore: vcs: true A default VCS ignore setting can be overridden on a per-session basis by passing the `--no-ignore-vcs` flag to the `create` command. Format and behavior ------------------- The format and behavior of Mutagen’s ignore patterns are designed to match those of Git, insofar as that makes sense for Mutagen’s somewhat different application. Ignore patterns are essentially paths that support special syntax for matching. At a base level, ignore patterns are built using the [doublestar](https://github.com/bmatcuk/doublestar) package, so all of the syntax there carries over. Ignore patterns use `/` as a path separator. All paths are treated as relative to the synchronization root. If an ignore pattern does not contain a `/` (i.e. it is a leaf name), then it will also be treated as relative to any subdirectory in the synchronization root. For example, an ignore pattern of `some/path` will only ignore content at `/some/path`, but an ignore pattern of `path` will ignore content at `/path`, `/some/path`, `/other/path`, etc. If you want to ignore content that exists directly at the root and not any other subpath, then prefix the ignore with `/`. For example, `build` will ignore content named `build` at any subdirectory, but `/build` will only ignore content at `/build`. Suffixing a pattern with `/` will cause it to match only directories. It’s important to note that this is the only way that a path can “become” ignored or unignored, and the way that this behaves with a three-way merge might be non-intuitive. For example, imagine that an ignore of `name/` is specified, and that both endpoints of the connection have a copy of a synchronized file (not a directory) called `name`. Imagine that one endpoint then replaces the file `name` with a directory called `name`. This directory will now be ignored. Since Mutagen will ignore a directory called `name` in its scans, it will appear to Mutagen’s three-way merge algorithm that the content at this path has been deleted on the side where the type has changed to a directory, and it will thus propagate deletion of the file called `name` to the other endpoint. This is still technically correct behavior, but it’s worth understanding before using this type of ignore pattern. Prefixing a pattern with `!` will cause it to negate previously matching ignores. E.g. specifying an ignore list like `["hot*", "!hotel"]` will ignore any content whose name begins with “hot”, unless the full content name is “hotel”. This can be a useful mechanism for overriding global ignores on a per-session basis. --- # Transports | Mutagen Contents Transports ========== Mutagen supports several different transports for synchronization and forwarding. Each transport has different features and abilities that are detailed in their respective documentation. Transports are specified by the URLs provided to `mutagen sync create` and `mutagen forward create`. They can be specified in arbitrary combinations to create local-to-local, local-to-remote, and remote-to-remote synchronization and forwarding sessions. Local ----- [Local](https://mutagen.io/documentation/transports/local/) synchronization and forwarding endpoints are the most basic Mutagen transport. They are simply local filesystem paths or network addresses. SSH --- Mutagen also support synchronization and forwarding endpoints that are accessible via [SSH](https://mutagen.io/documentation/transports/ssh/) . The SSH transport is particularly well-suited to long-lived remote infrastructure where SSH access is already enabled. Docker® containers ------------------ [Docker® containers](https://mutagen.io/documentation/transports/docker/) can also be used as synchronization and forwarding endpoints in a manner similar to SSH. --- # Licenses | Mutagen Contents Licenses ======== This page contains license and acknowledgement information for the fonts and libraries used by this website. For license information about Mutagen itself, please see the Mutagen [repository](https://github.com/mutagen-io/mutagen) . Fonts ----- ### Inter (Subsetted) [Website](https://rsms.me/inter/) · [Repository](https://github.com/rsms/inter/) **Copyright (c) 2016-2020 The Inter Project Authors.** **“Inter” is trademark of Rasmus Andersson.** This website uses a subsetted version of the Inter font, which is available under the SIL Open Font License, Version 1.1. A copy of this license can be found later in this text or online at [https://scripts.sil.org/OFL](https://scripts.sil.org/OFL) . Certain icons on this website are also derived from the Inter font. Icons ----- The Mutagen website makes use of the following icon sets: ### Feather [Website](https://feathericons.com/) · [Repository](https://github.com/feathericons/feather) **Copyright (c) 2013-2017 Cole Bemis** Used under the terms of the MIT License. A copy of this license can be found later in this text or online at [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) . Libraries --------- The Mutagen website makes use of the following JavaScript and/or CSS libraries: ### jQuery [Website](https://jquery.com/) · [Repository](https://github.com/jquery/jquery) **Copyright JS Foundation and other contributors, [https://js.foundation/](https://js.foundation/) ** Used under the terms of the MIT License. A copy of this license can be found later in this text or online at [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) . ### Popper.js [Website](https://popper.js.org/) · [Respoitory](https://github.com/FezVrasta/popper.js) **Copyright © 2016 Federico Zivolo and contributors** Used under the terms of the MIT License. A copy of this license can be found later in this text or online at [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) . ### Bootstrap [Website](https://getbootstrap.com/) · [Repository](https://github.com/twbs/bootstrap) **Copyright (c) 2011-2019 Twitter, Inc.** **Copyright (c) 2011-2019 The Bootstrap Authors** Used under the terms of the MIT License. A copy of this license can be found later in this text or online at [https://opensource.org/licenses/MIT](https://opensource.org/licenses/MIT) . License texts ------------- ### MIT License Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ### SIL Open Font License, Version 1.1 ----------------------------------------------------------- SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ----------------------------------------------------------- PREAMBLE The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others. The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives. DEFINITIONS "Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation. "Reserved Font Name" refers to any names specified as such after the copyright statement(s). "Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s). "Modified Version" refers to any derivative made by adding to, deleting, or substituting -- in part or in whole -- any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment. "Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software. PERMISSION & CONDITIONS Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions: 1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself. 2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user. 3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users. 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission. 5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software. TERMINATION This license becomes null and void if any of the above conditions are not met. DISCLAIMER THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. --- # Third-party trademarks | Mutagen Contents Third-party trademarks ====================== This page contains trademark notices for third-party trademarks used on this site. Notices ------- * Docker and the Docker logo are trademarks or registered trademarks of Docker, Inc. in the United States and/or other countries. Docker, Inc. and other parties may also have trademark rights in other terms used herein. * Kubernetes® is a registered trademark of The Linux Foundation in the United States and/or other countries. * Linux® is the registered trademark of Linus Torvalds in the U.S. and other countries. * macOS is a trademark of Apple Inc., registered in the U.S. and other countries. * Windows and Hyper-V are a registered trademarks of Microsoft Corporation in the United States and/or other countries. * TWITTER, TWEET, RETWEET and the Twitter logo are trademarks of Twitter, Inc. or its affiliates. --- # Symbolic links | Mutagen Contents Symbolic links ============== Mutagen has full support for symbolic links on both POSIX and Windows systems. Because POSIX and Windows platforms have different symbolic link implementations and interpretations, Mutagen provides a few different symbolic link synchronization modes aimed at providing maximum compatibility: * **`ignore`**: In this mode, Mutagen simply ignores any symbolic links that it encounters within a synchronization root. This means that it won’t propagate them and it won’t delete them. This mode is supported on both POSIX and Windows systems. * **`portable` (default)**: In this mode, Mutagen restricts itself to propagating only symbolic links that it defines as “portable”. Portable symbolic links are those which are relative paths, containing only safe characters, which do point outside the synchronization root at any point in their target path. In this mode, Mutagen also performs appropriate symbolic link normalization on Windows endpoints to ensure that symbolic links are correctly round-tripped to disk. If a non-portable symbolic link is detected within the synchronization root, the session will halt synchronization until it is removed or corrected. This mode is supported on both POSIX and Windows systems, though please see the [note](https://mutagen.io/documentation/synchronization/symbolic-links/#windows-permissions) below about Windows permissions. * **`posix-raw`**: In this mode, which is only supported for synchronization sessions between two POSIX endpoints, Mutagen will propagate raw symbolic link targets without any analysis or modification. Trying to use this mode when either endpoint is a Windows system will prevent synchronization from starting. These modes can be specified on a per-session basis by passing the `--symlink-mode=` flag to the `mutagen sync create` command and on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: symlink: mode: "" Windows permissions ------------------- On Windows, the `SeCreateSymbolicLinkPrivilege` permission is required to create symbolic links. By default, this permission is usually only granted to administrators. This has changed a bit in Windows 10, where anyone can create symbolic links if Developer Mode has been enabled. If you don’t have the `SeCreateSymbolicLinkPrivilege` permission and can’t add it for yourself, or you can’t enable Developer Mode in Windows 10, then you have two choices: 1. Do nothing. In this case, Mutagen will attempt to propagate symbolic links (if it’s in Portable mode), and will simply report that it is unable to do so. This won’t hurt anything, and it won’t stop other files from synchronizing. The only downside is that you’ll see problems indicated when listing or monitoring the session. 2. Switch to ignoring symbolic links. --- # SSH | Mutagen Contents SSH endpoints ============= Mutagen provides support for synchronizing files and forwarding network traffic via SSH. Requirements ------------ Mutagen requires an OpenSSH client installation to be available on your system. This is the default for almost all POSIX operating systems, so you probably don’t need to do anything if you’re on macOS, Linux®, or one of the BSDs. Windows is supported as well, but please see the [section on Windows support](https://mutagen.io/documentation/transports/ssh/#windows) for more detailed information. Mutagen should support most SSH server implementations, so long as they support OpenSSH’s `ssh` and `scp` implementations. If you run into trouble with a particular SSH server implementation, please [file an issue](https://github.com/mutagen-io/mutagen/issues/new) . Synchronization --------------- SSH synchronization endpoints can be specified to the `mutagen sync create` command using an SCP-like URL syntax of the form: [@][:]: The `` component is optional and will be passed to OpenSSH to override the default username. The `` component can be any IP address, hostname, or alias understood by OpenSSH. It is required and must not be empty. The `` component is also optional and is an extension to the standard SCP URL syntax. If specified, it will be passed to OpenSSH to override the default port. The `` component is interpreted in the same way as an SCP path. It is required and must not be empty. Example SSH synchronization URLs * `example.org:/var/www` Connect to `example.org` and target an absolute path. * `example.org:23:relative/path` Connect to `example.org` on a custom SSH port (`23`) and target a relative path. The path will be resolved relative to the default SSH working directory (typically the user's home directory). * `hostalias:~/path/in/home/directory` Connect to the server indicated by the alias `hostalias` and target a path relative to the user's home directory. * `george@example.org:~otheruser/path/in/their/home/directory` Connect to `example.org` as the user `george` and target a path relative to a specific user's home directory. Forwarding ---------- SSH forwarding endpoints can be specified to the `mutagen forward create` command using URLs of the form: [@][:]: The ``, ``, and `` components of this URL are the same those in the synchronization URL format described above, while the `` component is described in the [forwarding documentation](https://mutagen.io/documentation/forwarding/#endpoint-urls) . As before, the `` component is required and must not be empty, and the same applies to the ``. In the case of relative Unix domain socket paths in the `` component, path resolution will be performed relative to the default SSH working directory (typically the user’s home directory). Example SSH forwarding URLs * `example.org:tcp::8080` Connect to `example.org` and bind to all network interfaces on port `8080`. * `george@example.org:24:tcp:localhost:8080` Connect to `example.org` on a custom SSH port (`24`) as the user `george` and bind to or target the loopback interface on port `8080`. * `hostalias:tcp6:localhost:8080` Connect to server indicated by the alias `hostalias` and bind to or target the IPv6 loopback interface on port `8080`. * `george@example.org:tcp:10.0.1.25:6060` Connect to `example.org` as the user `george` and bind to or target `10.0.1.25` on port `6060`. * `example.org:unix:/path/to/socket.sock` Connect to `example.org` and bind to or target a Unix domain socket using an absolute path. * `example.org:unix:path/to/socket.sock` Connect to `example.org` and bind to or target a Unix domain socket using a relative path. Path resolution in this case is relative to the default SSH working directory (typically the user's home directory). * `example.org:unix:~/path/to/socket.sock` Connect to `example.org` and bind to or target a Unix domain socket relative to the user's home directory. * `example.org:unix:~otheruser/path/to/socket.sock` Connect to `example.org` and bind to or target a Unix domain socket relative to a specific user's home directory. Implementation -------------- Mutagen’s SSH support is provided by the OpenSSH installation on your system. Mutagen uses the OpenSSH suite’s `scp` command to copy agent binaries to remote systems and the `ssh` command to run and communicate with the agent binaries over standard input/output streams. Mutagen redirects SSH prompts to its `create`, `resume`, and `reset` commands via the `SSH_ASKPASS` environment variable. This design has a number of advantages: * OpenSSH installations are nearly universal in the POSIX world, and [OpenSSH is now making its way to Windows](https://blogs.msdn.microsoft.com/powershell/2017/12/15/using-the-openssh-beta-in-windows-10-fall-creators-update-and-windows-server-1709/) . * Mutagen automatically uses all existing SSH configuration, keys, and aliases. * There’s no risk of baking in an SSH library that might be found to have security vulnerabilities. * With OpenSSH being the _de facto_ SSH implementation, other SSH server implementations are far more likely to aim for compatibility with OpenSSH clients. * OpenSSH has a much longer develoment and security track record than any SSH library implementation. Mutagen may eventually support other SSH clients or embed the [Go SSH library](https://godoc.org/golang.org/x/crypto/ssh) , but these will always be fallback options. OpenSSH search path ------------------- On POSIX systems, Mutagen uses the first OpenSSH `ssh` and `scp` executables that are found in the user’s path. On Windows systems, Mutagen uses a different approach described [below](https://mutagen.io/documentation/transports/ssh/#windows) . Both of these search strategies can be overridden by setting the `MUTAGEN_SSH_PATH` environment variable (for the Mutagen daemon) to a path containing the desired OpenSSH executables. OpenSSH connection timeout -------------------------- Mutagen uses a default value of 5 seconds for the OpenSSH `ConnectTimeout` configuration parameter. This can be overridden by setting the `MUTAGEN_SSH_CONNECT_TIMEOUT` environment variable (for the Mutagen daemon) to an integer value specifying a timeout in seconds. Windows ------- Mutagen fully supports SSH on Windows, though you’ll need to bring your own OpenSSH client. Unfortunately the [official Windows OpenSSH client](https://blogs.msdn.microsoft.com/powershell/2017/12/15/using-the-openssh-beta-in-windows-10-fall-creators-update-and-windows-server-1709/) is still in beta and has a few blocking issues, primarily [PowerShell/Win32-OpenSSH#1152](https://github.com/PowerShell/Win32-OpenSSH/issues/1152) ,[1](https://mutagen.io/documentation/transports/ssh/#fn:1) that disallow its use by Mutagen at the moment. As soon as these issues are resolved, this will become Mutagen’s recommended client (though others will continue to be supported). Mutagen has a hardcoded set of OpenSSH clients that it will look for and use at the moment, including those from [Git for Windows](https://gitforwindows.org/) (recommended), [MSYS2](http://www.msys2.org/) , and [Cygwin](https://www.cygwin.com/) . You can see the full list of search paths [here](https://github.com/mutagen-io/mutagen/blob/781ab52616a0aebc90a4394df2eee323f3d97f2b/pkg/tools/ssh/ssh_windows.go#L9) . One thing to be aware of is that the MSYS2 and Cygwin OpenSSH clients will, by default, look for SSH configuration (`~/.ssh`) in the “virtual” home directory provided by the underlying Cygwin environment. This is not a problem, though be aware that Mutagen will continue to store its data (`~/.mutagen`) and look for its configuration (`~/.mutagen.yml`) in the user’s actual home directory (i.e. that specified by `%USERPROFILE%`). The Git for Windows OpenSSH implementation will look for SSH configuration in the actual home directory as well. ### SSH servers Mutagen is currently only known to work reliably with [Bitvise SSH Server](https://www.bitvise.com/ssh-server) on Windows. The [official Windows OpenSSH server](https://blogs.msdn.microsoft.com/powershell/2017/12/15/using-the-openssh-beta-in-windows-10-fall-creators-update-and-windows-server-1709/) is still in beta and has a few performance issues and other kinks that need to be ironed out before Mutagen can reliably support it. Mutagen will connect to this server and mostly work, but the performance is not great at the moment due to the server’s stream handling. Issues have also been experienced with stalled data streams. Mutagen should also work with other Windows SSH servers (for example, Cygwin’s OpenSSH server), though please [open an issue](https://github.com/mutagen-io/mutagen/issues/new) if you run into problems. ### PuTTY Mutagen does not support [PuTTY](https://www.putty.org/) . * * * 1. Issue 1152 has been resolved, but the fix hasn’t yet shipped as part of a Windows release. [↩︎](https://mutagen.io/documentation/transports/ssh/#fnref:1) --- # Version control systems | Mutagen Contents Version control systems ======================= Mutagen is designed to work in tandem with version control systems (VCSs), allowing you to, for example, clone and edit a project while mirroring it to a remote system and testing it as your make edits. This helps you to avoid needing a push/pull cycle every time you make a change that you want to test. When using Mutagen with a VCS repository, there are a few “best practices” of which you should be aware. Ignoring VCS directories ------------------------ **Caution:** In addition to the reasons listed below, the most important reason that VCS directories should not be synced is that they often contain scripts that are executed when certain VCS commands are run (for example, [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) ). These hooks are generally designed to help with VCS workflows, but they’re also a potential attack vector for remote code execution if synchronizing a VCS directory with an untrusted remote. VCS directories (for example, `.git`, `.svn`, `.hg`, etc.) _can_ be synchronized by Mutagen like any other directory, but they _shouldn’t_ be for a number of reasons. The reasons are more or less the same for each VCS, but we’ll cover the common case of a `.git` directory. These reasons are also not specific to Mutagen — they apply to any file synchronization tool or service. The first reason is that the Git index data structure (which resides in `.git`) records inode numbers, device ids, and modification times that are specific to the filesystem on which it resides. If you move it to another system, then the next time you run `git status` (or any command relying on similar Git infrastructure), Git is going to have to do a full re-hash of the working tree and will then write a new copy of the index with the inode numbers, device ids, and modification times for the working tree on which it was just run. This is fine if you just want to move a Git repository once, since you’ll just incur a little extra penalty the first time you run `git status`, but it won’t play well with constant synchronization. The Git index can also be a bit large (up to tens of MB for very large working trees) and is rewritten every time you run certain Git commands (for example, `git status`), so you’d be constantly resynchronizing it. A second reason is that Git’s object store is not homogenous or immutable. Some objects are stored as loose objects and some are stored in pack files, and it will be completely dependent on the history of a particular copy of a Git repository. They can also be pruned or relocated into pack files at any point by Git’s garbage collection. This will not play well with synchronization for a variety of reasons that are a bit too numerous to go into, but it will be more than a performance nuisance like the Git index — it may actually cause Git to complain about duplicate objects, or cause weird behavior when Git does its garbage collection. Again, this doesn’t matter when you’re just copying a Git repository one time, since in that case you’re not continuing to synchronize against it. The third reason is that Git isn’t expecting concurrent modifications of its `.git` directory. In fact it has an index lock that has to be held by Git processes specifically for this reason. There are a number of other reasons, but it basically comes down to the fact that only Git is in a position to be in control of what’s in its `.git` directory (at least when it comes to the index and object stores). Recommended workflow -------------------- The recommended workflow for using Mutagen with VCS repositories is to [ignore VCS directories](https://mutagen.io/documentation/synchronization/ignores/#version-control-systems) , keeping a copy of the VCS directory on only one side of the synchronization session and synchronizing only the working tree around it. You can think of the side with the VCS directory as the “master” and the side without as the “slave”, even though the synchronization is bidirectional. You can even have multiple “slaves” with a hub-spoke model. With this model, you can invoke VCS commands on the “master” side (usually your actual workstation) and, if any changes are made to the working tree, those changes will be synchronized out to the “slaves”. ### Supporting build tools Some build systems expect their working directory to be part of a VCS working tree so that they can extract metadata about the repository (for example, the current commit) to use as part of the build. This can require that at least a subset of the VCS directory be present on the remote. Typically this requirement only includes configuration data, so a useful workaround for these cases is to create a secondary session that unidirectionally mirrors a subset of the VCS directory. The configuration for a setup like this using Git might look something like: sync: code: alpha: "path/to/code" beta: "/path/to/remote/code" ignore: vcs: true vcs: alpha: "path/to/code/.git" beta: "/path/to/remote/code/.git" mode: "one-way-replica" ignore: paths: - "index" In this case, we’ve excluded the Git index file from synchronization since it’s large, modified frequently, and unnecessary to synchronize. Depending on your build tools’ exact needs, you could potentially synchronize just the Git configuration file, for example: sync: code: alpha: "path/to/code" beta: "/path/to/remote/code" ignore: vcs: true vcs: alpha: "path/to/code/.git" beta: "/path/to/remote/code/.git" mode: "one-way-replica" ignore: paths: - "*" - "!config" Workflows to avoid ------------------ In addition to avoiding direct synchronization of VCS directories, there are other setups that are also probably best avoided. For example, you could imagine a set up with a Git repository where you synchronize two copies of the repository, each with a `.git` directory, but exclude the `.git` directories from synchronization. At first this will appear to work, because both will show you the same result for `git status` and `git diff`. However, as soon as you do a `git commit` operation on one side, the other side will still be on the previous commit and see modified files while the committed side will show a clean working tree (even though both repositories have the exact same files in their working trees). The only way to propagate the commit to the other side would be to do a push/pull cycle, but to pull the commit you’d need to stash your working tree changes, which would revert your working directory back to the previous commit, which in the mean time would be sync’d back to the committed side, which would then show modifications, at least until you pulled down the commit on the other side, etc., etc. This is theoretically safe, but it is very clunky and likely to cause confusing behavior. --- # Permissions | Mutagen Contents Permissions =========== Mutagen’s permission synchronization model is designed around portability and development work. Unlike many synchronization systems, Mutagen does not propagate raw file ownership or permissions. Doing so is neither well-defined nor safe in general. Instead, the only permission that Mutagen propagates is POSIX executability. For any other files that Mutagen propagates or updates, ownership and permissions are set using explicit configuration parameters. Permissions for any other files in a synchronization root are left untouched by Mutagen. Executability propagation ------------------------- For development work, propagation and preservation of POSIX executability bits is crucial, and as such they are only permissions that Mutagen aims to support automatically. For filesystems that don’t preserve executability bits (for example, those on Windows), preservation is emulated in-memory as part of the reconciliation algorithm (as opposed to trying to attach metadata to files on disk). This allows users to, for example, edit POSIX shell scripts on Windows and have those changes synchronized without wiping out executability bits. Mutagen considers a file executable if any executability bit is set. When setting permissions for an executable file, executability bits are set for any entities that have a corresponding read bit set. Owners and groups ----------------- By default, files and directories are created with their owner set to the user under which Mutagen or its agent executable is operating and their group set to that user’s default group. Both of these behaviors are configurable. Default ownership can be specified on a per-session and/or per-endpoint basis by passing the `--default-owner=` or `--default-owner-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. Default ownership can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: permissions: defaultOwner: "" Default groups can be specified on a per-session and/or per-endpoint basis by passing the `--default-group=` or `--default-group-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. Default groups can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: permissions: defaultGroup: "" Owner and group specifications can be provided in three different formats: * POSIX-ID-based: A string of the form `id:N`, where `N` is a number representing the user or group ID. This is only supported for POSIX endpoints. * Windows-SID-based: A string of the form `sid:XXXXXXXXXX` where `XXXXXXXXXX` is some valid Windows SID (the formats are highly variable). This is only supported for Windows endpoints. * Name-based: A non-empty string that does not adhere to one of the above formats is treated as a literal user or group name. This is supported on both POSIX and Windows endpoints. Empty ownership specifications specify that the default ownership should be used for the file (whatever that happens to be on the endpoint). ### POSIX Please note that, on POSIX systems, superuser privileges are required to set ownership to a user other that oneself, or to set a group to which one does not belong. ### Windows On Windows systems, setting file ownership to a group or another user requires the `SeRestorePrivilege`, which has to be granted by a system administrator and then requires that the requesting process activate that privilege. Mutagen doesn’t activate this privilege at the moment because having the `SeRestorePrivilege` gives a process write access to an entire system (including system files). Setting group ownership on Windows also has essentially no effect, since group information is a relic of POSIX support on Windows and isn’t used by the Win32 subsystem. Permissions ----------- By default, files and directories have their permission bits set to user-only access (`0600` and `0700`, respectively). Default permissions can be specified on a per-session and/or per-endpoint basis by passing the `--default-(file|directory)-mode=` or `--default-(file|directory)-mode-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. Default permissions can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: permissions: defaultFileMode: 0XXX defaultDirectoryMode: 0XXX File and directory modes are specified in octal format with an optional `0` prefix (for example, `0644` or `750`). They default to `0600` for files and `0700` for directories. File modes should not include executability bits since these are managed by Mutagen. ### POSIX Please note that default file and directory permissions are still subject to [`umask`](https://en.wikipedia.org/wiki/Umask) . ### Windows At the moment, file and directory modes on Windows are processed as outlined in the Go [`os.Chmod`](https://golang.org/pkg/os/#Chmod) function. --- # Staging | Mutagen Contents Staging ======= When transferring files to an endpoint, Mutagen first stages them in a temporary directory so that they can be atomically relocated into place. By default, these files are staged in the Mutagen data directory (`~/.mutagen`), which works well for most synchronization root locations and keeps staged files consolidated in a single location. However, in cases where the synchronization root resides on a different filesystem than the user’s home directory, staging files in the Mutagen data directory incurs an additional copy operation to transition them into place. To work around this, Mutagen provides the following staging modes: * **`mutagen` (Default)**: Files are staged in the Mutagen data directory (`~/.mutagen`) before being relocated to the synchronization root. * **`neighboring`**: Files are staged in a hidden temporary directory that neighbors the synchronization root, allowing placement on the same filesystem as the synchronization root for faster relocation. * **`internal`**: Files are staged in a hidden temporary directory inside the synchronization root, allowing placement on the same filesystem as the synchronization root for faster relocation. This mode will fail if the synchronization root doesn’t already exist. It is only advantageous over `neighboring` when working with volume roots. These modes can be specified on a per-session and/or per-endpoint basis by passing the `--stage-mode=` or `--stage-mode-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. These modes can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: stageMode: "" --- # Probing and scanning | Mutagen Contents Probing and scanning ==================== On each synchronization cycle, Mutagen endpoints are probed for filesystem behavior and scanned to create a snapshot of synchronization root contents. In both cases, Mutagen can perform the operation in a variety of different ways. While the default behavior will be satisfactory for the vast majority of users, there are certain cases (outlined below) where users may wish to adjust Mutagen’s default behavior. Probing ------- Filesystem probing is used to determine certain filesystem behaviors that need to be understood in order to correctly synchronize files between different systems. In particular, Mutagen needs to know if a filesystem preserves POSIX executability bits and whether or not it decomposes Unicode filesystem names. Mutagen has two mechanisms for determining this information: it can either probe the filesystem to determine the exact behavior or assume behavior based on the platform. When probing a filesystem, Mutagen first checks the filesystem type. Mutagen has a conservative (but broadly applicable) database of filesystem types with well-known behavior, allowing it to skip direct probing on most filesystems. For filesystem types unknown to Mutagen or where behaviors are not well-defined, Mutagen performs direct probing using temporary files. These temporary files contain non-ASCII characters in their names and may cause problems for tools using filesystem watching. In that case, it may be advantageous to tell Mutagen to simply assume filesystem behavior based on the platform. To configure filesystem probing behavior, Mutagen offers two different modes: * **`probe` (Default)**: In this mode, Mutagen performs its default probing using filesystem type checks and (if necessary) temporary probe files. * **`assume`**: In this mode, Mutagen assumes filesystem behavior based on the platform. This is less accurate but (very marginally) faster and less likely to cause conflicts with other tools using filesystem watching. These modes can be specified on a per-session and/or per-endpoint basis by passing the `--probe-mode=` or `--probe-mode-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. These modes can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: probeMode: "" Scanning -------- Filesystem scanning is used to generate a snapshot of the synchronization root on an endpoint for use as input to Mutagen’s reconciliation algorithm. Mutagen has two different modes for performing scans: * **`accelerated` (Default)**: In this mode, Mutagen uses filesystem watching information to avoid performing a full synchronization root re-scan. For endpoints using recursive native watching, Mutagen tracks the files that have changed since the last scan and only re-scans those files and their parent directories. For systems using poll-based watching, Mutagen simply returns the last scan generated by polling. For systems with watching disabled, Mutagen simply falls back to a full scan. * **`full`**: In this mode, Mutagen always performs a full synchronization root re-scan. This is the most accurate option, though it comes with a performance hit for very large synchronization roots. These modes can be specified on a per-session and/or per-endpoint basis by passing the `--scan-mode=` or `--scan-mode-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. These modes can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: scanMode: "" It’s worth noting that even in cases where `accelerated` scanning returns a slightly outdated synchronization root snapshot, Mutagen’s change application algorithms will still detect conflicting changes that might have been missed in the outdated snapshot, so the safety behavior is the same as with `full` scanning. --- # Size limits | Mutagen Contents Size limits =========== Mutagen has two session configuration parameters to limit synchronization disk usage. Maximum staging file size ------------------------- The maximum file size that Mutagen will allow to be staged (transferred) can be set on a per-session basis by passing the `--max-staging-file-size=` flag to the `mutagen sync create` command. This limit can be set on a default per-session basis by including the following in `~/mutagen.yml`: sync: defaults: maxStagingFileSize: "" Size specifications can be provided as a numeric value representing byte count or as a string using human-friendly units (for example, `"1000 MB"`). A value of `0` (the default) indicates a limit of 264\-1 bytes. Maximum entry count ------------------- The maximum entry count (i.e. the total count of directories, files, and symbolic links in a synchronization root) that Mutagen will process is unlimited by default, but can be set on a per-session basis by passing the `--max-entry-count=` flag to the `mutagen sync create` command. This limit can be set on a default per-session basis by including the following in `~/.mutagen.yml`, for example: sync: defaults: maxEntryCount: The count should be a positive integer value. A value of `0` (the default) indicates a limit of 264\-1 entries. --- # Network forwarding | Mutagen Contents Network forwarding ================== Mutagen supports flexible network forwarding, allowing you to connect to services and access applications running on remote systems. It can be particularly useful when developing applications inside containers that you want to access locally. For example, you might want to develop a web application (potentially with multiple backing services) in a containerized environment and access it from your browser. Network forwarding can also be used to reverse tunnel traffic or forward Unix domain sockets, amongst other things. Design and architecture ----------------------- Mutagen’s forwarding sessions each operate between an arbitrary pair of endpoints, termed **source** and **destination**, forwarding source’s incoming connections to destination. As with synchronization sessions, remote data is transferred over an agent command’s input/output stream, multiplexed in this case to support multiple connection streams, avoiding the need to expose ports publicly. Endpoint URLs ------------- Forwarding endpoint URLs are similar to synchronization endpoint URLs, except that, instead of naming a filesystem location, they name a network endpoint. The exact format for forwarding endpoint URLs is [transport-dependent](https://mutagen.io/documentation/transports/) , but each contains a `` component which has the following format: :
This network endpoint is analagous to the path component of a synchronization URL. For source endpoints, the network endpoint is a listener address on which the endpoint will attempt to bind. For destination endpoints, the network endpoint is a target address that the endpoint will attempt to dial. The `` and `
` components allow the same values as the `network` and `address` arguments (respectively) of Go’s [`net.Dial`](https://golang.org/pkg/net/#Dial) and [`net.Listen`](https://golang.org/pkg/net/#Listen) functions, except that `` is restricted to `tcp`, `tcp4`, `tcp6`, and `unix`. On Windows endpoints, an additional `npipe` protocol is supported for dialing and listening on Windows named pipes. In the case of Unix domain sockets, the address component is a socket path, which can be either relative or absolute. If a relative path is specified, then it will be resolved relative in a manner dependent on the transport being used. In the case of Windows named pipes, the address component is a Windows named pipe path, for example `\\.\pipe\`. If you’re targeting such a pipe from a POSIX system, then you’ll likely need to escape backslashes in your shell. Example network endpoints * `tcp::8080` Bind to all interfaces on port 8080. * `tcp4:localhost:8080` Bind to or target the IPv4 loopback interface on port 8080. * `tcp6:localhost:8080` Bind to or target the IPv6 loopback interface on port 8080. * `tcp:10.0.1.25:6060` Bind to or target `10.0.1.25` on port 6060. * `tcp:example.org:6060` Target `example.org` on port 6060. * `unix:/path/to/socket.sock` Bind to or target a Unix domain socket using an absolute path. * `unix:path/to/socket.sock` Bind to or target a Unix domain socket using a relative path. Path resolution for relative paths is transport-dependent. * `unix:~/path/to/socket.sock` Bind to or target a Unix domain socket relative to the user's home directory. * `npipe:\\.\pipe\somepipename` Bind to or target a Windows named pipe. The endpoint must reside on a Windows system, though it can be targeted from a non-Windows system. Configuration ------------- Network forwarding configuration is currently minimal, with configuration options controlling: * [Unix domain socket overwrites](https://mutagen.io/documentation/forwarding/unix-domain-sockets/#overwrites) * [Unix domain socket ownership](https://mutagen.io/documentation/forwarding/unix-domain-sockets/#ownership) * [Unix domain socket permissions](https://mutagen.io/documentation/forwarding/unix-domain-sockets/#permissions) Session management ------------------ Forwarding sessions are managed using the `mutagen forward` commands, namely `create`, `list`, `monitor`, `pause`, `resume`, and `terminate`. Example usage for these commands can be found in the [Getting started](https://mutagen.io/documentation/introduction/getting-started/) guide. The `create` command comes with a number of flags that control the configuration of the sessions that it creates, and the other forwarding session management commands all include flags that control their behavior. For more information about a particular command, use: # Show help about a particular forwarding session management command. mutagen forward --help --- # Safety mechanisms | Mutagen Contents Safety mechanisms ================= Mutagen has several **best-effort** safety mechanisms aimed at avoiding unintentional bulk content deletion or replacement. Each of these mechanisms detects an “irregular” condition during synchronization and halts the synchronization session. Resolving the irregular condition and resuming the session depends on the user’s intent. If the deletion or replacement is desired, then the session can be resumed by manually deleting the content that would be deleted or replaced and then invoking `mutagen sync resume`. In the case of accidental deletion, the synchronization session history can be reset (which will cause Mutagen see the undeleted content as new content and propagate it back to the other side) using the `mutagen sync reset` command. More generally, a synchronization session can simply be deleted and/or recreated if some other resolution behavior is necessary. It’s important to note that these safety mechanisms don’t control directionality or conflict resolution in synchronization, which are instead controlled by the [synchronization mode](https://mutagen.io/documentation/synchronization/#modes) . Root deletion ------------- One of the changes that Mutagen avoids propagating is complete deletion of the synchronization root on one endpoint. This can be an indication of either accidental deletion or a non-persistent filesystem (such as a container filesystem). This detection is best-effort since directory deletion is non-atomic and Mutagen may see (and propagate) deletion of a large portion of a synchronization root before seeing that the entire root was deleted (though Mutagen does its best to avoid operating during concurrent file modifications when it detects them). Root emptying ------------- Mutagen also looks for cases where both synchronization endpoints are directories and one endpoint (but not both) deletes a non-trivial amount of content from the synchronization root and leaves it empty. This is generally an indication of a non-persistent filesystem (such as a container filesystem) being used as a synchronization root. This detection is best-effort for the same reasons described above. Root type change ---------------- Finally, Mutagen looks for replacement of the synchronization root with a root of a different type on one endpoint. This avoids (for example) accidentally overwriting a large directory with a single file. --- # TCP sockets | Mutagen Contents TCP sockets =========== TCP sockets provide a flexible and high-performance stream-based transport that is almost universally supported. They come with a few important considerations and caveats which are outlined below. Platform support ---------------- TCP sockets are supported on all platforms. Default bind interface ---------------------- Mutagen binds to _**all**_ interfaces if none is specified in a forwarding endpoint. This behavior mirrors that of programs like SSH. Example network binding behaviors * `tcp::8080` Bind to **all** interfaces on port 8080. * `tcp6::8080` Bind to **all** IPv6 interfaces on port 8080. * `tcp:localhost:8080` Bind to _only_ the loopback interface(s) on port 8080. * `tcp4:localhost:8080` Bind to _only_ the IPv4 loopback interface on port 8080. It’s important to be cognizant of this to avoid accidentally exposing secure internal infrastructure via an exposed port on your local system when working in a public network environment without a firewall (which, for example, macOS doesn’t enable by default). Privileged ports ---------------- Most platforms restrict which users and programs can bind to so-called “privileged ports”. Exactly which ports are privileged and which users/programs are allowed to bind to them varies by operating system, but typically any port less than `1024` (e.g. port `80` or `443`) is restricted to superusers or programs with certain permission bits set. The easiest way to work around these restrictions is to simply choose another port outside of this privileged range. For example, port `8080` is commonly used to replace port `80` in development. It’s worth noting that port numbers don’t have to match, so it’s perfectly acceptable to create a forwarding session like the following: mutagen forward create tcp:localhost:8080 docker://web_container:tcp:localhost:80 It’s also worth noting that these restrictions only affect the source end of the forwarding (i.e. the first endpoint specified to the `mutagen forward create` command), so there’s no problem forwarding _to_ privileged ports. For additional information, please see the discussion in [Issue #134](https://github.com/mutagen-io/mutagen/issues/134) . ### Linux On Linux, programs can also have permissions set by a superuser that enable them to bind to privileged ports. This is done using the `setcap` command. This is what allows certain programs (e.g. web servers) to bind to privileged ports without running as a superuser. For example, you can enable privileged ports for the Mutagen daemon using a command like: sudo setcap setcap 'cap_net_bind_service=+ep' /path/to/mutagen Note that this will only affect local Mutagen endpoints, not those running inside agents. You should consult the [`setcap` man page](https://linux.die.net/man/8/setcap) before running this command to ensure that you fully understand the implications. --- # Watching | Mutagen Contents Watching ======== Mutagen uses filesystem watching to know when it should scan for and propagate changes. Unfortunately, the filesystem watching landscape is _extremely_ varied in terms of implementation, efficiency, and robustness. Almost every platform uses a completely different mechanism, many of which are unreliable or non-scalable. Some systems (namely macOS and Windows) provide native recursive watching mechanisms that can monitor arbitrarily large directory hierarchies, though their behavior when the location being watched is deleted or changed is somewhat inconsistent, and Windows only supports using a directory as the root of such a recursive watch. Other systems (for example, Linux® and BSD systems) provide mechanisms that require a watch descriptor or file descriptor to be open for _every_ file or directory being watched in a directory hierarchy, which can quickly exhaust system quotas for directories that might be used in development (for example, imagine a synchronization root containing a `node_modules` directory). Mutagen takes a pragmatic approach to filesystem watching that attempts to maximize reliability and responsiveness while avoiding exhaustion of system resources or problematic behavior. Native recursive watching ------------------------- On systems that natively support recursive filesystem watching, a watch is established on either the synchronization root itself (on macOS) or the parent directory of the synchronization root (on Windows) and events are filtered to only those originating from the synchronization root. Because these systems can behave strangely if the root of a watch is deleted, a regular (but very cheap) polling mechanism is used to ensure that the watch root hasn’t been deleted or recreated. If a change to the watch root is detected, the watch is re-established. Polling ------- On all other systems, a polling mechanism is used to avoid exhausting watch/file descriptors. This polling mechanism is also used as a fallback in cases where native watching mechanisms fail unrecoverably. On Linux, this polling is coupled with a restricted set of native watches on the most recently updated contents, allowing for low-latency change notifications for most workflows without exhausting watch/file descriptors. Modes ----- Mutagen provides three different filesystem watching modes: * **`portable` (Default)**: In this mode, Mutagen uses the most efficient watching implementation possible for an endpoint. If some type of native watching mechanism is available, it is used, otherwise pure poll-based watching is used. * `force-poll`: In this mode, Mutagen will always use its poll-based watching implementation, even on systems that support native watching. * `no-watch`: In this mode, Mutagen won’t perform any filesystem watching, and endpoints using this mode will not be able to trigger a synchronization cycle. If this mode is used for the entire synchronization session, then a synchronization cycle only occurs when the `mutagen sync flush` command is used. These modes can be specified on a per-session and/or per-endpoint basis by passing the `--watch-mode=` or `--watch-mode-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command. These modes can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: watch: mode: "" ### Polling interval If using polling-based watching, the polling interval (which defaults to 10 seconds) can be specified on a per-session and/or per-endpoint basis by passing the `--watch-polling-interval=` or `--watch-polling-interval-(alpha|beta)=` flag, respectively, to the `mutagen sync create` command (where `` is an integer value representing seconds) and on a default per-session basis by including the following configuration in `~/.mutagen.yml`: sync: defaults: watch: pollingInterval: --- # Windows named pipes | Mutagen Contents Windows named pipes =================== Windows named pipes provide a secure, high-performance, stream-based transport accessible via Windows UNC paths. They come with a few platform restrictions, caveats, and known issues which are outlined below. Platform support ---------------- Windows named pipes are only supported on Windows endpoints, though they can be targeted as forwarding sources/destinations from non-Windows systems. Access rights ------------- Named pipe listeners are created with user-only access permissions. Remote clients (i.e. those attempting to access named pipes via an address of the form `\\\pipe\`) are rejected. Known issues ------------ * On Windows 7, the first connect operation to a named pipe listener hangs indefinitely. This is tracked by [microsoft/go-winio#173](https://github.com/microsoft/go-winio/issues/173) . If using a named pipe client such as the Docker® CLI, this typically results in the command hanging and needing to be cancelled. Subsequent connect operations will succeed. --- # Mutagen Compose | Mutagen Contents Mutagen Compose =============== **Note:** Mutagen Compose is now deprecated with the release of v0.18.0. For more information, please see the relevant [release notes](https://github.com/mutagen-io/mutagen-compose/releases/tag/v0.18.0) . This deprecation does not apply to Mutagen. [Mutagen Compose](https://github.com/mutagen-io/mutagen-compose) is a Mutagen sibling project that provides Mutagen integration with [Docker® Compose](https://docs.docker.com/compose/) , allowing you to automatically create Mutagen synchronization and forwarding sessions alongside your Compose-based services, volumes, and networks. Using Mutagen’s synchronization and forwarding sessions, you can replace bind mounts and exposed ports, allowing you to run your project on a remote and/or cloud-based Docker engine, while still editing code and accessing your application locally. Mutagen Compose can also be used with [Docker Desktop](https://www.docker.com/products/docker-desktop) to provide a high-performance alternative to the virtual filesystems used in Docker Desktop bind mounts. Getting started --------------- The following sections provide detailed information about using Mutagen’s support for Docker Compose, but the best way to experience it is to look at an example project and try it for yourself. You can find [an example web application](https://github.com/mutagen-io/mutagen-examples/tree/main/compose/web-go) that demonstrates using this integration in the Mutagen repository. Have a look at the corresponding [Compose YAML file](https://github.com/mutagen-io/mutagen-examples/tree/main/compose/web-go/compose.yml) to get an idea of what’s involved with integrating Mutagen, and try starting the project using `mutagen-compose up`. Here are a few other examples to get you started: * A simple [data science environment](https://github.com/mutagen-io/mutagen-examples/tree/main/compose/data-science) that uses Mutagen Compose integration * A [port of the Example Voting App](https://github.com/mutagen-io/example-voting-app) that has been [modified](https://github.com/mutagen-io/example-voting-app/commit/master) to support Mutagen Compose integration Usage ----- Mutagen Compose uses `x-mutagen` [extension fields](https://docs.docker.com/compose/compose-file/#extension-fields) in Compose YAML files to define synchronization and forwarding sessions that target Docker volumes and networks, respectively. The format of these extension fields is described [below](https://mutagen.io/documentation/orchestration/compose/#extension-fields) . Once you’ve added these fields, you can use the `mutagen-compose` command to start and operate your Compose project. The `mutagen-compose` command is a complete Compose implementation that understands `x-mutagen` configuration information and creates, updates, and terminates Mutagen synchronization and forwarding sessions alongside your Compose-based services, volumes, and networks. Extension fields ---------------- To define synchronization and forwarding sessions, you just need to include an `x-mutagen` field at the root of your Compose YAML with Mutagen configuration and session definitions. Here’s an example of what such a YAML file might look like: # Define networks networks: frontend: backend: # Define volumes volumes: code: # Define services services: database: ... networks: - backend web: ... volumes: - code:/code networks: - frontend - backend ... # Define synchronization and forwarding sessions x-mutagen: sync: defaults: ignore: vcs: true code: alpha: "." beta: "volume://code" forward: database: source: "tcp:localhost:5432" destination: "network://backend:tcp:database:5432" web: source: "tcp::8080" destination: "network://frontend:tcp:web:8080" In this example, we define a Mutagen session to synchronize code from the Compose project directory to a shared volume that we mount into our application container. We also define two Mutagen forwarding sessions: one that exposes the database to our local system (so that you can access it via a local client for development purposes) and one that exposes a web appplication on all interfaces on our local system (so that you can test it locally and from other devices on your local network). In this example, we use a separate volume to store code and we create networks manually. While volumes are necessary for synchronization targets, you don’t need to explicitly create networks as in this example—you can reference the `default` network by name. We’ve also avoided any major synchronization configuration here, whereas in real-world usage you’ll likely want to set up [ignores](https://mutagen.io/documentation/synchronization/ignores/) and [conflict resolution behavior](https://mutagen.io/documentation/synchronization/#modes) . See [this example](https://github.com/mutagen-io/mutagen-examples/tree/main/compose/web-go/compose.yml) for a more complete setup. The format of the `x-mutagen` field is an extension of the [global configuration format described in the introduction](https://mutagen.io/documentation/introduction/configuration/#format) . In addition to a `defaults` key for synchronization and forwarding, it allows you to define keys that refer to named sessions. Sessions defined in Compose projects can also have endpoint-specific configuration options, which are specified using the `configurationAlpha` and `configurationBeta` keys for synchronization sessions and `configurationSource` and `configurationDestination` keys for forwarding sessions. The most general `x-mutagen` configuration looks something like: x-mutagen: sync: defaults: ...default synchronization configuration... example-sync-session: alpha: ... beta: ... ...configuration... configurationAlpha: ...alpha-specific configuration... configurationBeta: ...beta-specific configuration... ... forward: defaults: ...default forwarding configuration... example-forwarding-session: source: ... destination: ... ...configuration... configurationSource: ...source-specific configuration... configurationDestination: ...destination-specific configuration... ... As with normal Compose projects, you can specify these configuration elements across multiple YAML files. When merging YAML files, Mutagen will merge `x-mutagen` fields at the level below the `sync` and `forward` keys (i.e. sessions with different names will be combined into a set, while sessions with the same name (and session type) found in different files will just use the last definition). This also applies to `defaults` keys. ### Endpoint URLs Mutagen’s Compose integration currently supports only a limited set of endpoint URL formats, though these should suffice for typical Compose usage. For synchronization sessions, one of the endpoint URLs must be a [local URL](https://mutagen.io/documentation/transports/local/) and the other must be a [volume URL](https://mutagen.io/documentation/orchestration/compose/#volume-urls) . For forwarding, the source endpoint URL must be a local URL and the destination endpoint URL must be a [network URL](https://mutagen.io/documentation/orchestration/compose/#network-urls) . Support for Mutagen’s other transports is under development. #### Volume URLs Volume URLs are of the form: volume://[] The `` component must refer to the name of a volume defined in the Compose YAML. The `` component is optional and should be an absolute path rooted at the volume root. If the `` component is omitted, then the volume root is used as the synchronization target. #### Network URLs Network URLs are of the form: network://: The `` component must refer to the name of a network defined in the Compose YAML. The `` component is described in the [forwarding documentation](https://mutagen.io/documentation/forwarding/#endpoint-urls) . Only TCP-based network endpoints are currently supported (i.e those prefixed with `tcp`, `tcp4`, or `tcp6`) and the host component of the endpoint should refer to a service defined in the Compose YAML and attached to the specified network. Implementation -------------- Mutagen Compose is [implemented](https://github.com/mutagen-io/mutagen-compose) as a small layer of lifecycle hooks on top of [Docker Compose V2](https://github.com/docker/compose) . This allows Mutagen Compose to focus only on managing Mutagen sessions, while leaving the heavy lifting of creating volumes, networks, and containers to the underlying Docker Compose implementation. When a Compose project is started, Mutagen Compose injects an additional sidecar service (called `mutagen`) through which synchronization and forwarding can be routed. The `mutagen` service service uses the [Mutagen sidecar image](https://hub.docker.com/r/mutagenio/sidecar) , which is essentially a no-op entrypoint suitable for hosting Mutagen agents. Creation of this service is fully managed by the `mutagen-compose` command, so there’s no need to define it as part of your Compose YAML (though it will show up alongside other containers in your project). The `mutagen` service and all synchronization and forwarding sessions are started before any of the project’s services are created. Additionally, all synchronization sessions are flushed (forced to complete an initial synchronization cycle) before any services are started, so you can be sure that any code or other files being synchronized will be available on the target volumes before any of your containers start. The synchronization and forwarding sessions operate using Mutagen’s [Docker container transport](https://mutagen.io/documentation/transports/docker/) . The Mutagen sidecar image also causes a few minor behavioral changes in Mutagen agents that are designed to make working with Compose projects easier. Specifically: * If a synchronization session targets an empty volume root and a non-default owner, group, or directory mode setting has been specified, then Mutagen will set the permissions of the volume root to match. This is a heuristic to work around the fact that Docker volumes don’t have an easy way to set permissions upon creation. * If no file staging mode is explicitly set in the container, then Mutagen will will stage files into a temporary directory in their target volumes, avoiding the need for file copy operations when applying changes. If this behavior is undesirable (e.g. due to conflicts with filesystem watchers), then you can choose to stage in the sidecar container filesystem itself by selecting the [`mutagen` staging mode](https://mutagen.io/documentation/synchronization/staging/) . Known limitations ----------------- There are a few minor limitations with Mutagen Compose that shouldn’t restrict most use cases. These will be improved/fixed in future releases. * The Mutagen Compose version you install must match the version of Mutagen that you have installed. * POSIX users and groups targeted by ownership settings in the `x-mutagen` section must be specified by numeric ID rather than name. This is because ownership setting happens in the Mutagen sidecar container, where (a) most names likely aren’t set to resolve to a numeric ID and (b) may resolve to different numeric IDs than in other images given that the sidecar image uses an Alpine base (e.g. `www-data` resolves to user/group ID `82` in Alpine-based images, but `33` in Debian-based images). * Docker Compose V2 (and thus Mutagen Compose) will only use BuildKit (which you should use) if explicitly opted-into on the Docker engine (via [JSON configuration](https://docs.docker.com/develop/develop-images/build_enhancements/#to-enable-buildkit-builds) ) or on the client (by setting `DOCKER_BUILDKIT=1` in the environment). Docker Desktop already opts-in to using BuildKit, so this caveat doesn’t affect it, but remote Docker engines typically do not. In this case, Docker Compose V2 will fall back to using the classic builder, but that currently leaves behind a number of excess containers and images. As such, it’s highly recommended that you set `DOCKER_BUILDKIT=1` when using Mutagen Compose if you’re targeting a non-Docker Desktop engine. This applies to Docker Compose V2 as much as Mutagen Compose. * Octal file modes (e.g. `0755`) must be specified with a leading `0` and should optimally be specified with a `0o` prefix (e.g. `0o755`) in YAML for complete future-proofing. This restriction will likely migrate to the rest of Mutagen’s configuration soon, as the YAML spec no longer supports `0`\-only prefixes for octal modes (and Mutagen Compose doesn’t have the ability to assume an octal value in the absence of any prefix because it doesn’t control YAML parsing when loading Compose files). * Only local and Compose-related (i.e. `volume://` and `network://`) URLs are currently supported by Mutagen Compose. This is a temporary limitation that will be removed as development continues. * Reverse network forwarding is not currently supported by Mutagen Compose. This is a temporary limitation that should be removed as development continues. You can still use Mutagen to manually set up reverse forwarding from Docker containers in your project if necessary. * Only Linux containers are currently supported by Mutagen’s Compose integration. This is a temporary limitation that will be removed as development continues. Support for Windows containers is expected (and mostly implemented). * Because the Mutagen service is created and started before all other services, containers cannot rely on [volumes being populated with container contents](https://docs.docker.com/storage/volumes/#populate-a-volume-using-a-container) . See [mutagen-io/mutagen#302](https://github.com/mutagen-io/mutagen/issues/302) for additional discussion. --- # Unix domain sockets | Mutagen Contents Unix domain sockets =================== Unix domain sockets provide a secure, high-performance, stream-based transport accessible via filesystem endpoints. They come with a few platform restrictions, caveats, and additional configuration options which are outlined below. Platform support ---------------- Unix domain sockets are supported on POSIX systems and Windows 10 (build 17063 or later). Access rights ------------- Filesystem socket entries have permissions just like any other file, and these are often critical to ensuring the security of an application. Mutagen allows socket ownership and permissions to be set for the listener sockets it creates. **Caution:** Due to POSIX and Windows API limitations, there will be a very small window when creating a Unix domain socket where the socket endpoint is visible on disk with its default permissions before Mutagen can set the specified ownership and permissions. On POSIX systems, the Unix domain socket will be created with ownership based on the user running the Mutagen daemon or agent process and permissions based on the associated [`umask`](https://en.wikipedia.org/wiki/Umask) value for the process. The `umask` value on most systems defaults to `0022`, which will restrict connectivity to the creating user (though you should verify this setting for your system(s)). On Windows systems, the socket will be created with the permissions of the parent directory by default. More information about Unix domain socket permissions on Windows can be found [here](https://devblogs.microsoft.com/commandline/af_unix-comes-to-windows/) . ### Ownership Socket ownership can be specified on a per-session and/or per-endpoint basis by passing the `--socket-owner=` or `--socket-owner-(source|destination)=` flag, respectively, to the `mutagen forward create` command. Socket ownership can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: forward: defaults: socket: owner: "" Socket groups can be specified on a per-session and/or per-endpoint basis by passing the `--socket-group=` or `--socket-group-(source|destination)=` flag, respectively, to the `mutagen forward create` command. Socket groups can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: forward: defaults: socket: group: "" Owner and group specifications are the same as those used in [synchronization ownership specifications](https://mutagen.io/documentation/synchronization/permissions/#owners-and-groups) and carry the same caveats. ### Permissions Socket permissions can be specified on a per-session and/or per-endpoint basis by passing the `--socket-permission-mode=` or `--socket-permission-mode-(source|destination)=` flag, respectively, to the `mutagen forward create` command. Default permissions can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: forward: defaults: socket: permissionMode: Permission specifications are the same as those used in [synchronization permission mode specifications](https://mutagen.io/documentation/synchronization/permissions/#permissions-1) and carry the same caveats. Overwrites ---------- When an application attempts to bind a Unix domain socket to a filesystem location and finds that an entry already exists at that path, the bind will fail. Although Mutagen cleans up its socket filesystem entries when it closes its Unix domain socket listeners, many applications do not, and there’s always the possibility that Mutagen is abruptly terminated without the opportunity to clean up up these entries. As a result, it’s often necessary to remove stale socket entries from the filesystem when creating a new listener. To that end, Mutagen has two different “socket overwrite” modes that control how it behaves when a conflicting filesystem entry exists: * **`leave` (Default)**: In this mode, Mutagen will leave any conflicting filesystem entry in place and abort creation of the listener. * **`overwrite`**: In this mode, Mutagen will remove any conflicting filesystem entry and re-attempt creation of the listener. Removal will only be attempted for a single filesystem entry, meaning that it can only remove a file, symbolic link, or socket — it can’t remove a conflicting directory. These modes can be specified on a per-session and/or per-endpoint basis by passing the `--socket-overwrite-mode=` or `--socket-overwrite-mode-(source|destination)=` flag, respectively, to the `mutagen forward create` command. These modes can be specified on a default per-session basis by including the following configuration in `~/.mutagen.yml`: forward: defaults: socket: overwriteMode: "" --- # Tooling Integration | Mutagen Contents Tooling Integration =================== For users looking to integrate Mutagen with their development workflows, several higher-level options exist to automate the management of synchronization and forwarding sessions. Docker Desktop Extension ------------------------ For Docker Desktop users looking to enhance the performance of bind-mounted files, the [Mutagen extension for Docker Desktop](https://mutagen.io/documentation/docker-desktop-extension/) is likely the easiest option. This extension allows users to create synchronized caches of host filesystem locations inside the Docker Desktop VM and then automatically replace bind mounts with those caches. Mutagen Compose --------------- For Docker users with a Compose-based containerized development workflow, another way to use Mutagen is by integrating it with your Docker Compose workflow. [Mutagen Compose](https://mutagen.io/documentation/orchestration/compose/) is a full Compose implementation (built on Docker Compose) that uses `x-mutagen` attributes in your Compose YAML files to automatically start and stop synchronization and forwarding sessions that target your Compose volumes and networks. This allows you to replace bind mounts and exposed ports and enables you to run your project on a cloud-based Docker engine while still editing code and accessing your application locally. Projects -------- If you’re not using Docker Desktop or Compose, or if you have more specific requirements, Mutagen also offers a more generic [project mechanism](https://mutagen.io/documentation/orchestration/projects/) that allows you to automate the creation and termination of synchronization and forwarding sessions. --- # Projects | Mutagen Contents Projects ======== Mutagen’s project format is a lightweight orchestration mechanism that offers a way to declare and automate the creation and management of synchronization and forwarding sessions alongside other operations. Projects are a good alternative when [Mutagen Compose](https://mutagen.io/documentation/orchestration/compose/) doesn’t fit your use case. By combining Mutagen’s project orchestration with scripts and container orchestration tools like Docker Compose or Kubernetes®, you can create reproducible development environments that can be shared across your development team and run on cloud-based infrastructure. Getting started --------------- The following sections provide information about using Mutagen’s project orchestration features, but the best way to experience this is simply to try it yourself. You can find [an example web application](https://github.com/mutagen-io/mutagen-examples/tree/main/projects/docker/web-go) in the Mutagen repository that combines a Docker Compose container setup with Mutagen project orchestration to create a reproducible, cloud-based, containerized development environment. Usage ----- Project orchestration is managed by the `mutagen project` commands. These commands operate on a `mutagen.yml` file in the current directory (or a file specified using the `-f/--project-file` flag). They create a lock on this file (to ensure that only a single instance of a project is running) and then operate on the synchronization and forwarding sessions defined within the file. Certain project commands also have hooks associated with them that can be used to attach custom behavior. The organization of the `mutagen project` commands mirrors that of [individual session management commands](https://mutagen.io/documentation/introduction/getting-started/) , with commands like `list`, `pause`, `resume`, and so on. The only difference is that these commands operate on all of the sessions in a project at once. However, the sessions in a project are otherwise normal sessions (they just have a label that binds them to the project), so they can also be managed individually using their names or session identifiers and the relevant `mutagen sync` and `mutagen forward` commands. ### Starting a project To create and start the sessions associated with a Mutagen project, switch to the project directory and run: # Start a Mutagen project. mutagen project start If the project file defines `beforeCreate` and/or `afterCreate` hooks containing commands, they will be run before/after all sessions are created, respectively. Sessions that have `flushOnCreate` specified (see below) will be flushed after session creation and before the `afterCreate` hook. This doesn’t apply if the sessions are being created in a paused state by using the `-p/--paused` flag with `mutagen project start`, in which case the sessions won’t be flushed. ### Running commands If the `mutagen.yml` file defines custom commands in a `commands` section, they can be invoked by name using: # Run a Mutagen project command. mutagen project run ### Listing sessions To list the sessions associated with a project, you can use: # List the status of project sessions. mutagen project list This will show the status of individual sessions, including any problems or conflicts that may have arisen. ### Flushing sessions To flush the synchronization sessions associated with a project, you can use: # Flush project synchronization sessions. mutagen project flush ### Pausing sessions To pause the sessions associated with a project, you can use: # Pause project synchronization and forwarding sessions. mutagen project pause If the project file defines `beforePause` and/or `afterPause` hooks containing commands, they will be run before/after all sessions are paused, respectively. ### Resuming sessions To resume or reconnect sessions associated with a project, you can use: # Resume project synchronization and forwarding sessions. mutagen project resume If the project file defines `beforeResume` and/or `afterResume` hooks containing commands, they will be run before/after all sessions are resumed, respectively. ### Resetting sessions To reset the synchronization sessions associated with a project, you can use: # Reset project synchronization sessions. mutagen project reset ### Terminating sessions To terminate all sessions associated with a project and shut down the project itself, you can use: # Terminate project synchronization and forwarding sessions. mutagen project terminate If the project file defines `beforeTerminate` and/or `afterTerminate` hooks containing commands, they will be run before/after all sessions are terminated, respectively. Project file format ------------------- To best understand the Mutagen project file format, check out the [example project’s `mutagen.yml` file](https://github.com/mutagen-io/mutagen-examples/blob/main/projects/docker/web-go/mutagen.yml) . Mutagen’s project file format is a simple extension of the global configuration file format [described in the introduction](https://mutagen.io/documentation/introduction/configuration/#format) . In addition to a `defaults` key for synchronization and forwarding, it allows you to define keys that refer to named sessions. Project sessions can also have endpoint-specific configuration options, which are specified using the `configurationAlpha` and `configurationBeta` keys for synchronization sessions and `configurationSource` and `configurationDestination` keys for forwarding sessions. Finally, synchronization sessions (including defaults) can have the `flushOnCreate` key specified, which indicates that they should have a full synchronization cycle forced right after creation. This is most useful when you need to start infrastructure in the `afterCreate` hook that relies on files existing remotely. The most general session configuration structure would look something like: sync: defaults: ...default synchronization configuration... flushOnCreate: ... example-sync-session: alpha: ... beta: ... flushOnCreate: ... ...configuration... configurationAlpha: ...alpha-specific configuration... configurationBeta: ...beta-specific configuration... ... forward: defaults: ...default forwarding configuration... example-forwarding-session: source: ... destination: ... ...configuration... configurationSource: ...source-specific configuration... configurationDestination: ...destination-specific configuration... ... ### Setup and teardown As previously mentioned, project files also allow you to define `beforeCreate`, `afterCreate`, `beforeTerminate`, and `afterTerminate` hooks, which run a series of commands before and after creation and termination of all sessions (not individual sessions). These are simply lists of commands that are run in the system shell, for example: beforeCreate: - docker-compose up --build --detach afterTerminate: - docker-compose down --rmi=all --volumes ### Custom commands Finally, to help with creating common workflows, you can also define commands in projects using the `commands` section. These commands can be run using the `mutagen project run` command, for example: commands: web-shell: docker-compose exec web bash db-shell: docker-compose exec psql -U appuser -d appdb --- # Mutagen Extension for Docker Desktop | Mutagen Contents Mutagen Extension for Docker Desktop ==================================== Synchronized File Shares ------------------------ **Note:** The Mutagen Extension for Docker Desktop has been replaced by [Synchronized File Shares](https://docs.docker.com/desktop/synchronized-file-sharing/) , available in Docker Desktop 4.27+. You will need a Docker Pro, Team, or Business [subscription](https://www.docker.com/pricing/) to use this functionality. The extension is no longer available for download. --- # Docker Privacy | Docker [Skip to content](https://mutagen.io/legal/privacy#wp--skip-link--target) ![gray](https://www.docker.com/app/uploads/brand/background/gray.png "- gray") Docker Privacy ============== #### Docker respects your preferences concerning the collection and use of your personal data. These are some of the measures we take to protect your personal data. ### Privacy Policy Docker’s [Privacy Policy](https://www.docker.com/legal/docker-privacy-policy)  details the different ways personal data received from users of our website (“Website”) collected via the Website, email, SMS, telephone, WAP or other means may be collected, used, and disclosed by Docker. ### Data Processing Addendum The [EU General Data Protection Regulation (GDPR)](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation)  came into effect on May 25, 2018. GDPR has a long reach and applies if you are based in the EU or do business in the EU. If you have any EU personal data in your Docker account, such as names, email addresses, ID numbers, or anything else that is personally identifiable, then GDPR applies. You are a Controller of personal data under GDPR, so you need to enter into GDPR-compliant data processing agreements with any online services and third party vendors you rely on, including Docker. These agreements are called a Data Processing Addendum, or DPA. The processing of EU personal data must be governed by a [GDPR-compliant data processing agreement](https://gdpr-info.eu/art-28-gdpr/) . Docker provides a [standard DPA](https://mutagen.io/static/Data_Processing_Agreement.pdf)  to extend GDPR privacy principles, rights, and obligations regarding personal data stored in the production system/technical instance of Docker’s subscriptions and/or services provided by Docker and ordered by a Docker customer. ### Subprocessors Docker uses third party subprocessors, such as cloud computing service providers and customer support software, to provide our services. We enter into a GDPR-compliant data processing agreement with each subprocessor, and require the same of them. --- # Docker Privacy | Docker [Skip to content](https://mutagen.io/legal/cookies#wp--skip-link--target) ![gray](https://www.docker.com/app/uploads/brand/background/gray.png "- gray") Docker Privacy ============== #### Docker respects your preferences concerning the collection and use of your personal data. These are some of the measures we take to protect your personal data. ### Privacy Policy Docker’s [Privacy Policy](https://www.docker.com/legal/docker-privacy-policy)  details the different ways personal data received from users of our website (“Website”) collected via the Website, email, SMS, telephone, WAP or other means may be collected, used, and disclosed by Docker. ### Data Processing Addendum The [EU General Data Protection Regulation (GDPR)](https://en.wikipedia.org/wiki/General_Data_Protection_Regulation)  came into effect on May 25, 2018. GDPR has a long reach and applies if you are based in the EU or do business in the EU. If you have any EU personal data in your Docker account, such as names, email addresses, ID numbers, or anything else that is personally identifiable, then GDPR applies. You are a Controller of personal data under GDPR, so you need to enter into GDPR-compliant data processing agreements with any online services and third party vendors you rely on, including Docker. These agreements are called a Data Processing Addendum, or DPA. The processing of EU personal data must be governed by a [GDPR-compliant data processing agreement](https://gdpr-info.eu/art-28-gdpr/) . Docker provides a [standard DPA](https://mutagen.io/static/Data_Processing_Agreement.pdf)  to extend GDPR privacy principles, rights, and obligations regarding personal data stored in the production system/technical instance of Docker’s subscriptions and/or services provided by Docker and ordered by a Docker customer. ### Subprocessors Docker uses third party subprocessors, such as cloud computing service providers and customer support software, to provide our services. We enter into a GDPR-compliant data processing agreement with each subprocessor, and require the same of them. --- # Docker Terms of Service | Docker [Skip to content](https://mutagen.io/legal/terms#wp--skip-link--target) ![gray](https://www.docker.com/app/uploads/brand/background/gray.png "- gray") Docker Terms of Service ======================= Effective as of: December 14, 2020 ### 1\. Your Agreement with Docker **1.1** This website and all other related websites on which a link to these Terms of Service (the “**Terms**”) is displayed, and the Docker content and Docker services available on or through any of the foregoing (collectively, our “**Service**”) are provided to you by Docker, Inc., located at 3790 El Camino Real #1052, Palo Alto, CA 94306 USA (“**Docker**”). These Terms govern all access and use of the Service unless your access and use of Docker software is being made available to you under separate license terms. **1.2** All use of the Service is subject to acceptance of these Terms. By accessing or using the Service, or any content or services provided on the Service, you are agreeing to these Terms. If you are entering into these Terms on behalf of an entity, such as your employer or the company you work for, you represent that you have the legal authority to bind, and do hereby bind, that entity to these Terms. You may not use the Service if you are a person barred from using the Service under the laws of the United States or other countries, including the country in which you are resident or from which you use the Service, or international laws or treaties. You may not use the Service if you are or represent an entity that is listed on any U.S. Government Denied Party/Person List. You affirm that you are over the age of 13, as the Service is not intended for children under 13. IF YOU ARE 13 OR OLDER BUT UNDER THE AGE OF 18, OR THE LEGAL AGE OF MAJORITY WHERE YOU RESIDE IF THAT JURISDICTION HAS AN OLDER AGE OF MAJORITY, THEN YOU AGREE TO REVIEW THE TERMS WITH YOUR PARENT OR GUARDIAN TO MAKE SURE THAT BOTH YOU AND YOUR PARENT OR GUARDIAN UNDERSTAND AND AGREE TO THESE TERMS. YOU AGREE TO HAVE YOUR PARENT OR GUARDIAN REVIEW AND ACCEPT THESE TERMS ON YOUR BEHALF. IF YOU ARE A PARENT OR GUARDIAN AGREEING TO THE TERMS FOR THE BENEFIT OF A CHILD OVER 13, THEN YOU AGREE TO AND ACCEPT FULL RESPONSIBILITY FOR THAT CHILD’S USE OF THE SERVICE, INCLUDING ALL FINANCIAL CHARGES AND LEGAL LIABILITY THAT HE OR SHE MAY INCUR. **1.3** You agree that your use of the Service is not contingent on the delivery of any future functionality or features or dependent on any oral or written public comments made by Docker or any third party regarding future functionality or features. ### 2\. Your Account and Use of the Service **2.1** You must provide accurate and complete registration information any time you register to use the Service. You are responsible for the security of your passwords and for any use of your account. If you become aware of any unauthorized use of your password or of your account, you agree to notify Docker immediately via our [company contact form](https://www.docker.com/company/contact) . You can also reset your password by logging into your account for the Service. **2.2** Your use of the Service must comply with all applicable laws, regulations and ordinances, including any laws regarding the export of data or software. **2.3** You agree not to (a) access (or attempt to access) the administrative interface of the Service by any means other than through the interface that is provided by Docker in connection with the Service, unless you have been specifically allowed to do so in a separate agreement with Docker, or (b) engage in any activity that interferes with or disrupts the Service (or the servers and networks which are connected to the Service). **2.4** You may not access or use the Service for the purpose of bringing an intellectual property infringement claim against Docker or for the purpose of creating a product or service competitive with the Service. **2.5** Your account may have: limitations placed on it that are determined by the type and category of account you have chosen as set forth at [https://www.docker.com/pricing](https://www.docker.com/pricing) . These limitations include but are not limited to quantity of data stored, age of data stored, pull rate (defined as the number of requests per hour to download data from an account on Docker Hub) and number of collaborators as more fully described at [https://docs.docker.com/docker-hub/repos/](https://docs.docker.com/docker-hub/repos/) . If your actions or other use of the Service exceed the permissions associated with your chosen level of service, Docker reserves the right to enforce, in its sole discretion, the limitations associated with your chosen service level, including deletion of data which exceeds those limitations.  Repeated violations of these limitations may lead to termination of your account. **2.6** Image Vulnerability Scanning. The Service may include an image vulnerability scanning feature that will scan the images that you specify, which may be based upon code you authored, or code of others, and may generate vulnerability reports or information. This feature may be provided by a third party and you understand that any reports or other information that you receive from Docker (directly or indirectly) about possible vulnerabilities are not guaranteed to be comprehensive, and there can be no assurance that every fault or vulnerability is discovered in a particular image. You agree that the Service should not be used as the basis to deploy systems that must be hardened or highly secure, or involve mission-critical business operations, the operation of nuclear facilities, aircraft navigation, important communication systems, medical devices, air traffic control devices, real time control systems or other situations in which an inaccuracy or error in a report or in the service could lead to death, personal injury, or physical property or environmental damage. ### 3\. Privacy and Restrictions on Use **3.1** Docker’s [Privacy Policy](https://www.docker.com/legal/docker-privacy-policy/)  describes Docker’s collection, use, storage and disclosure of your personal information, including collection by any third party software utilized by Docker, and is hereby incorporated by this reference into these Terms. You agree to the use of your data in accordance with Docker’s Privacy Policy. **3.2** You agree that you will protect the privacy and legal rights of the end users of your repositories or other content stored or managed via the Service. You must provide legally adequate privacy notice and protection for such end users. **3.3** You agree that you are responsible for your own conduct while accessing or using the Service and for any consequences thereof. You agree to use the Service only for purposes that are legal, proper and in accordance with these Terms and any applicable laws or regulations. By way of example, and not as a limitation, you may not and may not allow any third party to: a. Send, upload, distribute or disseminate or offer to do the same with respect to any unlawful, defamatory, harassing, abusive, fraudulent, obscene, or otherwise objectionable content; b. Distribute viruses, worms, defects, Trojan horses, corrupted files, hoaxes, or any other items of a destructive or deceptive nature; c. Impersonate another person (via the use of an email address or otherwise) or otherwise misrepresent yourself or the source of any content; d. Upload, post, transmit or otherwise make available through the Service any content that infringes any patent, trademark, copyright, trade secret or other proprietary right of any party, unless you are the owner of such rights or have the permission of the owner to post such content; e. Download any content posted by another user that you know, or reasonably should know, that cannot be legally distributed in such manner; f. Submit content that falsely expresses or implies that such content is sponsored or endorsed by Docker; g. Use the Service to violate the legal rights (such as rights of privacy and publicity) of others; h. Promote or encourage illegal activity; i. Interfere with other users’ enjoyment of the Service; j. Exploit the Service for any unauthorized commercial purpose; k. Modify, adapt, translate, or reverse engineer any portion of the Service; l. Remove any copyright, trademark or other proprietary rights notices contained in or on the Service or any content posted thereon; m. Reformat or frame any portion of the web pages that are part of the Service’s administration display; n. Use the Service in connection with illegal peer-to-peer file sharing; o. Display any content on the Service that contains any hate-related or violent content or contains any other material, products or services that violate or encourage conduct that would violate any criminal laws, any other applicable laws, or any third party rights; p. Use any robot, spider, site search/retrieval application, or other device to retrieve or index any portion of the Service or the content posted thereon or to collect information about its users for any unauthorized purpose; q. Create user accounts by automated means or under false or fraudulent pretenses; or r. Use the Service, or any interfaces provided with the Service, to access any Docker product or service in a manner that violates the Terms or other terms and conditions for use of such Docker product or service. ### 4\. Usernames **4.1** We reserve the right to reclaim usernames and organization names on behalf of businesses or individuals that hold legal claim or trademark to those usernames. Accounts using business names and/or logos that may be considered misleading to others may be permanently suspended. We also reserve the right to reclaim usernames and organization names using Docker trademarks or usernames and organization names that violate the [Docker Trademark Guidelines](https://www.docker.com/legal/trademark-guidelines)  which are hereby incorporated into these Terms by reference. **4.2** You agree that Docker, in its sole discretion and subject to your opt-out rights as described below, may use your trade names, trademarks, service marks, logos, domain names and other distinctive brand features in presentations, marketing materials, customer lists, financial reports and Web site listings (including links to your website) for the purpose of advertising or publicizing your use of the Service. You may opt out of granting Docker the foregoing license, or require that you and Docker execute a separate license agreement therefor, by providing written notice to Docker within five (5) calendar days of the date you enter into these Terms. **4.3** Username Squatting. You may not and may not allow any third party to engage in username squatting. Accounts that are inactive for more than six months or that do not have any repositories associated with the account may be terminated at our discretion and without further notice. We take into account several factors when determining what conduct is considered to be username squatting including, without limitation: a. The number of accounts created b. Creating accounts for the purpose of preventing others from using those account names c. Creating accounts for the purpose of selling those accounts **4.4** Selling Usernames. You may not and may not allow any third party to buy or sell usernames and organization names. ### 5\. Fees **5.1** Subject to the Terms, the Service is provided to you without charge up to certain limits. Usage over this limit may require you to purchase additional resources or services. Pricing is set forth at [https://www.docker.com/pricing](https://www.docker.com/pricing) . **5.2** For all purchased resources and services, including with limitation any purchased Applications (as defined in Section 9), Docker will charge your credit card at the interval indicated at [https://www.docker.com/pricing](https://www.docker.com/pricing) . Docker may change its fees and payment policies by notifying you at least fifteen (15) days before the beginning of the billing cycle in which such change will take effect. Late payments will bear interest at the rate of 1.5% per month (or the highest rate permitted by law, if less). All fees are non-refundable (except as expressly set forth in Section 11.3) and exclusive of applicable taxes. You are responsible for paying all taxes and government charges, and all reasonable expenses and attorneys fees Docker incurs collecting late amounts. You acknowledge and agree that any credit card and related billing and payment information that you provide to Docker may be shared by Docker with companies who work on Docker’s behalf, such as payment processors and/or credit agencies, solely for the purposes of checking credit, effecting payment to Docker and servicing your account. Docker may also provide information in response to valid legal process, such as subpoenas, search warrants and court orders, or to establish or exercise its legal rights or defend against legal claims. Docker shall not be liable for any use or disclosure of such information by such third parties. Docker reserves the right to disable your access to the Service for any late payments. Any outstanding balance becomes immediately due and payable upon termination of the Terms for any reason. ### 6\. User Content **6.1** The Service allows you and other users to submit, post, transmit, and share content with other users, which may include, without limitation, data files, text, articles, documents, computer software or code, music, images, audiovisual works, informational materials and any user comments submitted by you and other users on or through the Service (collectively, “**User Content**”). For the avoidance of doubt, User Content shall not include Third Party Content (as defined in Section 9). You retain all your ownership rights in your User Content. Docker simply displays or makes the User Content available to users of the Service and does not otherwise control the content thereof. Docker does not guarantee any accuracy or confidentiality with respect to any information contained in any User Content, and strongly recommends that you think carefully about what you transmit, submit or post to or through the Service. You understand that all information contained in User Content is the sole responsibility of the person from whom such User Content originated. This means that you, and not Docker, are entirely responsible for all User Content that you upload, post, transmit, or otherwise make available through the Service, as well as for any actions taken by Docker or other users as a result of such User Content. **6.2** Docker intends to, but does not guarantee that it will, display or make any User Content available on or through the Service, and Docker reserves the right to refuse to allow any User Content on the Service, or to edit or remove any User Content at any time with or without prior notice, if Docker reasonably believes that you or your User Content are in violation of these Terms or otherwise disrupt or threaten the operation of the Service. Without limiting the generality of the preceding sentence, Docker complies with the Digital Millennium Copyright Act, and will remove User Content from the Service upon receipt of a compliant takedown notice (see Section 16 below). You agree to immediately take down any User Content that violates the Terms, including pursuant to a take-down request from Docker. In the event that you elect not to comply with a request from Docker to take down certain User Content, Docker reserves the right to directly take down such User Content, or to suspend or terminate your use of the Service. **6.3** By uploading or submitting your User Content through the Service, you hereby grant Docker and its affiliates and partners (collectively, the “Docker Licensees”) a worldwide, non-exclusive, fully paid-up, royalty-free license to reproduce (including by making mechanical reproductions), reformat, distribute, publicly display, and publicly perform your User Content in connection with providing you and other users with the services, features and functionalities available on or through the Service; provided, that for any User Content that is subject to an open source license, Docker’s rights shall be limited to the rights granted under the applicable open source license. **6.4** The Service allows you to specify or upload the terms under which other users of the Service will be licensed to use your User Content. If you do not specify or upload such license terms with respect to any User Content, you hereby grant to any other users of the Service, a non-exclusive license to access, download, use, modify or otherwise exploit such part of your User Content for any personal or business purposes. **6.5** You are solely responsible for your own User Content and the consequences of posting or publishing them. In connection with User Content, you affirm, represent, and warrant that: (i) you either own your User Content or have the necessary licenses, rights, consents, and permissions to grant the rights and licenses granted in these Terms, and (ii) the Docker Licensee’s exercise of the license rights set forth in this Section 6, does not and will not require obtaining a license from or paying any fees and/or royalties by Docker to any third party for the exercise of any rights granted in these Terms. However, the foregoing shall not be deemed a warranty by you of non-infringement of any third party patent rights. **6.6** You understand that Docker may inspect your User Content, including but not limited to scanning for vulnerabilities, at any time to check for potential security vulnerabilities and other issues. Docker may request that you immediately remedy any issue it discovers in your User Content and retains the right to remove any User Content at any time without notice for any valid business or technical reasons, such as if security vulnerabilities are identified in such User Content. **6.7** You understand that User Content made available on or through the Service comes from a variety of sources and that Docker does not endorse and is not responsible for the accuracy, usefulness, or intellectual property rights of or relating to such User Content. You understand that Docker cannot, and does not, review all User Content and does not endorse any User Content. You further understand and acknowledge that you may be exposed to User Content that is inaccurate, misleading, infringing, or otherwise objectionable. You agree to waive, and hereby do waive, any legal or equitable rights or remedies you have or may have against Docker with respect thereto. IF YOU ARE A CALIFORNIA RESIDENT, YOU WAIVE CALIFORNIA CIVIL CODE SECTION 1542, WHICH SAYS: “A GENERAL RELEASE DOES NOT EXTEND TO CLAIMS WHICH THE CREDITOR DOES NOT KNOW OR SUSPECT TO EXIST IN HIS OR HER FAVOR AT THE TIME OF EXECUTING THE RELEASE, WHICH IF KNOWN BY HIM OR HER MUST HAVE MATERIALLY AFFECTED HIS OR HER SETTLEMENT WITH THE DEBTOR.” **6.8** You agree that Docker has no responsibility or liability for the deletion or failure to store any User Content and other communications maintained on or transmitted through use of the Service. You further acknowledge that you are solely responsible for securing and backing up any User Content or other communication you upload or transmit to or through the Service. ### 7\. Proprietary Rights You acknowledge and agree that Docker (or Docker’s licensors) own all legal right, title and interest in and to the Service. The visual interfaces, graphics, design, systems, methods, information, computer code, software, services, “look and feel”, organization, compilation of the content, code, data, images, and all other elements of the Service (collectively, the “**Docker Materials**”) are protected by United States copyright, trade dress, patent, and trademark laws, international conventions, and all other relevant intellectual property and proprietary rights, and applicable laws. Except for any User Content owned and/or posted by you or other users, all Docker Materials are the copyrighted property of Docker or its licensors. Furthermore, all trademarks, service marks, and trade names contained in the Docker Materials are proprietary to Docker or its licensors. Except as expressly set forth herein, your use of the Service does not grant to you ownership of or any other rights with respect to any content, code, data, user comments or other materials that you may access on or through the Service. Docker reserves all rights to the Docker Materials not expressly granted in the Terms. ### 8\. Feedback You may choose to or Docker may invite you to submit comments, bug reports, ideas or other feedback about the Service, including without limitation about how to improve the Service or any other Docker products (“**Feedback**“). By submitting any Feedback, you agree that Docker is free to use such Feedback at its discretion and without any additional compensation to you, and/or to disclose such Feedback to third parties on a non-confidential basis or otherwise. You hereby grant Docker a perpetual, irrevocable, nonexclusive license under all rights necessary to incorporate and use your Feedback for any purpose. ### 9\. Third-Party Store **9.1** Docker may make available to you additional content, applications and services that are offered by third parties (“**Third Party Content**“). You acknowledge that your use of Third Party Content may be subject to additional fees. You further acknowledge that your use of any Third Party Content may be subject to a separate agreement between you and the provider of the Third Party Content (“**the Third Party Content Provider**“), and that Docker shall not be a party to such separate agreement between you and the Third Party Content Provider. The Third Party Content Provider, and not Docker, is solely responsible for the applicable Third Party Content, and any claims that you or any other party may have relating to that Third Party Content or its use. Docker does not endorse and is not responsible for the accuracy, functionality, usefulness, or intellectual property rights of or relating to such Third Party Content. You acknowledge and agree that, notwithstanding the foregoing, Docker and its affiliates are third party beneficiaries of the agreement between you and the Third Party Content Provider and that Docker will have the right (and will be deemed to have accepted the right) to enforce such agreement against you as a third party beneficiary thereof. **9.2** By subscribing to or purchasing any Third Party Content, you grant Docker permission to share your User Content, and user information with the Third Party Content Provider as necessary for you to be provided the Third Party Content. ### 10\. Recommendations Docker may, and you grant Docker permission to, make recommendations via the Service or email for products or services that in Docker’s opinion may be of interest to you based on your User Content, and/or use of the Service. ### 11. Modification and Termination **11.1** Docker is constantly innovating in order to provide the best possible experience for its users. You acknowledge and agree that the form and nature of the Service may change from time to time without prior notice to you and that Docker may add new features and remove features or otherwise change any part of the Service at any time without notice. **11.2** You may terminate these Terms at any time by canceling your account on the Service and discontinuing your use of the Service. You will not receive any refunds if you cancel your account or otherwise terminate these Terms. **11.3** You agree that Docker, in its sole discretion and for any or no reason, may terminate these Terms and your account for the Service. You agree that any termination of your access to the Service may be without prior notice, and you agree that Docker will not be liable to you or any third party for such termination. If Docker terminates these Terms or your access or use of the Service due to your breach of these Terms or any suspected fraudulent, abusive, or illegal activity, then termination of these Terms shall be in addition to any other remedies Docker may have at law or in equity. Notwithstanding anything to the contrary herein, in the event of any termination by Docker other than due to your breach of these Terms, Docker will reimburse to you any fees you have prepaid for resources and services purchased hereunder, prorated to the date of such termination. **11.4** Upon any termination or expiration of these Terms, whether by you or Docker, ANY INFORMATION (INCLUDING USER CONTENT) THAT YOU HAVE POSTED OR SUBMITTED ON OR THROUGH THE SERVICE OR THAT WHICH IS RELATED TO YOUR ACCOUNT MAY NO LONGER BE ACCESSED BY YOU and Docker will have no obligation to maintain any such information in its databases or to forward any such information to you or any third party. You are solely responsible for retrieving your User Content from the Service prior to termination of your account for any reason, provided that if we terminate your account, we will provide you a reasonable opportunity to retrieve your User Content. **11.5** Upon any termination of these Terms or your account, Sections 5, 6, 7, 8, 11.4, 11.5, 12, 13, 14, 15, 19 and 20 shall survive. ### 12\. EXCLUSION OF WARRANTIES **12.1** NOTHING IN THESE TERMS SHALL EXCLUDE OR LIMIT DOCKER’S WARRANTY OR LIABILITY FOR LOSSES WHICH MAY NOT BE LAWFULLY EXCLUDED OR LIMITED BY APPLICABLE LAW. **12.2** YOU EXPRESSLY UNDERSTAND AND AGREE THAT YOUR USE OF THE SERVICE IS AT YOUR SOLE RISK AND THAT THE SERVICE IS PROVIDED “AS IS” AND “AS AVAILABLE” WITHOUT WARRANTIES OF ANY KIND EITHER EXPRESS OR IMPLIED. TO THE FULLEST EXTENT PERMISSIBLE PURSUANT TO APPLICABLE LAW, DOCKER, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS MAKE NO EXPRESS WARRANTIES AND DISCLAIM ALL IMPLIED WARRANTIES REGARDING THE SERVICE, USER CONTENT OR ANY THIRD PARTY CONTENT OR EXTERNAL SITES, INCLUDING IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT CORRECTNESS, ACCURACY AND RELIABILITY. WITHOUT LIMITING THE GENERALITY OF THE FOREGOING, DOCKER, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS DO NOT REPRESENT OR WARRANT TO YOU THAT: (A) YOUR USE OF THE SERVICE WILL MEET YOUR REQUIREMENTS, (B) YOUR USE OF THE SERVICE WILL BE UNINTERRUPTED, TIMELY, SECURE OR FREE FROM ERROR, (C) USAGE DATA PROVIDED THROUGH THE SERVICE WILL BE ACCURATE OR (D) THE SERVICE OR ANY CONTENT, SERVICES, OR FEATURES MADE AVAILABLE ON OR THROUGH THE SERVICE ARE FREE OF VIRUSES OR OTHER HARMFUL COMPONENTS. ### 13\. LIMITATION OF LIABILITY **13.1** SUBJECT TO SECTION 12 ABOVE, YOU UNDERSTAND AND AGREE THAT DOCKER, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS SHALL NOT BE LIABLE TO YOU FOR ANY INDIRECT, INCIDENTAL, SPECIAL CONSEQUENTIAL OR EXEMPLARY DAMAGES WHICH MAY BE INCURRED BY YOU, HOWEVER CAUSED AND UNDER ANY THEORY OF LIABILITY, INCLUDING, BUT NOT LIMITED TO, ANY LOSS OF PROFIT (WHETHER INCURRED DIRECTLY OR INDIRECTLY), ANY LOSS OF GOODWILL OR BUSINESS REPUTATION, ANY LOSS OF DATA SUFFERED, COST OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR OTHER INTANGIBLE LOSS, EVEN IF DOCKER OR A DOCKER AUTHORIZED REPRESENTATIVE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. **13.2** SUBJECT TO SECTION 12 ABOVE, YOU AGREE THAT THE AGGREGATE LIABILITY OF DOCKER, ITS SUBSIDIARIES AND AFFILIATES, AND ITS LICENSORS TO YOU FOR ALL CLAIMS ARISING OUT OF OR RELATING TO THE USE OF OR ANY INABILITY TO USE ANY PORTION OF THE SERVICE OR OTHERWISE UNDER THESE TERMS, WHETHER IN CONTRACT, TORT, OR OTHERWISE, IS LIMITED TO US$100. **13.3** YOU ACKNOWLEDGE AND AGREE THAT DOCKER HAS MADE AVAILABLE THE SERVICE AND ENTERED INTO THESE TERMS IN RELIANCE UPON THE WARRANTY DISCLAIMERS AND THE LIMITATIONS OF LIABILITY SET FORTH HEREIN, THAT THE WARRANTY DISCLAIMERS AND THE LIMITATIONS OF LIABILITY SET FORTH HEREIN REFLECT A REASONABLE AND FAIR ALLOCATION OF RISK BETWEEN YOU AND DOCKER, AND THAT THE WARRANTY DISCLAIMERS AND THE LIMITATIONS OF LIABILITY SET FORTH HEREIN FORM AN ESSENTIAL BASIS OF THE BARGAIN BETWEEN YOU AND DOCKER. DOCKER WOULD NOTE BE ABLE TO PROVIDE THE SERVICE TO YOU WITHOUT THESE LIMITATIONS. ### 14\. Indemnification You agree to hold harmless and indemnify Docker and its subsidiaries, affiliates, officers, agents, employees, advertisers, licensors, suppliers or partners from and against any third party claim arising from or in any way related to (a) your breach of the Terms, (b) your violation of applicable laws, rules or regulations in connection with the Service, or (c) your User Content, including any liability or expense arising from all claims, losses, damages (actual and consequential), suits, judgments, litigation costs and attorneys’ fees, of every kind and nature. In such case, Docker will provide you with written notice of such claim, suit or action; will provide you the opportunity to control the defense and/or settlement of such claim, suit or action; and will provide you reasonable assistance in such defense or settlement, upon reasonable request. ### 15\. User Disagreements You alone are responsible for your involvement and interactions with other users of the Service. Docker reserves the right, but has no obligation, to monitor disagreements between you and other users. If you have a dispute with any other users of the Service, you irrevocably and forever release Docker (and Docker’s affiliates, officers, directors, agents, subsidiaries, joint ventures and employees) from claims, demands and damages (actual and consequential) of every kind and nature, known and unknown, arising out of or in any way connected with such disputes. IF YOU ARE A CALIFORNIA RESIDENT, YOU WAIVE CALIFORNIA CIVIL CODE SECTION 1542, WHICH SAYS: “A GENERAL RELEASE DOES NOT EXTEND TO CLAIMS WHICH THE CREDITOR DOES NOT KNOW OR SUSPECT TO EXIST IN HIS OR HER FAVOR AT THE TIME OF EXECUTING THE RELEASE, WHICH IF KNOWN BY HIM OR HER MUST HAVE MATERIALLY AFFECTED HIS OR HER SETTLEMENT WITH THE DEBTOR.” ### 16\. Copyright Policy **16.1** Docker has established the following process to respond to notices of alleged infringement that comply with the United States’ Digital Millennium Copyright Act (“**DMCA notices**“). **16.2** If you believe that your copyrighted work has been copied in a way that constitutes copyright infringement and is accessible via the Service, please notify Docker’s copyright agent, as set forth in the Digital Millennium Copyright Act of 1998 (DMCA). For your complaint to be valid under the DMCA, you must provide the following information in writing: a. An electronic or physical signature of a person authorized to act on behalf of the copyright owner; b. Identification of the copyrighted work that you claim is being infringed; c. Identification of the material that is claimed to be infringing and where it is located on the Service; d. Information reasonably sufficient to permit Docker to contact you, such as your address, telephone number, and e-mail address; e. A statement that you have a good faith belief that use of the material in the manner complained of is not authorized by the copyright owner, its agent, or law; and f. A statement, made under penalty of perjury, that the above information is accurate, and that you are the copyright owner or are authorized to act on behalf of the owner. Docker’s Designated Copyright Agent to receive notifications of claimed infringement can be reached as follows: Attention: Copyright Agent Docker, Inc. 3790 El Camino Real #1052 Palo Alto CA 94306 Email: [dmca@docker.com](mailto:dmca@docker.com) For clarity, only DMCA notices should go to the Docker Designated Copyright Agent. Any other feedback, comments, requests for technical support or other communications should be directed to Docker through [support@docker.com](mailto:support@docker.com) . ### 17\. External Sites **17.1** The Service may include hyperlinks to other web sites or resources (collectively, “**External Sites**”) solely as a convenience to its users. Docker has no control over any External Sites which are provided by companies or persons other than Docker. **17.2** You acknowledge and agree that Docker is not responsible for the availability of any External Sites, and does not endorse any advertising, products or other materials on or available from the External Sites. **17.3** You acknowledge and agree that Docker is not liable for any loss or damage which may be incurred as a result of the availability of the External Sites, or as a result of any reliance placed by you on the completeness, accuracy or existence of any advertising, products or other materials on, or available from, the External Sites. ### 18\. Changes to the Terms Docker may make changes to the Terms from time to time. When such changes are made, Docker will make the updated Terms available on or through the Service. Please check these Terms periodically for changes. Unless otherwise agreed to between you and Docker in writing, your continued use of the Service after such changes have been published on or through the Service shall constitute your binding acceptance of such changes. Unless otherwise agreed to between you and Docker in writing, in the event that such changes materially alter your rights or obligations hereunder such amended Terms will automatically be effective upon the earlier of (i) your continued use of the Service with actual knowledge of such modifications, or (ii) 30 days from the date such modified Terms are made available on or through the Service. Notwithstanding the foregoing, the resolution of any dispute that arises between you and Docker will be governed by the Terms in effect at the time such dispute arose. ### 19\. Dispute Resolution and Arbitration **19.1** Generally. In the interest of resolving disputes between you and Docker in the most expedient and cost effective manner, you and Docker agree that every dispute arising in connection with these Terms will be resolved by binding arbitration. Arbitration is more informal than a lawsuit in court. Arbitration uses a neutral arbitrator instead of a judge or jury, may allow for more limited discovery than in court, and can be subject to very limited review by courts. Arbitrators can award the same damages and relief that a court can award. Our agreement to arbitrate disputes includes all claims arising out of or relating to any aspect of these Terms, whether based in contract, tort, statute, fraud, misrepresentation, or any other legal theory, and regardless of whether a claim arises during or after the termination of these Terms. YOU UNDERSTAND AND AGREE THAT, BY ENTERING INTO THESE TERMS, YOU AND DOCKER ARE EACH WAIVING THE RIGHT TO A TRIAL BY JURY OR TO PARTICIPATE IN A CLASS ACTION. **19.2** Exceptions. Despite the provisions of Section 19.1, we both agree that nothing in these Terms will be deemed to waive, preclude, or otherwise limit the right of either of us to: (a) bring an individual action in small claims court; (b) pursue an enforcement action through the applicable federal, state, or local agency if that action is available; (c) seek injunctive relief in a court of law; or (d) to file suit in a court of law to address an intellectual property infringement claim. **19.3** Arbitrator. Any arbitration between you and Docker will be governed by the Commercial Dispute Resolution Procedures and the Supplementary Procedures for Consumer Related Disputes (collectively, “**AAA Rules**“) of the American Arbitration Association (“**AAA**“), as modified by these Terms, and will be administered by the AAA. The AAA Rules and filing forms are available online at [www.adr.org](http://www.adr.org/) , by calling the AAA at 1-800-778-7879, or by contacting Docker. **19.4** Notice; Process. A party who intends to seek arbitration must first send a written notice of the dispute to the other, by certified mail or Federal Express (signature required), or if we do not have a physical address on file for you, by electronic mail (“**Notice**“). Docker’s address for Notice is: Docker, Inc., 3790 El Camino Real #1052, Palo Alto, CA 94306. The Notice must: (a) describe the nature and basis of the claim or dispute; and (b) set forth the specific relief sought (“**Demand**“). We agree to use good faith efforts to resolve the claim directly, but if we do not reach an agreement to do so within 30 days after the Notice is received, you or Docker may commence an arbitration proceeding. During the arbitration, the amount of any settlement offer made by you or Docker must not be disclosed to the arbitrator until after the arbitrator makes a final decision and award, if any. If our dispute is finally resolved through arbitration in your favor, Docker will pay you the highest of the following: (i) the amount awarded by the arbitrator, if any; (ii) the last written settlement amount offered by Docker in settlement of the dispute prior to the arbitrator’s award; or (iii) $1,000. **19.5** Fees. If you commence arbitration in accordance with these Terms, Docker will reimburse you for your payment of the filing fee, unless your claim is for more than $10,000, in which case the payment of any fees will be decided by the AAA Rules. Any arbitration hearing will take place at a location to be agreed upon in Santa Clara County, California USA but if the claim is for $10,000 or less, you may choose whether the arbitration will be conducted: (a) solely on the basis of documents submitted to the arbitrator; (b) through a non-appearance based telephone hearing; or (c) by an in-person hearing as established by the AAA Rules in the county (or parish) of your billing address. If the arbitrator finds that either the substance of your claim or the relief sought in the Demand is frivolous or brought for an improper purpose (as measured by the standards set forth in Federal Rule of Civil Procedure 11(b)), then the payment of all fees will be governed by the AAA Rules. In that case, you agree to reimburse Docker for all monies previously disbursed by it that are otherwise your obligation to pay under the AAA Rules. Regardless of the manner in which the arbitration is conducted, the arbitrator must issue a reasoned written decision sufficient to explain the essential findings and conclusions on which the decision and award, if any, are based. The arbitrator may make rulings and resolve disputes as to the payment and reimbursement of fees or expenses at any time during the proceeding and upon request from either party made within 14 days of the arbitrator’s ruling on the merits. **19.6** No Class Actions. YOU AND DOCKER AGREE THAT EACH MAY BRING CLAIMS AGAINST THE OTHER ONLY IN YOUR OR ITS INDIVIDUAL CAPACITY AND NOT AS A PLAINTIFF OR CLASS MEMBER IN ANY PURPORTED CLASS OR REPRESENTATIVE PROCEEDING. Further, unless both you and Docker agree otherwise, the arbitrator may not consolidate more than one person’s claims and may not otherwise preside over any form of a representative or class proceeding. **19.7** Modifications. If Docker makes any future change to this arbitration provision (other than a change to Docker’s address for Notice), you may reject the change by sending us written notice within 30 days of the change to Docker’s address for Notice, in which case your account with Docker will be immediately terminated and this arbitration provision, as in effect immediately prior to the amendments you reject will survive. **19.8** Enforceability. If Section 19.6 is found to be unenforceable or if the entirety of this Section 19 is found to be unenforceable, then the entirety of this Section 19 will be null and void and, in that case, the parties agree that the exclusive jurisdiction and venue described in Section 20.7 will govern any action arising out of or related to these Terms. ### 20\. General Legal Terms **20.1** The Terms constitute the whole legal agreement between you and Docker and govern your use of the Service (but excluding any services which Docker may provide to you under a separate written agreement) and completely replace any prior agreements between you and Docker in relation to the Service. **20.2** There are no third party beneficiaries to these Terms. The parties are independent contractors, and nothing in these Terms creates an agency, partnership or joint venture. **20.3** If Docker provides you with a translation of the English language version of these Terms, the English language version of these Terms will control if there is any conflict. **20.4** You agree that Docker may provide you with notices, including those regarding changes to the Terms, by email, regular mail, or postings on the Service. By providing Docker your email address, you consent to our using the email address to send you any notices required by law in lieu of communication by postal mail. You may provide us with legal notices at our postal address set forth above or via email to [support@docker.com](mailto:support@docker.com) . **20.5** You agree that if Docker does not exercise or enforce any legal right or remedy which is contained in the Terms (or which Docker has the benefit of under any applicable law), this will not be deemed a waiver of any such rights or remedies, and that those rights or remedies will still be available to Docker. **20.6** Docker shall not be liable for failing or delaying performance of its obligations resulting from any condition beyond its reasonable control, including but not limited to, governmental action, acts of terrorism, earthquake, fire, flood or other acts of God, labor conditions, power failures, and Internet disturbances. **20.7** The Terms, and your relationship with Docker under the Terms, shall be governed by the laws of the State of California without regard to its conflict of laws provisions. You and Docker agree to submit to the exclusive jurisdiction of the courts located within the county of Santa Clara, California USA to resolve any legal matter arising from the Terms. **20.8** You understand that the Service is subject to United States export controls administered by the U.S. Department of Commerce and the United States Department of Treasury Office of Foreign Assets Control. You acknowledge and agrees that the Service and any User Content or Third Party Content accessed by you shall not be used, transferred or otherwise exported or re-exported to countries as to which the United States, maintains an embargo (collectively, “**Embargoed Countries**“), or to or by a national or resident thereof, or any person or entity on the U.S. Department of Treasury’s List of Specially Designated Nationals or the U.S. Department of Commerce’s Entity List, Denied Persons List, or Unverified List, or the U.S. Department of State’s Nonproliferation Sanctions list (collectively, “**Designated Nationals**“). The lists of Embargoed Countries and Designated Nationals are subject to change without notice. By using the Service, including without limitation by uploading or accessing any User Content or Third Party Content, you represent and warrant that you are not located in, under the control of, or a national or resident of an Embargoed Country or Designated National. You agree to comply strictly with all U.S. export laws and assume sole responsibility for obtaining United States government export licenses to export or re-export as may be required. You will defend, indemnify, and hold harmless Docker and its suppliers and licensors from and against any violation of such laws or regulations by you or any of your agents, officers, directors or employees. **20.9** Neither party may assign any of its rights or obligations under these Terms, whether by operation of law or otherwise, without the prior written consent of the other party (not to be unreasonably withheld). Notwithstanding the foregoing, Docker may assign the entirety of its rights and obligations under these Terms, without your consent, to an affiliate or in connection with a merger, acquisition, corporate reorganization, or sale of all or substantially all of its assets. Any assignment attempted to be made in violation of these Terms will be void. Get started with Docker today ----------------------------- [Get started](https://www.docker.com/get-started/) --- # SSH Tips for Remote Development | Mutagen Contents * * * [![](https://mutagen.io/img/social/twitter_blue.svg) Share on Twitter](https://twitter.com/intent/tweet?text=SSH%20Tips%20for%20Remote%20Development&url=https%3a%2f%2fmutagen.io%2fblog%2fssh-tips-for-remote-development%2f&via=mutagen_io) SSH Tips for Remote Development =============================== ![Jacob Howard](https://mutagen.io/img/authors/jacob-howard.png) [Jacob Howard](https://twitter.com/xenoscopic) in [General](https://mutagen.io/blog/category/general) 8 January 2020 [![](https://mutagen.io/img/social/twitter_blue.svg) Share on Twitter](https://twitter.com/intent/tweet?text=SSH%20Tips%20for%20Remote%20Development&url=https%3a%2f%2fmutagen.io%2fblog%2fssh-tips-for-remote-development%2f&via=mutagen_io) SSH is undoubtedly one of the most powerful tools for enabling remote development. Over a history spanning decades, SSH has proven itself to be reliable, security-focused, and flexible. Since SSH is one of Mutagen’s core transports, I felt that it would be useful to share a handful of simple but powerful features that I use on a daily basis to drastically improve my SSH experience and remote development workflows. None of these features will be new or surprising for SSH aficionados, but new or infrequent SSH users will hopefully find them valuable. I’ve intentionally kept this list short and restricted to features that are simple and broadly useful. I’ve also restricted it to OpenSSH features since OpenSSH is by far the most common SSH implementation, but most of these features have analogs in other SSH clients. For a full list of SSH’s superpowers, I’d recommend you grab a cup of tea and drop into the [`ssh` man page](https://linux.die.net/man/1/ssh) —it’s well worth the time investment. Aliases and configuration ------------------------- Perhaps the most powerful SSH feature that users tend to avoid is its configuration system. The SSH client configuration file (stored in `~/.ssh/config` or specified via the `-F` flag) allows users to define hosts, aliases for those hosts, and host-specific configuration. This allows for less typing and significantly reduces the risk of command line typos. A minimal configuration block in `~/.ssh/config` might look like the following: Host example-server HostName host.example.org User me This configuration would cause the command `ssh example-server` to behave like `ssh me@host.example.org`. This may not seem like a huge gain, but it already avoids the need to specify the username when invoking SSH (how many times have you had to `Ctrl-C` SSH after seeing `@host.example.org`?). It also creates an alias for the SSH target (`example-server`) and adds it to SSH’s autocomplete functionality, meaning that if you type `ssh ex` and press `Tab`, you’ll see `example-server` in SSH’s list of suggestions (assuming you have autocomplete support enabled for your shell and SSH). A more complex configuration block might look like the following: Host example-server HostName host.example.org Port 24 User me IdentityFile ~/.ssh/id_rsa_example_org TCPKeepAlive yes ServerAliveInterval 60 In this example, a custom port has been specified, a non-default SSH private key has been provided, and other connection parameters have been set. Having to type each of these configuration parameters as separate flags when invoking SSH would be both tedious and error-prone. The best part of all of this is that programs that use SSH as a transport (usually) automatically inherit this functionality, meaning that you can insert the host alias into the location where you’d typically insert a more explicit specification, for example: scp example-server:~/ or mutagen sync create example-server:~/ These examples only scratch the surface of what is possible. For more information, including information on wildcard host matching, check out the [`ssh_config` man page](https://linux.die.net/man/5/ssh_config) . Factoring out SSH configuration from the command line to a configuration file has a huge impact on most SSH workflows, making it easier to manage large sets of servers and deal with complex server setups. The time invested in setting up this configuration is usually recouped within hours. Proxying connections -------------------- One of the coolest features of SSH is its `ProxyCommand` option. This option allows SSH to connect to a remote server via execution of an intermediate command, which is particularly useful in cases where an intermediate bastion server is used to access another internal SSH server. The SSH configuration for a bastion setup might look something like: Host bastion-server HostName bastion.example.org User bastionuser IdentityFile ~/.ssh/id_rsa_bastion Host internal-server HostName 10.0.1.25 User internaluser IdentityFile ~/.ssh/id_rsa_internal ProxyCommand ssh bastion-server -W %h:%p In this setup, a bastion server (`bastion.example.org`) is being used to access a private internal server (with the IP address `10.0.1.25`). The `ProxyCommand` option is used to specify a command that will open a TCP connection to the target SSH server and connect it to the standard input and output of the proxy command process. SSH will then use this proxied stream to communicate with the target SSH server. In this case, we’re using `ssh` itself as the proxy command, specifying the handy `-W` flag to open a connection to the internal SSH server via the bastion server, but you can also use tools like `nc` as the proxy command. The `ProxyCommand` option provides support for templated placeholders like `%h` and `%p` that are used to pass information about the target SSH server to the proxy command. In this case, the hostname passed to the proxy command (filling in the `%h` placeholder) will be `10.0.1.25` and the port value (filling in `%p`) will default to 22. Generally speaking, you’ll want the `HostName` value specified for the target SSH server to be relative to the intermediate server, so it’s quite possible that you might have an internal IP or hostname specified for `HostName`, as is the case here. What do we get for all this trouble? Well, now we can do: ssh internal-server and be directly connected to the internal server. No more intermediate SSH sessions (at least none that are visible to the user). Moreover, because other tools inherit SSH aliases and their behavior, we can do things like: scp internal-server:~/ or mutagen forward create tcp:localhost:8080 internal-server:tcp:localhost:8080 The flexibility of `ProxyCommand` (and its relative `ProxyJump`) cannot be overstated. While it’s typically used for connecting via bastion servers, it can be used for other types of proxies as well (or to chain multiple proxies together). The only requirement is that the proxy command somehow create a TCP connection to the target SSH server and connect it to the process’ standard input/output. In theory you could write a proxy command that sends SSH data via a web socket, connects via a SOCKS proxy, or even bounces data off the moon using lasers (though the latency probably wouldn’t be ideal). Loading private keys -------------------- When using public key authentication, you ideally want to password-protect your private keys, though many people don’t. Those that do set a password when creating a private key are rewarded by needing to endlessly type in the password for that private key every time they connect to a server where the key is being used for authentication (which is doubly fun when using `ProxyCommand`). Fortunately there’s a way to have your cake and secure it too. The `ssh-agent` command is a daemon that lives on the local system and stores your unlocked private keys in-memory, allowing SSH to grab them when necessary and only requiring you to type in the password once. You don’t actually start `ssh-agent` directly, but instead use the `ssh-add` command to unlock a private key and automatically start the `ssh-agent` daemon if it’s not already running. This basically looks like: # Unlock a private key and add it to ssh-agent. ssh-add ~/.ssh/id_rsa Enter passphrase: All you have to do is specify the private key that you want to unlock. Once added to `ssh-agent`, the private key will be available to SSH (and any other programs using SSH) without you needing to enter the password for the key. There’s a lot more that one can do with `ssh-agent` than what’s outlined here, and there are also some security implementations worth reading about (especially on multi-user systems), but for single-user systems with secure SSH keys, `ssh-agent` can be a game changer. For more information, check out the [`ssh-agent` man page](https://linux.die.net/man/1/ssh-agent) . Port and socket forwarding -------------------------- Besides creating interactive terminal sessions and forwarding input and output to and from remote commands, SSH’s third major utility is forwarding network traffic. This forwarding is controlled by the `ssh` command’s `-L` and `-R` flags and the exact format for these flags is detailed extensively in the [`ssh` man page](https://linux.die.net/man/1/ssh) , so I won’t regurgitate that here. Instead, I just want to touch on a few related topics. Of course I’ll also point out that you can perform the exact same forwarding with Mutagen, and it behaves better in some ways (for example, cleaning up sockets), but sometimes SSH is the right tool for the job (especially if it’s the only one available). The first thing to mention is the `-N` flag, which essentially tells the `ssh` command that it’s only being used for forwarding and that it shouldn’t start an interactive session or execute any command. Using this flag, a typical TCP forwarding setup might look something like this: # Start an SSH session that performs port forwarding and does nothing else. ssh -N -L 'localhost:8080:localhost:8080' user@example.org Nothing will be printed when you run this command (unless SSH needs a password or some other input), but the TCP forwarding will be established and continue to function until the command is terminated. Second, while we’re on the topic of TCP forwarding, it’s really important to mention that the default bind if no hostname is specified is _**all interfaces**_, not `localhost`. This means that you don’t want to do something like: # WARNING: This binds to port 5432 on *ALL* local interfaces! ssh -N -L '5432:localhost:5432' user@sensitive-postgres-server.example.org Doing so while sitting on a public network and without any local firewall would mean that your secure server was now exposed to anyone on that network who might be scanning for open ports. This same caveat also applies to Mutagen’s network forwarding. Third, just in case it wasn’t clear, you can forward multiple ports with the same `ssh` command invocation (using repeated `-L` and/or `-R` specifications) and you can mix the `-L` and `-R` flags. Combining multiple forwarding specifications can be a simple and secure mechanism for tying together different application components (e.g. a local web application and a remote database). Fourth, you can mix TCP and Unix domain socket endpoints when forwarding (for example, forwarding connections from a remote Unix domain socket to a local TCP server). This doesn’t have a lot of practical applications, but it is cool. Fifth, you may want to remove stale Unix domain sockets when starting forwarding. SSH doesn’t clean up the Unix domain sockets that it creates, so starting a new forwarding command can require tedious removal of the previously created socket. The next best thing is using the `StreamLocalBindUnlink` option, which will remove any conflicting Unix domain sockets when starting forwarding, for example: # Tell SSH to remove any conflicting Unix domain sockets when forwarding. ssh -N -o 'StreamLocalBindUnlink=yes' -L '/home/me/local.sock:/var/remote.sock' example.org Note that `StreamLocalBindUnlink` doesn’t determine whether or not the conflicting socket is in use—it simply removes any conflicting socket. Sixth, you may want to set permissions on the socket. This is particularly important when forwarding sockets to a remote daemon that needs to remain secure. This can be done using the `StreamLocalBindMask` option, which overrides the default [`umask`](https://en.wikipedia.org/wiki/Umask) when creating sockets. The default mask is `0177`, which results in sockets which are only accessible by the current user (which is the safest default). Here’s an example of what explicitly specifying such a mask would look like: # Tell SSH to use a umask of 0177 for setting Unix domain socket permissions. ssh -N -o 'StreamLocalBindMask=0177' -L '/home/me/local.sock:/var/remote.sock' example.org It’s worth noting that not all platforms use socket permissions to restrict access (though most modern systems do), so you should consult the relevant documentation for your platform. Finally, it’s worth mentioning one important application of this forwarding: accessing a remote Docker® daemon. For example, if you had a Docker daemon installation accessible via SSH, this forwarding might look like: # Forward a local socket to a remote Docker daemon. ssh -N -o 'StreamLocalBindUnlink=yes' -o 'StreamLocalBindMask=0177' -L '/Users/me/docker.sock:/var/run/docker.sock' dockeruser@dockerhost.example.org You can then tell your Docker client (and any software that runs on top of the client, e.g. Docker Compose or Mutagen) to connect to the remote daemon via this forwarded socket using the `DOCKER_HOST` environment variable, e.g. # Tell the Docker client to use a non-standard socket to connect to the daemon. export DOCKER_HOST=unix:///Users/me/docker.sock This is a fantastic way to set up and access a Docker daemon without having to virtualize it on your laptop. All you need in this case is the Docker client, which is significantly easier to install. You can also use Mutagen to set up this forwarding, in which case the Mutagen daemon will keep this forwarding alive in the background and allow you to just add the `DOCKER_HOST` setting to your shell initialization file (e.g. `.profile` or `.bashrc`) and access it all the time. Multiplexing ------------ All SSH connections are inherently multiplexed, meaning that the single TCP connection made from the `ssh` command to the SSH server handles multiple data streams. For example, one data stream might be used to create an interactive terminal session and another data stream might be used to forward a network connection (depending on what the `ssh` command has been told to do). SSH allows us to exploit this multiplexing even further by using a single multiplexed TCP connection to serve multiple `ssh` command invocations. Instead of opening a new TCP connection every time `ssh` is invoked, SSH can cache and store the TCP connection created for an `ssh` command and re-use it for subsequent `ssh` invocations. Of course, this also applies to commands that use the `ssh` command internally, such as `scp`, `rsync`, or `git`. This can drastically improve the performance of commands that regularly interface with the same SSH host (such as `git push` and `git pull` commands), and makes establishing new interactive SSH sessions lightning fast. The way this multiplexing is established is via the `ControlMaster` directive. A typical configuration might look like: Host git.example.org ControlMaster auto ControlPath ~/.ssh/connections/%r_%h_%p ControlPersist 1h The way that `ControlMaster` connections work is by creating a Unix domain socket (set via the `ControlPath` parameter) that will be used by `ssh` commands as the default mechanism for connecting to the remote host. By specifying `auto` for `ControlMaster`, we’re telling SSH that it should first try to connect via this Unix domain socket, but fall back to creating a standard TCP connection if the socket doesn’t exist. If an `ssh` command does create a TCP connection, it will then make that connection available via a Unix domain socket at the target path. Thus, you need to specfy a path where those connections should be created and make sure the parent directory (`~/.ssh/connections` in this example) is secure (usually with `0700` permissions). The `ControlPath` option also needs to uniquely correspond to the target connection (so that, for example, `ssh user1@server1.example.org` and `ssh user2@server2.example.org` don’t use the same Unix domain socket). Fortunately, the `ControlPath` option also allows for placeholders to be used in the path, and in the example above we use the `%r`, `%h`, and `%p` placeholders (username, hostname, and port, respectively) to uniquely identify connection parameters. It sounds complicated, but basically the three lines starting with `Control` in the example above are all you need to add. You can even use them as-is, though you’ll need to create and secure `~/.ssh/connections`. While `ControlMaster` is a game-changer for many SSH performance woes, it can actually hurt certain applications, because all traffic to the remote SSH server is going over the same TCP connection. This can lead to contention and (in my experience) head-of-line blocking in certain use cases. For things like `git` operations and interactive sessions, it works exceptionally well. For tools like Mutagen and rsync, I’ve found it’s actually best to avoid using `ControlMaster`. Fortunately, SSH’s flexible configuration makes it easy to enable `ControlMaster` only where it’s helpful. Conclusion ---------- So that’s my list. There’s still much more that SSH can do, and by combining SSH’s behavioral primitives via other mechanisms, the setups that you can create are effectively limitless. In any case, I hope that these features are helpful in sparking workflow ideas and making your complex remote development experience just a little bit easier. --- # Building a Robust Future for Mutagen | Mutagen Contents * * * [![](https://mutagen.io/img/social/twitter_blue.svg) Share on Twitter](https://twitter.com/intent/tweet?text=Building%20a%20Robust%20Future%20for%20Mutagen&url=https%3a%2f%2fmutagen.io%2fblog%2fbuilding-a-robust-future-for-mutagen%2f&via=mutagen_io) Building a Robust Future for Mutagen ==================================== ![Jacob Howard](https://mutagen.io/img/authors/jacob-howard.png) [Jacob Howard](https://twitter.com/xenoscopic) in [General](https://mutagen.io/blog/category/general) 21 February 2023 [![](https://mutagen.io/img/social/twitter_blue.svg) Share on Twitter](https://twitter.com/intent/tweet?text=Building%20a%20Robust%20Future%20for%20Mutagen&url=https%3a%2f%2fmutagen.io%2fblog%2fbuilding-a-robust-future-for-mutagen%2f&via=mutagen_io) [Mutagen v0.17](https://github.com/mutagen-io/mutagen/releases/tag/v0.17.0) is bringing some fundamental changes to Mutagen’s licensing and monetization model, but not its commitment to open-source and sustainability. I wanted to give users an overview of Mutagen’s roadmap and hopefully address any concerns that might arise due to these changes. What’s changing for users? -------------------------- Starting with Mutagen v0.17, certain _new_ Mutagen features are going to require a paid, subscription-based license. This is the exact same subscription currently used in the [Mutagen Extension for Docker Desktop](https://mutagen.io/documentation/docker-desktop-extension/) , so existing customers will have immediate access to this new functionality. We’re also giving this subscription a name: **Mutagen Pro**. ~You can sign up for a Mutagen Pro subscription at [mutagen.io](https://mutagen.io/) . The current cost for this subscription is $7/user/month. Users interested in volume licensing can contact [sales@mutagen.io](mailto:sales@mutagen.io) .~ **Note:** Mutagen Pro subscriptions are no longer being offered. Two new features in v0.17 will require this subscription: [xxHash](https://cyan4973.github.io/xxHash/) hashing and [Zstandard](https://facebook.github.io/zstd/) compression. Both of these are focused on synchronization performance and provide measurable performance boosts to filesystem scanning and file transfers (see the [release notes](https://github.com/mutagen-io/mutagen/releases/tag/v0.17.0) for more information). Going forward, Mutagen will continue to add functionality to both its free and paid tiers. We expect upcoming releases to add paid support for UDP forwarding, additional permissions-related functionality, custom transports, and more. We’re also planning to ship some exciting new functionality in the Docker Desktop extension, but that’s a story for another blog post 🙂. Most importantly, by building a sustainable revenue stream for Mutagen, we’ll be able to continue improving the free core functionality that Mutagen offers. What’s changing in the code and releases? ----------------------------------------- First and foremost: **nothing is being taken away.** All of Mutagen’s core code is staying under the MIT license, with all dependencies similarly staying under non-copyleft licenses. Any Mutagen functionality that falls under the Mutagen Pro subscription will be _new_ functionality, and all of it will be open-source. Yes, that’s right: **all of the source code for the new paid functionality shipping in the Mutagen release binaries will be available under the [Server Side Public License](https://www.mongodb.com/licensing/server-side-public-license) **. Mutagen has already been shipping certain code under this license since mid-2022, specifically its support for [`fanotify`](https://man7.org/linux/man-pages/man7/fanotify.7.html) filesystem watching in the Mutagen sidecar image. We plan to use this license for all new paid Mutagen features, as well as certain unpaid features such as the aforementioned `fanotify` support and future Mutagen API client libraries. Why ship everything open-source? Well, we like open-source — Mutagen wouldn’t exist without it, it feels like the morally right thing to do, it makes export compliance simpler, and it provides a guarantee of future availability that closed-source software simply cannot. While we’re aware of the objections to the SSPL, the simple reality is that there’s no other open-source license out there that solves the SaaS value-extraction problem. The SSPL is also nearly identical to the venerable GNU General Public License, with the only additional restrictions affecting SaaS platforms, not individual users. Because of this new functionality, Mutagen’s official release binaries are now going to include a mix of MIT, SSPL, and other non-copyleft code. These binaries are the same for both free-tier and Mutagen Pro functionality — the paid functionality will simply be disabled without a Mutagen Pro subscription. These new binaries may not be suitable for all platforms, projects, and products, so we’ve gone to great lengths to ensure that MIT + non-copyleft binaries (which are what we’ve been shipping since Mutagen’s inception) can still be built and interoperate with the official release binaries. The story is the same for Mutagen Compose binaries. We’re also going to continue building and shipping a non-SSPL variant of the Mutagen sidecar image. If you’re a non-profit, open-source project using Mutagen and these new SSPL-licensed binaries aren’t suitable for your use case, please feel free to reach out to [support@mutagen.io](mailto:support@mutagen.io) or join the [Mutagen Community Slack Workspace](https://join.slack.com/t/mutagen-io/shared_invite/zt-ppq2mcow-YzBvrj8wB1_zpE4G~dXL4A) and we’d be happy to help you build binaries with only MIT and non-copyleft code. What about sponsorship? ----------------------- Over the years, many users have asked about supporting Mutagen via platforms such as GitHub Sponsors and Patreon. While these platforms are wonderful initiatives, they can be a tax complexity nightmare if you want to give something back to your users in return for their support. Moreover, they’ve proven to be an unreliable source of sustainment for many (if not most) open-source projects and open-core businesses, and in almost all cases they put the burden of sustaining a project on individual end-users, not the companies or products extracting the most significant value from a project. By offering its own subscription at a price akin to common GitHub Sponsors tiers, Mutagen will be able to ensure its compliance with sales tax, VAT, and GST regulations, while also giving something back to its paying users. It will also allow Mutagen to offer volume and/or commercial licenses to companies who are using Mutagen at scale or embedding Mutagen into their own revenue-generating products. What’s changing for projects and products? ------------------------------------------ _**NOTE:** This section is not legal advice — it is merely a high-level overview of the relevant Mutagen changes. You should consult legal counsel for a full understanding of the implications of this change._ For other projects and products, the biggest change is going to be the inclusion of SSPL-licensed code in the official Mutagen release binaries. If you are currently vendoring the official Mutagen release binaries, then you’ll need to be cognizant of this change when updating to v0.17.x or later. This change will not affect the v0.16.x release series (which will still be supported until 21 March 2023) or any older release series. The most important effect of this change will likely be the inclusion of SSPL-licensed code in `mutagen-agent` binaries, meaning that using those binaries as part of a SaaS platform will trigger Section 13 of the SSPL. Other aspects of the SSPL may also be triggered by tight integration and the exchange of data with a `mutagen` binary containing SSPL-licensed code. If you’re building Mutagen binaries from source or including Mutagen source code into your project, then nothing will change automatically — all of the SSPL-licensed functionality is opt-in when building the code, so it can’t be activated accidentally. For companies who are interested in acquiring a commercial license for Mutagen’s SSPL-licensed code, or receiving support for building non-copyleft binaries, we are offering a commercial licensing scheme with add-ons for consulting and contracting support (including on-site support). For more information on this program, please reach out to [sales@mutagen.io](mailto:sales@mutagen.io) . The future ---------- At the moment, Mutagen’s future looks positive. Not only has it seen significant user growth over the last three years, but it’s seen adoption in products from Docker, Adobe, Garden, Bunnyshell, Jetpack.io, and others. Going forward, we want to experiment with new models of open-core sustainability, but more importantly we want to offer new and more ergonomic modes of cloud-based development. Building a more sustainable revenue stream, especially in proportion to the value that Mutagen creates for other products, will be crucial to sustaining its pace of development. --- # General | Mutagen [Blog](https://mutagen.io/blog) › General * * * [![](https://mutagen.io/img/social/twitter_blue.svg) Follow on Twitter](https://twitter.com/mutagen_io) [Blog](https://mutagen.io/blog) › General * * * [![](https://mutagen.io/img/social/twitter_blue.svg) Follow on Twitter](https://twitter.com/mutagen_io) [Docker Acquires Mutagen for Continued Investment in Performance and Flexibility of Docker Desktop\ =================================================================================================](https://mutagen.io/blog/mutagen-is-joining-docker/) ![Justin Cormack](https://mutagen.io/img/authors/justin-cormack.png) [Justin Cormack](https://www.docker.com/author/justin-cormack/) in [General](https://mutagen.io/blog/category/general) 27 June 2023 I’m excited to announce that Docker, voted the most-used and most-desired tool in Stack Overflow’s [2023 Developer Survey](https://survey.stackoverflow.co/2023/#section-most-popular-technologies-other-tools) , has acquired [Mutagen IO, Inc](https://mutagen.io/) , the company behind the open source Mutagen file synchronization and networking technologies that enable high-performance remote development. [Read more →](https://mutagen.io/blog/mutagen-is-joining-docker/) [Building a Robust Future for Mutagen\ ====================================](https://mutagen.io/blog/building-a-robust-future-for-mutagen/) ![Jacob Howard](https://mutagen.io/img/authors/jacob-howard.png) [Jacob Howard](https://twitter.com/xenoscopic) in [General](https://mutagen.io/blog/category/general) 21 February 2023 [Mutagen v0.17](https://github.com/mutagen-io/mutagen/releases/tag/v0.17.0) is bringing some fundamental changes to Mutagen’s licensing and monetization model, but not its commitment to open-source and sustainability. I wanted to give users an overview of Mutagen’s roadmap and hopefully address any concerns that might arise due to these changes. [Read more →](https://mutagen.io/blog/building-a-robust-future-for-mutagen/) [SSH Tips for Remote Development\ ===============================](https://mutagen.io/blog/ssh-tips-for-remote-development/) ![Jacob Howard](https://mutagen.io/img/authors/jacob-howard.png) [Jacob Howard](https://twitter.com/xenoscopic) in [General](https://mutagen.io/blog/category/general) 8 January 2020 SSH is undoubtedly one of the most powerful tools for enabling remote development. Over a history spanning decades, SSH has proven itself to be reliable, security-focused, and flexible. Since SSH is one of Mutagen’s core transports, I felt that it would be useful to share a handful of simple but powerful features that I use on a daily basis to drastically improve my SSH experience and remote development workflows. [Read more →](https://mutagen.io/blog/ssh-tips-for-remote-development/) --- # Docker Acquires Mutagen to Invest in Docker Desktop | Docker Docker Acquires Mutagen for Continued Investment in Performance and Flexibility of Docker Desktop ================================================================================================= Posted Jun 27, 2023 ![](https://www.docker.com/app/uploads/2022/03/Justin_Cormack_bg.jpeg) [Justin Cormack](https://www.docker.com/contributors/justin-cormack/) I’m excited to announce that Docker, voted the most-used and most-desired tool in Stack Overflow’s [2023 Developer Survey](https://survey.stackoverflow.co/2023/#section-most-popular-technologies-other-tools) , has acquired [Mutagen IO, Inc.](https://mutagen.io/) , the company behind the open source Mutagen file synchronization and networking technologies that enable high-performance remote development. Mutagen’s synchronization and forwarding capabilities facilitate the seamless transfer of code, binary artifacts, and network requests between arbitrary locations, connecting local and remote development environments. When combined with Docker’s existing developer tools, Mutagen unlocks new possibilities for developers to innovate and accelerate development velocity with local and remote containerized development. “Docker is more than a container tool. It comprises multiple developer tools that have become the industry standard for self-service developer platforms, empowering teams to be more efficient, secure, and collaborative,” says Docker CEO Scott Johnston. “Bringing Mutagen into the Docker family is another example of how we continuously evolve our offering to meet the needs of developers with a product that works seamlessly and improves the way developers work.” ![Mutagen banner 2400x1260 Docker logo and Mutagen logo on red background](https://www.docker.com/app/uploads/2023/06/2400x1260-2048x1075.png "- 2400x1260") The [Mutagen acquisition](https://mutagen.io/blog/mutagen-is-joining-docker/#mutagen-faq) introduces novel mechanisms for developers to extract the highest level of performance from their local hardware while simultaneously opening the gateway to the newest remote development solutions. We continue scaling the abilities of Docker Desktop to meet the needs of the growing number of developers, businesses, and enterprises relying on the platform.  “Docker Desktop is focused on equipping every developer and dev team with blazing-fast tools to accelerate app creation and iteration by harnessing the combined might of local and cloud resources. By seamlessly integrating and magnifying Mutagen’s capabilities within our platform, we will provide our users and customers with unrivaled flexibility and an extraordinary opportunity to innovate rapidly,” says Webb Stevens, General Manager, [Docker Desktop](https://www.docker.com/products/docker-desktop/) .  “There are so many captivating integration and experimentation opportunities that were previously inaccessible as a third-party offering,” says Jacob Howard, the CEO at Mutagen. “As Mutagen’s lead developer and a Docker Captain, my ultimate goal has always been to enhance the development experience for Docker users. As an integral part of Docker’s technology landscape, Mutagen is now in a privileged position to achieve that goal.” Jacob will join Docker’s engineering team, spearheading the integration of Mutagen’s technologies into Docker Desktop and other Docker products. You can get started with Mutagen today by downloading the [latest version of Docker Desktop](https://www.docker.com/products/docker-desktop/) and installing the Mutagen extension, available in the [Docker Extensions Marketplace](https://hub.docker.com/u/mutagenio) . Support for current Mutagen offerings, open source and paid, will continue as we develop new and better integration options. FAQ | Docker Acquisition of Mutagen ----------------------------------- With Docker’s acquisition of Mutagen, you’re sure to have questions. We’ve answered the most common ones in this FAQ. As with all of our open source efforts, Docker strives to do right by the community. We want this acquisition to benefit everyone — community and customer — in keeping with our developer obsession. ### What will happen to Mutagen Pro subscriptions and the Mutagen Extension for Docker Desktop? Both will continue as we evaluate and develop new and better integration options. Existing Mutagen Pro subscribers will see an update to the supplier on their invoices, but no other billing changes will occur. ### Will Mutagen become closed-source? There are no plans to change the licensing structure of Mutagen’s open source components. Docker has always valued the contributions of open source communities. ### Will Mutagen or its companion projects be discontinued? There are no plans to discontinue any Mutagen projects.  ### Will people still be able to contribute to Mutagen’s open source projects? Yes! Mutagen has always benefited from outside collaboration in the form of feedback, discussion, and code contributions, and there’s no desire to change that relationship. For more information about how to participate in Mutagen’s development, see the [contributing guidelines](https://github.com/mutagen-io/mutagen/blob/master/CONTRIBUTING.md) . ### What about other downstream users, companies, and projects using Mutagen? Mutagen’s open source licenses continue to allow the embedding and use of Mutagen by other projects, products, and tooling. ### Who will provide support for Mutagen projects and products? In the short term, support for Mutagen’s projects and products will continue to be provided through the existing support channels. We will work to merge support into Docker’s channels in the near future. ### Is this replacing Virtiofs, gRPC-FUSE, or osxfs? No, virtual filesystems will continue to be the default path for bind mounts in Docker Desktop. Docker is continuing to invest in the performance of these technologies. ### How does Mutagen compare with other virtual or remote filesystems? Mutagen is a synchronization engine rather than a virtual or remote filesystem. Mutagen can be used to synchronize files to native filesystems, such as ext4, trading typically imperceptible amounts of latency for full native filesystem performance. ### How does Mutagen compare with other synchronization solutions? Mutagen focuses primarily on configuration and functionality relevant to developers. ### How can I get started with Mutagen? To get started with Mutagen, [download](https://www.docker.com/products/docker-desktop/) the latest version of Docker Desktop and install the [Mutagen Extension](https://mutagen.io/documentation/docker-desktop-extension) from the [Docker Desktop Extensions Marketplace](https://open.docker.com/extensions/marketplace?extensionId=mutagenio/docker-desktop-extension) . ### About the Authors ![](https://www.docker.com/app/uploads/2022/03/Justin_Cormack_bg.jpeg) CTO, Docker Open source, cloud, technology, NetBSD, unikernels, work @docker [cloud](https://www.docker.com/blog/tag/cloud/) [containers](https://www.docker.com/blog/tag/containers/) [Docker Desktop](https://www.docker.com/blog/tag/docker-desktop/) [Company](https://www.docker.com/blog/category/company/) Table of contents [](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fwww.docker.com%2Fblog%2Fmutagen-acquisition%2F "Visit this Linkedin profile") [](https://twitter.com/intent/tweet?url=https%3A%2F%2Fwww.docker.com%2Fblog%2Fmutagen-acquisition%2F "Visit this X profile") [](https://www.facebook.com/sharer/sharer.php?u=https%3A%2F%2Fwww.docker.com%2Fblog%2Fmutagen-acquisition%2F "Visit this Facebook profile") Related Posts ------------- * [Mar 13, 2026\ \ #### Secure Agent Execution with NanoClaw and Docker Sandboxes\ \ NanoClaw integrates with Docker Sandboxes to run AI agents in disposable MicroVMs, combining transparency and isolation for secure execution.\ \ ![](https://www.docker.com/app/uploads/2025/11/Headshot-Eli-Aleyner.jpg "Posts by Eli Aleyner")\ \ ![](https://www.docker.com/app/uploads/2025/05/headshot-Nikhil-Kaul.jpg "Posts by Nikhil Kaul")\ \ Eli Aleyner\ \ and\ \ Nikhil Kaul\ \ Read now](https://www.docker.com/blog/nanoclaw-docker-sandboxes-agent-security/) * [Docker Captain Mar 18, 2026\ \ #### From the Captain’s Chair: Naga Santhosh Reddy Vootukuri\ \ Docker Captains are leaders from the developer community that are both experts in their field and are passionate about sharing their Docker knowledge with others. “From the Captain’s Chair” is a blog series where we get a closer look at one Captain to learn more about them and their experiences.  Today we are interviewing Naga…\ \ ![](https://www.docker.com/app/uploads/2025/06/santhosh-headshot-Naga-Santhosh-Reddy-Vootukuri.jpeg "Posts by Naga Santhosh Reddy Vootukuri")\ \ Naga Santhosh Reddy Vootukuri\ \ Read now](https://www.docker.com/blog/from-the-captains-chair-naga-santhosh-reddy-vootukuri/) * [Guest Contributor Mar 13, 2026\ \ #### Achieving Test Reliability for Native E2E Testing: Beyond Fixing Broken Tests\ \ Stop chasing flaky native E2E tests. Learn how to stabilize environments, define ownership, improve alerting, and scale runs with Dockerized emulators.\ \ ![](https://www.docker.com/app/uploads/2026/03/avatar_hu78678d8b1ce137513dfff69105085015_10322957_270x270_fill_lanczos_center_2-Vivek-Maskara-Tech-Ed.png)\ \ Vivek Maskara\ \ Read now](https://www.docker.com/blog/native-e2e-test-reliability/) * [Mar 13, 2026\ \ #### How to Run Claude Code with Docker: Local Models, MCP Servers, and Secure Sandboxes\ \ Run Claude Code with Docker Model Runner, connect tools via MCP servers, and use secure sandboxes so agents can act with control.\ \ ![](https://www.docker.com/app/uploads/2024/10/yiwen-xu.jpeg "Posts by Yiwen Xu")\ \ Yiwen Xu\ \ Read now](https://www.docker.com/blog/run-claude-code-with-docker/) --- # Legal | Docker [Skip to content](https://mutagen.io/legal/#wp--skip-link--target) ![gray](https://www.docker.com/app/uploads/brand/background/gray.png "- gray") Docker Legal Terms ================== | Document | Link | | --- | --- | | Subscription Service Agreement | [https://www.docker.com/legal/docker-subscription-service-agreement](https://www.docker.com/legal/docker-subscription-service-agreement) | | Support Service Level Agreement | [https://www.docker.com/support/](https://www.docker.com/support/) | | Data Processing Agreement (DPA) | [Data\_Processing\_Agreement.pdf](https://www.docker.com/static/Data_Processing_Agreement.pdf) | | Privacy | [https://www.docker.com/legal/privacy/](https://www.docker.com/legal/privacy) | | Extensions Marketplace Developer Agreement | [https://www.docker.com/legal/extensions\_marketplace\_developer\_agreement/](https://www.docker.com/legal/extensions_marketplace_developer_agreement/) | | Compliance | [https://www.docker.com/trust/compliance/](https://www.docker.com/trust/compliance/) | | Vulnerability Disclosure Policy | [https://www.docker.com/trust/vulnerability-disclosure-policy](https://www.docker.com/trust/vulnerability-disclosure-policy) | | Docker Gordon Supplemental Terms | [https://www.docker.com/legal/docker-ai-supplemental-terms/](https://www.docker.com/legal/docker-ai-supplemental-terms/) | ---