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

@ossy/deployment-tools

v1.40.2

Published

Collection of scripts and tools to aid deployment of containers and static files to Amazon Web Services through GitHub Actions

Readme

@ossy/deployment-tools

Infrastructure and CDK tooling for the Ossy platform EC2 host.

The host runs Caddy as a reverse proxy plus several Docker containers managed by systemd. Apps are deployed by running ossy app publish.

Architecture

Internet → Caddy (:443)
             ├── api.ossy.se          → ossy-api (:3001)
             ├── ossy.se              → ossy-website-ossy (:3002)  ← temporary
             ├── www.plexus-sanitas.com → ossy-website-plexus-sanitas (:3003)  ← temporary
             └── *.* (on-demand TLS)  → ossy-platform (:3000)
                                           └── loads build from CMS on first request

Caddy uses on-demand TLS: before issuing a certificate for any domain, it calls GET http://localhost:3001/api/v0/apps/ask?domain=<domain>. If the domain is registered (i.e. ossy app publish has been run for it), Caddy issues the cert and proxies to the platform runtime.

Services

All services run as Docker containers managed by systemd. Service files are written to the EC2 host by CDK user data at instance creation.

| Service | Unit file | Port | Image | |---|---|---|---| | Caddy | caddy-route53.service | 80, 443 | — | | Ossy API | ossy-api.service | 3001 | ghcr.io/ossy-se/api:latest | | Ossy Platform | ossy-runtime.service | 3000 | ghcr.io/ossy-se/platform:latest | | configured via services | <name>.service | per config | per config |

Additional services are generated automatically from the services array in platforms.json — see the Configuration section below.

Configuration — platforms.json

packages/infrastructure/platforms.json is the single source of truth for a platform. Each entry becomes a CDK Stage with its own set of stacks.

| Field | Required | Description | |---|---|---| | platformName | Yes | Unique name, used as the CDK stage name and CloudFormation stack prefix | | awsAccountId | Yes | AWS account ID | | awsKeyPairName | Yes | EC2 key pair name for SSH access | | awsInstanceClass | No | EC2 instance class (e.g. t3, t4g, m5). Defaults to t3 | | awsInstanceSize | No | EC2 instance size (e.g. small, medium, large). Defaults to small | | sesDomains | No | Domains to configure SES email identity for | | domains | No | Domains to create Route53 A records for, pointing to the EC2 Elastic IP. Supports wildcards (e.g. *.ossy.se). | | services | No | Per-platform container services (see below) | | dnsRecords | No | Additional DNS records by root domain (currently supports MX) | | env | No | Environment variables written to /etc/environment on the EC2 host at boot. Never uploaded to S3. |

services — container/domain mapping

Services come in two flavours: HTTP (routed through Caddy) and TCP/UDP (raw socket, bypasses Caddy). Both generate a systemd unit that pulls the image on every restart and forwards /etc/environment to the container.

HTTP service (default)

Generates a Caddy reverse-proxy block with Route53 TLS. The container must listen on port 3000.

"services": [
  {
    "name": "ossy-website-ossy",
    "domain": "ossy.se",
    "image": "ghcr.io/ossy-se/website-ossy:latest"
  }
]

| Field | Description | |---|---| | name | Unique service name — Docker container name and systemd unit (<name>.service). | | domain | Hostname routed by Caddy to this container (Route53 TLS via dns route53). | | image | Docker image to pull and run. |

Host ports are auto-assigned starting at 3002, counting only HTTP services (TCP entries are skipped). Appending new HTTP entries is safe; avoid reordering existing ones.

TCP/UDP service

No Caddy block. Ports are mapped directly (HOST:CONTAINER) and opened in the EC2 security group. Use this for game servers or any other raw socket protocol.

"services": [
  {
    "name": "minecraft",
    "type": "tcp",
    "image": "itzg/minecraft-server",
    "ports": [25565],
    "protocol": "tcp"
  }
]

| Field | Description | |---|---| | name | Unique service name — Docker container name and systemd unit. | | type | Must be "tcp" to enable this mode. | | image | Docker image to pull and run. | | ports | Array of port numbers to expose on the host and open in the security group. | | protocol | "tcp" (default), "udp", or "both". |

Fixed built-in services (always present, not configurable via services):

  • ossy-api — the Ossy API (ghcr.io/ossy-se/api:latest, port 3001)
  • ossy-runtime — the platform runtime serving all CMS-published apps (ghcr.io/ossy-se/platform:latest, port 3000, catch-all)

Custom domains: For customer-owned domains (e.g. woodhill.com), the customer adds an A record pointing to the Elastic IP at their registrar. No infrastructure change needed — Caddy's on-demand TLS issues the cert automatically once the domain is registered via ossy app publish.

Wildcard subdomains: Add *.ossy.se to domains for a Route53 wildcard A record. This covers any *.ossy.se subdomain without individual records.

MEDIA_REPOSITORY and MEDIA_CDN_DOMAIN_NAME are derived automatically from the provisioned S3 bucket and CloudFront distribution — do not set them in env.

To add a new platform, add an entry to platforms.json. No bucket name or CDN domain is needed; these are auto-generated by CloudFormation.

CDK Stacks

Each platform is a CDK Stage containing five stacks:

| Stack | Description | |---|---| | storage-static | S3 bucket (auto-named), daily backup plan, CloudFront CDN for /media. Kept separate from the EC2 stack so storage resources are never touched during instance updates. | | deployment-target | EC2 instance with Elastic IP. Imports the S3 bucket from storage-static via cross-stack reference. | | dns | Route53 A records for all domains in platforms.json, pointing to the Elastic IP. | | ses | SES email sending identity and DKIM records. |

The Elastic IP ensures the EC2 instance can be replaced (instance type changes, user data updates) without breaking DNS or CloudFormation cross-stack exports.

Bootstrapping a new platform

cd packages/deployment-tools
npx cdk deploy 'ossybot/**' --profile ossybot --require-approval never

CDK provisions the instance, writes all service files, writes /etc/environment from platforms.json, and starts all services automatically. No manual SSH steps are required.

Note: EC2 user data only runs on first boot. To apply infrastructure changes to an existing instance you must terminate and recreate it, or SSH in and apply changes manually.

Deploying changes

Target a single platform:

npx cdk deploy 'ossybot/**' --profile ossybot

Target all platforms:

npx cdk deploy '**' --profile ossybot

Preview changes without deploying:

npx cdk diff 'ossybot/**' --profile ossybot

List all stacks:

npx cdk list

Redeploying after a code change

All services pull the latest image from GHCR on every restart — no manual build step needed.

# API — push to main triggers CI → ghcr.io/ossy-se/api:latest
sudo systemctl restart ossy-api

# Platform runtime — merge to main in ossy monorepo → ghcr.io/ossy-se/platform:latest
sudo systemctl restart ossy-runtime

# website-ossy — push to main in website-ossy repo → ghcr.io/ossy-se/website-ossy:latest
sudo systemctl restart ossy-website-ossy

# website-plexus-sanitas — push to main → ghcr.io/ossy-se/website-plexus-sanitas:latest
sudo systemctl restart ossy-website-plexus-sanitas

Environment variables

Defined in the env block of platforms.json, written to /etc/environment at boot. The following variables are injected automatically by CDK and should not be set manually:

| Variable | Source | |---|---| | MEDIA_REPOSITORY | S3 bucket name from storage-static stack | | MEDIA_CDN_DOMAIN_NAME | CloudFront domain from storage-static stack |

All other env vars:

| Variable | Used by | Description | |---|---|---| | DB_URL | API | Atlas MongoDB connection string | | DB_NAME | API | MongoDB database name | | TOKEN_SECRET | API | JWT signing secret | | AWS_ACCESS_KEY_ID | API | AWS credentials for S3 | | AWS_SECRET_ACCESS_KEY | API | AWS credentials for S3 | | OSSY_API_KEY | Platform, websites | API JWT for CMS reads | | OSSY_COOKIE_SECRET | Websites | Cookie signing secret | | OPENAI_API_KEY | Worker | OpenAI API key | | OPENAI_ORGANIZATION | Worker | OpenAI organisation ID |

Useful commands

SSH into instance

ssh -i path/to/keys ubuntu@<elastic-ip>

View service logs

journalctl -u ossy-runtime.service -n 200 -f
journalctl -u ossy-api.service -n 200 -f
journalctl -u ossy-website-ossy.service -n 200 -f
journalctl -u caddy-route53.service -n 200 -f

View running containers

docker ps

View container logs

docker logs ossy-runtime
docker logs ossy-api
docker logs ossy-website-ossy

Reload Caddy config

sudo systemctl reload caddy-route53.service