Introduction Link to heading

If you’re running multiple applications behind Traefik, you probably want a login screen. This guide shows how to set up Pocket ID (identity provider) and TinyAuth (forward auth proxy) for centralized authentication.

Why this approach:

  • One login for all apps - Users log in once, access everything
  • Works with any app - OIDC apps authenticate directly; others get protected by TinyAuth
  • No code changes - All configuration via Docker labels
  • Centralized user management - All users in Pocket ID

How It Works Link to heading

Pocket ID is your identity provider—a centralized login server where all your users are stored.

TinyAuth is a “forward auth” proxy that intercepts requests and checks for valid login sessions. If no session exists, it redirects to Pocket ID. This works with any app, even those without built-in auth.

OIDC-capable apps skip TinyAuth and authenticate directly with Pocket ID.


Setup Guide Link to heading

If the above approach sounds good, here’s how to implement it.

Prerequisites Link to heading

  • Traefik already running and routing your applications - This is the foundation. Both Pocket ID and TinyAuth integrate with Traefik via labels and middleware.
  • HTTPS/TLS configured in Traefik - Both Pocket ID and TinyAuth must be served over HTTPS. Ensure your Traefik instance has TLS certificates configured (via Let’s Encrypt, self-signed, or your cert provider).
  • A domain name with subdomains (e.g., id.example.com, auth.example.com)
  • TinyAuth must run on the same Docker network as Traefik - TinyAuth acts as a Traefik middleware, so it needs to communicate with Traefik via your shared Docker network (whatever network your Traefik instance uses—e.g., traefik, proxy, backend, etc.). Both the compose files reference this as the traefik network, but you’ll replace it with your actual network name.
  • Pocket ID can run anywhere (same host or a different server—just needs to be accessible by domain)

Step 1: Deploy Pocket ID Link to heading

Pocket ID is your identity provider. It stores users and handles logins.

Create a new directory and set up the compose files. Start by creating the directory structure:

mkdir -p idp

Then create these files:

File: idp/docker-compose.yml

services:
  pocket-id:
    image: ghcr.io/pocket-id/pocket-id:v1
    restart: unless-stopped
    env_file: .env
    volumes:
      - "./data:/app/data"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.pocket-id.rule=Host(`id.example.com`)"
      - "traefik.http.services.pocket-id.loadbalancer.server.port=1411"
    networks:
      traefik:

networks:
  traefik:
    external: true

File: idp/.env

# The external HTTPS URL where Pocket ID will be accessible
APP_URL=https://id.example.com

# Encryption key for Pocket ID's database
# Generate a key with: openssl rand -base64 32
ENCRYPTION_KEY=<YOUR_GENERATED_KEY>

# Trust X-Forwarded-* headers from Traefik
# This is required since Traefik is the reverse proxy
TRUST_PROXY=true

To generate the ENCRYPTION_KEY, run:

openssl rand -base64 32

Then paste the output into your .env file.

Step 2: Deploy TinyAuth Link to heading

TinyAuth is the authentication gateway. It checks if users are logged in and guards your apps.

Create a separate compose file for TinyAuth (you’ll add the .env file in Step 3). Start by creating the directory:

mkdir -p tinyauth

Alternatively, you can add this service directly to your existing reverse-proxy/compose.yaml file.

File: tinyauth/docker-compose.yml

services:
  tinyauth:
    image: ghcr.io/steveiliop56/tinyauth:v4
    restart: unless-stopped
    environment:
      # TinyAuth's own URL
      - APP_URL=https://auth.example.com
      
      # Pocket ID OIDC client credentials
      # (obtain these from Pocket ID admin panel)
      - PROVIDERS_POCKETID_CLIENT_ID=${POCKETID_CLIENT_ID}
      - PROVIDERS_POCKETID_CLIENT_SECRET=${POCKETID_CLIENT_SECRET}
      
      # Pocket ID OIDC endpoints
      - PROVIDERS_POCKETID_AUTH_URL=${POCKETID_URL}/authorize
      - PROVIDERS_POCKETID_TOKEN_URL=${POCKETID_URL}/api/oidc/token
      - PROVIDERS_POCKETID_USER_INFO_URL=${POCKETID_URL}/api/oidc/userinfo
      - PROVIDERS_POCKETID_REDIRECT_URL=https://auth.example.com/api/oauth/callback/pocketid
      
      # Scopes to request from Pocket ID
      - PROVIDERS_POCKETID_SCOPES=openid email profile groups
      
      # Human-readable provider name
      - PROVIDERS_POCKETID_NAME=Pocket ID
      
      # Auto-redirect to Pocket ID if no provider is specified
      - OAUTH_AUTO_REDIRECT=pocketid
    
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.tinyauth.rule=Host(`auth.example.com`)"
      # Tell Traefik where to reach TinyAuth's auth endpoint
      - "traefik.http.middlewares.tinyauth.forwardauth.address=http://tinyauth:3000/api/auth/traefik"
    
    volumes:
      - tinyauth:/data
    
    networks:
      traefik:

volumes:
  tinyauth:

networks:
  traefik:
    external: true

Step 3: Configure Pocket ID and TinyAuth to Work Together Link to heading

There are five tasks here. The first three are required and sequential: initialize Pocket ID, create credentials for TinyAuth, then configure TinyAuth. Setting up groups is optional but useful for access control later. Finally, test the connection.

Initialize Pocket ID Link to heading

  1. Start Pocket ID by running docker compose up -d in the idp/ directory
  2. Wait 10-15 seconds for the container to start, then visit https://id.example.com/setup in your browser
  3. Create an admin account (this is your first user and admin for Pocket ID)
  4. Log in with the admin account

Create a Pocket ID OIDC Client for TinyAuth Link to heading

Once logged in:

  1. Go to Admin PanelOIDC Clients (or OAuth Clients)
  2. Click Create New Client or Add Client
  3. Fill in the following:
    • Client Name: TinyAuth (or any name you prefer)
    • Redirect URI: https://auth.example.com/api/oauth/callback/pocketid (this must match exactly)
    • Allowed Scopes: Select openid, email, profile, and groups
  4. Click Save or Create
  5. Copy the Client ID and Client Secret (save these for the next step)
  6. Verify the client appears in your OIDC Clients list

Configure TinyAuth with Pocket ID Credentials Link to heading

Create a .env file in your tinyauth/ directory with these credentials:

POCKETID_URL=https://id.example.com
POCKETID_CLIENT_ID=<YOUR_CLIENT_ID>
POCKETID_CLIENT_SECRET=<YOUR_CLIENT_SECRET>

Now start TinyAuth by running docker compose up -d in the tinyauth/ directory.

(Optional) Set Up Groups in Pocket ID Link to heading

If you want to restrict access to apps by group membership, set up groups now. First add users to Pocket ID (in Admin PanelUsers), then:

  1. Go to Admin PanelGroups (or Teams)
  2. Create groups like staff, admin, developers, etc.
  3. Add your users to the appropriate groups

You’ll reference these group names in TinyAuth access control labels later.

Test the Connection Link to heading

Visit https://auth.example.com in your browser. You should see a login screen with a “Login with Pocket ID” button. Try logging in with your admin account. If successful, you’ll see your username, email, and group memberships displayed—this confirms TinyAuth is correctly connected to Pocket ID.

Step 4: Protect Your Applications Link to heading

You have two options depending on whether your app supports OIDC:

Option A: Apps with OIDC Support Link to heading

Apps like Nextcloud, Gitea, or Bookstack can authenticate directly with Pocket ID. No TinyAuth needed. When a user accesses the app, they’re redirected to Pocket ID to log in, then redirected back to the app—all handled internally by the app.

  1. Register the app as an OIDC client in Pocket ID
  2. Configure the app with the Pocket ID OIDC settings
  3. Users log in directly through the app’s login form

(See your app’s documentation for OIDC setup instructions)

Option B: Apps Without OIDC Support Link to heading

For apps that don’t support OIDC (most simple apps), use TinyAuth by adding the middleware label to Docker:

services:
  myapp:
    image: example/myapp
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.rule=Host(`myapp.example.com`)"
      - "traefik.http.routers.myapp.middlewares=tinyauth@docker"  # ← Add this for non-OIDC apps

networks:
  traefik:
    external: true

Users will be required to log in before accessing myapp.example.com.

Access Control: Restricting Who Can Access an App Link to heading

By default, anyone who logs in to Pocket ID can access TinyAuth-protected apps. If you want to restrict access, choose one of the methods below:

Which method should you use?

  • Group-based restriction (recommended): Use this if you set up groups in Step 3. It scales well as your homelab grows—just manage group membership in Pocket ID. This is the best approach for most setups.
  • Email-based restriction: Use this only for quick, one-off access control (1-2 people per app). For anything beyond that, groups are easier to maintain.

Restrict by Pocket ID Group (recommended):

services:
  admin-dashboard:
    image: example/admin
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.admin.rule=Host(`admin.example.com`)"
      - "traefik.http.routers.admin.middlewares=tinyauth@docker"
      - "tinyauth.apps.admin.oauth.groups=staff"  # Only staff group

networks:
  traefik:
    external: true

Restrict by Email Address:

In the admin-dashboard service’s labels: array, replace the tinyauth.apps.admin.oauth.groups=staff line with:

See the TinyAuth Access Controls documentation for more options (IP-based, path-based, etc.).

Apps with Built-in HTTP Basic Auth Link to heading

Some services (like Prometheus, Grafana, or Servarr apps) have built-in HTTP Basic Auth with no way to disable it. When protecting these with TinyAuth, automatically inject credentials so authenticated users don’t face a separate basic auth prompt:

services:
  prometheus:
    image: prom/prometheus
    networks:
      - traefik
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.prometheus.rule=Host(`prometheus.example.com`)"
      - "traefik.http.routers.prometheus.middlewares=tinyauth@docker"
      # TinyAuth injects these credentials automatically
      - "tinyauth.apps.prometheus.response.basicauth.username=promuser"
      - "tinyauth.apps.prometheus.response.basicauth.password=prompass123"

networks:
  traefik:
    external: true

When a user logs in through TinyAuth and accesses the app, TinyAuth automatically injects the Basic Auth credentials. The app receives the request as if the user had already entered the username and password.

See the TinyAuth Docker Labels Reference for more options.

Troubleshooting Link to heading

Pocket ID Won’t Start Link to heading

Check the logs:

cd idp/
docker compose logs pocket-id

Common issues:

  • Port 1411 already in use: Change the port in the Traefik label loadbalancer.server.port to an available port
  • Data directory permission denied: Docker should auto-create ./data, but if you see permission errors, run mkdir data && chmod 755 data
  • Invalid ENCRYPTION_KEY: Verify you generated it with openssl rand -base64 32

TinyAuth Login Fails or Redirects in Circles Link to heading

This usually means TinyAuth can’t reach Pocket ID:

  1. Verify POCKETID_URL in tinyauth/.env is accessible from your browser (e.g., https://id.example.com)
  2. Check TinyAuth logs:
    cd tinyauth/
    docker compose logs tinyauth
    
  3. Verify the Redirect URI in Pocket ID matches exactly: https://auth.example.com/api/oauth/callback/pocketid
  4. Double-check that POCKETID_CLIENT_ID and POCKETID_CLIENT_SECRET are correct in tinyauth/.env

Group Restrictions Aren’t Working Link to heading

  1. Verify the groups scope is in PROVIDERS_POCKETID_SCOPES in TinyAuth’s compose file
  2. Confirm users are actually assigned to the group in Pocket ID
  3. Check the label syntax: tinyauth.apps.admin.oauth.groups=staff (not groups.allow or other variants)
  4. Restart TinyAuth after changing labels: docker compose restart in the tinyauth/ directory

Advanced Options Link to heading

Local User Accounts (Alternative to OIDC) Link to heading

Not everyone wants to set up a full OIDC provider. TinyAuth also supports local user accounts.

To create a local user, use the TinyAuth container:

# Create a local user
docker compose -f tinyauth/docker-compose.yml exec tinyauth tinyauth create-user
# Username: john
# Password: [enter password]
# Output: john:$2y$12$abcdef1234567890abcdef1234567890abcdef1234567890abcdef

Copy the entire output (username:hash) to your tinyauth/.env file:

USERS=john:$2y$12$abcdef1234567890abcdef1234567890abcdef1234567890abcdef,jane:$2y$12$1234567890abcdef1234567890abcdef1234567890abcdef123456

Then restart TinyAuth by running docker compose up -d in the tinyauth/ directory. You can mix local users and OIDC users in the same system.

Security Considerations Link to heading

Back Up Your Data Link to heading

Pocket ID stores all user accounts and configuration in the ./data directory. Back this up regularly:

# Run this in your idp/ directory
cp -r data data.backup.$(date +%Y-%m-%d)

TinyAuth also stores session data in its Docker volume (tinyauth:/data). While users can simply log in again if needed, you may want to back this up too. Set up automated backups to a separate server or cloud storage for both.

Protect Your .env Files Link to heading

Your .env files contain sensitive secrets:

  • ENCRYPTION_KEY (Pocket ID)
  • POCKETID_CLIENT_SECRET (TinyAuth)

Never commit these to version control. Add to .gitignore:

echo ".env" >> .gitignore
echo ".env.local" >> .gitignore

HTTPS Required Link to heading

Both Pocket ID and TinyAuth must be served over HTTPS. Your reverse proxy (Traefik) should handle this automatically if you’ve set up TLS certificates (via Let’s Encrypt or similar).

Limit User Access Link to heading

Use TinyAuth’s access control features (user allow-lists, group restrictions) to limit which users can access each application. See the “Restricting Who Can Access an App” section under Step 4 for examples.

Keep Containers Updated Link to heading

Periodically update your container images:

docker compose pull
docker compose up -d

Conclusion Link to heading

With Pocket ID and TinyAuth, adding authentication to your routes is simple:

  1. Deploy Pocket ID once (stores all your users)
  2. Deploy TinyAuth once (guards your apps)
  3. Add the TinyAuth middleware label to any app you want to protect

No code changes needed. No complex configuration. Just Docker labels.

For more details, see:

Pocket ID

TinyAuth