npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@sprisa/composure_darwin-arm64

v0.0.4

Published

Deploy docker-compose files to multiple hosts via SSH with Composure

Readme

Composure

Deploy docker-compose files to multiple hosts via SSH with Composure

Composure is a simple CLI tool for deploying Docker Compose applications across multiple remote servers via SSH. No Kubernetes, no Swarm — just your familiar docker-compose.yml files deployed exactly where you want them.

Why Composure?

You have a docker-compose.yml file. You have multiple servers. You want your application running on all of them without the complexity of Kubernetes or the overhead of a full orchestration platform.

Composure keeps it simple:

  • Uses your existing docker-compose.yml files
  • Deploys over SSH—no agents, no daemons
  • Supports server-specific configurations
  • Parallel deployments for speed

Install

Homebrew (auto updates)

brew install sprisa/tap/composure

NPM

npm i -g @sprisa/composure
# Or run directly
npx @sprisa/composure

Golang Source

go install github.com/sprisa/composure@latest
# Or run directly
go run github.com/sprisa/composure@latest

Usage

Add a composure label to your docker-compose services. This described which SSH host to deploy the docker service to. This can be any DOCKER_HOST variable.

services:
  # Simple Hello World application
  hello-world:
    image: crccheck/hello-world
    ports:
      - "8081:8000"
    restart: unless-stopped
    labels:
      composure: ssh://[email protected] # <- Deploy to jackfruit server. Can be any IP or DNS name

  # Nginx reverse proxy
  nginx:
    image: nginx:alpine
    ports:
      - "8080:80"
    restart: unless-stopped
    labels:
      composure: ssh://[email protected] # <- Deploy to mango server. Can be any IP or DNS name

Now we can deploy with composure up. This accepts the same flags as docker compose up.

# Deploy in background
composure up -d 

# Destroy services
compose down

Options

Show Help

~ ❯ composure
Composure - Calm docker compose deployments

Usage: composure <command>

Commands:
  up       - Start services
  down     - Stop services
  restart  - Restart services
  plan     - Show deployment plan
  setup    - Setup shared volumes (NFS)
  help     - Show this help message

Recommendations

Use absolute paths for Volumes

Docker resolves relative paths like ./ or ~ based the machine you ran composure up from, not the host target machine. It's recommended to use explicit absolute paths for portability.

Assuming username is ubuntu

services:
  plex:
    image: lscr.io/linuxserver/plex:latest
    ports:
      - 32400:32400
    # Use absolute paths instead of related paths
    volumes:
      - /home/ubuntu/plex/library:/config
      # The below is not as portable
      # - ~/plex/library:/config
    labels:
      composure: ssh://[email protected]

Multi-Host Networking

Composure automatically enables cross-host service discovery. When you deploy services to different hosts, each service gets extra_hosts entries injected so it can resolve other services by name.

For example, given services hello-world on jackfruit.local and nginx on mango.local:

  • hello-world can reach nginx at nginx:<published-port>
  • nginx can reach hello-world at hello-world:<published-port>

Composure resolves each SSH host's IP at deploy time and adds the mappings automatically. Services on the same host are skipped since they already share Docker's internal network. Any existing extra_hosts you define are preserved.

Note: Services communicate over the host network using published ports, not container ports. Ensure the relevant ports are exposed and accessible between hosts.

Shared Volumes (NFS)

When services on different hosts need access to the same data, Composure can share volumes over NFS. Declare shared volumes using the composure-nfs driver in the top-level volumes block:

volumes:
  media:
    driver: composure-nfs
    driver_opts:
      host: ssh://[email protected]   # Host that owns the data
      path: /home/gabe/lib/plex            # Absolute path on that host

services:
  plex:
    volumes:
      - media:/data
    labels:
      composure: ssh://[email protected]

  overseerr:
    volumes:
      - media:/data
    labels:
      composure: ssh://[email protected]

During deployment, Composure rewrites these volumes per-host:

  • On the source host (coconut), the named volume becomes a local bind mount to /home/gabe/lib/plex
  • On other hosts (kiwi), it becomes an NFS mount pointing to coconut

One-time setup

Before deploying, run composure setup to install NFS packages and configure exports. It will SSH into each host, create the source directories, and attempt to install packages via sudo. If sudo requires a password, you'll be prompted interactively. If it fails, the commands are printed for you to run manually.

composure setup

Rendered Compose Files

Each time you deploy, Composure writes the rendered docker-compose YAML to ~/.config/composure/<project>.yml on each remote host. This is the final YAML after NFS volume rewriting and host filtering — exactly what docker compose sees. You can inspect it at any time:

ssh gabe@kiwi cat ~/.config/composure/plex.yml

Debugging NFS

If NFS mounts aren't working after setup, verify the configuration on the server host:

# Check the NFS server service is running
sudo systemctl status nfs-server        # Fedora/Arch
sudo systemctl status nfs-kernel-server # Debian/Ubuntu

# View configured exports
cat /etc/exports

# View active exports
sudo exportfs -v

# Restart and re-export if needed
sudo exportfs -ra
sudo systemctl restart nfs-server

From a client host, verify the server is reachable:

# List exports available from the server
showmount -e <server-hostname>

# Test mount manually
sudo mkdir -p /tmp/nfs-test
sudo mount -t nfs4 <server-hostname>:/path/to/share /tmp/nfs-test
ls /tmp/nfs-test
sudo umount /tmp/nfs-test

Not Yet Supported

  • Cross host service.depends_on