# Securing Your Instance
Source: https://dorkos.ai/docs/self-hosting/securing-your-instance

Enable login, expose DorkOS safely, and issue per-user API keys for MCP, scripts, and agents





# Securing Your Instance [#securing-your-instance]

By default, DorkOS runs with **no login**: instant start, no accounts, localhost only. That is the right default for a tool running on your own machine. The moment you want to reach DorkOS from another device, you turn on a real login: an owner account backed by a password, not a PIN.

<Callout type="info">
  Login is **optional and off by default**. Turning it on adds an owner account and a sign-in
  screen; nothing else about local use changes.
</Callout>

## Enabling login [#enabling-login]

<Steps>
  <Step>
    ### Open Settings → Security [#open-settings--security]

    Open **Settings** (gear icon), then the **Security** tab.
  </Step>

  <Step>
    ### Turn on "Require login" [#turn-on-require-login]

    Toggle **Require login**. DorkOS walks you through creating the **owner account**: an email and a password.

    The email is a **local identifier only**: it is never verified and no email is ever sent.
  </Step>

  <Step>
    ### You're signed in [#youre-signed-in]

    Once the owner account exists, login is required. Your session persists for 7 days with sliding refresh, so you stay signed in across reloads and restarts. Sign out anytime from **Settings → Security**.

    Turning **Require login** back off doesn't delete the owner account, it just stops asking for it: the account and any API keys stay put, and the instance goes back to the no-login default.
  </Step>
</Steps>

## Exposing DorkOS beyond localhost [#exposing-dorkos-beyond-localhost]

Want to reach DorkOS from your phone or another computer? Turn on login first. It is the only way in once you leave localhost, whether you get there through a tunnel or by binding to another network interface (any address other than your own machine, like your Wi-Fi IP).

<Callout type="warn">
  **Breaking change:** the 6-digit tunnel passcode is gone. Exposing DorkOS requires an owner
  account. Existing passcode settings are removed automatically on upgrade.
</Callout>

* **Starting a tunnel*&#x2A; with login off routes you into owner-account creation first, with the copy &#x2A;"Exposing DorkOS requires a login."* After the owner exists and login is on, the tunnel starts.
* **Binding to a non-loopback host** (setting `DORKOS_HOST` to anything other than `localhost` / `127.0.0.1` / `::1`) with login not configured **refuses to start** with an actionable error. Enable login first, then restart.

Remote visitors reaching an exposed instance get the **sign-in screen**: static assets load so the login page renders, but every API call requires a valid session.

<Callout type="warn">
  **Docker operators, this is you.** The official Docker image bakes in
  `DORKOS_ALLOW_INSECURE_BIND=true`. That is what lets the container accept connections through
  Docker's port forwarding, and it skips the bind gate that would otherwise stop a login-off server
  from listening beyond localhost. It does **not** turn on login. So if you expose the container to
  anyone else, you are exactly who must [enable login
  first](/docs/self-hosting/docker#with-a-reverse-proxy).
</Callout>

<Callout type="info">
  DorkOS already slows password guessing: it allows 10 sign-in attempts from one IP address every 15
  minutes, then briefly blocks that address. Set `DORKOS_AUTH_SIGNIN_RATE_LIMIT` to a different
  number if that default gets in your way.
</Callout>

## API keys for MCP, scripts, and agents [#api-keys-for-mcp-scripts-and-agents]

External agents (Claude Code, Cursor, Windsurf), scripts, and the MCP endpoint authenticate with **per-user API keys** instead of a single global key.

<Steps>
  <Step>
    ### Create a key [#create-a-key]

    **Settings → Security → API keys → Create.** Give it a name and an optional expiry.
  </Step>

  <Step>
    ### Copy it once [#copy-it-once]

    The key value is shown **exactly once** at creation. Copy it immediately: DorkOS never displays it again. Revoke a key anytime from the same screen.
  </Step>

  <Step>
    ### Use it as a Bearer token [#use-it-as-a-bearer-token]

    Send the key as a Bearer token (a kind of key you attach to each request) in an `Authorization: Bearer <key>` header, to `/mcp` or any `/api/*` route.

    **Reference:** here's what that looks like in practice.

    ```bash
    curl -H "Authorization: Bearer dork_..." http://localhost:4242/mcp
    ```
  </Step>
</Steps>

<Callout type="info">
  **Headless deployments** (a server running with nobody signed in at a screen, like CI or a
  background job): the `MCP_API_KEY` environment variable is still honored as a static override for
  the `/mcp` endpoint. It takes priority over per-user keys and cannot be revoked from the UI.
</Callout>

The old global MCP key (and its `POST /api/config/mcp/generate-key` / `DELETE /api/config/mcp/api-key` endpoints) have been removed. If you had a global MCP key configured, it is **migrated automatically** into an owner-owned API key the first time you create the owner account (or on the next server start if an owner already exists), so existing MCP clients keep working without changes.

## Recovering a lost password [#recovering-a-lost-password]

There is no "forgot password" email: the local edition sends no email, and a laptop that already trusts you doesn't need one. Because machine access already implies owner-level trust, you recover from the command line:

```bash
# Reset the owner password (prompts, or pipe it in for non-interactive use)
dorkos auth reset-password
```

You can also create the owner and turn on login entirely from the CLI (useful before you ever open the UI, or when preparing a server to expose):

```bash
# Create the owner account and require login
dorkos auth enable
dorkos auth enable --email you@example.com --password '<secret>'
```

<Callout type="warn">
  If a server is already running, restart it after `dorkos auth enable`. The CLI writes
  `~/.dork/config.json` directly and the running server does not watch the file.
</Callout>

## Who can use an exposed instance [#who-can-use-an-exposed-instance]

<Callout type="error">
  Anyone who can drive agents on an instance effectively has the server process's filesystem access
  and spends the owner's Claude quota. That is why registration is **owner-only**: the first account
  is the owner, and further sign-ups are closed. There is no second account today: sharing access
  means sharing the owner login itself. A viewer/operator role model that safely admits more people
  is a planned fast-follow; until it exists, only share the owner login with people you trust with
  your machine and your Claude account.
</Callout>

## Next Steps [#next-steps]

<Cards>
  <Card title="Tunnel Setup" href="/docs/self-hosting/tunnel-setup">
    Expose your instance remotely via ngrok
  </Card>

  <Card title="Reverse Proxy" href="/docs/self-hosting/reverse-proxy">
    Put DorkOS behind nginx or Caddy
  </Card>

  <Card title="Configuration" href="/docs/getting-started/configuration">
    Full config reference, including the auth and cloud sections
  </Card>
</Cards>
