# Protect an app

> Add a password with nginx basic auth, or sign-in inside the app, since Rootsy doesn't put a login in front of what a computer serves.

This page covers putting a login in front of an app you serve: a password in nginx, or sign-in inside the app. Rootsy puts no login in front of apps. Anything your computer serves is reachable by anyone who has its address or one of its custom domains. To keep an app private, add a login yourself.

Signing in to Rootsy protects your workspace: the Terminal, the Editor and the dashboard. It has no effect on the address or custom domains.

## Password-protect an app with nginx

nginx basic auth makes the browser ask for a username and password before it shows anything. It suits a private tool, a staging copy, or a site that isn't ready. It gives everyone the same kind of access.

First, create a password file. This generates a random password for a user named `alice`, stores its hash in `~/.htpasswd`, and prints the password so you can pass it on:

```sh
PASSWORD=$(openssl rand -base64 18)
printf 'alice:%s\n' "$(openssl passwd -apr1 "$PASSWORD")" >> ~/.htpasswd
echo "alice / $PASSWORD"
```

Run the first two lines again with another name to add more users. To remove a user, delete their line from `~/.htpasswd`.

nginx runs as the `dev` user, so it can read the file. Keep it outside `~/sites/` so it's never served.

Then add two lines to the server block you want to protect. For the default site, edit `/etc/nginx/sites-iwmwn/000-default.conf`:

```nginx
server {
  listen 8090 default_server;
  server_name _;
  root /home/dev/sites/default;
  index index.html;

  auth_basic "Private";
  auth_basic_user_file /home/dev/.htpasswd;

  location / { try_files $uri $uri/ =404; }
}
```

For an app you proxy to, put the same two lines in its server block. To protect only part of a site, put them inside a `location` block instead. Then reload:

```sh
sudo nginx -t && sudo nginx -s reload
```

Check it from the computer. The first request should get 401 and the second 200:

```sh
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8090/
curl -s -o /dev/null -w '%{http_code}\n' -u "alice:$PASSWORD" http://127.0.0.1:8090/
```

Basic auth sends the password with every request, so share the `https://` link. Browsers remember the password until they're closed. There's no sign-out button.

The password file lives in your home directory, so it survives Reset. Your server blocks in `/etc` don't. Keep a copy of them under `~` and put them back after a Reset. See [Backups and Reset](https://rootsy.io/docs/reference/backups-and-reset.md#before-you-reset).

## Add sign-in inside the app

Build sign-in into the app when people need their own accounts, a sign-out button, or different permissions. Use your framework's auth library, a hosted identity provider, or email magic links. Rootsy doesn't provide accounts or sessions for your app.

Store sessions on disk or in a database, never in process memory. The computer sleeps when idle and your app can restart when it wakes. An in-memory session store signs everyone out each time. Express's default `MemoryStore` has this problem. Give it a file or SQLite store. See [Sleep and wake](https://rootsy.io/docs/reference/sleep.md).

## Schedules and protected apps

Requests from a schedule don't carry a password. They arrive with the computer's schedule hostname in the `Host` header. If no server block names that hostname, they go to the default server. So if you protect the default server, every delivery fails with Error 401.

Serve the endpoint from its own server block for the schedule hostname, as [Scheduled tasks](https://rootsy.io/docs/reference/scheduled-tasks.md) shows. Or turn auth off for the endpoint's path in the server block that receives deliveries:

```nginx
location /jobs/ {
  auth_basic off;
  proxy_pass http://127.0.0.1:3001;
  proxy_set_header Host $host;
}
```

An endpoint without a password still has to check each request's signature before doing any work.

## The Preview window

The workspace's Preview window embeds your app. Embedded pages can't reliably show a password prompt or keep a sign-in. After adding a login, run:

```sh
rootsy preview window
```

The Preview then shows an **Open in its own window** button. The password prompt and sign-in work in that window. See [Preview and testing](https://rootsy.io/docs/reference/preview-and-testing.md).

---
Page: https://rootsy.io/docs/reference/protect-an-app/ · Updated: 2026-10-21 · All docs: https://rootsy.io/llms.txt
