-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: allow login without authentication #929
Comments
💡 This can be split into two steps:
|
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. |
Is there no way to reset your password? I can't login. |
|
I'm no js/svelte dev but maybe something like main...sammcj:open-webui:main |
@duhow do you have a PR / Fork for this? |
True, its sort of weird to see an authentication page for a local app. |
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. |
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. |
Related: #483 |
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 🎉: 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. |
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. |
If there was a 💯 reaction emoji you would have just got it. |
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 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: &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: {} |
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... |
Oh, just found this ticket! |
@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. |
@sammcj investigating |
@tjbck thanks it looks like that fixed webui_auth:true + authentik. FYI the behaviour is now:
Note however -
|
Just updated the code, see if that did anything for you. |
That fixed it! Now:
You folks are awesome :) |
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:
The text was updated successfully, but these errors were encountered: