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

@pruddiman/fleet

v0.1.11

Published

A TypeScript CLI tool for managing deployments

Downloads

1,366

Readme

Fleet

Fleet was built to simplify deploying multiple Docker Compose stacks to a single server where all stacks need to share ports 80 and 443. Fleet manages the ingress layer for you — a shared Caddy reverse proxy is automatically bootstrapped and configured so each stack gets its own domain and HTTPS without port conflicts.

Fleet is a TypeScript CLI tool for deploying Docker Compose applications to remote servers over SSH. It uploads your Compose and environment files, starts containers, and configures a Caddy reverse proxy with automatic HTTPS — all from a single fleet deploy command driven by a declarative fleet.yml configuration file.

Fleet targets developers and small teams who want code-defined deployments without the operational overhead of Kubernetes or a full container orchestration platform.

How it works

A fleet deploy runs a 17-step pipeline that:

  1. Loads and validates fleet.yml and your Compose file locally
  2. Opens an SSH connection to the target server
  3. Bootstraps a Caddy reverse proxy container (once, idempotent)
  4. Uploads your Compose and environment files
  5. Computes SHA-256 hashes of service definitions, image digests, and env files to classify each service as deploy, restart, or skip — avoiding unnecessary container churn
  6. Pulls images and starts only the containers that changed
  7. Runs health checks and registers routes with Caddy
  8. Writes deployment state to ~/.fleet/state.json on the server

Installation

npm install -g @pruddiman/fleet
# or use directly via npx
npx fleet <command>

Requires Node.js ≥ 20. The target server requires Docker and Docker Compose V2.

Quick start

1. Scaffold a configuration file:

fleet init

This reads your docker-compose.yml and generates a fleet.yml interactively.

2. Validate before deploying:

fleet validate

Runs pre-flight checks locally with no SSH connection required.

3. Deploy:

fleet deploy

fleet.yml reference

version: "1"

server:
  host: your-server.example.com
  user: deploy
  port: 22
  identity_file: ~/.ssh/id_ed25519   # or omit to use SSH_AUTH_SOCK

stack:
  name: myapp                         # lowercase letters, digits, hyphens only
  compose_file: docker-compose.yml    # relative to fleet.yml; default: docker-compose.yml

# Three mutually exclusive env modes:

# Mode 1 — inline key-value pairs
env:
  - key: NODE_ENV
    value: production

# Mode 2 — upload a local .env file (recommended for CI/CD)
env:
  file: .env.production

# Mode 3 — export secrets from Infisical
env:
  infisical:
    token: $INFISICAL_TOKEN          # $VAR references are expanded at load time
    project_id: your-project-id
    environment: production
    path: /

routes:
  - domain: myapp.example.com
    port: 3000
    service: myapp
    tls: true
    acme_email: [email protected]       # recommended for production
    health_check:
      path: /health
      timeout_seconds: 30
      interval_seconds: 5

server fields

| Field | Required | Default | Description | |-------|----------|---------|-------------| | host | Yes | — | Server hostname or IP address | | port | No | 22 | SSH port | | user | No | "root" | SSH username | | identity_file | No | — | Path to SSH private key; falls back to SSH_AUTH_SOCK if omitted |

stack fields

| Field | Required | Default | Description | |-------|----------|---------|-------------| | name | Yes | — | Docker Compose project name (-p flag); must match /^[a-z\d][a-z\d-]*$/ | | compose_file | No | "docker-compose.yml" | Path to Compose file, relative to fleet.yml |

routes fields

| Field | Required | Default | Description | |-------|----------|---------|-------------| | domain | Yes | — | Fully qualified domain name | | port | Yes | — | Container port to proxy traffic to | | service | No | "default" | Docker Compose service name | | tls | No | true | Enable automatic HTTPS via Let's Encrypt | | acme_email | No | — | Email for ACME account registration | | health_check.path | No | "/" | HTTP path to poll after deploy | | health_check.timeout_seconds | No | 60 | Max wait time (1–3600) | | health_check.interval_seconds | No | 2 | Poll interval (1–60) |

Commands

| Command | Description | |---------|-------------| | fleet init | Scaffold a fleet.yml from an existing Compose file | | fleet validate [file] | Check fleet.yml and Compose file for errors (no SSH required) | | fleet deploy | Deploy services to the remote server | | fleet env | Push or refresh secrets on the remote server without redeploying | | fleet ps | Show running container status and deployment timestamps | | fleet logs | Stream live container logs | | fleet restart | Restart a service in a deployed stack | | fleet stop | Stop a stack without destroying it | | fleet teardown | Remove a stack, its containers, and optionally its volumes | | fleet proxy status | Show live Caddy route status, surfacing ghost or missing routes | | fleet proxy reload | Force-reload all Caddy routes from server state |

fleet deploy flags

| Flag | Description | |------|-------------| | --force | Redeploy all services regardless of hash changes | | --dry-run | Print what would be deployed without making changes | | --skip-pull | Skip docker pull before starting containers | | --no-health-check | Skip health checks after deployment |

CI/CD integration

Fleet is non-interactive and designed for automation. Use git commit SHAs as image tags for traceability and simple rollbacks.

Recommended pattern

Tag images with the commit SHA, write secrets to a .env file, then validate and deploy:

# Build and push
docker build -t ghcr.io/yourorg/myapp:$GIT_SHA .
docker push ghcr.io/yourorg/myapp:$GIT_SHA

# Write env file
echo "IMAGE_TAG=$GIT_SHA" > .env.production
echo "DATABASE_URL=$DATABASE_URL" >> .env.production

# Validate and deploy
npx fleet validate
npx fleet deploy

SSH key setup

Store your deploy key as a CI secret, write it at pipeline runtime:

echo "$SSH_PRIVATE_KEY" > /tmp/deploy_key
chmod 600 /tmp/deploy_key

Reference it in fleet.yml:

server:
  host: your-server.example.com
  user: deploy
  identity_file: /tmp/deploy_key

GitHub Actions example

name: Build and Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ghcr.io/yourorg/myapp:${{ github.sha }}

      - uses: actions/setup-node@v4
        with:
          node-version: "20"

      - run: npm install

      - name: Write environment file
        run: |
          cat <<EOF > .env.production
          IMAGE_TAG=${{ github.sha }}
          DATABASE_URL=${{ secrets.DATABASE_URL }}
          NODE_ENV=production
          EOF

      - run: npx fleet validate

      - name: Write SSH key
        run: |
          echo "${{ secrets.SSH_PRIVATE_KEY }}" > /tmp/deploy_key
          chmod 600 /tmp/deploy_key

      - run: npx fleet deploy

Remote filesystem layout

Fleet stores all deployment artifacts under /opt/fleet or ~/fleet on the remote server:

/opt/fleet (or ~/fleet)
├── proxy/
│   └── compose.yml          # Caddy container definition
└── stacks/
    ├── myapp/
    │   ├── docker-compose.yml
    │   └── .env
    └── blog/
        ├── docker-compose.yml
        └── .env

~/.fleet/
└── state.json               # Deployment state (all stacks)

Limitations (v1)

  • Single server per fleet.yml — use separate config files for multiple servers
  • No image building — build images in your CI pipeline before deploying
  • No deployment history or rollback — roll back by redeploying a previous commit SHA
  • No blue/green or canary strategies — in-place container replacement only
  • No concurrency control — concurrent deploys to the same server can corrupt state
  • No web UI — CLI only

Documentation