
Tinyauth 自托管 身份验证 中间件
Source && Doc
https://github.com/steveiliop56/tinyauth?tab=readme-ov-file
https://tinyauth.app/docs/about.html
强烈建议阅读,此文章只是个推荐,重复造轮子
介绍
首先说一下需求,在Selfhost 缺少身份验证或者是类似PHP等这种很容易存在漏洞应用,需要多一层验证(当然最佳实践应该是直接使用VPN内部访问,不公开到公网,但是有些应用还是存在这种使用场景)。
本身其实有大量的身份验证应用比如Authelia/Authentik/Keycloack之类。
原因1
大部分这些工具为了企业级生产力需求会十分复杂。比如之前使用的Authentik,他的compose需要简简单单147行(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
services:
authentik-postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
start_period: 20s
interval: 30s
retries: 5
timeout: 5s
volumes:
- ./database:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS:?database password required}
POSTGRES_USER: ${PG_USER:-authentik}
POSTGRES_DB: ${PG_DB:-authentik}
env_file:
- .env
networks:
- default
authentik-redis:
image: docker.io/library/redis:alpine
command: --save 60 1 --loglevel warning
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "redis-cli ping | grep PONG"]
start_period: 20s
interval: 30s
retries: 5
timeout: 3s
volumes:
- redis_authentik:/data
networks:
- default
authentik-server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG}
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
volumes:
- ./authentik/media:/media
- ./authentik/custom-templates:/templates
# - /var/run/docker.sock:/var/run/docker.sock
env_file:
- .env
# ports:
# - "${COMPOSE_PORT_HTTP:-9000}:9000"
# - "${COMPOSE_PORT_HTTPS:-9443}:9443"
networks:
- public_web
- default
depends_on:
authentik-postgresql:
condition: service_healthy
authentik-redis:
condition: service_healthy
labels:
homepage.group: Networking
homepage.name: Authentik
homepage.icon: authentik
homepage.href: "https://auth.CHANGEME.com"
traefik.enable: true
traefik.http.routers.authentik.rule: Host(`auth.CHANGEME.com`)
traefik.http.services.authentik.loadbalancer.server.port: 9000
traefik.docker.network: public_web
traefik.public: true
authentik-proxy:
image: ghcr.io/goauthentik/proxy:${AUTHENTIK_TAG:-2024.10.5}
# ports:
# - 9000:9000
# - 9443:9443
networks:
- public_web
- default
environment:
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_HOST: http://authentik-server:9000
AUTHENTIK_INSECURE: "true"
AUTHENTIK_TOKEN: ${AUTHENTIK_TRAEFIK_EXT_OUTPOST_TOKEN}
# Starting with 2021.9, you can optionally set this too
# when authentik_host for internal communication doesn't match the public URL
AUTHENTIK_HOST_BROWSER: https://auth.CHANGEME.com
# for logging edit log_level in outpost config from ui
labels:
traefik.enable: true
traefik.port: 9000
traefik.http.routers.authentik-proxy.rule: Host(`CHANGEME.com`) && PathPrefix(`/outpost.goauthentik.io/`)
# `authentik-proxy` refers to the service name in the compose file.
traefik.http.middlewares.authentik-proxy.forwardauth.address: http://authentik-proxy:9000/outpost.goauthentik.io/auth/traefik
traefik.http.middlewares.authentik-proxy.forwardauth.trustForwardHeader: true
traefik.http.middlewares.authentik-proxy.forwardauth.authResponseHeaders: X-authentik-username,X-authentik-groups,X-authentik-entitlements,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
traefik.public: true
kop.namespace: none
restart: unless-stopped
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.10.5}
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: authentik-redis
AUTHENTIK_POSTGRESQL__HOST: authentik-postgresql
AUTHENTIK_POSTGRESQL__USER: ${PG_USER:-authentik}
AUTHENTIK_POSTGRESQL__NAME: ${PG_DB:-authentik}
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
# `user: root` and the docker socket volume are optional.
# See more for the docker socket integration here:
# https://goauthentik.io/docs/outposts/integrations/docker
# Removing `user: root` also prevents the worker from fixing the permissions
# on the mounted folders, so when removing this make sure the folders have the correct UID/GID
# (1000:1000 by default)
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./authentik/media:/media
- ./authentik/certs:/certs
- ./authentik/custom-templates:/templates
env_file:
- .env
depends_on:
authentik-postgresql:
condition: service_healthy
authentik-redis:
condition: service_healthy
networks:
- default
networks:
default:
internal: true
public_web:
external: true
volumes:
redis_authentik:
driver: local
原因2
最近把家里的架构由Nginx手动创建变成了Compose + Traefik,现在我创建一个服务的反向代理,只需要向下面这样,在docker compose,反向代理将自动化生成。所以支持通过labels描述,并且自动加载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
labels:
traefik.enable: true
traefik.public: true
traefik.docker.network: traefik_external_public_web
#-----
traefik.http.routers.hlpj-alist.rule: Host(`alist.homelabproject.cc`)||Host(`file.homelabproject.cc`)
traefik.http.routers.hlpj-alist.entrypoints: cf
traefik.http.services.hlpj-alist.loadbalancer.server.port: 5244
traefik.http.routers.hlpj-alist.service: hlpj-alist
#---cloudflared---
cloudflare.tunnel.enable: "true"
cloudflare.tunnel.0.hostname: alist.homelabproject.cc
cloudflare.tunnel.0.service: http://traefik:808
cloudflare.tunnel.0.zonename: homelabproject.cc
cloudflare.tunnel.1.hostname: file.homelabproject.cc
cloudflare.tunnel.1.service: http://traefik:808
cloudflare.tunnel.1.zonename: homelabproject.cc
配置
基础容器
首先你需要最基础3个条件
- SECERT变量
直接在命令行行随机生成一个32字节的随机密钥
1
openssl rand -base64 32 | tr -dc 'a-zA-Z0-9' | head -c 32
- USERS
你的用户名密码,命令行输入下面,会进入交互,记得在问你是否使用docker的时候选择yes
1
docker run -i -t --rm ghcr.io/steveiliop56/tinyauth:v3 user create --interactive
你就会得到转换完用于登陆的账号密码的bcrypt 哈希。如果你有多个账号密码用,
隔开
- 用于验证的域名
tinyauth的访问流程:当你访问需要身份验证的域名,他会转条到tinyauth.你的域名.com
验证账号密码,然后你再回到你服务的域名就能正常访问了。
所以需要提前配置好你的域名
最后,配置你下面的环境变量,启动即可
1
2
3
4
5
6
7
8
9
10
11
12
tinyauth:
image: ghcr.io/steveiliop56/tinyauth:v3
container_name: tinyauth
restart: unless-stopped
environment:
- SECRET=some-random-32-chars-string
- APP_URL=https://tinyauth.你的域名.com
- USERS=your-username-password-hash
labels:
traefik.enable: true
traefik.http.routers.tinyauth.rule: Host(`tinyauth.你的域名.com`)
traefik.http.middlewares.tinyauth.forwardauth.address: http://tinyauth:3000/api/auth/traefik
配置需要验证的应用
你只需要附带Label,添加Router的中间件,即可访问
1
2
labels:
traefik.http.routers.[你的服务].middlewares: tinyauth@docker
总结
tinyauth的目的本身就不是为了生产力,对于Homelab来说就是简洁高效,个人觉得还是挺好用。