287 lines
9.1 KiB
Markdown
287 lines
9.1 KiB
Markdown
---
|
|
title: TinyAuth
|
|
description: Install TinyAuth, a lightweight forward-auth proxy, and pair it with Pocket ID to add SSO login in front of your self-hosted apps.
|
|
---
|
|
|
|
|
|
:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}
|
|
# TinyAuth
|
|
|
|
::note
|
|
🎯 __Objectives:__
|
|
|
|
- Install TinyAuth
|
|
- Log in via [Pocket ID](/serveex/security/pocket-id) (OIDC)
|
|
- Protect an app behind Swag with forward-auth
|
|
::
|
|
|
|
[TinyAuth](https://tinyauth.app) is a small forward-auth proxy: a single login page that Swag can insert in front of any app before letting a request through, similar in spirit to [Authentik](/serveex/advanced/authentik)'s reverse-proxy mode, but without the rest of Authentik's identity-provider machinery.
|
|
|
|
It supports a simple local username/password login out of the box, and can also delegate login to an external OIDC provider. Here we'll use [Pocket ID](/serveex/security/pocket-id), so anyone visiting a protected app first authenticates with a passkey via Pocket ID, then gets forwarded through.
|
|
|
|
- [TinyAuth documentation](https://tinyauth.app/docs)
|
|
- [TinyAuth on GitHub](https://github.com/tinyauthapp/tinyauth)
|
|
|
|
::note
|
|
|
|
This guide assumes you've already installed [Pocket ID](/serveex/security/pocket-id). You can skip the Pocket ID sections below and use TinyAuth with just a local username/password instead.
|
|
::
|
|
|
|
## Installation
|
|
Folder structure:
|
|
```text [Directory tree]
|
|
root
|
|
└── docker
|
|
└── tinyauth
|
|
├── compose.yaml
|
|
├── .env
|
|
└── data
|
|
```
|
|
|
|
Create the data folder:
|
|
|
|
```bash [Terminal]
|
|
sudo mkdir -p /docker/tinyauth/data
|
|
```
|
|
|
|
Generate a password hash for your local account:
|
|
|
|
```bash [Terminal]
|
|
sudo docker run -i -t --rm ghcr.io/tinyauthapp/tinyauth:v5 user create --interactive
|
|
```
|
|
|
|
::note
|
|
|
|
Enable "Format for Docker" when prompted, so the generated hash is already escaped for use in a `.env` file.
|
|
::
|
|
|
|
Open Dockge, click `compose`, name the stack `tinyauth`, and add the following config:
|
|
|
|
```yaml [compose.yaml]
|
|
---
|
|
services:
|
|
tinyauth:
|
|
image: ghcr.io/tinyauthapp/tinyauth:v5
|
|
container_name: tinyauth
|
|
restart: unless-stopped
|
|
env_file:
|
|
|
|
- .env
|
|
volumes:
|
|
|
|
- /docker/tinyauth/data:/data
|
|
ports:
|
|
|
|
- 3000:3000
|
|
```
|
|
|
|
::tip
|
|
✨ Add the Watchtower label to automate updates:
|
|
|
|
```yaml [compose.yaml]
|
|
services:
|
|
tinyauth:
|
|
#...
|
|
labels:
|
|
|
|
- com.centurylinklabs.watchtower.enable=true
|
|
```
|
|
::
|
|
|
|
Fill in the `.env` file:
|
|
|
|
```properties [.env]
|
|
TINYAUTH_APPURL=https://tinyauth.mydomain.com
|
|
TINYAUTH_AUTH_USERS=
|
|
```
|
|
|
|
| Variable | Value | Example |
|
|
|----------|-------|---------|
|
|
| `TINYAUTH_APPURL`{lang=properties} | The public URL you'll use to reach TinyAuth (see exposure below) | `https://tinyauth.mydomain.com` |
|
|
| `TINYAUTH_AUTH_USERS`{lang=properties} | The hash generated above | `user:$$2a$$10$$UdLYoJ5lgPsC0RKq...` |
|
|
|
|
Deploy the stack. The local interface is available at `http://yourserverip:3000`.
|
|
|
|
## Exposing TinyAuth with Swag
|
|
TinyAuth needs its own subdomain: it's the page users land on before being forwarded to the app they actually want.
|
|
|
|
::note
|
|
|
|
We assume you have the subdomain `tinyauth.mydomain.com` with a `CNAME` pointing to `mydomain.com` in your [DNS zone](/general/networking/dns). And of course, [unless you use Cloudflare Zero Trust](/serveex/security/cloudflare), your box's port `443` must be forwarded to your server's port `443` in [NAT rules](/general/networking/nat).
|
|
::
|
|
|
|
Go to Dockge and edit SWAG's compose file by adding TinyAuth's network:
|
|
|
|
```yaml [compose.yaml]
|
|
services:
|
|
swag:
|
|
container_name: # ...
|
|
# ...
|
|
networks: # Attach container to custom network
|
|
# ...
|
|
|
|
- tinyauth # Name of the declared network
|
|
|
|
networks: # Define the custom network
|
|
# ...
|
|
tinyauth: # Declared network name
|
|
name: tinyauth_default # Actual external network name
|
|
external: true # Marks it as externally defined
|
|
```
|
|
|
|
Redeploy the stack and wait for SWAG to be fully operational.
|
|
|
|
::note
|
|
|
|
Here we assume the TinyAuth network name is `tinyauth_default`. You can check the connection by visiting SWAG's dashboard at `http://yourserverip:81`.
|
|
::
|
|
|
|
In the Swag folders, create the file `tinyauth.subdomain.conf`:
|
|
|
|
::tip{icon=""}
|
|
✨ __Tip:__ Use [File Browser](/serveex/files/file-browser) to navigate and edit files instead of using terminal commands.
|
|
::
|
|
|
|
```bash [Terminal]
|
|
sudo nano /docker/swag/config/nginx/proxy-confs/tinyauth.subdomain.conf
|
|
```
|
|
|
|
Paste the following configuration:
|
|
|
|
```nginx [tinyauth.subdomain.conf]
|
|
## Version 2023/12/19
|
|
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
server_name tinyauth.*;
|
|
|
|
include /config/nginx/ssl.conf;
|
|
|
|
client_max_body_size 0;
|
|
|
|
location / {
|
|
include /config/nginx/proxy.conf;
|
|
include /config/nginx/resolver.conf;
|
|
set $upstream_app tinyauth;
|
|
set $upstream_port 3000;
|
|
set $upstream_proto http;
|
|
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
|
}
|
|
}
|
|
```
|
|
|
|
Press :kbd{value="Ctrl+O"}, then :kbd{value="Enter"} to save, and :kbd{value="Ctrl+X"} to exit.
|
|
|
|
Wait a few minutes, then open `https://tinyauth.mydomain.com` in your browser and log in with the username/password you created above.
|
|
|
|
::caution
|
|
|
|
__If it fails:__ check your firewall rules.
|
|
::
|
|
|
|
## Connecting TinyAuth to Pocket ID
|
|
First, [register TinyAuth as an OIDC client in Pocket ID](/serveex/security/pocket-id#registering-an-oidc-client), using this callback URL:
|
|
|
|
```text
|
|
https://tinyauth.mydomain.com/api/oauth/callback/pocketid
|
|
```
|
|
|
|
Copy the __Client ID__ and __Client Secret__ Pocket ID gives you, then edit TinyAuth's `.env` file:
|
|
|
|
```bash [Terminal]
|
|
sudo nano /docker/tinyauth/.env
|
|
```
|
|
|
|
Add the following:
|
|
|
|
```properties [.env]
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_NAME=Pocket ID
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_CLIENTID=
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_CLIENTSECRET=
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_AUTHURL=https://id.mydomain.com/authorize
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_TOKENURL=https://id.mydomain.com/api/oidc/token
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_USERINFOURL=https://id.mydomain.com/api/oidc/userinfo
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_REDIRECTURL=https://tinyauth.mydomain.com/api/oauth/callback/pocketid
|
|
TINYAUTH_OAUTH_PROVIDERS_POCKETID_SCOPES=openid email profile
|
|
```
|
|
|
|
| Variable | Value |
|
|
|----------|-------|
|
|
| `CLIENTID`{lang=properties} | The client ID copied from Pocket ID |
|
|
| `CLIENTSECRET`{lang=properties} | The client secret copied from Pocket ID |
|
|
| `AUTHURL` / `TOKENURL` / `USERINFOURL`{lang=properties} | Pocket ID's public URL, with the paths shown above |
|
|
|
|
Press :kbd{value="Ctrl+O"}, then :kbd{value="Enter"} to save, and :kbd{value="Ctrl+X"} to exit.
|
|
|
|
Redeploy the TinyAuth stack. On your next visit to `https://tinyauth.mydomain.com`, you'll see a "Login with Pocket ID" option alongside the local login form.
|
|
|
|
::tip
|
|
✨ To skip straight to Pocket ID and hide the local login form, add `TINYAUTH_OAUTH_AUTOREDIRECT=pocketid` to the same `.env` file.
|
|
::
|
|
|
|
## Protecting an app via reverse proxy
|
|
Unlike Authentik, Swag doesn't ship a ready-made include file for TinyAuth, so we'll add the forward-auth check directly to the app's own `*.subdomain.conf`. We'll use Dockge as an example.
|
|
|
|
Open the file:
|
|
|
|
```bash [Terminal]
|
|
sudo nano /docker/swag/config/nginx/proxy-confs/dockge.subdomain.conf
|
|
```
|
|
|
|
Add an internal `/tinyauth` location, and reference it from the app's `location /` block with `auth_request`:
|
|
|
|
```nginx [dockge.subdomain.conf]{9-11,25}
|
|
server {
|
|
listen 443 ssl;
|
|
listen [::]:443 ssl;
|
|
|
|
server_name dockge.*;
|
|
|
|
include /config/nginx/ssl.conf;
|
|
|
|
client_max_body_size 0;
|
|
|
|
location /tinyauth {
|
|
internal;
|
|
proxy_pass http://tinyauth:3000/api/auth/nginx;
|
|
proxy_pass_request_body off;
|
|
proxy_set_header Content-Length "";
|
|
proxy_set_header X-Forwarded-Proto $scheme;
|
|
proxy_set_header X-Forwarded-Host $http_host;
|
|
proxy_set_header X-Forwarded-Uri $request_uri;
|
|
}
|
|
|
|
location @tinyauth_login {
|
|
return 302 https://tinyauth.mydomain.com/login?redirect_uri=$scheme://$http_host$request_uri;
|
|
}
|
|
|
|
location / {
|
|
auth_request /tinyauth;
|
|
error_page 401 = @tinyauth_login;
|
|
|
|
include /config/nginx/proxy.conf;
|
|
include /config/nginx/resolver.conf;
|
|
set $upstream_app dockge;
|
|
set $upstream_port 5001;
|
|
set $upstream_proto http;
|
|
proxy_pass $upstream_proto://$upstream_app:$upstream_port;
|
|
}
|
|
}
|
|
```
|
|
|
|
::note
|
|
|
|
The `location /tinyauth` block must be able to reach the TinyAuth container by its Docker name (`tinyauth` here). Add TinyAuth's network to this stack's compose file the same way you did [for Swag](/serveex/security/tinyauth#exposing-tinyauth-with-swag) if it isn't already attached.
|
|
::
|
|
|
|
Press :kbd{value="Ctrl+O"}, then :kbd{value="Enter"} to save, and :kbd{value="Ctrl+X"} to exit.
|
|
|
|
That's it! Visiting `https://dockge.mydomain.com` now redirects to TinyAuth first. Repeat this `location /tinyauth` / `auth_request` pattern in any other app's `*.subdomain.conf` to protect it the same way.
|
|
|
|
::note
|
|
|
|
Repeat this process for each app you want to protect (unless it has native OIDC support, in which case you can point it directly at Pocket ID instead).
|
|
::
|