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

@studiometa/trafic-agent

v0.1.41

Published

Server agent for DDEV preview environments — auth, scale-to-zero, auto-start

Downloads

691

Readme

@studiometa/trafic-agent

Server agent for DDEV preview environments — auth, scale-to-zero, and auto-start.

Part of Trafic, a tool for managing DDEV preview environments on Linux servers.

Features

  • Forward auth — Traefik middleware for IP whitelist, basic auth, and token auth
  • Scale-to-zero — Automatically stop idle DDEV projects to save RAM
  • Auto-start — Show a waiting page and restart stopped projects on request
  • Per-project config — Override auth and idle timeout per project

Installation

npm install -g @studiometa/trafic-agent

Commands

trafic-agent serve

Start the agent server.

trafic-agent serve
# or with custom config
trafic-agent serve --config /etc/trafic/config.toml

trafic-agent setup

Interactive server setup — installs Docker, DDEV, configures DNS, and sets up the agent as a systemd service.

trafic-agent setup --tld previews.example.com

Requirements:

  • Ubuntu 24.04 LTS
  • Root access (for initial setup)
  • Wildcard DNS pointing to the server

trafic-agent upgrade / trafic-agent update

Upgrade the server to the latest version of trafic-agent in one command. update is an alias for upgrade.

Steps:

  1. Check for updates — queries the npm registry for the latest version
  2. Install — runs npm install -g @studiometa/trafic-agent@latest if a newer version is available
  3. Migrations — runs any pending server migrations (forward-only, idempotent)
  4. Restart — restarts the trafic-agent systemd service

Fresh servers set up with trafic-agent setup have all migrations automatically marked as applied, so migrations only run when needed on existing deployments.

# Upgrade to the latest version (recommended)
sudo trafic-agent upgrade

# Preview what would be done without making changes
sudo trafic-agent upgrade --dry-run

# List all migrations and their status (no install or restart)
trafic-agent upgrade --list

Example --list output:

✓ 0001__ddev_apt_repo     Migrate DDEV from manual tarball to apt repository   (applied)
✓ 0002__mkcert_ddev_user  Install mkcert CA in the ddev user trust store       (applied)

Migration state is stored in /etc/trafic/.migrations.json and updated after each individual migration, so a partial failure leaves the state consistent.

Configuration

Create /etc/trafic/config.toml:

# Required: TLD for DDEV projects
tld = "previews.example.com"

# Agent HTTP server port (default: 9876)
port = 9876

# Scale-to-zero: stop idle projects after this duration
idle_timeout = "4h"

# Authentication
[auth]
default_policy = "basic"  # allow, deny, basic, or token

# Proxies in front of the agent (default: 1 = ddev-router/Traefik alone).
# Raise by one for each extra proxy: a CDN or load balancer ahead of
# Traefik makes it 2. Set this before using allowed_ips — it decides which
# X-Forwarded-For entry is treated as the client address.
trusted_proxy_hops = 1

# IP whitelist (bypasses auth)
allowed_ips = ["192.168.1.0/24", "10.0.0.0/8"]

# Bearer tokens for CI/API access
tokens = ["your-ci-token"]

# Basic auth credentials
basic_auth = ["user:password"]

# Per-hostname rules
[[auth.rules]]
match = "*.public.*"
policy = "allow"

[[auth.rules]]
match = "admin.*"
policy = "basic"

Per-project configuration

Create .ddev/config.trafic.yaml in your project:

# Override auth policy for this project
auth_policy: allow  # allow, deny, basic, or token

# Override idle timeout (or disable with "never")
idle_timeout: never

How it works

HTTPS request
     │
     ▼
Traefik (DDEV router)
     │
     ├─► forwardAuth → trafic-agent
     │        │
     │        ├─► 200 OK → DDEV project
     │        └─► 401 → Basic auth prompt
     │
     └─► 502 error → errors middleware → trafic-agent
                          │
                          ├─► known project → Waiting page + auto-start
                          └─► unknown → Error page

The agent:

  1. Handles forward auth requests from Traefik
  2. Checks IP whitelist, tokens, or basic auth
  3. Tracks project activity for scale-to-zero
  4. Starts stopped projects when requested
  5. Shows a waiting page while projects start

Endpoints

All internal endpoints are prefixed with __ so they cannot collide with a project's own paths. Everything else is treated as a request for a project.

| Endpoint | Description | |----------|-------------| | GET /__auth__ | Forward auth for Traefik. 200 allows, 401 prompts for basic auth | | GET /__status__?project=<name> | Project status as JSON, for the waiting page to poll | | GET /__health__ | Agent health and version | | anything else | Waiting page for a known project, error page otherwise |

TLS

Traefik obtains the certificates, and setup --email is what turns that on:

trafic setup --host server.example.com --tld previews.example.com \
  --email [email protected]

With an email, DDEV sets use_letsencrypt=true and Traefik requests a certificate per project hostname on first use — previews included, since each one gets its own router. Without an email, projects are served with a locally trusted mkcert certificate, which is fine behind a proxy that terminates TLS itself but shows a browser warning if used directly.

Two limits worth knowing before you rely on it:

  • Let's Encrypt allows 50 new certificates per registered domain per week. Each preview hostname is a new certificate, so environments that churn fast can hit the ceiling. Renewals do not count against it.
  • Turning Let's Encrypt off does not discard certificates already issued. Traefik keeps them in acme.json in the ddev-global-cache volume and serves them again after a restart, so configureDdev deletes that storage when Let's Encrypt is disabled.

Wildcard certificates would avoid the per-hostname limit but need a DNS-01 challenge, which DDEV does not do. If you churn tens of previews a week, put a proxy in front that can (Caddy or Traefik with a DNS provider) and disable Let's Encrypt in DDEV so the two do not both try.

Network exposure

ufw default deny incoming does not cover the ports Docker publishes. Docker adds its rules to nat/PREROUTING and the DOCKER chain of FORWARD, both of which are evaluated before UFW's chains. So the ports ddev-router publishes are reachable from the internet whatever UFW says about them, and ufw status will not tell you otherwise.

setup opens 22, 80 and 443, and 9876 for the agent from the Docker bridge only. Those rules are accurate. What they do not do is close the ports ddev-router publishes for DDEV's tools:

| Port | Service | |------|---------| | 8025, 8026 | Mailpit | | 8142, 8143 | xhgui |

Both layers now apply:

  1. DOCKER-USER rules, installed by setup. That is the chain Docker jumps to first in FORWARD and never flushes, so it is the only host-level hook that can filter a published port. The rules drop traffic to the tool ports unless it comes from Docker's own networks. They match on the original destination port (-m conntrack --ctorigdstport), because by FORWARD the destination has already been rewritten to the container.

    They live in /usr/local/sbin/trafic-docker-firewall, reapplied at boot and after any Docker restart by trafic-docker-firewall.service — Docker recreates DOCKER-USER empty and nothing else would restore them. They will not appear in ufw status. Inspect them with iptables -S DOCKER-USER.

  2. Forward auth, attached to every entry point ddev-router publishes, so a request that does reach a tool port still needs credentials. An earlier version attached it only to 80 and 443, which left xhgui answering from the internet with no authentication at all.

Access from the host itself is unaffected: a connection to 127.0.0.1:8026 goes through Docker's userland proxy rather than FORWARD, so an SSH tunnel still works:

ssh -L 8026:127.0.0.1:8026 [email protected]
# then open https://localhost:8026

A provider firewall is not a substitute

Recommended as an extra layer, but do not rely on it alone. Measured on an OVH dedicated server with the Edge Firewall enabled and a correct rule denying these ports: a connection from another host inside OVH still completed in 113ms, while a port with nothing listening was dropped and timed out at 12s. The deny applies to traffic crossing the provider's edge; traffic that never crosses it is not filtered.

Anyone able to rent a VM from the same provider is inside that blind spot, which for a large host is a very low bar. That is why the DOCKER-USER rules above exist: they apply to every packet regardless of origin.

On OVH the setting is the Network Firewall in the control panel. Two things to know: it is stateless, so permit tcp established is required or return traffic for outbound connections is dropped, and it is IPv4-only. setup does not configure it — it can neither create nor verify it.

Binding ddev-router to loopback only (router-bind-all-interfaces=false) closes everything at once, but then nothing serves the public and you need a host proxy in front. That is a reasonable setup; it is just a different one from what setup builds.

License

MIT — see LICENSE