Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d8ee13a
docs: add OIDC server setup guide and configuration reference
dosubot[bot] Apr 9, 2026
bd9f835
docs: add OIDC server guide and configuration reference
dosubot[bot] Apr 11, 2026
2a810b2
chore: merge user attributes update
steveiliop56 Jul 11, 2026
28c03bf
chore: remove dosu comments
steveiliop56 Jul 11, 2026
a13e958
feat: add new options to config reference
steveiliop56 Jul 11, 2026
7c4e636
feat: add oidc certification status to oidc guide
steveiliop56 Jul 11, 2026
f1edfa3
refactor: update tool styles
steveiliop56 Jul 11, 2026
7f2c90d
chore: update about section
steveiliop56 Jul 11, 2026
f047415
feat: add tailscale integration
steveiliop56 Jul 11, 2026
0522c4b
feat: add docs for deny-by-default acls
steveiliop56 Jul 11, 2026
9702036
chore: update changelog
steveiliop56 Jul 11, 2026
2f7375f
feat: add note for subdomains enabled
steveiliop56 Jul 12, 2026
1c6aa25
feat: tailscale auth guide
steveiliop56 Jul 12, 2026
2d603f4
chore: update main screenshot
steveiliop56 Jul 12, 2026
d32c97c
chore: update screenshots
steveiliop56 Jul 12, 2026
e14593d
feat: add yaml config options
steveiliop56 Jul 12, 2026
724bb6d
feat: update index
steveiliop56 Jul 12, 2026
f092b9e
feat: add note on tinyauth api
steveiliop56 Jul 12, 2026
2759165
fix: review comments
steveiliop56 Jul 12, 2026
5259b59
Merge branch 'main' into feat/v5.1.0
steveiliop56 Jul 12, 2026
9a87beb
chore: remove public prefix in screenshots
steveiliop56 Jul 12, 2026
205b777
chore: add tailscale integration back to sidebar
steveiliop56 Jul 12, 2026
573dbf6
feat: add beszel guide
steveiliop56 Jul 15, 2026
5aba190
feat: add notes on trusted proxies
steveiliop56 Jul 15, 2026
e10c887
chore: update notes on trusted proxies
steveiliop56 Jul 15, 2026
ad44b3e
fix: rabbit comments
steveiliop56 Jul 15, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,6 @@ pnpm-debug.log*

# macOS-specific files
.DS_Store

# idea
/.idea/
12 changes: 12 additions & 0 deletions astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,10 @@ export default defineConfig({
label: "Runtipi",
slug: "docs/guides/runtipi",
},
{
label: "Tailscale",
slug: "docs/guides/tailscale",
},
{
label: "Using the Binary",
slug: "docs/guides/using-the-binary",
Expand All @@ -134,10 +138,18 @@ export default defineConfig({
label: "Zerobyte",
slug: "docs/integrations/zerobyte",
},
{
label: "Tailscale",
slug: "docs/integrations/tailscale",
},
{
label: "Immich",
slug: "docs/integrations/immich",
},
{
label: "Beszel",
slug: "docs/integrations/beszel",
},
],
},
{
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/screenshots/beszel/beszel_login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/screenshots/beszel/beszel_providers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/screenshots/oidc/authorize.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/screenshots/tailscale/tailscale_keys.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/screenshots/tailscale/tailscale_login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/tinyauth-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/content/docs/docs/about.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Tinyauth was developed as a personal challenge to create a robust application an

## Suitable Use Cases

Tinyauth is not intended for production environments. Its primary purpose is to add a login screen to applications in homelabs or to facilitate resource sharing with family and friends. For scenarios requiring advanced user management, Authentik is recommended.
Tinyauth's main purpose is to add a login screen to applications in homelabs or to facilitate resource sharing with family and friends. It is not designed for production environments, which require features like RBAC and more granular permissions. For scenarios requiring advanced user management, Authentik is recommended.

## Future Direction

Expand Down
6 changes: 6 additions & 0 deletions src/content/docs/docs/community/caddy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ services:
caddy.reverse_proxy: "{{upstreams 3000}}"
```

It is recommended (and required for IP address ACLs) that you set the `TINYAUTH_AUTH_TRUSTEDPROXIES` environment variable (`--auth.trustedproxies` for CLI flags and `auth.trustedProxies` for YAML) to the IP address of your Caddy instance so Tinyauth can trust the `X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP.

:::note
For Caddy setups in Docker (like this one), you will need to ensure that Caddy detects the correct IP address. Because Docker uses NAT for containers, you will probably need to run Caddy in `network_mode: host`.
:::

## Securing a Service

Place any service behind Tinyauth. The only addition required to secure a service is the reusable snippet, `tinyauth_forwarder`, created earlier:
Expand Down
4 changes: 4 additions & 0 deletions src/content/docs/docs/community/kubernetes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ spec:
periodSeconds: 10
```

It is recommended (and required for IP address ACLs) that you also set the `TINYAUTH_AUTH_TRUSTEDPROXIES` environment variable to the IP address of your Nginx/Istio instance so Tinyauth can trust the `X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## Create a Service

Create the service:
Expand Down Expand Up @@ -159,6 +161,8 @@ extensionProviders:
pathPrefix: "/api/auth/envoy?path="
includeRequestHeadersInCheck: ["cookie", "x-forwarded-for", "x-forwarded-proto", "x-forwarded-host", "accept", "user-agent"]
includeAdditionalHeadersInCheck:
"x-forwarded-for": "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%"
"x-real-ip": "%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%"
"x-forwarded-proto": "%REQ(:SCHEME)%"
"x-forwarded-host": "%REQ(:AUTHORITY)%"
"x-forwarded-uri": "%REQ(:PATH)%"
Expand Down
8 changes: 8 additions & 0 deletions src/content/docs/docs/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,13 @@ tinyauth:
traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik
```

It is recommended (and required for IP address ACLs) that you set the `TINYAUTH_AUTH_TRUSTEDPROXIES` environment variable (`--auth.trustedproxies` for CLI flags and `auth.trustedProxies` for YAML) to the IP address of your Traefik instance so Tinyauth can trust the `X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP. For a Docker-based deployment,
`172.17.0.0/16` should work.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

:::caution
For Traefik setups in Docker (like this one), you will need to ensure that Traefik detects the correct IP address. Because Docker uses NAT for containers, you will probably need to run Traefik in `network_mode: host`.
:::

To protect additional applications, include the following label in their configuration:

```yaml
Expand Down Expand Up @@ -145,6 +152,7 @@ services:
environment:
- TINYAUTH_APPURL=https://tinyauth.example.com
- TINYAUTH_AUTH_USERS=user:$$2a$$10$$UdLYoJ5lgPsC0RKqYH/jMua7zIn0g9kPqWmhYayJYLaZQ/FTmH2/u # user:password
- TINYAUTH_AUTH_TRUSTEDPROXIES=172.17.0.0/16
labels:
traefik.enable: true
traefik.http.routers.tinyauth.rule: Host(`tinyauth.example.com`)
Expand Down
37 changes: 35 additions & 2 deletions src/content/docs/docs/guides/access-controls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ description: Tinyauth has support for docker label-based access controls.
Tinyauth supports basic access controls with either Docker labels or environment variables. These labels (or environment variables) can restrict or allow access to applications.

:::caution[Proxy configuration matters]
Tinyauth relies on the `X-Forwarded-Host` header (set by your reverse proxy) to determine which app's access controls apply to a given request. If your proxy doesn't overwrite this header, or if tinyauth is directly reachable on the network without going through the proxy, a user could send a request with a spoofed host that doesn't match any configured app. When no app matches, tinyauth treats the request as having no restrictions and allows any authenticated user through.
Tinyauth relies on the `X-Forwarded-Host` header (set by your reverse proxy) to determine which app's access controls apply to a given request. If your proxy doesn't overwrite this header, or if Tinyauth is directly reachable on the network without going through the proxy, a user could send a request with a spoofed host that doesn't match any configured app. When no app matches, Tinyauth treats the request as having no restrictions and allows any authenticated user through.

To avoid this, make sure your reverse proxy always sets `X-Forwarded-Host` itself and doesn't pass through client-supplied values. Traefik and Caddy do this by default. For nginx, use `proxy_set_header X-Forwarded-Host $host;` in your location block. You should also make sure tinyauth is not directly accessible from the network — only your reverse proxy should be able to reach it.
To avoid this, make sure your reverse proxy always sets `X-Forwarded-Host` itself and doesn't pass through client-supplied values. Traefik and Caddy do this by default. For Nginx, use `proxy_set_header X-Forwarded-Host $host;` in your location block. You should also make sure Tinyauth is not directly accessible from the network — only your reverse proxy should be able to reach it.

It is also recommended (and required for IP address ACLs) that your proxy sets correctly the `X-Forwarded-For` and `X-Real-IP` headers so Tinyauth can get the correct client IP and perform ACLs. You will also need to configure the `TINYAUTH_AUTH_TRUSTEDPROXIES` environment variable (`--auth.trustedproxies` for CLI flags and `auth.trustedProxies` for YAML) to point to your proxy IP. In case your proxy runs in Docker, you will most likely need to run it with `network_mode: host`.
:::

## Modifying the Tinyauth Container
Expand Down Expand Up @@ -95,6 +97,37 @@ Tinyauth will now use the domain to match the configuration instead of the app I
Labels are dynamic and can be updated at runtime, environment variables are not and require a restart of Tinyauth to take effect.
:::

## Access Control Policy

Tinyauth supports both an allow-by-default and a deny-by-default approach in access controls. The policy can be defined
using the `TINYAUTH_AUTH_ACLS_POLICY` environment variable or the `--auth.acls.policy` CLI flag. The configuration option
supports either `deny` or `allow`. The default policy is `allow`.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

In both examples we have the following ACLs defined as Docker labels.

```yaml
tinyauth.apps.myapp.config.domain: myapp.example.com
```

**Allow-by-default example**

In this example we have `TINYAUTH_AUTH_ACLS_POLICY=allow`.

With this config, every user you define in Tinyauth will be allowed unless you set up
a user allow or block list.

**Deny-by-default example**

In this example we have `TINYAUTH_AUTH_ACLS_POLICY=deny`.

With this config, every user you define in Tinyauth will be denied access to the app
unless you manually allow them with a whitelist.

:::caution
Due to the setup-specific nature of the IP and OAuth Group access controls, they are excluded
from the deny-by-default policy and are only applied if you manually specify a blocklist.
:::

## User ACLs

*Going forward, the guide will use the labels format but everything mentioned also applies to environment variables.*
Expand Down
13 changes: 13 additions & 0 deletions src/content/docs/docs/guides/advanced.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ description: Guides and tips for advanced setups.

Below, you can find some guides for advanced setups.

## Tinyauth API

Tinyauth exposes its API under `/api`. Documentation for the API is not available so you will have to consult
the controller [sources](https://github.com/tinyauthapp/tinyauth/tree/main/internal/controller). The API endpoint
is designed to be consumed only by the frontend and **no guarantees** can be made that it will remain stable
throughout updates. In case you are building an application that utilizes the Tinyauth API, please make sure
to consult the release notes of each Tinyauth release to ensure that no changes have been made.

:::note
Even though the API endpoints are not guaranteed to remain stable, user-facing endpoints like the forward-auth,
OAuth and OpenID Connect endpoints **are guaranteed** to remain stable.
:::

## Authenticating to Apps with Basic Auth

Some apps already offer authentication methods like basic auth (e.g. browser pop-ups). This can be inconvenient as it requires logging in to both Tinyauth and the protected app. Tinyauth supports authenticating to apps automatically by adding basic auth labels to the protected app.
Expand Down
8 changes: 8 additions & 0 deletions src/content/docs/docs/guides/nginx-proxy-manager.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,20 @@ location /tinyauth {
proxy_pass http://tinyauth:3000/api/auth/nginx;

# Pass the request headers
proxy_set_header x-forwarded-for $remote_addr;
proxy_set_header x-real-ip $remote_addr;
proxy_set_header x-forwarded-proto $scheme;
proxy_set_header x-forwarded-host $http_host;
proxy_set_header x-forwarded-uri $request_uri;
}
```

It is recommended (and required for IP address ACLs) that you set the `TINYAUTH_AUTH_TRUSTEDPROXIES` environment variable (`--auth.trustedproxies` for CLI flags and `auth.trustedProxies` for YAML) to the IP address of your Nginx instance so Tinyauth can trust the `X-Real-IP` and `X-Forwarded-For`headers and get the correct client IP.

:::caution
For Nginx setups in Docker (like this one), you will need to ensure that Nginx detects the correct IP address. Because Docker uses NAT for containers, you will probably need to run Nginx in `network_mode: host`.
:::

:::note
The `/tinyauth` path can be renamed for convenience.
:::
Expand Down
39 changes: 36 additions & 3 deletions src/content/docs/docs/guides/oidc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ description: Use Tinyauth's OIDC server to authenticate applications.
import { Tabs, TabItem } from '@astrojs/starlight/components';
import CreateOidcClientTool from "../../../../components/create-oidc-client-tool.astro";

In Tinyauth v5, a major milestone was the introduction of the OIDC server, which allows Tinyauth not only to use other identity providers but also to act as an identity provider itself. This means that Tinyauth can serve as a central authentication gateway for multiple applications, providing a single sign-on experience for users.
From v5.1.0 and going forward, Tinyauth is an OpenID Connect™ Certified server. This means that Tinyauth has been tested and verified to comply with the OpenID Connect Core 1.0 specification, ensuring that it meets the standards for secure authentication and identity management.

You can use the OpenID Connect server of Tinyauth to authenticate applications and provide a seamless login experience for users using a centralized authentication system. This allows for better security, easier user management, and a more streamlined user experience across multiple applications.

<img alt="OpenID Certified" width="200" src="https://openid.net/wordpress-content/uploads/2016/05/oid-l-certification-mark-l-cmyk-150dpi-90mm.jpg" />

## What is OpenID Connect?

Expand Down Expand Up @@ -36,17 +40,40 @@ Supported scopes:
- `openid`
- `profile`
- `email`
- `phone`
- `address`
- `groups`

Supported claims:

- `sub`
- `name`
- `given_name`
- `family_name`
- `middle_name`
- `nickname`
- `profile`
- `picture`
- `website`
- `gender`
- `birthdate`
- `zoneinfo`
- `locale`
- `email`
- `preferred_username`
- `email_verified`
- `phone_number`
- `phone_number_verified`
- `address`
- `groups`
- `updated_at`
- `email_verified`

These claims align with the OpenID Connect Core 1.0 specification's standard claims.
Comment thread
coderabbitai[bot] marked this conversation as resolved.

:::note
The `groups` claim and scope are an addition to the OpenID Connect Core 1.0 specification and
not something officially supported by the OpenID Foundation.
:::

Supported token endpoint authentication methods:

Expand All @@ -61,7 +88,7 @@ While no promises can be made, if you feel a required OpenID Connect feature is

## Important Considerations

Tinyauth’s core idea is to be a stateless application, but OIDC requires persistence for session and key storage. Everything is stored in the `/data` directory so, if you are using Docker, add the corresponding volume to your `docker-compose.yml` file:
Tinyauth’s core idea is to be a stateless application however, OpenID Connect requires persistence for sessions and keys. Everything is stored in the `/data` directory so, if you are using Docker, add the corresponding volume to your `docker-compose.yml` file:

```yaml
services:
Expand All @@ -76,6 +103,12 @@ You also need to specify the paths where the public and private keys are stored.

Lastly, for the OIDC server to work, HTTPS is **required** on the app URL, which will become the issuer URL. You can use a self‑signed certificate or a certificate from a trusted CA.

:::tip
In case you are planning to use Tinyauth as a standalone OpenID Connect provider, you can use
`TINYAUTH_AUTH_SUBDOMAINSENABLED=false` to disable support for wildcard cookies and increase
security. By disabling wildcard cookies, the forward-auth middleware will ***not*** work.
:::

## Creating OIDC Clients

To create an OIDC client, use the `oidc create` command. For example:
Expand Down
108 changes: 108 additions & 0 deletions src/content/docs/docs/guides/tailscale.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
title: Tailscale Authentication
description: Use your Tailscale connection to automatically log in to Tinyauth.
---

Tinyauth has support for detecting your Tailscale connection and automatically logging you in with
your Tailscale identity. This is made possible using the Tailscale API.

## Requirements

- A Tailscale account
- A Tinyauth instance

:::warning
You will need your proxy to correctly forward the client IP to Tinyauth for the Tailscale detection
to work. This differs from proxy to proxy, but usually you will need your proxy container to run
with `network_mode: host` in Docker.
:::

### K3S

In case you are using K3S (and possibly other Kubernetes deployments that use Traefik+MetalLB) you can use
the following Helm chart config for Traefik to forward the correct client IP to your applications (including
Tinyauth):

```yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik-config
namespace: kube-system
spec:
valuesContent: |-
service:
spec:
externalTrafficPolicy: Local

entryPoints:
web:
address: ':80'
forwardedHeaders:
trustedIPs:
- 10.42.0.0/24
websecure:
address: ':443'
forwardedHeaders:
trustedIPs:
- 10.42.0.0/24
```

You can check if Tinyauth is receiving the correct client IP by visiting it and checking the
`client_ip` section in the info logs.

## Get the Tailscale API token

Before configuring Tinyauth, you need to obtain your Tailnet ID and an API token from Tailscale. This can be
done by visiting the Tailscale [admin console](https://login.tailscale.com/admin/settings/general). The Tailnet
ID is the first thing you see in the page.

![Tailscale Settings](/screenshots/tailscale/tailscale_settings.png)

:::note
While you can use the Legacy Tailnet ID, it is recommended to use the new random one.
:::

Then, you can generate an API token in the [keys](https://login.tailscale.com/admin/settings/keys) page.

![Tailscale keys page](/screenshots/tailscale/tailscale_keys.png)

There click the **Generate access token** button, give it a name and click **Generate access token** again.
You should then be greeted by the following page.

![Tailscale API tokens](/screenshots/tailscale/tailscale_api_token.png)

Make sure to note down your Tailnet ID and the new API token as we will need them in the next part.

## Configure Tinyauth

With your Tailnet ID and API token you can configure Tinyauth in the following way:

```yaml
services:
tinyauth:
environment:
- TINYAUTH_TAILSCALE_ENABLED=true
- TINYAUTH_TAILSCALE_APITOKEN=your-api-token # TINYAUTH_TAILSCALE_APITOKENFILE also supported
- TINYAUTH_TAILSCALE_TAILNET=your-tailnet-id
```

Tinyauth by default caches the user and device list for 5 minutes, you can reduce the cache duration with
`TINYAUTH_TAILSCALE_CACHEDURATION` (in seconds).

:::note
Tinyauth does ***not*** support serving on a Tailscale domain (like `tinyauth.funny-name.ts.net`). This is
because we would need the `tsnet` library to serve on Tailscale which adds a lot of unnecessary weight to the
binary (+20MB). Features requiring the `tsnet` library will ***not*** be added.
:::

Make sure to restart Tinyauth after updating the configuration.

## Usage

After restarting and assuming Tinyauth can get your client IP, you should see the following screen
when visiting Tinyauth to login:

![Tinyauth Tailscale Login](/screenshots/tailscale/tailscale_login.png)

After clicking **Continue with Tailscale**, authentication should proceed as normal.
Loading