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

@rockysurf/provider-aws

v0.1.6

Published

AWS EC2 compute provider — plain RunInstances, no CloudFormation.

Readme

@rockysurf/provider-aws

Runs Rocky Surf dev boxes as EC2 instances in your own AWS account. It calls RunInstances directly — no CloudFormation — so there is no stack to drift, no template to reconcile, and nothing left behind that Rocky Surf's own reaper cannot see. It creates instances, one shared SSH security group per region, and nothing else.

How you get it

It is already there. The rockysurf CLI depends on this package, so npx rockysurf can reach AWS as soon as you switch it on. Providers are constructed at boot, so a configuration change takes effect at the next restart.

Install it directly only if you are embedding Rocky Surf's Provider in something of your own:

pnpm add @rockysurf/provider-aws
import aws from '@rockysurf/provider-aws'

const config = aws.configSchema.parse({ region: 'us-east-1', sshAllowedCidr: '203.0.113.7/32' })
const provider = aws.createProvider(config)

createProvider is synchronous and does no I/O, so a caller can load the Provider, show its identity and validate its configuration before it holds anything live. Credentials are proven separately, by validateCredentials().

Configuration

providers:
  aws:
    enabled: true
    region: us-east-1
    sshAllowedCidr: "203.0.113.7/32"   # required — see below
    profile: my-profile                # optional; omit to use the default credential chain

| field | default | what it does | |---|---|---| | region | us-east-1 | the one region this Provider manages. Two regions means two Providers; listManaged() is scoped at construction | | sshAllowedCidr | none — required | which network may reach SSH on your boxes | | allowAllCidr | false | the second signature 0.0.0.0/0 needs | | profile | none | named profile from your shared credentials file | | managedBy | rockysurf | value of the managed-by tag this Provider owns. listManaged() filters on it and validateSpec() refuses a spec that disagrees | | securityGroupName | rockysurf-ssh | the shared SSH group, one per region, reused by every Server | | rootVolumeGb | 20 | root volume size in GiB, 8 to 16384 | | amiParameterPrefix | /aws/service/canonical/ubuntu/server/24.04/stable/current | SSM public parameter path for the base image, with {arch} substituted |

sshAllowedCidr has no default, and that is the security decision of the package. Enabling aws without it means the Provider refuses its own section and is dropped at startup; the app still comes up, says why on the New Server page, and names it in the boot log. Opening SSH to the whole internet takes two lines rather than one typo:

    sshAllowedCidr: "0.0.0.0/0"
    allowAllCidr: true

These boxes run agent-authored code and hold a git token, so a /0 that arrives by accident is the difference between a dev box and an incident.

Credentials

The standard AWS credential chain, in the SDK's usual order. There is nowhere in rockysurf.config.yaml to paste an access key, and nothing asks you for one.

aws sso login --profile my-profile          # SSO / IAM Identity Center
export AWS_PROFILE=my-profile               # a named profile
export AWS_ACCESS_KEY_ID=… AWS_SECRET_ACCESS_KEY=…
# or nothing at all, if you run core on an EC2 instance with an instance role

If aws sts get-caller-identity works in your shell, this Provider authenticates the same way.

What it needs in your account

A policy covering the EC2 and SSM calls the Provider makes, and nothing wider. docs/providers/aws.md carries the JSON, statement by statement, with the reason for each. deploy/aws/iam-role.yaml deploys it as a role.

Two things keep that document honest rather than aspirational. scripts/check-iam-policy.mjs asserts the published policy still covers every API call the source makes, so a new call with no matching action fails lint instead of failing in a stranger's account. The nightly real-cloud job then runs the full lifecycle under a principal holding exactly that policy.

The region also needs a default VPC with a default subnet, which is what an account comes with unless someone removed it. This Provider does not create networking: without one it refuses the launch and says so. It does create the shared SSH security group on first launch if it is absent.

Capabilities

| capability | value | what it means for you | |---|---|---| | stop | true | a box can be stopped and restarted with its disk intact | | ipStableAcrossStop | false | a restarted instance gets a new public IPv4. Rocky Surf re-reads the address and tells you your SSH config is stale. No Elastic IP is allocated: it would be one more per-server resource to create, tag and reap | | canInjectHostKeys | true | core mints the host key before the box exists and ships it in #cloud-config, then verifies it on the first connection — the one carrying your secrets file. There is no trust-on-first-use window | | userDataMaxBytes | 16384 | EC2's hard limit, measured on the raw bytes before base64. Push-mode documents run about 2.1KB, so the ceiling is not a live constraint | | generatesUserData | true | cloud-init does the pre-boot work |

Instances also report a consoleUrl, so a Server links to its EC2 page from the moment RunInstances returns. Nothing extra needs configuring for that: region plus instance id is the whole URL.

Evidence for each value is in docs/providers/capability-matrix.md.

Prices

Bundled, not live. AWS publishes its price list through a separate service, so reading it at runtime would add a dependency for a number that changes a few times a year. The table ships with 14 burstable types (t3.* amd64, t4g.* arm64) priced in USD for us-east-1 only, stamped with the time it was read and the time AWS published it. Everywhere else hourly is null, which the SDK defines as unknown, never free rather than zero.

The table is generated from the same public feed the EC2 on-demand pricing page renders — no credentials, no account, no SDK — so nothing in it was rounded by hand:

node scripts/refresh-prices.mjs            # AWS is the default; --check asserts it is current

Verified

A full lifecycle on real EC2, on 2026-08-12, under a principal holding the published IAM policy and nothing else. Create, bootstrap, SSH, stop, start and terminate ran on both architectures — t4g.small/arm64 in 333s and t3.small/amd64 in 255s, us-east-1 — each ending in a zero-orphan audit. That run found a real bug in the published policy, which is why it was worth doing.

It is re-run nightly, at 07:00 UTC, by .github/workflows/nightly-real-cloud.yml, under credentials that chain into the role deployed from deploy/aws/iam-role.yaml; the job asserts that identity is in force before it launches anything. A Provider call the published policy does not cover fails the nightly the first morning after it lands.

Two limits worth stating. The nightly exercises what the lifecycle exercises, so a code path no end-to-end run reaches is still unproven. And an account that has run Rocky Surf before already owns the shared security group, so CreateSecurityGroup and AuthorizeSecurityGroupIngress — the two calls a first launch makes — are covered by EC2 dry-run probes rather than by the nightly.

Writing your own Provider

This package is one implementation of a frozen contract. To write another, start with @rockysurf/provider-sdk for the types and docs/writing-a-provider.md for the workflow.

One local detail if you are auditing dependencies: this is the only package in the workspace that pulls in @aws-sdk/*, and scripts/check-npx-closure.mjs enforces that every AWS SDK package in the shipped CLI closure arrives through this one. Dropping this Provider drops all of them.