---
title: TinyAuth
description: Installer TinyAuth, un proxy de forward-auth léger, et l'associer à Pocket ID pour ajouter une connexion SSO devant vos applications auto-hébergées. Protéger votre application derrière Swag avec le forward-auth.
---


:ellipsis{left=0px width=40rem top=10rem blur=140px zIndex=60}

[TinyAuth](https://tinyauth.app) est une application qui permet de forcer une authentification avant d'accéder à un servoce : une page de connexion que Swag peut insérer devant n'importe quelle application avant de laisser passer une requête, en vérifiant si le visiteur est authentifié avant de le rediriger.

![tinyauth](/img/serveex/tinyauth.png)

Nativement il gère une simple connexion locale identifiant/mot de passe, c'est ce que nous mettrons en place ici. Il peut aussi déléguer la connexion à un fournisseur OIDC externe comme [Pocket ID](/serveex/security/pocket-id), de sorte que quiconque visite une application protégée s'authentifie avec une passkey via Pocket ID puis est redirigé : installez Pocket ID ensuite et suivez [son tutoriel](/serveex/security/pocket-id#connecting-pocket-id-to-tinyauth) pour relier les deux.

- [Documentation de TinyAuth](https://tinyauth.app/docs)
- [TinyAuth sur GitHub](https://github.com/tinyauthapp/tinyauth)

## Installation

::file-tree
---
tree:
  /:
    - srv:
      - docker:
        - tinyauth:
          - compose.yaml
          - .env
          - data/
---
::

::steps{level="3"}
### Créer le dossier de données

```bash [Terminal]
sudo mkdir -p /srv/docker/tinyauth/data
```

### Générer un hash de mot de passe

```bash [Terminal]
sudo docker run -i -t --rm ghcr.io/tinyauthapp/tinyauth:v5 user create --interactive
```

::note

Activez « Format for Docker » quand la question est posée, ainsi le hash généré est déjà échappé pour être utilisé dans un fichier `.env`.
::

### Déployer la stack

Ouvrez Dockge, cliquez sur `compose`, nommez la stack `tinyauth`, et ajoutez la configuration suivante :

```yaml [compose.yaml]
---
services:
  tinyauth:
    image: ghcr.io/tinyauthapp/tinyauth:v5
    container_name: tinyauth
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - /srv/docker/tinyauth/data:/data
    ports:
      - 3000:3000
```

::tip{icon=""}
✨ Ajoutez le label Watchtower pour automatiser les mises à jour :

```yaml [compose.yaml]
---
services:
  tinyauth:
    #...
    labels:
      - com.centurylinklabs.watchtower.enable=true
```
::

### Renseigner vos variables d'environnement

Remplissez le fichier `.env` :

```properties [.env]
TINYAUTH_APPURL=https://tinyauth.mondomaine.fr
TINYAUTH_AUTH_USERS=
```

| Variable | Valeur | Exemple |
|----------|-------|---------|
| `TINYAUTH_APPURL`{lang=properties} | L'URL publique par laquelle vous joindrez TinyAuth (voir l'exposition plus bas) | `https://tinyauth.mondomaine.fr` |
| `TINYAUTH_AUTH_USERS`{lang=properties} | Le hash généré ci-dessus | `user:$$2a$$10$$UdLYoJ5lgPsC0RKq...` |

Déployez la stack. L'interface locale est disponible sur `http://ipdevotreserveur:3000`.

### Terminé !
::

## Activer l'authentification à deux facteurs
TinyAuth peut exiger un code TOTP issu d'une application d'authentification (Google Authenticator, Aegis...) en plus du mot de passe local, utilisateur par utilisateur. C'est une propriété de l'entrée utilisateur elle-même, pas une option de l'interface web.

::steps{level="3"}
### Générer un secret TOTP

```bash [Terminal]
sudo docker run -i -t --rm ghcr.io/tinyauthapp/tinyauth:v5 totp generate --interactive
```

Saisissez la paire `username:hash` générée lors de l'installation. TinyAuth affiche un QR code à scanner avec votre application d'authentification, puis produit la chaîne de connexion mise à jour sous la forme `username:hash:secret`.

::note

`docker run` comme `docker exec` ont besoin des options `-it` ici : la commande est interactive et affiche le QR code dans le terminal, ce qui nécessite un TTY (et une fenêtre assez large) pour s'afficher correctement.
::

### Mettre à jour votre variable d'environnement

Remplacez l'entrée de cet utilisateur dans `TINYAUTH_AUTH_USERS` par la nouvelle chaîne `username:hash:secret`, puis redéployez la stack.

::tip{icon=""}
✨ __Astuce :__ vérifiez que tout fonctionne avant de compter dessus :

```bash [Terminal]
sudo docker run -i -t --rm ghcr.io/tinyauthapp/tinyauth:v5 user verify --interactive
```

Elle redemande l'identifiant, le mot de passe et le code à 6 chiffres du moment.
::

### Terminé !
::

À partir de maintenant, cet utilisateur a besoin à la fois de son mot de passe et d'un code valide de son application d'authentification pour se connecter.

## Exposer TinyAuth avec Swag
TinyAuth a besoin de son propre sous-domaine : c'est la page sur laquelle les utilisateurs arrivent avant d'être redirigés vers l'application qu'ils veulent réellement.

::note

Nous partons du principe que vous avez le sous-domaine `tinyauth.mondomaine.fr` avec un `CNAME` pointant vers `mondomaine.fr` dans votre [zone DNS](/general/networking/dns). Et bien sûr, [à moins d'utiliser Cloudflare Zero Trust](/serveex/security/cloudflare), le port `443` de votre box doit être redirigé vers le port `443` de votre serveur dans les [règles NAT](/general/networking/nat).
::

::steps{level="3"}
### Ajouter le réseau de TinyAuth à SWAG

Allez dans Dockge et modifiez le fichier compose de SWAG en y ajoutant le réseau de TinyAuth :

```yaml [compose.yaml]
---
services:
  swag:
     container_name: # ...
      # ... 
     networks:               # Rattache le conteneur au réseau personnalisé 
      # ...           
      - tinyauth             # Nom du réseau déclaré

networks:                    # Définit le réseau personnalisé
  # ...
  tinyauth:                  # Nom du réseau déclaré
    name: tinyauth_default   # Nom réel du réseau externe
    external: true           # Le marque comme défini à l'extérieur
```

Redéployez la stack et attendez que SWAG soit pleinement opérationnel.

::note

Nous partons ici du principe que le nom du réseau de TinyAuth est `tinyauth_default`. Vous pouvez vérifier la connexion en visitant le tableau de bord de SWAG sur `http://ipdevotreserveur:81`.
::

### Créer le fichier subdomain.conf

Dans les dossiers de Swag, créez le fichier `tinyauth.subdomain.conf` :

::tip{icon="" to="/serveex/files/file-browser-quantum"}
✨ __Astuce :__ utilisez **File Browser Quantum** pour naviguer et modifier les fichiers plutôt que des commandes dans le terminal.
::

```bash [Terminal]
sudo nano /srv/docker/swag/config/nginx/proxy-confs/tinyauth.subdomain.conf
```

Collez la configuration suivante :

```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;
    }
}
```

Appuyez sur :kbd{value="Ctrl+O"}, puis :kbd{value="Enter"} pour enregistrer, et :kbd{value="Ctrl+X"} pour quitter.

### Visiter votre nouveau sous-domaine

Attendez quelques minutes, puis ouvrez `https://tinyauth.mondomaine.fr` dans votre navigateur et connectez-vous avec l'identifiant et le mot de passe créés plus haut.

::caution

__Si ça ne marche pas :__ vérifiez les règles de votre pare-feu.
::

### Terminé !
::

## Protéger une application via le reverse proxy
Swag ne fournit pas de fichier d'inclusion tout prêt pour TinyAuth, nous ajouterons donc la vérification forward-auth directement dans le `*.subdomain.conf` de l'application. Nous prendrons Dockge en exemple.

::steps{level="3"}
### Ouvrir le fichier subdomain.conf de l'application

```bash [Terminal]
sudo nano /srv/docker/swag/config/nginx/proxy-confs/dockge.subdomain.conf
```

### Ajouter la vérification forward-auth

Ajoutez un bloc `location /tinyauth` interne, et référencez-le depuis le bloc `location /` de l'application avec `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.mondomaine.fr/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{to="/serveex/security/tinyauth#exposing-tinyauth-with-swag"}

Le bloc `location /tinyauth` s'exécute dans le conteneur de SWAG lui-même, SWAG doit donc être sur le réseau Docker de TinyAuth pour le joindre par son nom (`tinyauth` ici). Cela devrait déjà être en place depuis **l'exposition de TinyAuth**. Si vous rencontrez une erreur, revérifiez que le fichier compose de SWAG a toujours ce réseau rattaché.
::

Appuyez sur :kbd{value="Ctrl+O"}, puis :kbd{value="Enter"} pour enregistrer, et :kbd{value="Ctrl+X"} pour quitter.

### Terminé !
::

Et voilà ! Visiter `https://dockge.mondomaine.fr` redirige désormais d'abord vers TinyAuth. Répétez ce motif `location /tinyauth` / `auth_request` dans le `*.subdomain.conf` de n'importe quelle autre application pour la protéger de la même façon.

::note

Répétez cette procédure pour chaque application que vous voulez protéger (sauf si elle gère nativement OIDC, auquel cas vous pouvez la pointer directement sur Pocket ID).
::

## Laisser certains chemins publics
Il arrive qu'on veuille verrouiller l'essentiel d'une application derrière TinyAuth, mais laisser une poignée de chemins ouverts, par exemple une page de statut publique, ou les endpoints d'API sur lesquels une application mobile s'appuie. Contrairement à Authentik, TinyAuth n'a pas de réglage intégré de « chemins authentifiés » pour ça : c'est un simple problème nginx, et il se résout avec le système de correspondance de `location` de nginx.

Un bloc `location` en expression régulière est toujours prioritaire sur le bloc `location /` simple, quel que soit celui qui apparaît en premier dans le fichier. Tout chemin correspondant à une location en regex que vous définissez exécute donc son propre `proxy_pass`, sans jamais atteindre la ligne `auth_request /tinyauth;` du `location /`.

Par exemple, pour laisser ouverte la page de statut publique d'Uptime-Kuma et ses ressources tout en protégeant le reste :

```nginx [dockge.subdomain.conf]{9-16}
server {
    listen 443 ssl;
    listen [::]:443 ssl;

    server_name stats.*;

    include /config/nginx/ssl.conf;

    location ~ ^/(status|assets|icon\.svg|api|upload|metrics) {
        include /config/nginx/proxy.conf;
        include /config/nginx/resolver.conf;
        set $upstream_app uptime-kuma;
        set $upstream_port 3001;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }

    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.mondomaine.fr/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 uptime-kuma;
        set $upstream_port 3001;
        set $upstream_proto http;
        proxy_pass $upstream_proto://$upstream_app:$upstream_port;
    }
}
```

::note

Adaptez la liste des chemins exclus à ce dont l'application que vous protégez a réellement besoin en public. Ne laissez jamais un chemin d'administration ou de réglages dans cette liste, uniquement ce que l'application elle-même documente comme sûr à exposer sans authentification.
::
