diff --git a/docs/install/panel-security/tinyAuth-for-nginx.md b/docs/install/panel-security/tinyAuth-for-nginx.md index 28a2201..405a17d 100644 --- a/docs/install/panel-security/tinyAuth-for-nginx.md +++ b/docs/install/panel-security/tinyAuth-for-nginx.md @@ -4,80 +4,107 @@ slug: /security/tinyauth-for-nginx title: TinyAuth for Nginx --- -TinyAuth is the simplest way to protect your apps with a login screen +TinyAuth is a lightweight authentication middleware that protects your applications with a login screen. + +This guide uses the Remnawave TinyAuth image based on TinyAuth v5.0.7: + +```text +ghcr.io/maposia/remnawave-tinyauth:v5 +``` + +:::caution Breaking changes in v5 + +TinyAuth v5 uses a new configuration format. Environment variables such as `PORT`, `APP_URL`, `USERS`, and `USERS_FILE` must be renamed before upgrading. See [Breaking changes: v4 to v5](#breaking-changes-v4-to-v5) before replacing a running v4 container. + +::: ## Installation -Now it's time to add TinyAuth to your existing docker-compose.yml file or create a new one. If creating a new file, don't forget to add the `services:` section. The configuration can be as simple as this: +Add TinyAuth to your existing `docker-compose.yml` file. If you are creating a new file, include the `services:` section. ```yaml title="docker-compose.yml" -tinyauth: +services: + tinyauth: container_name: tinyauth hostname: tinyauth - image: ghcr.io/maposia/remnawave-tinyauth:latest - restart: always + image: ghcr.io/maposia/remnawave-tinyauth:v5 + restart: unless-stopped ports: - - '127.0.0.1:3002:3002' + - "127.0.0.1:3002:3002" networks: - remnawave-network environment: - - PORT=3002 - - APP_URL=https://tinyauth.example.com - - USERS=your-username-password-hash - - SECRET=some-random-32-chars-string + - TINYAUTH_SERVER_PORT=3002 + - TINYAUTH_APPURL=https://tinyauth.example.com + - TINYAUTH_AUTH_USERS=your-username-password-hash + - TINYAUTH_AUTH_SECURECOOKIE=true + - TINYAUTH_DATABASE_PATH=/data/tinyauth.db volumes: - ./data:/data - # To get USERS and SECRET read below - ``` -## Configuring variables +Replace `tinyauth.example.com` with the domain where TinyAuth will be exposed. -To generate your first hash for user, use the following command +:::warning -```bash -docker run -it --rm ghcr.io/maposia/remnawave-tinyauth:latest user create --interactive -``` - -After running, you will be prompted to enter a username and password. You will also need to select -output format-docker - -After that, you will see a message that the user has been created and a username:passwordHash will appear which needs to be used in docker-compose.yml in the env USERS - -:::info - -After you start the container, you can generate a hash for a user using the running tinyAuth container with the command. - -```bash -docker exec -it tinyauth ./tinyauth user create --interactive -``` +Do not publish port `3002` on all interfaces. Binding it to `127.0.0.1` ensures that only Nginx on the same host can access TinyAuth directly. ::: -:::info +## Creating a user -Every configuration option that has a `FILE` equivalent (e.g. `USERS` and `USERS_FILE`), then the file can be used instead of the environment variable. +Generate the first user with the v5 image: -`USERS=` comma separated list of tinyauth users.*(required)* +```bash +docker run -it --rm ghcr.io/maposia/remnawave-tinyauth:v5 user create --interactive +``` -`USERS_FILE=` A file containing a list of tinyauth users. +Enter a username and password, then select the Docker output format. The command returns a value in the following format: -All environment variables you can see on official documentation https://tinyauth.app/docs/reference/configuration +```text +username:passwordHash +``` -::: +Use this value for `TINYAUTH_AUTH_USERS` in `docker-compose.yml`. -To generate the SECRET environment variable using openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32. +After TinyAuth is running, you can create another user with: -## Configure +```bash +docker exec -it tinyauth tinyauth user create --interactive +``` -Next, you need to configure nginx.conf to protect the required path. +Multiple users can be provided as a comma-separated list: + +```yaml +environment: + - TINYAUTH_AUTH_USERS=user1:passwordHash1,user2:passwordHash2 +``` + +To load users from a file instead, use `TINYAUTH_AUTH_USERSFILE`: + +```yaml +environment: + - TINYAUTH_AUTH_USERSFILE=/run/secrets/tinyauth-users +``` + +The old `SECRET` environment variable is not used by TinyAuth v5 and must be removed. + +See the [official configuration reference](https://tinyauth.app/docs/reference/configuration/) for all supported options. + +## Configuring Nginx + +First, configure the TinyAuth upstream: ```nginx title="nginx.conf" upstream tinyauth { server 127.0.0.1:3002; + keepalive 16; } +``` +Expose the TinyAuth login interface on its own domain: +```nginx title="nginx.conf" server { server_name tinyauth.example.com; listen 443 ssl; @@ -97,9 +124,13 @@ server { proxy_set_header X-Forwarded-Port $server_port; proxy_send_timeout 60s; proxy_read_timeout 60s; - } + } } +``` +Add the following configuration to every application that should be protected: + +```nginx title="nginx.conf" server { server_name panel.remnawave.com; listen 443 ssl; @@ -110,8 +141,9 @@ server { ssl_trusted_certificate "/etc/nginx/ssl/panel.remnawave.com/fullchain.pem"; location / { - auth_request /tinyauth; - error_page 401 = @tinyauth_login; + auth_request /tinyauth; + auth_request_set $tinyauth_location $upstream_http_x_tinyauth_location; + error_page 401 403 =302 $tinyauth_location; proxy_http_version 1.1; proxy_pass http://remnawave; @@ -121,57 +153,153 @@ server { proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Port $server_port; + + # Preserve credentials intended for the protected application. + proxy_set_header Authorization $http_authorization; + + # TinyAuth credentials must not be forwarded to the application. + proxy_set_header X-Api-Key ""; + proxy_send_timeout 60s; proxy_read_timeout 60s; } -location /tinyauth { - proxy_pass http://tinyauth/api/auth/nginx; + location = /tinyauth { + internal; + proxy_pass http://tinyauth/api/auth/nginx; + proxy_pass_request_body off; + proxy_set_header Content-Length ""; - 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; + # Always overwrite forwarded values instead of trusting client headers. + proxy_set_header X-Forwarded-Proto $scheme; + proxy_set_header X-Forwarded-Host $host; + proxy_set_header X-Forwarded-Uri $request_uri; + + # X-Api-Key authenticates the request in TinyAuth while the original + # Authorization header remains available to the protected application. + proxy_set_header X-Api-Key $http_x_api_key; + proxy_set_header Authorization $http_authorization; + } } - - location @tinyauth_login { - return 302 https://tinyauth.example.com/login?redirect_uri=$scheme://$http_host$request_uri; -} - -#Make sure to replace the http://tinyauth.example.com with your own app URL ``` -## Running the container +TinyAuth v5 returns the appropriate login, unauthorized, or error URL through the `X-Tinyauth-Location` response header. Nginx stores it in `$tinyauth_location` and uses it for the redirect, so a hardcoded `/login?redirect_uri=...` location is no longer required. -After that, restart nginx and launch tinyAuth +Validate and reload Nginx: ```bash -docker compose down && docker compose up -d && docker compose logs -f +sudo nginx -t && sudo systemctl reload nginx ``` -:::warning +## Starting TinyAuth -Important: If you used tinyAuth before 01.12.2025 and updated, you have switched from version 3 to 4. - -::: -## Updating from v3 to v4 - -Starting from v4, Tinyauth is a stateful application that uses a SQLite database to store sessions. This change improves security. For Docker setups, include the following volume: +Start or recreate the TinyAuth container: ```bash -services: - tinyauth: - volumes: - - ./data:/data +docker compose up -d --force-recreate tinyauth +docker compose logs -f tinyauth ``` -## Issuing API-keys +Open a protected application and confirm that Nginx redirects the browser to `https://tinyauth.example.com`. -:::info - -You can use Basic base64(username:password) in the `X-Api-Key` header of your requests to the API. +## Using `X-Api-Key` -Example: `X-Api-Key: Basic dXNlcm5hbWU6cGFzc3dvcmQ=` +The Remnawave TinyAuth image supports TinyAuth credentials in a separate `X-Api-Key` header. This allows the original `Authorization` header to pass through to the protected application. -::: +The header must contain HTTP Basic credentials: + +```text +X-Api-Key: Basic base64(username:password) +``` + +For example: + +```text +X-Api-Key: Basic dXNlcm5hbWU6cGFzc3dvcmQ= +``` + +Example request: + +```bash +curl https://panel.remnawave.com/api/example \ + -H "X-Api-Key: Basic $(printf 'username:password' | base64)" \ + -H "Authorization: Bearer application-token" +``` + +If `X-Api-Key` is absent, TinyAuth falls back to standard Basic authentication from the `Authorization` header. If `X-Api-Key` is present but malformed or uses a different scheme, authentication is rejected without fallback. + +## Breaking changes: v4 to v5 + +TinyAuth v5 introduces a unified configuration format. All TinyAuth environment variables now use the `TINYAUTH_` prefix and are grouped by section. + +| TinyAuth v4 | TinyAuth v5 | +| --- | --- | +| `PORT=3002` | `TINYAUTH_SERVER_PORT=3002` | +| `APP_URL=https://tinyauth.example.com` | `TINYAUTH_APPURL=https://tinyauth.example.com` | +| `USERS=...` | `TINYAUTH_AUTH_USERS=...` | +| `USERS_FILE=/path/to/users` | `TINYAUTH_AUTH_USERSFILE=/path/to/users` | +| `SECURE_COOKIE=true` | `TINYAUTH_AUTH_SECURECOOKIE=true` | + +The complete mapping is available in the [official v4 to v5 migration guide](https://tinyauth.app/docs/breaking-updates/4-to-5/). + +The Nginx integration also changes: + +- Continue using `/api/auth/nginx` for the authentication subrequest. +- Read redirects from `X-Tinyauth-Location` instead of constructing the login URL manually. +- Mark the auth location as `internal`. +- Explicitly overwrite `X-Forwarded-Host` and the other forwarded headers. +- Explicitly pass `X-Api-Key` and `Authorization` to the auth subrequest. +- Clear `X-Api-Key` before proxying the request to the protected application. + +### Upgrade procedure + +1. Stop TinyAuth without deleting its data: + + ```bash + docker compose stop tinyauth + ``` + +2. Back up the SQLite database and current Compose configuration: + + ```bash + cp -a ./data ./data-v4-backup + cp docker-compose.yml docker-compose.v4.yml + ``` + +3. Rename all v4 environment variables to their v5 equivalents and remove `SECRET`. + +4. Update the image: + + ```yaml + image: ghcr.io/maposia/remnawave-tinyauth:v5 + ``` + +5. Update the Nginx configuration and validate it: + + ```bash + sudo nginx -t + ``` + +6. Pull and start TinyAuth v5: + + ```bash + docker compose pull tinyauth + docker compose up -d --force-recreate tinyauth + docker compose logs -f tinyauth + ``` + +7. Verify browser login, cookie login, `X-Api-Key` authentication, and access to the protected application before removing the backup. + +### Rollback + +TinyAuth v5 applies additional SQLite migrations. Do not start TinyAuth v4 against a database that has already been migrated by v5. + +To roll back, restore both the v4 Compose file and the v4 data backup: + +```bash +docker compose stop tinyauth +rm -rf ./data +cp -a ./data-v4-backup ./data +cp docker-compose.v4.yml docker-compose.yml +docker compose up -d tinyauth +```