Satis or Toran Proxy

Toran Proxy is a commercial alternative to Satis offering professional support as well as a web UI to manage everything and a better integration with Composer. It also provides proxying/mirroring for git repos and package zip files which makes installs faster and independent from third party systems.

Toran’s revenue is also used to pay for Composer and Packagist development and hosting so using it is a good way to support open source financially. You can find more information about how to set it up and use it on theToran Proxy website.

Satis#

Satis on the other hand is open source but only a static composer repository generator. It is a bit like an ultra-lightweight, static file-based version of packagist and can be used to host the metadata of your company’s private packages, or your own. You can get it from GitHub or install via CLI: php composer.phar create-project composer/satis --stability=dev --keep-vcs.

Setup#

For example let’s assume you have a few packages you want to reuse across your company but don’t really want to open-source. You would first define a Satis configuration: a json file with an arbitrary name that lists your curated repositories.

Here is an example configuration, you see that it holds a few VCS repositories, but those could be any types ofrepositories. Then it uses "require-all": true which selects all versions of all packages in the repositories you defined.

The default file Satis looks for is satis.json in the root of the repository.

{
    "name": "My Repository",
    "homepage": "http://packages.example.org",
    "repositories": [
        { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
        { "type": "vcs", "url": "http://svn.example.org/private/repo" },
        { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
    ],
    "require-all": true
}

If you want to cherry pick which packages you want, you can list all the packages you want to have in your satis repository inside the classic composer require key, using a "*" constraint to make sure all versions are selected, or another constraint if you want really specific versions.

{
    "repositories": [
        { "type": "vcs", "url": "https://github.com/mycompany/privaterepo" },
        { "type": "vcs", "url": "http://svn.example.org/private/repo" },
        { "type": "vcs", "url": "https://github.com/mycompany/privaterepo2" }
    ],
    "require": {
        "company/package": "*",
        "company/package2": "*",
        "company/package3": "2.0.0"
    }
}

Once you’ve done this, you just run php bin/satis build <configuration file> <build dir>. For example php bin/satis build satis.json web/ would read the satis.json file and build a static repository inside the web/ directory.

When you ironed out that process, what you would typically do is run this command as a cron job on a server. It would then update all your package info much like Packagist does.

Note that if your private packages are hosted on GitHub, your server should have an ssh key that gives it access to those packages, and then you should add the --no-interaction (or -n) flag to the command to make sure it falls back to ssh key authentication instead of prompting for a password. This is also a good trick for continuous integration servers.

Set up a virtual-host that points to that web/ directory, let’s say it is packages.example.org. Alternatively, with PHP >= 5.4.0, you can use the built-in CLI server php -S localhost:port -t satis-output-dir/ for a temporary solution.

Partial Updates#

You can tell Satis to selectively update only particular packages or process only a repository with a given URL. This cuts down the time it takes to rebuild the package.json file and is helpful if you use (custom) webhooks to trigger rebuilds whenever code is pushed into one of your repositories.

To rebuild only particular packages, pass the package names on the command line like so:

php bin/satis build satis.json web/ this/package that/other-package

Note that this will still need to pull and scan all of your VCS repositories because any VCS repository might contain (on any branch) one of the selected packages.