Originally created by @mckennajones on GitHub (Feb 26, 2024).
Originally assigned to: @tjbck on GitHub.
Many self hosted programs have an authentication-by-default approach these days. I get why that's the case, but, if a user has deployed the app only locally in their intranet, or if it's behind a secure network using a tool like Tailscale, then a password protected app isn't as necessary, and feels a bit cumbersome.
Possible solutions:
A setting that enables "no password mode" for the whole instance of the app. Meaning that there is no concept of multiple users anymore. Thought here is that the app would probably only be used by one user anyways.
Keep the concept of multiple users, but have some type of auto-login option. For example define a default user/password in the docker compose and when the user hits the login page, just auto login them in if those settings are set. This has less impact on the existing functionality of the app.
Originally created by @mckennajones on GitHub (Feb 26, 2024).
Originally assigned to: @tjbck on GitHub.
Many self hosted programs have an authentication-by-default approach these days. I get why that's the case, but, if a user has deployed the app only locally in their intranet, or if it's behind a secure network using a tool like Tailscale, then a password protected app isn't as necessary, and feels a bit cumbersome.
Possible solutions:
- A setting that enables "no password mode" for the whole instance of the app. Meaning that there is no concept of multiple users anymore. Thought here is that the app would probably only be used by one user anyways.
- Keep the concept of multiple users, but have some type of auto-login option. For example define a default user/password in the docker compose and when the user hits the login page, just auto login them in if those settings are set. This has less impact on the existing functionality of the app.
create or initialize a default admin account, can be done as a separate Container action to insert the user record in DB
if user session request is not found, create the admin session user (skip login)
@duhow commented on GitHub (Feb 27, 2024):
💡 This can be split into two steps:
- create or initialize a default admin account, can be done as a separate Container action to insert the user record in DB
- if user session request is not found, create the admin session user (skip login)
Frontend will need a way to disable the login screen anyway if we're to implement a system whereby we can have a separate build flag to produce the "Lite" version of the UI only.
@justinh-rahb commented on GitHub (Feb 27, 2024):
Frontend will need a way to disable the login screen anyway if we're to implement a system whereby we can have a separate build flag to produce the "Lite" version of the UI only.
@justinh-rahb commented on GitHub (Mar 4, 2024):
> Is there no way to reset your password? I can't login.
https://github.com/open-webui/open-webui/discussions/1027#discussioncomment-8661327
@sammcj commented on GitHub (Mar 20, 2024):
I'm no js/svelte dev but maybe something like https://github.com/open-webui/open-webui/compare/main...sammcj:open-webui:main
I tried to disable signup with hope to be able login without signup but It doesnt work. I am glad for this open issue, I hope someone can implement it soon.
@luboszima commented on GitHub (Mar 29, 2024):
Any update?
I tried to disable signup with hope to be able login without signup but It doesnt work. I am glad for this open issue, I hope someone can implement it soon.
I thought if there is no OIDC auth in this app, i could just disable logins and secure the app with a reverse proxy. Either one would be nice to have.
@blazp7 commented on GitHub (Apr 3, 2024):
I thought if there is no OIDC auth in this app, i could just disable logins and secure the app with a reverse proxy. Either one would be nice to have.
I’ve tried hacking on the code a few times to try and contribute a fix but my limited webdev skills only got me so far.
Running the app behind existing authentication or even in single user mode would be ideal but I’m not sure I can craft a good enough fix to submit.
I’ve just sponsored the project, so I hope that helps at least.
@sammcj commented on GitHub (Apr 6, 2024):
I’ve tried hacking on the code a few times to try and contribute a fix but my limited webdev skills only got me so far.
Running the app behind existing authentication or even in single user mode would be ideal but I’m not sure I can craft a good enough fix to submit.
I’ve just sponsored the project, so I hope that helps at least.
Thanks @tjbck, I suspect this might resolve quite a number of the use cases that people in this thread share (i.e. those of us that already have the app running behind an auth system such as Authentik etc...).
For me I am now able to use Open WebUI without logging in a second time by simply passing through the email header from Authentik 🎉:
I think there are probably still quite a few people that want no authentication all together but this is a good step forward.
@sammcj commented on GitHub (Apr 7, 2024):
Thanks @tjbck, I suspect this might resolve quite a number of the use cases that people in this thread share (i.e. those of us that already have the app running behind an auth system such as Authentik etc...).
For me I am now able to use Open WebUI without logging in a second time by simply passing through the email header from Authentik 🎉:
```yaml
services:
open-webui:
...
environment:
WEBUI_AUTH_TRUSTED_EMAIL_HEADER: 'X-authentik-email'
networks:
- traefik-servicenet
labels:
traefik.enable: true
traefik.http.routers.open-webui.middlewares: authentik
traefik.http.middlewares.open-webui-auth.headers.customrequestheaders.X-authentik-email: "true"
```
I think there are probably still quite a few people that want no authentication all together but this is a good step forward.
I think there are probably still quite a few people that want no authentication all together but this is a good step forward.
Not gonna lie, I think I like this solution better than building auth in ourselves, and it's been our stated opinion that we feel auth shouldn't be optional.
@justinh-rahb commented on GitHub (Apr 7, 2024):
> I think there are probably still quite a few people that want no authentication all together but this is a good step forward.
Not gonna lie, I think I like this solution _better_ than building auth in ourselves, and it's been our stated opinion that we feel auth shouldn't be optional.
I might even do a PR to add an example docker-compose with everything you need for auth with Traefik+Authentik, but perhaps there's a lighter weight option than Authentik (it's java 🤮) I'm not aware of that'd be better suited.
@sammcj commented on GitHub (Apr 7, 2024):
I might even do a PR to add an example docker-compose with everything you need for auth with Traefik+Authentik, but perhaps there's a lighter weight option than Authentik (it's java 🤮) I'm not aware of that'd be better suited.
I might even do a PR to add an example docker-compose with everything you need for auth with Traefik+Authentik, but perhaps there's a lighter weight option than Authentik I'm not aware of that'd be better suited.
I am not against this, if it can be done as an optional additional compose file like we've done for GPU support for example, I say go for it.
@justinh-rahb commented on GitHub (Apr 7, 2024):
> I might even do a PR to add an example docker-compose with everything you need for auth with Traefik+Authentik, but perhaps there's a lighter weight option than Authentik I'm not aware of that'd be better suited.
I am not against this, if it can be done as an optional additional compose file like we've done for GPU support for example, I say go for it.
I am not against this, if it can be done as an optional additional compose file like we've done for GPU support for example, I say go for it.
Here's a really rough example if anyone else wants it, you'll need to tweak things for your environment/network/secrets etc... and follow a tutorial on setting up Authentik for domain forward auth.
example-docker-compose.yaml
---#### !THIS IS AN EXAMPLE! ##### You will need to modify this to suit your needs.### YAML Anchors ###x-restart:&restartrestart:unless-stoppedx-secopts:&secoptssecurity_opt:- no-new-privileges:truex-default-app-user:&default-app-user# Create a user on the host with the same UID and GID as you set here.user:3001:3002environment:- PUID=3001- PGID=3002x-default-backend-user:&default-backend-user# Create a user on the host with the same UID and GID as you set here.user:4001:4002environment:- PUID=4001- PGID=4002networks:traefik-servicenet:# Network for containers with internal services (proxy)external:true# Create this on the host with something like: docker network create --attachable traefik-servicenet --subnet 172.18.0.0/16 --gateway 172.18.0.1name:traefik-servicenetauthentik-internal:external:falsedocker-proxynet:external:falsesecrets:traefik_acme_hostname:file:/path/to/your/secret/files/traefik/acme_hostnametraefik_acme_email:file:/path/to/your/secret/files/traefik/acme_emailtraefik_cloudflare_email:file:/path/to/your/secret/files/traefik/cloudflare_emailtraefik_acme_auth:file:/path/to/your/secret/files/traefik/acme_authtraefik_cloudflare_api_key:file:/path/to/your/secret/files/traefik/cloudflare_api_keyauthentik_postgresql_database:file:/path/to/your/secret/files/authentik/postgresql_dbauthentik_postgresql_user:file:/path/to/your/secret/files/authentik/postgresql_userauthentik_postgresql_password:file:/path/to/your/secret/files/authentik/postgresql_passwordauthentik_smtp_password:file:/path/to/your/secret/files/authentik/smtp_passwordauthentik_secret_key:file:/path/to/your/secret/files/authentik/secret_keyservices:### Traefik for networking ###traefik:<<:[*restart,*secopts,*default-backend-user]container_name:traefikimage:traefik:v3.0read_only:truemem_limit:1Gshm_size:256Mcap_add:- NET_BIND_SERVICEulimits:nproc:65535nofile:soft:10240hard:10240command:- "--log.level=INFO"#WARN- "--api=true"- "--api.insecure=false"- "--api.dashboard=true"- "--global.sendAnonymousUsage=false"- "--global.checkNewVersion=true"#- "--providers.docker=true"- "--providers.docker.exposedbydefault=false"- "--providers.docker.watch=true"- "--providers.docker.endpoint=tcp://dockerproxy:2375"### web ###- "--entrypoints.web.address=:80"# web- "--entrypoints.websecure.address=:443"# websecure- "--entrypoints.websecure.http3.advertisedport=443"- "--entrypoints.websecure.http.tls.domains[0].main=your.internal.domain"- "--entrypoints.websecure.http.tls.domains[0].sans=*.your.internal.domain"### Certificates ###- "--certificatesresolvers.le.acme.dnschallenge=true"- "--certificatesresolvers.le.acme.dnschallenge.provider=cloudflare"- "--certificatesresolvers.le.acme.dnschallenge.delaybeforecheck=10"- "--certificatesresolvers.le.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"# - "--certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" # Staging with fake certs but higher rate limits- "--certificatesresolvers.le.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"- "--certificatesresolvers.le.acme.storage=/etc/traefik/acme.json"labels:traefik.enable:truetraefik.docker.network:docker-proxynet# add .your.internal.domain to all requests (before http->https!)traefik.http.middlewares.redirect-short-domains.redirectregex.regex:"^(https?)://([^./]+)(/.*)?$"traefik.http.middlewares.redirect-short-domains.redirectregex.replacement:"https://$$2.your.internal.domain$$3"traefik.http.middlewares.redirect-short-domains.redirectregex.permanent:true# redirect http to httpstraefik.http.middlewares.redirect-http-https.redirectscheme.scheme:httpstraefik.http.middlewares.redirect-http-https.redirectscheme.permanent:truetraefik.http.routers.redirect-short-domains.entrypoints:webtraefik.http.routers.redirect-short-domains.middlewares:redirect-short-domains,redirect-http-https# Redirect anything that is not a subdomain to the subdomain, unless it contains.your.internal.domain`)traefik.http.routers.redirect-short-domains.rule:PathPrefix(`/`) && !HostRegexp(`{subdomain:[a-z]+}.your.internal.domain`)traefik.http.routers.redirect-short-domains.priority:1000### Security ###tls.options.default.minVersion:VersionTLS12tls.options.default.cipherSuites:TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256tls.options.default.curvePreferences:CurveP521,CurveP384tls.options.default.sniStrict:truetraefik.http.middlewares.secHeaders.headers.browserXssFilter:truetraefik.http.middlewares.secHeaders.headers.contentTypeNosniff:truetraefik.http.middlewares.secHeaders.headers.frameDeny:truetraefik.http.middlewares.secHeaders.headers.stsIncludeSubdomains:truetraefik.http.middlewares.secHeaders.headers.stsPreload:truetraefik.http.middlewares.secHeaders.headers.stsSeconds:31536000traefik.http.middlewares.secHeaders.headers.customFrameOptionsValue:SAMEORIGINtraefik.http.middlewares.secHeaders.headers.customResponseHeaders.server:""traefik.http.middlewares.secHeaders.headers.customResponseHeaders.x-poweredby:""# Websockets with SSLtraefik.http.middlewares.websocketsSSL.headers.customrequestheaders.X-Forwarded-Proto:https# Global Authentik middleware / proxyingtraefik.http.middlewares.authentik.forwardauth.address:http://authentik-server:9000/outpost.goauthentik.io/auth/traefiktraefik.http.middlewares.authentik.forwardauth.trustForwardHeader:truetraefik.http.middlewares.authentik.forwardauth.authResponseHeaders:X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-versionnetworks:- traefik-servicenet- docker-proxynet- defaultports:- "80:80"- "443:443"secrets:- traefik_acme_auth- traefik_acme_email- traefik_cloudflare_api_key- traefik_cloudflare_email- traefik_acme_hostnamevolumes:- traefik-acme.json:/etc/traefik/acme.json:rw# certificate storage- traefik-letsencrypt:/letsencrypt:rw- traefik-plugins-storage:/plugins-storage:rwdepends_on:dockerproxy:condition:service_started### Docker Socket Proxy ###dockerproxy:<<:[*restart,*secopts]environment:- LOG_LEVEL=warning# debug,info,notice,warning,err,crit,alert,emerg- ENABLE_IPV6=false## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.).# 0 to revoke access.# 1 to grant access.- ALLOW_RESTARTS=1- ALLOW_START=1- ALLOW_STOP=1## Granted by Default- EVENTS=1- PING=1- VERSION=1## Revoked by Default# Security critical- AUTH=0- SECRETS=0- POST=0# Not always needed- BUILD=0- COMMIT=0- CONFIGS=0- CONTAINERS=1# Traefik etc.- DISTRIBUTION=0- EXEC=0- IMAGES=1# Authentik- INFO=0- NETWORKS=1# Traefik- NODES=0- PLUGINS=0- SERVICES=1# Traefik- SESSION=0- SWARM=0- SYSTEM=0- TASKS=0- VOLUMES=0container_name:dockerproxyhostname:dockerproxyimage:ghcr.io/tecnativa/docker-socket-proxy:edgeprivileged:true# Required for Docker socket accessvolumes:- /var/run/docker.sock:/var/run/docker.sock:ro- /var/run/server-state:/var/lib/haproxy/server-state:rwnetworks:docker-proxynet:aliases:- dockerproxydeploy:restart_policy:condition:on-failureports:- "2375:2375"labels:- "org.hotio.pullio.update=true"healthcheck:test:wget -q "http://localhost:2375/version" -O /dev/null || exit 1interval:"29s"timeout:"5s"retries:5start_period:"10s"### Authentik for authentication ###authentik-server:<<:[*restart,*secopts,*default-backend-user]container_name:authentik-serverhostname:authentik-serverimage:ghcr.io/goauthentik/server:2024.2.1command:servernetworks:- traefik-servicenet- authentik-internal- defaultvolumes:- authentik-media:/media- authentik-templates:/templates- authentik-certs:/certs- geoip:/geoipports:- 9000- 9443depends_on:- authentik-postgresql- authentik-redis- traefiksecrets:- authentik_postgresql_password- authentik_postgresql_user- authentik_postgresql_database- authentik_smtp_password- authentik_secret_keylabels:traefik.enable:truetraefik.docker.network:traefik-servicenet## HTTP Routerstraefik.http.routers.authentik-rtr.rule:Host(`auth.your.internal.domain`) || Host(`authentik.your.internal.domain`) || Host(`authentic-server.your.internal.domain`) || ( HostRegexp(`{subdomain:[a-z0-9]+}.your.internal.domain`)) && PathPrefix(`/outpost.goauthentik.io/`)traefik.http.routers.authentik-rtr.entrypoints:websecuretraefik.http.routers.authentik-rtr.tls:truetraefik.http.routers.authentik-rtr.tls.domains[0].main:"*.your.internal.domain"traefik.http.routers.authentik-rtr.tls.certresolver:le## HTTP Servicestraefik.http.routers.authentik-rtr.service:authentik-svctraefik.http.services.authentik-svc.loadBalancer.server.port:9000&nameauthentik-worker:<<:[*restart,*secopts,*default-backend-user]depends_on:- authentik-server- authentik-postgresql- authentik-redisimage:ghcr.io/goauthentik/server:2024.2.1container_name:*namehostname:*namecommand:workerulimits:nofile:soft:10240hard:10240networks:- authentik-internalvolumes:- authentik-media:/media- authentik-templates:/templates- authentik-certs:/certssecrets:- authentik_postgresql_password- authentik_postgresql_user- authentik_postgresql_database- authentik_smtp_password- authentik_secret_key&nameauthentik-postgresql:<<:[*restart,*secopts,*default-backend-user]image:docker.io/library/postgres:15-alpinecontainer_name:*namehostname:*nameuser:volumes:- authentik-database:/var/lib/postgresql/dataenvironment:POSTGRES_PASSWORD:${AUTHENTIK_POSTGRESQL__PASSWORD}POSTGRES_USER:${PG_USER:-authentik}POSTGRES_DB:${PG_DB:-authentik}secrets:- authentik_postgresql_password- authentik_postgresql_user- authentik_postgresql_databasenetworks:- traefik-servicenet- authentik-internalports:- 5432&nameauthentik-redis:<<:[*restart,*secopts,*default-backend-user]container_name:*namehostname:*nameimage:docker.io/library/redis:alpinecommand:--save 60 1 --loglevel warningvolumes:- authentik-redis:/datanetworks:- authentik-internal- traefik-servicenetsecrets:- authentik_secret_key&namegeoipupdate:user:3001:2002# Create a user on the host with the same UID and GID as you set here.image:maxmindinc/geoipupdate:latestcontainer_name:*namehostname:*namevolumes:- geoip:/usr/share/GeoIP:rw### Ollama Server ###&nameollama:<<:[*restart,*secopts,*default-app-user]container_name:*namehostname:*namepull_policy:alwaystty:truerestart:unless-stoppedimage:ollama/ollama:latestenvironment:port:11434OLLAMA_HOST:0.0.0.0GIN_MODE:releaseCUDA_USE_TENSOR_CORES:1volumes:- ollama:/root/.ollamaports:- 11434networks:- traefik-servicenet- defaultextra_hosts:- "host.docker.internal:host-gateway"labels:traefik.enable:"true"traefik.http.routers.ollama.rule:Host(`ollama.your.domain`)traefik.http.routers.ollama.tls.certresolver:letraefik.http.routers.ollama.entrypoints:websecuretraefik.http.routers.ollama.tls.domains[0].main:"*.your.domain"traefik.http.routers.ollama.service:ollama-servicetraefik.http.services.ollama-service.loadbalancer.server.port:11434### Open WebUI ###&nameopen-webui:<<:[*restart,*secopts,*default-app-user]container_name:*namehostname:*namebuild:context:https://github.com/open-webui/open-webui.git#maindockerfile:Dockerfilevolumes:- open-webui:/app/backend/datadepends_on:- ollama- traefik- authentik-serverports:- 8080environment:OLLAMA_BASE_URL:https://ollama.your.domainWEBUI_AUTH_TRUSTED_EMAIL_HEADER:'X-authentik-email'networks:- traefik-servicenetextra_hosts:- host.docker.internal:host-gatewaylabels:traefik.enable:"true"traefik.http.routers.open-webui.rule:Host(`open-webui.your.domain`) || Host(`openwebui.your.domain`)traefik.http.routers.open-webui.tls.certresolver:letraefik.http.routers.open-webui.entrypoints:websecuretraefik.http.routers.open-webui.tls.domains[0].main:"*.your.domain"traefik.http.routers.open-webui.service:open-webui-servicetraefik.http.services.open-webui-service.loadbalancer.server.port:8080traefik.http.routers.open-webui.middlewares:authentiktraefik.http.middlewares.open-webui-auth.headers.customrequestheaders.X-authentik-email:"true"volumes:ollama:{}open-webui:{}authentik-media:{}authentik-templates:{}authentik-certs:{}authentik-utils:{}authentik-database:{}authentik-redis:{}traefik-acme:{}traefik-letsencrypt:{}traefik-plugins-storage:{}geoip:{}
@sammcj commented on GitHub (Apr 7, 2024):
> I am not against this, if it can be done as an optional additional compose file like we've done for GPU support for example, I say go for it.
Here's a really rough example if anyone else wants it, you'll need to tweak things for your environment/network/secrets etc... and follow a tutorial on setting up Authentik for domain forward auth.
<details>
<summary>example-docker-compose.yaml</summary>
```yaml
---
#### !THIS IS AN EXAMPLE! ####
# You will need to modify this to suit your needs.
### YAML Anchors ###
x-restart: &restart
restart: unless-stopped
x-secopts: &secopts
security_opt:
- no-new-privileges:true
x-default-app-user: &default-app-user # Create a user on the host with the same UID and GID as you set here.
user: 3001:3002
environment:
- PUID=3001
- PGID=3002
x-default-backend-user: &default-backend-user # Create a user on the host with the same UID and GID as you set here.
user: 4001:4002
environment:
- PUID=4001
- PGID=4002
networks:
traefik-servicenet: # Network for containers with internal services (proxy)
external: true
# Create this on the host with something like: docker network create --attachable traefik-servicenet --subnet 172.18.0.0/16 --gateway 172.18.0.1
name: traefik-servicenet
authentik-internal:
external: false
docker-proxynet:
external: false
secrets:
traefik_acme_hostname:
file: /path/to/your/secret/files/traefik/acme_hostname
traefik_acme_email:
file: /path/to/your/secret/files/traefik/acme_email
traefik_cloudflare_email:
file: /path/to/your/secret/files/traefik/cloudflare_email
traefik_acme_auth:
file: /path/to/your/secret/files/traefik/acme_auth
traefik_cloudflare_api_key:
file: /path/to/your/secret/files/traefik/cloudflare_api_key
authentik_postgresql_database:
file: /path/to/your/secret/files/authentik/postgresql_db
authentik_postgresql_user:
file: /path/to/your/secret/files/authentik/postgresql_user
authentik_postgresql_password:
file: /path/to/your/secret/files/authentik/postgresql_password
authentik_smtp_password:
file: /path/to/your/secret/files/authentik/smtp_password
authentik_secret_key:
file: /path/to/your/secret/files/authentik/secret_key
services:
### Traefik for networking ###
traefik:
<<: [ *restart, *secopts, *default-backend-user ]
container_name: traefik
image: traefik:v3.0
read_only: true
mem_limit: 1G
shm_size: 256M
cap_add:
- NET_BIND_SERVICE
ulimits:
nproc: 65535
nofile:
soft: 10240
hard: 10240
command:
- "--log.level=INFO" #WARN
- "--api=true"
- "--api.insecure=false"
- "--api.dashboard=true"
- "--global.sendAnonymousUsage=false"
- "--global.checkNewVersion=true"
#
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--providers.docker.watch=true"
- "--providers.docker.endpoint=tcp://dockerproxy:2375"
### web ###
- "--entrypoints.web.address=:80" # web
- "--entrypoints.websecure.address=:443" # websecure
- "--entrypoints.websecure.http3.advertisedport=443"
- "--entrypoints.websecure.http.tls.domains[0].main=your.internal.domain"
- "--entrypoints.websecure.http.tls.domains[0].sans=*.your.internal.domain"
### Certificates ###
- "--certificatesresolvers.le.acme.dnschallenge=true"
- "--certificatesresolvers.le.acme.dnschallenge.provider=cloudflare"
- "--certificatesresolvers.le.acme.dnschallenge.delaybeforecheck=10"
- "--certificatesresolvers.le.acme.dnschallenge.resolvers=1.1.1.1:53,1.0.0.1:53"
# - "--certificatesresolvers.le.acme.caserver=https://acme-staging-v02.api.letsencrypt.org/directory" # Staging with fake certs but higher rate limits
- "--certificatesresolvers.le.acme.caserver=https://acme-v02.api.letsencrypt.org/directory"
- "--certificatesresolvers.le.acme.storage=/etc/traefik/acme.json"
labels:
traefik.enable: true
traefik.docker.network: docker-proxynet
# add .your.internal.domain to all requests (before http->https!)
traefik.http.middlewares.redirect-short-domains.redirectregex.regex: "^(https?)://([^./]+)(/.*)?$"
traefik.http.middlewares.redirect-short-domains.redirectregex.replacement: "https://$$2.your.internal.domain$$3"
traefik.http.middlewares.redirect-short-domains.redirectregex.permanent: true
# redirect http to https
traefik.http.middlewares.redirect-http-https.redirectscheme.scheme: https
traefik.http.middlewares.redirect-http-https.redirectscheme.permanent: true
traefik.http.routers.redirect-short-domains.entrypoints: web
traefik.http.routers.redirect-short-domains.middlewares: redirect-short-domains,redirect-http-https
# Redirect anything that is not a subdomain to the subdomain, unless it contains.your.internal.domain`)
traefik.http.routers.redirect-short-domains.rule: PathPrefix(`/`) && !HostRegexp(`{subdomain:[a-z]+}.your.internal.domain`)
traefik.http.routers.redirect-short-domains.priority: 1000
### Security ###
tls.options.default.minVersion: VersionTLS12
tls.options.default.cipherSuites: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305,TLS_AES_128_GCM_SHA256,TLS_AES_256_GCM_SHA384,TLS_CHACHA20_POLY1305_SHA256
tls.options.default.curvePreferences: CurveP521,CurveP384
tls.options.default.sniStrict: true
traefik.http.middlewares.secHeaders.headers.browserXssFilter: true
traefik.http.middlewares.secHeaders.headers.contentTypeNosniff: true
traefik.http.middlewares.secHeaders.headers.frameDeny: true
traefik.http.middlewares.secHeaders.headers.stsIncludeSubdomains: true
traefik.http.middlewares.secHeaders.headers.stsPreload: true
traefik.http.middlewares.secHeaders.headers.stsSeconds: 31536000
traefik.http.middlewares.secHeaders.headers.customFrameOptionsValue: SAMEORIGIN
traefik.http.middlewares.secHeaders.headers.customResponseHeaders.server: ""
traefik.http.middlewares.secHeaders.headers.customResponseHeaders.x-poweredby: ""
# Websockets with SSL
traefik.http.middlewares.websocketsSSL.headers.customrequestheaders.X-Forwarded-Proto: https
# Global Authentik middleware / proxying
traefik.http.middlewares.authentik.forwardauth.address: http://authentik-server:9000/outpost.goauthentik.io/auth/traefik
traefik.http.middlewares.authentik.forwardauth.trustForwardHeader: true
traefik.http.middlewares.authentik.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-email,X-authentik-name,X-authentik-uid,X-authentik-jwt,X-authentik-meta-jwks,X-authentik-meta-outpost,X-authentik-meta-provider,X-authentik-meta-app,X-authentik-meta-version
networks:
- traefik-servicenet
- docker-proxynet
- default
ports:
- "80:80"
- "443:443"
secrets:
- traefik_acme_auth
- traefik_acme_email
- traefik_cloudflare_api_key
- traefik_cloudflare_email
- traefik_acme_hostname
volumes:
- traefik-acme.json:/etc/traefik/acme.json:rw # certificate storage
- traefik-letsencrypt:/letsencrypt:rw
- traefik-plugins-storage:/plugins-storage:rw
depends_on:
dockerproxy:
condition: service_started
### Docker Socket Proxy ###
dockerproxy:
<<: [ *restart, *secopts ]
environment:
- LOG_LEVEL=warning # debug,info,notice,warning,err,crit,alert,emerg
- ENABLE_IPV6=false
## Variables match the URL prefix (i.e. AUTH blocks access to /auth/* parts of the API, etc.).
# 0 to revoke access.
# 1 to grant access.
- ALLOW_RESTARTS=1
- ALLOW_START=1
- ALLOW_STOP=1
## Granted by Default
- EVENTS=1
- PING=1
- VERSION=1
## Revoked by Default
# Security critical
- AUTH=0
- SECRETS=0
- POST=0
# Not always needed
- BUILD=0
- COMMIT=0
- CONFIGS=0
- CONTAINERS=1 # Traefik etc.
- DISTRIBUTION=0
- EXEC=0
- IMAGES=1 # Authentik
- INFO=0
- NETWORKS=1 # Traefik
- NODES=0
- PLUGINS=0
- SERVICES=1 # Traefik
- SESSION=0
- SWARM=0
- SYSTEM=0
- TASKS=0
- VOLUMES=0
container_name: dockerproxy
hostname: dockerproxy
image: ghcr.io/tecnativa/docker-socket-proxy:edge
privileged: true # Required for Docker socket access
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
- /var/run/server-state:/var/lib/haproxy/server-state:rw
networks:
docker-proxynet:
aliases:
- dockerproxy
deploy:
restart_policy:
condition: on-failure
ports:
- "2375:2375"
labels:
- "org.hotio.pullio.update=true"
healthcheck:
test: wget -q "http://localhost:2375/version" -O /dev/null || exit 1
interval: "29s"
timeout: "5s"
retries: 5
start_period: "10s"
### Authentik for authentication ###
authentik-server:
<<: [ *restart, *secopts, *default-backend-user ]
container_name: authentik-server
hostname: authentik-server
image: ghcr.io/goauthentik/server:2024.2.1
command: server
networks:
- traefik-servicenet
- authentik-internal
- default
volumes:
- authentik-media:/media
- authentik-templates:/templates
- authentik-certs:/certs
- geoip:/geoip
ports:
- 9000
- 9443
depends_on:
- authentik-postgresql
- authentik-redis
- traefik
secrets:
- authentik_postgresql_password
- authentik_postgresql_user
- authentik_postgresql_database
- authentik_smtp_password
- authentik_secret_key
labels:
traefik.enable: true
traefik.docker.network: traefik-servicenet
## HTTP Routers
traefik.http.routers.authentik-rtr.rule: Host(`auth.your.internal.domain`) || Host(`authentik.your.internal.domain`) || Host(`authentic-server.your.internal.domain`) || ( HostRegexp(`{subdomain:[a-z0-9]+}.your.internal.domain`)) && PathPrefix(`/outpost.goauthentik.io/`)
traefik.http.routers.authentik-rtr.entrypoints: websecure
traefik.http.routers.authentik-rtr.tls: true
traefik.http.routers.authentik-rtr.tls.domains[0].main: "*.your.internal.domain"
traefik.http.routers.authentik-rtr.tls.certresolver: le
## HTTP Services
traefik.http.routers.authentik-rtr.service: authentik-svc
traefik.http.services.authentik-svc.loadBalancer.server.port: 9000
&name authentik-worker:
<<: [ *restart, *secopts, *default-backend-user ]
depends_on:
- authentik-server
- authentik-postgresql
- authentik-redis
image: ghcr.io/goauthentik/server:2024.2.1
container_name: *name
hostname: *name
command: worker
ulimits:
nofile:
soft: 10240
hard: 10240
networks:
- authentik-internal
volumes:
- authentik-media:/media
- authentik-templates:/templates
- authentik-certs:/certs
secrets:
- authentik_postgresql_password
- authentik_postgresql_user
- authentik_postgresql_database
- authentik_smtp_password
- authentik_secret_key
&name authentik-postgresql:
<<: [ *restart, *secopts, *default-backend-user ]
image: docker.io/library/postgres:15-alpine
container_name: *name
hostname: *name
user:
volumes:
- authentik-database:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${AUTHENTIK_POSTGRESQL__PASSWORD}
POSTGRES_USER: ${PG_USER:-authentik}
POSTGRES_DB: ${PG_DB:-authentik}
secrets:
- authentik_postgresql_password
- authentik_postgresql_user
- authentik_postgresql_database
networks:
- traefik-servicenet
- authentik-internal
ports:
- 5432
&name authentik-redis:
<<: [ *restart, *secopts, *default-backend-user ]
container_name: *name
hostname: *name
image: docker.io/library/redis:alpine
command: --save 60 1 --loglevel warning
volumes:
- authentik-redis:/data
networks:
- authentik-internal
- traefik-servicenet
secrets:
- authentik_secret_key
&name geoipupdate:
user: 3001:2002 # Create a user on the host with the same UID and GID as you set here.
image: maxmindinc/geoipupdate:latest
container_name: *name
hostname: *name
volumes:
- geoip:/usr/share/GeoIP:rw
### Ollama Server ###
&name ollama:
<<: [ *restart, *secopts, *default-app-user ]
container_name: *name
hostname: *name
pull_policy: always
tty: true
restart: unless-stopped
image: ollama/ollama:latest
environment:
port: 11434
OLLAMA_HOST: 0.0.0.0
GIN_MODE: release
CUDA_USE_TENSOR_CORES: 1
volumes:
- ollama:/root/.ollama
ports:
- 11434
networks:
- traefik-servicenet
- default
extra_hosts:
- "host.docker.internal:host-gateway"
labels:
traefik.enable: "true"
traefik.http.routers.ollama.rule: Host(`ollama.your.domain`)
traefik.http.routers.ollama.tls.certresolver: le
traefik.http.routers.ollama.entrypoints: websecure
traefik.http.routers.ollama.tls.domains[0].main: "*.your.domain"
traefik.http.routers.ollama.service: ollama-service
traefik.http.services.ollama-service.loadbalancer.server.port: 11434
### Open WebUI ###
&name open-webui:
<<: [ *restart, *secopts, *default-app-user ]
container_name: *name
hostname: *name
build:
context: https://github.com/open-webui/open-webui.git#main
dockerfile: Dockerfile
volumes:
- open-webui:/app/backend/data
depends_on:
- ollama
- traefik
- authentik-server
ports:
- 8080
environment:
OLLAMA_BASE_URL: https://ollama.your.domain
WEBUI_AUTH_TRUSTED_EMAIL_HEADER: 'X-authentik-email'
networks:
- traefik-servicenet
extra_hosts:
- host.docker.internal:host-gateway
labels:
traefik.enable: "true"
traefik.http.routers.open-webui.rule: Host(`open-webui.your.domain`) || Host(`openwebui.your.domain`)
traefik.http.routers.open-webui.tls.certresolver: le
traefik.http.routers.open-webui.entrypoints: websecure
traefik.http.routers.open-webui.tls.domains[0].main: "*.your.domain"
traefik.http.routers.open-webui.service: open-webui-service
traefik.http.services.open-webui-service.loadbalancer.server.port: 8080
traefik.http.routers.open-webui.middlewares: authentik
traefik.http.middlewares.open-webui-auth.headers.customrequestheaders.X-authentik-email: "true"
volumes:
ollama: {}
open-webui: {}
authentik-media: {}
authentik-templates: {}
authentik-certs: {}
authentik-utils: {}
authentik-database: {}
authentik-redis: {}
traefik-acme: {}
traefik-letsencrypt: {}
traefik-plugins-storage: {}
geoip: {}
```
</details>
be able login without signup but It doesnt work. I am glad for this open issue, I hope someone can implement it soon.
Another option would be to rely authorization on header flags set by a reverse proxy - so that my apache2 can do openid and set the username as "x-forwarded-user" flag and the "x-forwarded-group" as admin, if the user should have administrative privileges...
@eingemaischt commented on GitHub (Apr 10, 2024):
> be able login without signup but It doesnt work. I am glad for this open issue, I hope someone can implement it soon.
Another option would be to rely authorization on header flags set by a reverse proxy - so that my apache2 can do openid and set the username as "x-forwarded-user" flag and the "x-forwarded-group" as admin, if the user should have administrative privileges...
@chrisbward commented on GitHub (Apr 30, 2024):
Oh, just found this ticket!
I've tried running the docker container with the documented env flag set to "False", and still have the login form;
https://github.com/open-webui/open-webui/issues/1875
@sammcj The intent of this "feature" wasn't to be replaced by something like Authentik. That could have already been put in in-front of our authentication before, using the trusted email auth header which effectively delegates it to an external proxy.
@justinh-rahb commented on GitHub (May 8, 2024):
@sammcj The intent of this "feature" wasn't to be replaced by something like Authentik. That could have already been put in in-front of our authentication before, using the trusted email auth header which effectively delegates it to an external proxy.
@tjbck thanks it looks like that fixed webui_auth:true + authentik.
FYI the behaviour is now:
webui_auth: true + authentik (w/ header) = works ✅
webui_auth: true (no authentik) = works ✅
webui_auth: false + authentik (w/ header) = You do not have permission to access this resource. Please contact your administrator for assistance. (I suspect this is intended behaviour and as such a ✅)
Note however -
webui_auth: false + authentik (no header) + rm -rf the db = You do not have permission to access this resource. Please contact your administrator for assistance. 🤔
webui_auth: false (no authentik) + rm -rf the db = You do not have permission to access this resource. Please contact your administrator for assistance. 🤔
@sammcj commented on GitHub (May 8, 2024):
@tjbck thanks it looks like that fixed webui_auth:true + authentik.
FYI the behaviour is now:
- webui_auth: true + authentik (w/ header) = works ✅
- webui_auth: true (no authentik) = works ✅
- webui_auth: false + authentik (w/ header) = You do not have permission to access this resource. Please contact your administrator for assistance. (I suspect this is intended behaviour and as such a ✅)
Note however -
- webui_auth: false + authentik (no header) + rm -rf the db = You do not have permission to access this resource. Please contact your administrator for assistance. 🤔
- webui_auth: false (no authentik) + rm -rf the db = You do not have permission to access this resource. Please contact your administrator for assistance. 🤔
webui_auth: false + authentik (no header) + rm -rf the db = works (user shows as 'user') ✅
webui_auth: false (no authentik) + rm -rf the db = works (user shows as the pass email) ✅
You folks are awesome :)
@sammcj commented on GitHub (May 8, 2024):
That fixed it!
Now:
- webui_auth: false + authentik (no header) + rm -rf the db = works (user shows as 'user') ✅
- webui_auth: false (no authentik) + rm -rf the db = works (user shows as the pass email) ✅
You folks are awesome :)
That could have already been put in in-front of our authentication before, using the trusted email auth header which effectively delegates it to an external proxy.
Can an example be provided? Per issue #13090 , simply setting WEBUI_AUTH_TRUSTED_EMAIL_HEADER to the header field containing the user's email as provided by the external authentication mechanism / reverse proxy (e.g. keycloak + OpenResty + lua-resty-openidc) doesn't appear to be sufficient.
@qhaas commented on GitHub (Apr 22, 2025):
> That could have already been put in in-front of our authentication before, using the trusted email auth header which effectively delegates it to an external proxy.
Can an example be provided? Per issue #13090 , simply setting `WEBUI_AUTH_TRUSTED_EMAIL_HEADER` to the header field containing the user's email as provided by the external authentication mechanism / reverse proxy (e.g. keycloak + OpenResty + lua-resty-openidc) doesn't appear to be sufficient.
Like many other people, per the official advice, I originally installed open-webui using docker and setup a local admin account etc. At the time I wondered why this was necessary, but there didn't immediately seem to be a way to avoid this.
Later, after it became too annoying I landed here trying to figure out how to remove auth. Unfortunately just setting WEBUI_AUTH=False when starting the service won't work (as advertised) and it wasn't initially clear how to deal with this.
So, for anyone else using Ubuntu with the docker version of open-webui, and who has the db maintained externally per the official run command (docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:main), this is what I did to resolve the issue. Note that this maintains a copy of the original db should one want to revert, but the result will, necessarily, remove all history etc from the UI so it's as if starting from new albeit no longer requiring login credentials:
That's it, you should now be able to use open-webui without login. To revert you'd stop the instance again and simply move (or copy) the renamed db back to it's original name eg:
Finally, as comment for any future development, if it were possible to auth just with a simple username instead of a full email address that may be less aggravating? If one could use a simple one-letter user/pass then it may address some of the other comments/issues I've seen, and may not require much re-factoring in the present code to implement?
@eroyee commented on GitHub (May 11, 2025):
Like many other people, per the official advice, I originally installed open-webui using docker and setup a local admin account etc. At the time I wondered why this was necessary, but there didn't immediately seem to be a way to avoid this.
Later, after it became too annoying I landed here trying to figure out how to remove auth. Unfortunately just setting WEBUI_AUTH=False when starting the service won't work (as advertised) and it wasn't initially clear how to deal with this.
So, for anyone else using Ubuntu with the docker version of open-webui, and who has the db maintained externally per the official run command (docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:main), this is what I did to resolve the issue. Note that _this maintains a copy of the original db should one want to revert_, but the result will, necessarily, remove all history etc from the UI so it's as if starting from new albeit no longer requiring login credentials:
`docker stop open-webui`
`mv /var/lib/docker/volumes/open-webui/_data/webui.db /var/lib/docker/volumes/open-webui/_data/webui.db.original`
`docker rm open-webui`
`docker run -d -p 3000:8080 -e WEBUI_AUTH=False -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:main`
That's it, you should now be able to use open-webui without login. To revert you'd stop the instance again and simply move (or copy) the renamed db back to it's original name eg:
`mv /var/lib/docker/volumes/open-webui/_data/webui.db.original /var/lib/docker/volumes/open-webui/_data/webui.db`
Finally, as comment for any future development, if it were possible to auth just with a simple username instead of a full email address that may be less aggravating? If one could use a simple one-letter user/pass then it may address some of the other comments/issues I've seen, and may not require much re-factoring in the present code to implement?
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Originally created by @mckennajones on GitHub (Feb 26, 2024).
Originally assigned to: @tjbck on GitHub.
Many self hosted programs have an authentication-by-default approach these days. I get why that's the case, but, if a user has deployed the app only locally in their intranet, or if it's behind a secure network using a tool like Tailscale, then a password protected app isn't as necessary, and feels a bit cumbersome.
Possible solutions:
@duhow commented on GitHub (Feb 27, 2024):
💡 This can be split into two steps:
@justinh-rahb commented on GitHub (Feb 27, 2024):
Frontend will need a way to disable the login screen anyway if we're to implement a system whereby we can have a separate build flag to produce the "Lite" version of the UI only.
@adlostwolf commented on GitHub (Mar 4, 2024):
Is there no way to reset your password? I can't login.
@justinh-rahb commented on GitHub (Mar 4, 2024):
https://github.com/open-webui/open-webui/discussions/1027#discussioncomment-8661327
@sammcj commented on GitHub (Mar 20, 2024):
I'm no js/svelte dev but maybe something like https://github.com/open-webui/open-webui/compare/main...sammcj:open-webui:main
@Chukarslan commented on GitHub (Mar 21, 2024):
@duhow do you have a PR / Fork for this?
@jikkuatwork commented on GitHub (Mar 25, 2024):
True, its sort of weird to see an authentication page for a local app.
@luboszima commented on GitHub (Mar 29, 2024):
Any update?
I tried to disable signup with hope to be able login without signup but It doesnt work. I am glad for this open issue, I hope someone can implement it soon.
@blazp7 commented on GitHub (Apr 3, 2024):
I thought if there is no OIDC auth in this app, i could just disable logins and secure the app with a reverse proxy. Either one would be nice to have.
@sammcj commented on GitHub (Apr 6, 2024):
I’ve tried hacking on the code a few times to try and contribute a fix but my limited webdev skills only got me so far.
Running the app behind existing authentication or even in single user mode would be ideal but I’m not sure I can craft a good enough fix to submit.
I’ve just sponsored the project, so I hope that helps at least.
@tjbck commented on GitHub (Apr 6, 2024):
Related: https://github.com/open-webui/open-webui/issues/483
@sammcj commented on GitHub (Apr 7, 2024):
Thanks @tjbck, I suspect this might resolve quite a number of the use cases that people in this thread share (i.e. those of us that already have the app running behind an auth system such as Authentik etc...).
For me I am now able to use Open WebUI without logging in a second time by simply passing through the email header from Authentik 🎉:
I think there are probably still quite a few people that want no authentication all together but this is a good step forward.
@justinh-rahb commented on GitHub (Apr 7, 2024):
Not gonna lie, I think I like this solution better than building auth in ourselves, and it's been our stated opinion that we feel auth shouldn't be optional.
@sammcj commented on GitHub (Apr 7, 2024):
If there was a 💯 reaction emoji you would have just got it.
@sammcj commented on GitHub (Apr 7, 2024):
I might even do a PR to add an example docker-compose with everything you need for auth with Traefik+Authentik, but perhaps there's a lighter weight option than Authentik (it's java 🤮) I'm not aware of that'd be better suited.
@justinh-rahb commented on GitHub (Apr 7, 2024):
I am not against this, if it can be done as an optional additional compose file like we've done for GPU support for example, I say go for it.
@sammcj commented on GitHub (Apr 7, 2024):
Here's a really rough example if anyone else wants it, you'll need to tweak things for your environment/network/secrets etc... and follow a tutorial on setting up Authentik for domain forward auth.
example-docker-compose.yaml
@eingemaischt commented on GitHub (Apr 10, 2024):
Another option would be to rely authorization on header flags set by a reverse proxy - so that my apache2 can do openid and set the username as "x-forwarded-user" flag and the "x-forwarded-group" as admin, if the user should have administrative privileges...
@chrisbward commented on GitHub (Apr 30, 2024):
Oh, just found this ticket!
I've tried running the docker container with the documented env flag set to "False", and still have the login form;
https://github.com/open-webui/open-webui/issues/1875
@tjbck commented on GitHub (May 8, 2024):
https://docs.openwebui.com/getting-started/env-configuration#webui_auth
@sammcj commented on GitHub (May 8, 2024):
Maybe I'm doing something wrong, but with a fresh install / container volumes with
WEBUI_AUTH: falsegives the error:docker-compose:
@justinh-rahb commented on GitHub (May 8, 2024):
@sammcj The intent of this "feature" wasn't to be replaced by something like Authentik. That could have already been put in in-front of our authentication before, using the trusted email auth header which effectively delegates it to an external proxy.
@tjbck commented on GitHub (May 8, 2024):
@sammcj investigating
@sammcj commented on GitHub (May 8, 2024):
@tjbck thanks it looks like that fixed webui_auth:true + authentik.
FYI the behaviour is now:
Note however -
@tjbck commented on GitHub (May 8, 2024):
Just updated the code, see if that did anything for you.
@sammcj commented on GitHub (May 8, 2024):
That fixed it!
Now:
You folks are awesome :)
@f1am3d commented on GitHub (Mar 13, 2025):
Just fork and remove this nonsense
@qhaas commented on GitHub (Apr 22, 2025):
Can an example be provided? Per issue #13090 , simply setting
WEBUI_AUTH_TRUSTED_EMAIL_HEADERto the header field containing the user's email as provided by the external authentication mechanism / reverse proxy (e.g. keycloak + OpenResty + lua-resty-openidc) doesn't appear to be sufficient.@eroyee commented on GitHub (May 11, 2025):
Like many other people, per the official advice, I originally installed open-webui using docker and setup a local admin account etc. At the time I wondered why this was necessary, but there didn't immediately seem to be a way to avoid this.
Later, after it became too annoying I landed here trying to figure out how to remove auth. Unfortunately just setting WEBUI_AUTH=False when starting the service won't work (as advertised) and it wasn't initially clear how to deal with this.
So, for anyone else using Ubuntu with the docker version of open-webui, and who has the db maintained externally per the official run command (docker run -d -p 3000:8080 -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:main), this is what I did to resolve the issue. Note that this maintains a copy of the original db should one want to revert, but the result will, necessarily, remove all history etc from the UI so it's as if starting from new albeit no longer requiring login credentials:
docker stop open-webuimv /var/lib/docker/volumes/open-webui/_data/webui.db /var/lib/docker/volumes/open-webui/_data/webui.db.originaldocker rm open-webuidocker run -d -p 3000:8080 -e WEBUI_AUTH=False -v open-webui:/app/backend/data --name open-webui ghcr.io/open-webui/open-webui:mainThat's it, you should now be able to use open-webui without login. To revert you'd stop the instance again and simply move (or copy) the renamed db back to it's original name eg:
mv /var/lib/docker/volumes/open-webui/_data/webui.db.original /var/lib/docker/volumes/open-webui/_data/webui.dbFinally, as comment for any future development, if it were possible to auth just with a simple username instead of a full email address that may be less aggravating? If one could use a simple one-letter user/pass then it may address some of the other comments/issues I've seen, and may not require much re-factoring in the present code to implement?