--- 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). ::