Adit Rakhman
Adit Rakhman
Published on 2026-06-19 / 3 Visits
1
0

Terbongkar! Ini Dia Portal IAM Ringan, Gunakan Authelia!

Selamat malam sobat isiotak, kali ini saya akan membahas IAM (Identity and Access Management) portal ringan, seringan tanggapan pejabat pemerintah dalam menanggapi isu yang beredar di masyarakat. Ehhh..., maksud saya IAM portal ringan yaitu Authelia. Saya sendiri menggunakan Authelia sebagai portal untuk dashboard dan aplikasi yang tidak memiliki IAM portal bawaan. Sobat isiotak bisa dengan mudah untuk men-deploy Authelia dengan docker dan bisa ditempatkan di VPS atau di PC.

Terus mengapa menggunakan Authelia? Jelas, saya tidak ingin informasi yang ada di dalam dashboard dan aplikasi saya terekspos dengan bebas, lalu bisa seenaknya dilihat oleh Antek Asing! Oleh karena itu, saya menggunakan Authelia. Selain itu, Authelia juga ringan, jika sobat isiotak lihat dari dokumentasi Authelia, penggunaan RAM normal dari Authelia itu hanya sekitar 20-30 megabytes, gokil kan?

Sobat isiotak seharusnya masih ingat dengan Traefik kan? Kalau lupa bisa kunjungi URL di bawah ini.

https://www.isiotak.com/archives/migrasi-dari-nginx-proxy-manager-ke-traefik

Nantinya saya akan mengintegrasikan Authelia dengan Traefik untuk menambah fitur keamanannya sebagai portal dari dashboard dan aplikasi kita. Oke, langsung saja kita masuk ke cara deploy-nya.

Docker Compose Authelia

Kalian bisa dengan mudah untuk mendapatkan file docker compose Authelia dengan clone dari repositori yang sudah saya buat.

git clone https://github.com/uvewexyz/authelia-docker-compose.git

Atau bisa salin source code-nya di bawah ini:

secrets:
  JWT_SECRET:
    file: ~/authelia/secrets/JWT_SECRET
  SESSION_SECRET:
    file: ~/authelia/secrets/SESSION_SECRET
  STORAGE_PASSWORD:
    file: ~/authelia/secrets/STORAGE_PASSWORD
  STORAGE_ENCRYPTION_KEY:
    file: ~/authelia/secrets/STORAGE_ENCRYPTION_KEY
  SMTP_PASSWORD:
    file: ~/authelia/secrets/SMTP_PASSWORD

services:
  authelia:
    image: authelia/authelia
    container_name: "authelia"
    volumes:
      - "/var/log/authelia:/var/log/authelia"
      - "./config:/config"
    networks:
      - proxy
      - backend
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.authelia.rule=Host(`authelia.local.domain.tld`)"
      - "traefik.http.routers.authelia.entrypoints=websecure"
      - "traefik.http.routers.authelia.tls=true"
      - "traefik.http.routers.authelia.tls.certresolver=le"
      - "traefik.http.routers.authelia.service=authelia"
      - "traefik.http.services.authelia.loadbalancer.server.port=9091"

      - "traefik.http.middlewares.authelia.forwardauth.address=http://authelia:9091/api/authz/forward-auth"
      - "traefik.http.middlewares.authelia.forwardauth.trustForwardHeader=true"
      - "traefik.http.middlewares.authelia.forwardauth.maxResponseBodySize=10485760"
      - "traefik.http.middlewares.authelia.forwardauth.maxBodySize=10485760"
      - "traefik.http.middlewares.authelia.forwardauth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Name,Remote-Email"
    restart: unless-stopped
    healthcheck:
      disable: true
    secrets: 
      - JWT_SECRET
      - SESSION_SECRET
      - STORAGE_PASSWORD
      - STORAGE_ENCRYPTION_KEY
      - SMTP_PASSWORD
    environment:
      - "AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE=/run/secrets/JWT_SECRET"
      - "AUTHELIA_SESSION_SECRET_FILE=/run/secrets/SESSION_SECRET"
      - "AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE=/run/secrets/STORAGE_PASSWORD"
      - "AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE=/run/secrets/STORAGE_ENCRYPTION_KEY"
      - "AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE=/run/secrets/SMTP_PASSWORD"
      - "AUTHELIA_LOG_LEVEL=info"

networks:
  proxy:
    external: true
  backend:
    external: true

Lalu, sobat isiotak bisa membuat dua direktori untuk menyimpan file konfigurasi dan file secret.

mkdir config secrets

Di dalam direktori config, buat 2 file yaitu configuration.yml dan users_database.yml.

File configuration.yml berisi parameter yang sudah ditentukan dan disesuaikan dengan kebutuhan saya, jika sobat isiotak ingin menyesuaikannya lagi, bisa melihat template-nya di bawah ini:

https://github.com/authelia/authelia/blob/master/config.template.yml

# Konfigurasi alamat server dari Authelia.
server:
  address: 'tcp://:9091'
  asset_path: '/config/assets/'
  disable_healthcheck: true

# Tema dari Authelia, pilihan yang tersedia: light, dark, grey, auto.
theme: 'grey'

# Konfigurasi fitur TOTP pada Authelia.
totp:
  disable: false
  algorithm: 'sha256'
  issuer: 'Authelia'
  period: 30
  skew: 1

# Konfigurasi WebAuthn.
webauthn:
  disable: true

# Konfigurasi untuk memvalidasi identias user, fitur ini dipakai pada reset password dan antisipasi elevasi sesi dari user.
identity_validation:
  reset_password:
    jwt_lifespan: '10m'
    jwt_algorithm: 'HS512'

# Konfigurasi level, format, dan tempat log disimpan.
log:
  level: 'info'
  file_path: '/var/log/authelia/authelia.log'
  keep_stdout: false

# Konfigurasi untuk metric Authelia (untuk monitoring biasanya).
telemetry:
  metrics:
    enabled: false

# Konfigurasi untuk menyimpan informasi detail dari user, memilih algoritma hashing untuk user, dan cara menyimpan konfignya (bentuk file atau LDAP.
authentication_backend:
  file:
    path: '/config/users_database.yml'
    watch: true
    password:
      algorithm: 'argon2'
      argon2:
        variant: 'argon2id'
        iterations: 3
        memory: 65536
        salt_length: 16
        parallelism: 4
        key_length: 32

# Konfigurasi untuk mengontrol aturan seperti bypass, two_factor, deny ke subjek seperti domain atau IP address.
access_control:
  default_policy: 'deny'
  rules:
    - domain:
      - 'app1.local.domain.tld'
      - 'app2.local.domain.tld'
      - 'nginx.local.domain.tld'
      - 'app3.local.domain.tld'
      policy: 'two_factor'

# Konfigurasi untuk tempat menyimpan cookies dari user, bisa menggunakan memory ataupun redis.
session:
  cookies:
    - domain: 'local.domain.tld'
      authelia_url: 'https://authelia.local.domain.tld'
      name: 'authelia_session'
      same_site: 'lax'
      expiration: '12h'
      remember_me: -1

# Konfigurasi untuk mencegah akses brute-force.
regulation:
  modes:
    - 'ip'
  max_retries: 3
  find_time: '2 minutes'
  ban_time: '5 minutes'

# Konfigurasi untuk penyimpanan seperti preferensi user, perangkat 2FA, secrets, dan log dari Authelia.
storage:
  postgres:
    address: 'tcp://postgresql:5432'
    database: 'authelia_db'
    username: 'authelia'

# Konfigurasi untuk notifikasi dari Authelia, bisa dengan file lokal di system atau bisa dengan SMTP.
notifier:
  smtp:
    username: 'yourgmail@gmail.com'
    address: 'submission://smtp.gmail.com:587'
    sender: 'authelia@local.domain.tld'
    startup_check_address: 'yourgmail@gmail.com'

Selanjutnya, masih di dalam direktori config, buat file users_database.yml. Untuk template-nya, sobat isiotak bisa mengunjungi URL di bawah ini:

https://github.com/authelia/authelia/blob/master/examples/compose/local/authelia/users_database.yml

users:
  userone:
    disabled: false
    displayname: 'userone'
    # Generate below command to encrypt string password
    # docker run --rm authelia/authelia:latest authelia crypto hash generate argon2 --password 'Us3r_0n3'
    # Detail https://www.authelia.com/reference/guides/passwords/#passwords
    # password decrypt: Us3r_0n3
    password: '$argon2id$v=19$m=65536,t=3,p=4$TEYAOC4n0ttFVJQ3RSQf3A$rBMPvp691RQHwMoRYJtZfn2Jq7IHC/Q2qRGpSd9qjJM'
    email: 'userone@gmail.com'
    groups:
      - 'admins'
      - 'dev'

Oke, sebelum lanjut ke konfigurasi Traefik. Coba untuk cek pada file configuration.yml. Karena pada parameter storage: saya menentukan storage backend-nya adalah PostgreSQL, kita harus membuat docker compose untuk kontainer PostgreSQL-nya. Sobat isiotak bisa melihat konfigurasinya di bawah ini:

services:
  postgresql:
    container_name: postgresql
    environment:
      - "POSTGRES_DB=${PG_DB}"
      - "POSTGRES_PASSWORD=${PG_PASS}"
      - "POSTGRES_USER=${PG_USER}"
    healthcheck:
      interval: 1m
      retries: 5
      start_period: 20s
      test:
        - CMD-SHELL
        - pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}
      timeout: 5s
    image: docker.io/library/postgres:16-alpine
    restart: unless-stopped
    env_file:
      - .env
    volumes:
      - database:/var/lib/postgresql/data
    networks:
      - backend

volumes:
  database:
    driver: local

networks:
  backend:
    external: true

Jangan lupa membuat file .env untuk variabel secret dari kontainer PostgreSQL

PG_DB=authelia_db

# Digenerate dari command di bawah ini
# LENGTH=64 && tr -cd '[:alnum:]' < /dev/urandom | fold -w "${LENGTH}" | head -n 1 | tr -d '\n' ; echo
PG_PASS=BQ4IDMblACfU8Bx7u7S0UJou1FsUS8fqBRnQ5GxP4uYlxVpcWJBk88yw3fKlg1L1

PG_USER=authelia

Lanjut, di dalam direktori secret buat beberapa file secret seperti di bawah ini:

  • JWT_SECRET

  • SESSION_SECRET

  • STORAGE_ENCRYPTION_KEY

  • STORAGE_PASSWORD

Generate perintah di bawah ini, nanti hasilnya bisa sobat salin ke dalam file-file tersebut.

LENGTH=64 && tr -cd '[:alnum:]' < /dev/urandom | fold -w "${LENGTH}" | head -n 1 | tr -d '\n' ; echo

Ada opsi lainnya, untuk menghasilkan secret tersebut, kunjungi url di bawah ini:

https://www.authelia.com/reference/guides/generating-secure-values/#generating-a-random-alphanumeric-string

Lalu buat satu file secret lagi yaitu SMTP_PASSWORD, untuk menyimpan app password dari gmail.

Konfigurasi Traefik

Untuk konfigurasi docker compose dari Traefik, sobat isiotak bisa clone repository saya yang ada di bawah ini:

git clone git@github.com:uvewexyz/traefik-docker-compose.git

Lalu pilih file traefik-compose.yml_authelia dan ganti ekstensinya menjadi .yml saja. Atau bisa salin source code di bawah ini:

services:
  traefik:
    image: "traefik:v3.6.11"
    container_name: "traefik"
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true

    networks:
      - proxy

    ports:
      - "80:80"
      - "443:443"

    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "/var/log/traefik/:/var/log/traefik/"
      - "~/traefik/conf/traefik.yaml:/etc/traefik/traefik.yaml:ro"
      - "~/traefik/conf/:/etc/traefik/conf"
      - "~/traefik/certs/:/certs"
    
    environment:
      - "TZ=${TZ}"
      - "CLOUDFLARE_EMAIL=${CF_API_EMAIL}"
      - "CLOUDFLARE_DNS_API_TOKEN=${CF_DNS_API_TOKEN}"

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=websecure"
      - "traefik.http.routers.traefik.rule=Host(`traefik.example.com`)"
      - "traefik.http.routers.traefik.tls=true"
      - "traefik.http.routers.traefik.service=api@internal"
      - "traefik.http.routers.traefik.tls.certresolver=le"

      # Traefik with authelia portal security
      - "traefik.http.routers.traefik.middlewares=authelia@docker,traefik-headers,traefik-ratelimit"

      - "traefik.http.middlewares.traefik-headers.headers.frameDeny=true"
      - "traefik.http.middlewares.traefik-headers.headers.browserXssFilter=true"
      - "traefik.http.middlewares.traefik-headers.headers.contentTypeNosniff=true"
      - "traefik.http.middlewares.traefik-headers.headers.stsSeconds=31536000"
      - "traefik.http.middlewares.traefik-headers.headers.stsIncludeSubdomains=true"
      - "traefik.http.middlewares.traefik-headers.headers.forceSTSHeader=true"
      - "traefik.http.middlewares.traefik-headers.headers.referrerPolicy=same-origin" 
      - "traefik.http.middlewares.traefik-headers.headers.customResponseHeaders.Server="
      - "traefik.http.middlewares.traefik-headers.headers.customResponseHeaders.X-Powered-By="

      - "traefik.http.middlewares.traefik-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.traefik-ratelimit.ratelimit.period=2s"
      - "traefik.http.middlewares.traefik-ratelimit.ratelimit.burst=200"

networks:
  proxy:
    name: proxy

Buat juga file .env dan sesuaikan value dari variable-nya kredensial di bawah ini:

CF_API_EMAIL="examplemail@yourmail.com"
CF_DNS_API_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
TZ="xxx/xxx"
BASIC_AUTH="admin:$$xx$$xx$$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Buat direktori conf untuk menyimpan konfig dari Traefik dan buat juga direktori certs untuk menyimpan file sertifikat yang dihasilkan Traefik, untuk direktori certs biarkan kosong saja, karena nanti akan diisi otomatis oleh Traefik.

Buat file traefik.yaml di dalam direktori conf dan salin isinya seperti di bawah ini:

global:
  sendAnonymousUsage: false

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
          permanent: true
  websecure:
    address: ":443"
    http:
      tls: {}

providers:
  docker:
    exposedByDefault: false
    endpoint: "unix:///var/run/docker.sock"
    network: proxy
    watch: true

  file:
    directory: "/etc/traefik/dynamic"
    watch: true

api:
  dashboard: true
  insecure: false

serversTransport:
  insecureSkipVerify: true

log:
  level: INFO
  filepath: "/var/log/traefik/traefik.log"

accessLog:
  filepath: "/var/log/traefik/access.log"

certificatesResolvers:
  le:
    acme:
      email: examplemail@yourmail.com
      # I recommend to try deploy with staging caServer, if successfully you can comment it.
      # caServer: https://acme-staging-v02.api.letsencrypt.org/directory
      storage: /certs/acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"

Headers And Rate Limit Middleware

Jadi sobat isiotak, bisa diperhatikan pada label dari docker compose Traefik. Pada bagian di bawah ini:

- "traefik.http.routers.traefik.middlewares=authelia@docker,traefik-headers,traefik-ratelimit"

Pada value pertama label tersebut, gunakan middleware dari Authelia, karena saya hanya menentukan label Authelia langsung di docker compose-nya, tulis saja authelia@docker.

Kemudian lihat pada middleware kedua yaitu traefik-headers. Middleware headers ini memuat beberapa label yaitu:

Label

Fungsi

"traefik.http.middlewares.traefik-headers.headers.frameDeny=true"

Mencegah halaman web bisa diselipkan frame web lainnya di dalam elemen seperti iframe, frame, embed, ataupun object

"traefik.http.middlewares.traefik-headers.headers.browserXssFilter=true"

Mencegah halaman web diselipkan skrip/kode Javascript berbahaya melalui parameter URL atau form

"traefik.http.middlewares.traefik-headers.headers.contentTypeNosniff=true"

Mencegah browser untuk memindai tipe file yang dikirim server, sehingga jika ada kode JS berbahaya di dalam file gambar atau teks tidak akan tereksekusi

"traefik.http.middlewares.traefik-headers.headers.stsSeconds=31536000"

Memaksa web browser hanya terhubung ke halaman kita hanya melalui HTTPS selama tepat satu tahun

"traefik.http.middlewares.traefik-headers.headers.stsIncludeSubdomains=true"

Fungsinya sama seperti header HSTS (HTTP Strict Transport Security) di atas yang memaksa semua subdomain kita untuk terhubung dengan HTTPS

"traefik.http.middlewares.traefik-headers.headers.forceSTSHeader=true"

Memaksa Traefik untuk menyisipkan header HSTS (HTTP Strict-Transport-Security) ke dalam respon, bahkan jika request awal terhubung dengan HTTP

"traefik.http.middlewares.traefik-headers.headers.referrerPolicy=same-origin"

Mencegah detail informasi dari header Referer halaman web kita terkirim ketika pindah halaman web lainnya

"traefik.http.middlewares.traefik-headers.headers.customResponseHeaders.Server="

Memaksa Traefik untuk menyembunyikan atau menghapus respon header yang memuat software web server yang digunakan halaman web

"traefik.http.middlewares.traefik-headers.headers.customResponseHeaders.X-Powered-By="

Kurang lebih fungsinya sama seperti parameter di atasnya

Middleware ketiga yaitu traefik-ratelimit, berikut penjelasannya

Label

Fungsi

"traefik.http.middlewares.traefik-ratelimit.ratelimit.average=100"

Disini saya mengizinkan untuk rata-rata request sebanyak 100

"traefik.http.middlewares.traefik-ratelimit.ratelimit.period=2s"

Nah 100 request di atas, diizinkan selama 2 detik. Jadi jika selama 2 detik request lebih dari 100 maka hasilnya respons 429 Too Many Requests

"traefik.http.middlewares.traefik-ratelimit.ratelimit.burst=200"

Burst 200 berfungsi hanya ketika ada lonjakan akses/trafik. Jadi batas maksimum request yang boleh masuk sekaligus itu 200

Compose UP!

docker compose -f traefik-compose.yaml up
docker compose -f postgresql-compose.yaml up
docker compose -f authelia-compose.yaml up

Pastikan semua service dari docker compose UP!

Setup Authelia

Jika service docker compose Authelia UP! Akses dashboardnya dengan mengunjungi url https://authelia.local.domain.tld:9091. Sesuaikan ya dengan url masing-masing milik sobat isiotak.

image-fzgh.png

Akses dengan kredensial yang ada di file users_database.yml. Selanjutnya sobat isiotak bisa melihat konfigurasinya seperti gambar di bawah ini, cukup mudah bukan?

image-lldv.png
image-o5l3.png
image-az9j.png

Untuk pengecekan lainnya bisa akses dashboard Traefik, seharusnya ketika pertama kali akses akan diarahkan ke dashboard Authelia, untuk login terlebih dahulu. Sobat isiotak juga bisa test middleware dari header yang sudah dibuat. Jalankan perintah di bawah ini:

curl -k -I https://traefik.local.domain.tld

Seharusnya respons-nya akan HTTP/2 302, karena URL ke Traefik akan dialihkan ke dashboard Authelia terlebih dahulu. Lalu akan ada output seperti di bawah ini:

x-content-type-options: nosniff
x-dns-prefetch-control: off
x-frame-options: DENY

Untuk testing rate limit sobat isiotak bisa coba untuk restart dashboard Authelia berkali-kali secara spam dan hasilnya seharusnya respon 429 (Too Many Requests)

image-nyrt.png

Referensi

https://www.authelia.com/integration/deployment/docker/#standalone-example

https://github.com/authelia/authelia/blob/v4.39.19/config.template.yml

https://www.authelia.com/reference/guides/passwords/

https://www.authelia.com/reference/guides/generating-secure-values/#generating-a-random-alphanumeric-string

https://github.com/uvewexyz/authelia-docker-compose

https://www.isiotak.com/archives/migrasi-dari-nginx-proxy-manager-ke-traefik#5.-compose-up!

https://github.com/uvewexyz/traefik-docker-compose


Comment