nz
Push a directory of HTML, get a url back.
$ nz push ./report --password meow
expires 2026-11-17T19:40:02.000Z, password protected
https://k3x9q.example.com/
Minimalism
nz is a few files you can read in one sitting:
| file | what |
|---|---|
worker.js |
Cloudflare Worker, plain JS, no dependencies, no build |
nz |
POSIX sh CLI: tar + curl, nothing to install |
nz.ps1 |
the same CLI for PowerShell on Windows |
test.sh |
end-to-end test against wrangler dev |
A site is one KV entry: the value is a tar of the directory, and the metadata is
{ exp, pw }. KV expiration deletes it when the TTL runs out.
Install
wrangler kv namespace create SITES # paste the id into wrangler.jsonc
# set DOMAIN + routes in wrangler.jsonc, add a proxied DNS record: * AAAA 100::
wrangler secret put TOKEN
wrangler deploy
ln -s "$PWD/nz" ~/bin/nz
mkdir -p ~/.config/nz && printf 'NZ_SERVER=https://example.com\nNZ_TOKEN=...\n' > ~/.config/nz/config
On Windows, put nz.ps1 somewhere on your PATH and write the same config. It needs
Windows 10 or later, which ships tar.exe and curl.exe:
Unblock-File .\nz.ps1 # if it came from a download
New-Item -ItemType Directory -Force ~\.config\nz | Out-Null
"NZ_SERVER=https://example.com`nNZ_TOKEN=..." | Set-Content -Encoding ascii ~\.config\nz\config
nz.ps1 push .\site --ttl 7d --password meow
CLI
nz push <dir|file> [--ttl 14d|never] [--password PW] [--new]
nz update <id> [dir|file] [--ttl 14d|never] [--password PW | --no-password]
pushupdates the site last pushed from the same path (~/, one.config/ nz/ sites id<TAB>pathper line), or makes a new one if there is none, it expired, or--new.updatetargets an id. Without a path it only changes ttl/password.nz.ps1takes the same commands, and also accepts PowerShell-style-ttl,-password,-new.- A single file is published as
index.html. Dotfiles andnode_modulesare skipped. - TTL:
30m,12h,14d,2w,never. DefaultDEFAULT_TTL(14d). Omitted on update = kept. - The url goes to stdout and details to stderr, so
open "$(nz push .)"works.
API
The CLI is a thin wrapper around this. Everything lives on the apex host:
tar --format=ustar -cf - -C site . |
curl -H "authorization: Bearer $TOKEN" -H 'nz-ttl: 7d' -H 'nz-password: meow' \
--data-binary @- https://example.com/ # POST: new site -> 201
curl -X PUT ... --data-binary @site.tar https://example.com/k3x9q # replace content
curl -X PUT -H "authorization: ..." -H 'nz-password;' https://example.com/k3x9q # policy only
The response is the url on line 1 and a details line on line 2. nz-password; (empty) removes the
password. Omitted headers keep their current value on PUT.
Sites live at https:/, so each one is its own browser origin. Password-protected
sites show a form. Unlocking sets a host-only __Host-nz cookie that lasts 7 days and is signed
over the password verifier, so changing the password logs everyone out. Unlock attempts are
rate-limited to 5 per minute per ip and site.
License
0BSD