Security
ติดตั้ง Authentik บน VPS — ระบบ SSO Identity Provider ส่วนตัว
Authentik คือ Identity Provider (IdP) แบบ open-source ที่รองรับ SSO, OAuth2, OIDC, SAML2 และ LDAP — เปรียบเหมือน Okta หรือ Auth0 แต่รันบน VPS ของคุณเอง ควบคุม authentication ได้ 100% ไม่ต้องพึ่ง cloud บุคคลที่สาม
ในบทความนี้จะติดตั้ง Authentik บน VPS Ubuntu 22.04 ด้วย Docker Compose พร้อม Nginx reverse proxy และ SSL จาก Let's Encrypt ใช้เวลาประมาณ 30 นาทีก็พร้อมใช้งาน
Authentik คืออะไร ต่างจาก Keycloak อย่างไร
Authentik และ Keycloak ต่างเป็น self-hosted IdP แต่มีจุดต่าง:
| Feature | Authentik | Keycloak |
|---|---|---|
| ภาษา/Stack | Python/Django + Go proxy | Java/Quarkus |
| RAM minimum | ~1 GB | ~2 GB |
| UI Admin | ทันสมัย, ใช้งานง่าย | ซับซ้อนกว่า |
| Forward Auth | Built-in Traefik/Nginx | ต้องใช้ plugin |
| Flows UI | Visual drag-and-drop | Config file |
Authentik เหมาะกับทีมขนาดเล็กถึงกลางที่ต้องการตั้งค่าเร็วและ UI ที่ใช้งานง่าย
ความต้องการของระบบ
- VPS: Ubuntu 22.04 LTS — RAM อย่างน้อย 2 GB (แนะนำ 4 GB)
- CPU: 1 vCPU ขึ้นไป (2 vCPU แนะนำสำหรับ production)
- Docker Engine 24+ และ Docker Compose v2
- Domain พร้อม DNS record ชี้มา VPS (เช่น
auth.example.com) - Port 80 และ 443 เปิด
ขั้นตอนที่ 1: ติดตั้ง Docker
# อัปเดต package และติดตั้ง Docker
sudo apt update && sudo apt upgrade -y
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
newgrp docker
# ตรวจสอบ Docker version
docker --version
docker compose version
ขั้นตอนที่ 2: สร้าง Docker Compose สำหรับ Authentik
สร้าง directory และ environment file:
mkdir -p /opt/authentik && cd /opt/authentik
# สร้าง secret keys
echo "PG_PASS=$(openssl rand -base64 36 | tr -dc 'a-zA-Z0-9' | head -c 36)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 60 | tr -dc 'a-zA-Z0-9' | head -c 60)" >> .env
echo "AUTHENTIK_ERROR_REPORTING__ENABLED=false" >> .env
cat .env
สร้างไฟล์ docker-compose.yml:
cat > /opt/authentik/docker-compose.yml << 'EOF'
services:
postgresql:
image: docker.io/library/postgres:16-alpine
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
interval: 30s
timeout: 5s
retries: 5
volumes:
- database:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: ${PG_PASS}
POSTGRES_USER: authentik
POSTGRES_DB: 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"]
interval: 30s
timeout: 3s
retries: 5
volumes:
- redis:/data
server:
image: ghcr.io/goauthentik/server:2024.12
restart: unless-stopped
command: server
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_ERROR_REPORTING__ENABLED: ${AUTHENTIK_ERROR_REPORTING__ENABLED}
volumes:
- ./media:/media
- ./custom-templates:/templates
ports:
- "9000:9000"
- "9443:9443"
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
worker:
image: ghcr.io/goauthentik/server:2024.12
restart: unless-stopped
command: worker
environment:
AUTHENTIK_REDIS__HOST: redis
AUTHENTIK_POSTGRESQL__HOST: postgresql
AUTHENTIK_POSTGRESQL__USER: authentik
AUTHENTIK_POSTGRESQL__NAME: authentik
AUTHENTIK_POSTGRESQL__PASSWORD: ${PG_PASS}
AUTHENTIK_SECRET_KEY: ${AUTHENTIK_SECRET_KEY}
AUTHENTIK_ERROR_REPORTING__ENABLED: ${AUTHENTIK_ERROR_REPORTING__ENABLED}
user: root
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./media:/media
- ./certs:/certs
- ./custom-templates:/templates
depends_on:
postgresql:
condition: service_healthy
redis:
condition: service_healthy
volumes:
database:
redis:
EOF
ขั้นตอนที่ 3: ตั้งค่า Nginx Reverse Proxy
ติดตั้ง Nginx และสร้าง virtual host สำหรับ Authentik:
sudo apt install -y nginx certbot python3-certbot-nginx
# สร้าง config สำหรับ auth.example.com (แก้ domain ให้ตรง)
sudo tee /etc/nginx/sites-available/authentik << 'EOF'
server {
listen 80;
server_name auth.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name auth.example.com;
ssl_certificate /etc/letsencrypt/live/auth.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/auth.example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
add_header Strict-Transport-Security "max-age=63072000" always;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
EOF
sudo ln -s /etc/nginx/sites-available/authentik /etc/nginx/sites-enabled/
sudo nginx -t
ขั้นตอนที่ 4: ขอ SSL Certificate และเริ่มต้นระบบ
# ขอ SSL จาก Let's Encrypt (แก้ domain และ email)
sudo certbot certonly --nginx -d auth.example.com --email [email protected] --agree-tos -n
# เริ่มต้น Nginx
sudo systemctl reload nginx
# เริ่มต้น Authentik
cd /opt/authentik
docker compose pull
docker compose up -d
# ดู logs ระหว่างรอ startup (ใช้เวลา 1-2 นาที)
docker compose logs -f server
ขั้นตอนที่ 5: Initial Setup ครั้งแรก
เปิด browser ไปที่ https://auth.example.com/if/flow/initial-setup/ จะพบหน้าตั้งค่า admin account ครั้งแรก:
- กรอก Email และ Password สำหรับ admin account
- คลิก Continue — Authentik จะสร้าง admin user ให้อัตโนมัติ
- Login เข้า Admin Interface ที่
https://auth.example.com/if/admin/
ขั้นตอนที่ 6: สร้าง Application และ Provider
ตัวอย่างการสร้าง OAuth2/OIDC Provider สำหรับ application:
- ไปที่ Admin Interface → Applications → Providers → Create
- เลือก OAuth2/OpenID Provider
- ตั้งชื่อและเลือก Authorization flow (ใช้ default:
default-provider-authorization-explicit-consent) - กรอก Redirect URIs ของ application (เช่น
https://app.example.com/callback) - บันทึก — คัดลอก Client ID และ Client Secret
- ไปที่ Applications → Create แล้วเชื่อม Provider ที่สร้างไว้
ขั้นตอนที่ 7: ใช้ Forward Auth กับ Nginx
Authentik รองรับ forward authentication — ป้องกัน application ที่ไม่มี built-in auth เอง:
# สร้าง Nginx config สำหรับ app ที่ต้องการ protect
sudo tee /etc/nginx/snippets/authentik-auth.conf << 'EOF'
# ส่ง request ไปตรวจสอบที่ Authentik ก่อน
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = @goauthentik_proxy_signin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
auth_request_set $authentik_username $upstream_http_x_authentik_username;
auth_request_set $authentik_groups $upstream_http_x_authentik_groups;
EOF
# เพิ่มใน server block ของ app ที่ต้องการ protect
# include /etc/nginx/snippets/authentik-auth.conf;
ตรวจสอบว่า Authentik ทำงานถูกต้อง
# ตรวจสอบ container ทั้งหมดกำลัง running
docker compose -f /opt/authentik/docker-compose.yml ps
# ตรวจสอบ health check
curl -s https://auth.example.com/-/health/live/ && echo " — OK"
curl -s https://auth.example.com/-/health/ready/ && echo " — Ready"
# ดู Authentik version
curl -s https://auth.example.com/api/v3/root/config/ | python3 -m json.tool | grep version
# ตรวจสอบ database connection
docker compose -f /opt/authentik/docker-compose.yml exec server ak check_config
/-/health/ready/ จะ return 200 OK เมื่อ Authentik พร้อมรับ request จริงๆ ใช้ endpoint นี้สำหรับ health check ใน load balancer หรือ uptime monitorแก้ปัญหาที่พบบ่อย
Error: "CSRF verification failed. Request aborted."
เกิดเมื่อ Nginx ไม่ส่ง header X-Forwarded-Proto ให้ Authentik ทำให้ระบบ CSRF ตรวจสอบ protocol ผิดพลาด
# แก้ไขใน Nginx config — เพิ่ม header เหล่านี้ใน location block
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $http_host;
# รัน certbot หากยังใช้ HTTP อยู่
sudo certbot --nginx -d auth.example.com
sudo nginx -t && sudo systemctl reload nginx
Error: "relation 'authentik_core_application' does not exist"
Database migration ยังไม่เสร็จสมบูรณ์ หรือ PostgreSQL container ยังไม่พร้อม
# รอให้ server container healthy แล้วรัน migration manually
docker compose -f /opt/authentik/docker-compose.yml exec server ak migrate
# ดู migration status
docker compose -f /opt/authentik/docker-compose.yml logs server | grep -i "migrat"
# Restart containers ถ้ายังมีปัญหา
docker compose -f /opt/authentik/docker-compose.yml restart
Error: "No such file or directory: /certs/..."
Worker container ต้องการ directory certs/ สำหรับ certificate management
mkdir -p /opt/authentik/certs /opt/authentik/media /opt/authentik/custom-templates
chown -R 1000:1000 /opt/authentik/media /opt/authentik/certs
docker compose -f /opt/authentik/docker-compose.yml up -d
Error: "authentik.lib.config — Config value X is not set"
ค่า environment variable ใน .env ขาดหรือ format ผิด
# ตรวจสอบว่า .env โหลดได้ถูกต้อง
cd /opt/authentik && docker compose config | grep -A 5 "environment:"
# ดู variables ที่ตั้งไว้
cat /opt/authentik/.env
# ตรวจสอบ secret key ไม่มีอักขระพิเศษที่ทำให้ YAML parser สับสน
grep AUTHENTIK_SECRET_KEY /opt/authentik/.env
Authentik login loop — redirect วนซ้ำไม่หยุด
มักเกิดจาก cookie domain ไม่ตรงกัน หรือ reverse proxy ไม่ส่ง header ที่ถูกต้อง
# ตรวจสอบ Authentik config
docker compose -f /opt/authentik/docker-compose.yml exec server ak check_config
# ล้าง browser cookies แล้วลองใหม่
# หรือเข้าใน incognito mode
# ตรวจสอบ Nginx config ให้มี upgrade header สำหรับ WebSocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
คำถามที่พบบ่อย
Authentik รองรับ protocol อะไรบ้าง?
Authentik รองรับ OAuth2/OIDC, SAML2, LDAP (สำหรับ application ที่ต้องการ LDAP), RADIUS, SCIM (สำหรับ user provisioning), และ forward authentication สำหรับ Nginx/Traefik/Caddy — ครอบคลุม use case เกือบทุกอย่างในองค์กรหรือ homelab
Authentik ต้องการ RAM เท่าไหร่?
สำหรับ production แนะนำ 2–4 GB RAM: server container ใช้ประมาณ 500 MB, worker ใช้ 300 MB, PostgreSQL ใช้ 200–500 MB ขึ้นกับ workload และ Redis ใช้น้อยมาก ต่ำกว่า 1 GB RAM ทั้งหมดจะทำให้ระบบช้าหรือ crash ได้
อัปเกรด Authentik เป็น version ใหม่ทำอย่างไร?
แก้ tag image ใน docker-compose.yml แล้วรัน pull และ up:
# แก้ image tag เป็น version ใหม่
sed -i 's/server:2024.12/server:2025.2/g' /opt/authentik/docker-compose.yml
# Pull image ใหม่และ restart
cd /opt/authentik
docker compose pull
docker compose up -d
# ดู migration log
docker compose logs -f server | grep -i "migrat"