Private apps

Lock an app behind an access token. Requests without a valid token are turned away before they reach your app.

By default, every app is reachable by anyone at its dockhold.app URL. Switch an app to private and every request must present a valid access token. Anything without one gets a 401 at the edge, before your app is even reached.

Private apps are on the Pro and Scale plans. Free apps are public. Upgrade to flip any app to private from its Access tab.

Setting it up

  1. Go private. Open your app, go to the Access tab, and set visibility to Private.
  2. Create a token. Add one or more named tokens. The full token is shown only once, so copy it somewhere safe.
  3. Send it. Pass the token on every request.
  4. Rotate anytime. Delete or replace a token from the Access tab. Revoking one takes effect within about 30 seconds.

Calling a private app

Use whichever auth style fits your client. Both are accepted on every request, including WebSocket upgrades.

# Bearer token (good for code)
curl https://your-app.dockhold.app/api/hello \
  -H "Authorization: Bearer dh_live_abc123..."

# HTTP Basic (works in a browser; token goes in the password field)
curl https://your-app.dockhold.app/api/hello \
  -u "anything:dh_live_abc123..."

A browser pointed straight at a private app gets a login prompt. Paste the token into the password field and the browser remembers it for the session.

How tokens are kept safe

Tokens are stored only as cryptographically hashed values with a server-side pepper, so the plaintext never lands in the database. Each request is checked with a constant-time comparison, so a leaked database dump can't be turned back into working tokens.

Extra controls

  • IP allow-list: pin a token to specific IP ranges (CIDR, up to 32 entries, IPv4 and IPv6). The list is checked before the token, so a request from a disallowed IP never reaches the token check. Leave it empty to allow any IP.
  • Brute-force protection: an IP that fails auth more than 10 times a minute is throttled with 429 until the window resets, per app and per source IP.
  • Streaming and WebSockets: HTTP, server-sent events, and WebSocket upgrades all work. The token is checked once at the handshake.

Don't put a token in client-side code. A token in a browser bundle is a public token. Use them from your backend, your CLI, or trusted runners, and use the IP allow-list to limit the damage if one ever leaks.

If you move from Pro or Scale back to the free plan while you still have private apps, they flip back to public, it's recorded in your audit log, and you're notified. Tokens are kept, hashed and inert, in case you upgrade again.