Private Composer repository with Satis

This post is a brief case study and a guide on how to create your own private Composer repository with Satis.

At Magently, we are preparing to release a module we made. Early on, we faced an issue of how to deliver the module along with its dependencies in an easy way before it is published on Magento Marketplace. We didn’t want to share our private code repo, neither did we want to create file packs nor use GitHub. Instead, we focused on something fundamental for Magento – the Composer.

Composer + Satis

The problem

Everyone working with Magento should be familiar with Composer. It allows easy management of a project’s dependencies. An extensive package repo already exists, namely Packagist, but we wanted to have our own. We were able to actually do it using Satis – a tool that allows creating your own repositories of Composer packages.

As already mentioned, we wanted to avoid using GitHub as a code provider, although it would likely be enough to let Composer load the required code.

Also, we wanted to deliver multiple versions of the module to allow a user to “block” a certain version, in case it doesn’t work in a specific environment at a given time.

The solution

Satis is a special tool that solved our problem perfectly. We wanted a fully automated process of releasing subsequent module version and Satis was a great match to our collection of tools for Continuous Integration and Continuous Deployment.

The workflow of new releases is fairly easy and simple. The changes merged with the master branch (once carefully tested) and with a new version tag added by GitHub are automatically made available to the users. Hence, we wrote a simple script that runs on the repository push tag and creates a new package on our private Composer repo. Let’s dive into the Satis configuration, which itself is fairly simple.

Enter Satis

Creating a new Satis instance is as easy as downloading a proper package: composer create-project composer/satis.

The next step is to set up Satis using the satis.json file. In our case, the config file looks more or less like this:

  "name": "Magently Repository",
  "homepage": "",
  "repositories": [
      "type": "vcs",
      "url": "../packages/mb-magento2"
      "type": "vcs",
      "url": "../packages/mb-lib"
  "require": {
    "magently/mb-magento2": "dev-master || >=1.0",
    "magently/mb-lib": "dev-master || >=1.0"
  "output-dir": ".",
  "archive": {
    "directory": "dist",
    "format": "tar"

Long story short, we define the name and the repository homepage. For repository, we enter a place where Satis should load the code from. For require, we enter package names to be created and their versions. In the example above, for the dev-master version, there is always the newest version loaded. We also get tags for versions >=1.0, e.g.  1.0.0, 1.0.1, 1.1.0 and so on. Finally, for output-dir, we set a target location and format for our packs to dist and tar respectively (archive section).

The config above does not ensure authentication to control who downloads the module as we don’t need it here. However, Satis allows using a certificate, SSH keys or HTTP headers.

Building a package is done with the php bin/satis build command. This is it. The packs are built and ready to download.

Why is it so convenient? Installing the module requires only two commands (or two composer.json file modifications):

composer config repositories.magently composer
composer require magently/mb-magento2

Since magently/mb-magento2  module requires magently/mb-lib and other external packs, Composer will handle loading all required dependencies.

Private Composer repository – Summary

As seen above, the Satis configuration is by no means complex. This solution can surely be enhanced and expanded to be more flexible but as for now, it does its job perfectly. Do you have any suggestions or improvements? How do you use Satis? Share your thoughts in the comments!