Ubuntu 24.04 에 Ory Kratos 오픈 소스 ID 및 사용자 관리 시스템 배포

작성자

카테고리:

← 피드로
DEV Community · Sanskriti Harmukh · 2026-06-24 개발(SW)

Ory Kratos is an open-source, API-first identity and user management system handling registration, login, recovery, verification, and session management with a self-service UI. This guide deploys Kratos using Docker Compose with PostgreSQL, the self-service UI Node, and Traefik handling automatic HTTPS for the public API. By the end, you’ll have Kratos managing identities and sessions for users registering through your domain over HTTPS.

Prerequisite: SMTP credentials are required for verification and recovery emails. The admin API stays bound to 127.0.0.1 on purpose — never expose it publicly.

Set Up the Directory Structure

1. Create the project directories:

$ mkdir -p ~/ory-kratos/{config,data/postgres}
$ cd ~/ory-kratos

Enter fullscreen mode Exit fullscreen mode

2. Create the environment file:

$ nano .env

Enter fullscreen mode Exit fullscreen mode

DOMAIN=kratos.example.com
[email protected]
KRATOS_VERSION=v26.2.0
POSTGRES_USER=kratos
POSTGRES_PASSWORD=EXAMPLE_DB_PASSWORD
POSTGRES_DB=kratosdb
LOG_LEVEL=info

Enter fullscreen mode Exit fullscreen mode

3. Create the identity schema — defines the user fields (email + name) and how the email maps to login, recovery, and verification:

$ nano config/identity.schema.json

Enter fullscreen mode Exit fullscreen mode

Use the schema described in the Vultr Docs walkthrough — email is the login identifier with password auth; name is a free-text trait.

4. Create the Kratos configuration — public/admin API URLs, password policy (12-char minimum + HaveIBeenPwned), session lifetimes, self-service flows, SMTP courier:

$ nano config/kratos.yml

Enter fullscreen mode Exit fullscreen mode

Fill in the full configuration from the source article. Key points to keep consistent with the stack below:

  • Public API listens on the internal port and is fronted by Traefik on ${DOMAIN}.
  • Admin API listens on 127.0.0.1:4434 only — used by tooling on the host.
  • The DSN points at the postgres service (postgres://kratos:...@postgres:5432/kratosdb?sslmode=disable).
  • The courier section uses your SMTP provider for verification mail.

Deploy with Docker Compose

1. Create the Compose manifest:

$ nano docker-compose.yml

Enter fullscreen mode Exit fullscreen mode

services:
  traefik:
    image: traefik:v3.6
    container_name: traefik
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencrypt.acme.email=${LETSENCRYPT_EMAIL}"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
    restart: unless-stopped

  postgres:
    image: postgres:16
    container_name: kratos-postgres
    environment:
      POSTGRES_USER: ${POSTGRES_USER}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
    volumes:
      - ./data/postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "${POSTGRES_USER}", "-d", "${POSTGRES_DB}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  kratos-migrate:
    image: oryd/kratos:${KRATOS_VERSION}
    container_name: kratos-migrate
    depends_on:
      postgres:
        condition: service_healthy
    volumes:
      - ./config:/etc/config/kratos:ro
    environment:
      DSN: "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable"
    command: migrate -c /etc/config/kratos/kratos.yml sql -e --yes

  kratos:
    image: oryd/kratos:${KRATOS_VERSION}
    container_name: kratos
    depends_on:
      kratos-migrate:
        condition: service_completed_successfully
    volumes:
      - ./config:/etc/config/kratos:ro
    environment:
      DSN: "postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}?sslmode=disable"
      LOG_LEVEL: ${LOG_LEVEL}
    command: serve -c /etc/config/kratos/kratos.yml --watch-courier
    ports:
      - "127.0.0.1:4434:4434"
    expose:
      - "4433"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.kratos.rule=Host(`${DOMAIN}`) && PathPrefix(`/.ory/kratos/public`)"
      - "traefik.http.routers.kratos.entrypoints=websecure"
      - "traefik.http.routers.kratos.tls.certresolver=letsencrypt"
      - "traefik.http.services.kratos.loadbalancer.server.port=4433"
    restart: unless-stopped

  kratos-ui:
    image: oryd/kratos-selfservice-ui-node:${KRATOS_VERSION}
    container_name: kratos-ui
    depends_on:
      - kratos
    environment:
      KRATOS_PUBLIC_URL: https://${DOMAIN}/.ory/kratos/public
      KRATOS_BROWSER_URL: https://${DOMAIN}/.ory/kratos/public
    expose:
      - "3000"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.kratos-ui.rule=Host(`${DOMAIN}`)"
      - "traefik.http.routers.kratos-ui.entrypoints=websecure"
      - "traefik.http.routers.kratos-ui.tls.certresolver=letsencrypt"
      - "traefik.http.services.kratos-ui.loadbalancer.server.port=3000"
    restart: unless-stopped

Enter fullscreen mode Exit fullscreen mode

2. Start the stack:

$ docker compose up -d
$ docker compose ps -a
$ docker compose logs

Enter fullscreen mode Exit fullscreen mode

Health Checks

1. Probe the admin API on the loopback:

$ docker compose exec kratos wget -qO- http://127.0.0.1:4434/health/alive

Enter fullscreen mode Exit fullscreen mode

2. Probe the public API over HTTPS:

$ curl -s https://kratos.example.com/.ory/kratos/public/health/alive

Enter fullscreen mode Exit fullscreen mode

3. Confirm the self-service UI loads:

$ curl -s -o /dev/null -w "%{http_code}" https://kratos.example.com/

Enter fullscreen mode Exit fullscreen mode

Register and Sign In via the API

1. Open a registration flow:

$ curl -s https://kratos.example.com/.ory/kratos/public/self-service/registration/api

Enter fullscreen mode Exit fullscreen mode

Capture the id from the response — it’s the FLOW_ID below.

2. Submit the registration:

$ curl -s -X POST \
    "https://kratos.example.com/.ory/kratos/public/self-service/registration?flow=FLOW_ID" \
    -H 'Content-Type: application/json' \
    -d '{
      "method": "password",
      "password": "YOUR-PASSWORD",
      "traits": {
        "email": "YOUR-EMAIL",
        "name": { "first": "FIRST-NAME", "last": "LAST-NAME" }
      }
    }'

Enter fullscreen mode Exit fullscreen mode

3. List identities through the admin API:

$ docker compose exec kratos wget -qO- http://127.0.0.1:4434/admin/identities

Enter fullscreen mode Exit fullscreen mode

4. Sign in:

$ curl -s https://kratos.example.com/.ory/kratos/public/self-service/login/api
$ curl -s -X POST \
    "https://kratos.example.com/.ory/kratos/public/self-service/login?flow=FLOW_ID" \
    -H 'Content-Type: application/json' \
    -d '{
      "method": "password",
      "identifier": "YOUR-EMAIL",
      "password": "YOUR-PASSWORD"
    }'

Enter fullscreen mode Exit fullscreen mode

5. Verify the session:

$ curl -s https://kratos.example.com/.ory/kratos/public/sessions/whoami \
    -H "X-Session-Token: SESSION_TOKEN"

Enter fullscreen mode Exit fullscreen mode

Next Steps

Kratos is running with PostgreSQL persistence, the self-service UI, and HTTPS in front of the public API. From here you can:

  • Add social sign-in (Google, GitHub, Apple) through the OIDC provider list
  • Wire Kratos sessions to other services via Ory Oathkeeper or forward-auth
  • Use Ory Hydra alongside Kratos to expose OpenID Connect to client apps

For the full guide with additional tips, visit the original article on Vultr Docs.

원문에서 계속 ↗

코멘트

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다