depsite
v2.0.1
Published
Deploy Node.js apps behind nginx with one command. Production-ready reverse-proxy and Let's Encrypt automation.
Maintainers
Readme
depsite
Deploy Node.js apps behind nginx with one command.
depsite automates the boring parts of putting a Node.js service behind an
nginx reverse proxy on a Linux server: writing the config, enabling the site,
running nginx -t, reloading, and (optionally) provisioning a Let's Encrypt
certificate via certbot. Every step is interactive, validated, and reversible.
┌ depsite v2.0.0
│
◆ Project name
│ api
│
◆ Domain
│ api.example.com
│
◆ Port your Node.js app listens on
│ 3000
│
◆ Set up Let's Encrypt SSL?
│ Yes
│
◇ Writing nginx configuration ✓
◇ Enabling site ✓
◇ Testing nginx configuration ✓
◇ Reloading nginx ✓
◇ Provisioning SSL ✓
◇ Recording site in registry ✓
│
└ Done.
✓ Deployment complete
URL https://api.example.com
Site api
Port 3000
SSL enabled
Time 11.4sFeatures
- Beautiful CLI built on @clack/prompts.
- Snapshot-tested config generator — the output of every flag combination is locked down so a regression cannot ship without a failing test.
- State machine + rollback log — if any step fails (config, symlink, syntax test, reload, SSL), every prior step is reverted and nginx is restored to a known-good state.
- Site registry at
~/.depsite/sites.json—depsite list,statusandremovework from a real inventory, not by scanning/etc/nginx. - DNS pre-flight — checks the domain resolves to this server before asking certbot for a cert (avoids burning the 5-fail/hr LE rate limit).
--ssl-staging— use the Let's Encrypt staging endpoint while you're iterating, no rate limits.--non-interactive+--json— runs cleanly in CI/scripts.- Single-binary install — no Bun or Node needed on the server.
Install
Single-file binary (recommended for servers)
curl -fsSL https://raw.githubusercontent.com/kemora13conf/depsite/master/scripts/install.sh | bashThe installer downloads the right binary for your architecture
(x86_64 / aarch64) from GitHub Releases, verifies its SHA-256, and
drops it at /usr/local/bin/depsite. No Bun or Node.js required.
From npm
# Globally
npm install -g depsite # or: bun install -g depsite
# Or one-shot, no install
bunx depsite # or: npx depsiteQuickstart
# Interactive
depsite
# Scripted
depsite deploy \
--name api \
--domain api.example.com \
--port 3000 \
--ssl --email [email protected] \
--non-interactive --yesThen later:
depsite list
depsite status api
depsite renew api
depsite remove apiCommands
| Command | What it does |
| ----------------------- | ------------------------------------------------ |
| depsite deploy | Interactive (or flag-driven) deployment |
| depsite remove <name> | Disable + delete a site, reload nginx |
| depsite list | List sites recorded in the registry |
| depsite status <name> | Show enable state, SSL state, paths |
| depsite renew [name] | certbot renew then reload nginx |
| depsite doctor | Diagnose host readiness (deps, sudo, disk, …) |
| depsite init | Scaffold a depsite.config.json template |
Run depsite <command> --help for the full flag set.
Global flags
--json, --quiet, --verbose, --no-color, -y/--yes.
Configuration file (optional)
Generate a starter config:
depsite initThen deploy from it:
depsite deploy --config depsite.config.json --non-interactive --yesRequirements
- Linux (x86_64 or aarch64)
- nginx ≥ 1.28.2 (
depsite doctorwarns on older — see CVE-2026-1642) - certbot (optional, only for
--ssl) - Passwordless sudo for the user running depsite (it needs
nginx -t,systemctl reload nginx,teeandln -sf)
What gets generated
depsite writes a single file to /etc/nginx/sites-available/<name> and
symlinks it into sites-enabled/. The HTTP block is rendered from a
snapshot-tested template; the HTTPS block is added by certbot --nginx
itself when SSL is enabled (so HSTS and SSL-engine config never drift).
# Managed by depsite — do not edit by hand.
upstream api_prod {
server 127.0.0.1:3000;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name api.example.com;
client_max_body_size 20M;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "geolocation=(), microphone=(), camera=()" always;
location / {
proxy_pass http://api_prod;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
proxy_buffering on;
proxy_buffer_size 16k;
proxy_buffers 8 16k;
}
location = /healthz { return 200 "ok\n"; }
location ~ /\.(?!well-known) { deny all; }
}Development
git clone https://github.com/kemora13conf/depsite
cd depsite
bun install
bun run dev -- --help # run from source
bun test --coverage # 100+ tests, snapshot-locked nginx output
bun run typecheck
bun run lint # biome
bun run build # bundle to dist/
bun run build:bin # compile single Linux x64 binaryProject layout
src/
├── bin/depsite.ts Commander entry
├── commands/ One file per subcommand
├── core/ Pure logic — template, workflow, errors, schemas
├── services/ I/O — shell, nginx, certbot, dns, registry, fs
├── ui/ log, prompts, spinner, summary, banner
├── utils/ sanitize, Result<T,E>
└── config/ constants
tests/ bun:test, mirroring src/CI / Releases
- Every PR runs lint, typecheck, tests with coverage, and binary builds
for
linux-x64andlinux-arm64(see.github/workflows/ci.yml). - Pushing a
vX.Y.Ztag publishes to npm withNPM_CONFIG_PROVENANCE=true(signed attestation tied to the workflow). Pre-release tags (v2.0.0-alpha.1,-beta.1,-rc.1) automatically use the matching npm dist-tag. Binaries +SHA256SUMSare attached to the GitHub Release. Authentication uses theNPM_TOKENrepo secret.
Migrating from v1.x
v2 is a full rewrite. Breaking changes:
- Runs on Bun (or as a precompiled binary). Node.js is no longer required at runtime.
depsite removerequires the exact slug (consultdepsite list).- v1's hand-written HTTPS server block was removed —
certbot --nginxowns the HTTPS block now. Existing sites continue to work; re-runningdepsite deploywith--forcere-issues a clean v2 config. - New flags:
--ssl-staging,--websockets,--require-running,--skip-dns.
License
MIT — see LICENSE.
