diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..801b422 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +.git/ +.gitignore +*.md +*.postman_collection.json +*.postman_environment.json +example_bulk_request.json +install-authelia-api.sh +docker/configuration.yml.example +docker/compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e3f9858 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +# syntax=docker/dockerfile:1 +# +# Authelia + Authelia-API combined container +# =========================================== +# Runs both Authelia (auth portal, port 9091) and Authelia-API +# (user management API, port 8080) in a single container. +# +# Volumes: +# /config — Authelia config + user DB + notification templates +# /data — Authelia-API SQLite DB +# /certs — TLS certificates (optional) +# + +# --- Stage 1: fetch Authelia binary --- +FROM alpine:3.21 AS authelia-dl + +ARG AUTHELIA_VERSION=4.39.20 +ARG TARGETARCH=amd64 +ARG TARGETPLATFORM=linux/amd64 + +WORKDIR /tmp +ADD https://github.com/authelia/authelia/releases/download/v${AUTHELIA_VERSION}/authelia-v${AUTHELIA_VERSION}-linux-${TARGETARCH}.tar.gz /tmp/authelia.tar.gz +RUN tar -xzf /tmp/authelia.tar.gz && \ + mv authelia /usr/local/bin/authelia && \ + chmod +x /usr/local/bin/authelia + +# --- Stage 2: runtime image (glibc-based for Authelia binary) --- +FROM debian:bookworm-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + tzdata \ + libsqlite3-0 \ + netcat-openbsd \ + && rm -rf /var/lib/apt/lists/* + +# Copy binaries +COPY --from=authelia-dl /usr/local/bin/authelia /usr/local/bin/authelia +COPY authelia-api /usr/local/bin/authelia-api + +# Create directories +RUN mkdir -p /config /data /certs && \ + chmod 755 /config /data /certs + +# Add non-root user +RUN groupadd -r authelia && \ + useradd -r -g authelia -d /config -s /sbin/nologin authelia && \ + chown authelia:authelia /config /data /certs + +# Entrypoint +COPY docker/entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +EXPOSE 9091 8080 + +VOLUME ["/config", "/data", "/certs"] + +ENTRYPOINT ["/entrypoint.sh"] diff --git a/README.md b/README.md index e8ba3e9..6a739b0 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,28 @@ curl -fsSL https://git.lohmar.co.uk/cclohmar/autehlia-api/raw/branch/main/instal sudo ./install-authelia-api.sh ``` +### Docker Deployment + +A combined container with **both Authelia and Authelia-API** is available on Docker Hub: + +```bash +# Create config directory with your Authelia configuration +mkdir -p config data certs +# Copy and edit the example config: +# docker/configuration.yml.example → config/configuration.yml +# Set secrets, domains, and other settings. + +# Pull and start +docker compose up -d +``` + +| Port | Service | +|------|---------| +| `9091` | Authelia web portal | +| `8080` | Authelia-API (user management API) | + +The container handles first-time bootstrap automatically — the admin user is created using the `session.secret` value from your Authelia config as the API bearer token. + ### Development Installation For building from source, see the [src/README.md](src/README.md) file. @@ -71,6 +93,9 @@ See [POSTMAN_GUIDE.md](POSTMAN_GUIDE.md) for detailed instructions. - `authelia-api` - Ready-to-use binary (production) - `install-authelia-api.sh` - Installation script +- `Dockerfile` - Combined Authelia + Authelia-API container image +- `docker-compose.yml` - Quick Docker deployment with volumes +- `docker/` - Container entrypoint and configuration templates - `POSTMAN_GUIDE.md` - API testing guide - `src/` - Source code and build instructions - `authelia-api.postman_collection.json` - Postman collection @@ -78,7 +103,9 @@ See [POSTMAN_GUIDE.md](POSTMAN_GUIDE.md) for detailed instructions. ## Production Deployment -The repository provides a ready-to-deploy binary. The installation script handles: +**Docker** (recommended): Use `docker compose up -d` — see [Docker Deployment](#docker-deployment) above. + +**Bare-metal**: The repository also provides a ready-to-deploy binary. The installation script handles: - Systemd service creation - Database setup - Configuration generation diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..3187b17 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,37 @@ +# ============================================================================= +# Authelia + Authelia-API Docker Compose +# ============================================================================= +# Usage: +# docker compose up -d +# +# Before first run: +# 1. Edit ./config/configuration.yml — set secrets, domains, etc. +# 2. Make sure ./config/users_database.yml exists (can be empty) +# 3. Adjust volumes to match your host paths +# ============================================================================= + +services: + authelia: + image: git24hcom/authelia:latest + container_name: authelia + restart: unless-stopped + ports: + - "9091:9091" # Authelia web portal + - "8080:8080" # Authelia-API + volumes: + - ./config:/config # Authelia config, user DB, notifications + - ./data:/data # Authelia-API database + - ./certs:/certs # TLS certificates (optional) + environment: + - TZ=UTC + # Authelia-API settings (override defaults if needed) + # - AUTHELIA_API_LISTEN=0.0.0.0:8080 + # - AUTHELIA_API_LOG_LEVEL=info + # Authelia settings + # - AUTHELIA_CONFIG=/config/configuration.yml + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:9091/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 15s diff --git a/docker/configuration.yml.example b/docker/configuration.yml.example new file mode 100644 index 0000000..8317bb6 --- /dev/null +++ b/docker/configuration.yml.example @@ -0,0 +1,99 @@ +####################################################### +# Authelia Configuration — Docker combined container +# ===================================================== +# Authelia v4.39.20 format (YAML). +# Mount this file to /config/configuration.yml inside +# the container, or edit the in-container copy. +# +# Reference: +# https://www.authelia.com/configuration/ +####################################################### + +# --- Server --- +server: + address: tcp://0.0.0.0:9091 + tls: + key: /certs/key.pem # optional, mount into /certs + certificate: /certs/cert.pem + +# --- Logging --- +log: + level: info + format: text + +# --- Theme --- +theme: auto + +# --- Identity validation (replaces jwt_secret) --- +identity_validation: + reset_password: + jwt_secret: change_me_to_a_random_hex_string_at_least_64_chars_long + +# --- Default redirect --- +default_redirection_url: https://auth.example.com + +# --- TOTP --- +totp: + issuer: authelia.example.com + period: 30 + skew: 1 + +# --- Authentication backend: file-based --- +authentication_backend: + file: + path: /config/users_database.yml + password: + algorithm: argon2id + iterations: 1 + salt_length: 16 + parallelism: 8 + memory: 64 + +# --- Access Control (at least one rule required) --- +access_control: + default_policy: two_factor + rules: + - domain: auth.example.com + policy: bypass + resources: + - "^/api/health$" + +# --- Session --- +session: + name: authelia_session + secret: change_me_to_a_random_hex_string_at_least_64_chars_long + expiration: 1h + inactivity: 5m + remember_me: 1M + domain: example.com + +# --- Regulation (login rate limiting) --- +regulation: + max_retries: 5 + find_time: 2m + ban_time: 5m + +# --- Storage: local SQLite --- +storage: + encryption_key: change_me_to_a_random_hex_string_at_least_64_chars_long + local: + path: /config/db.sqlite3 + +# --- Notifier --- +notifier: + filesystem: + filename: /config/notifications.yml + +# --- WebAuthn (optional) --- +# webauthn: +# disable: false +# display_name: Authelia +# attestation_conveyance_preference: indirect +# user_verification: preferred +# timeout: 60s + +# --- OIDC (optional) --- +# identity_providers: +# oidc: +# hmac_secret: change_me_to_a_random_hex_string +# issuers: [] diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh new file mode 100755 index 0000000..2033253 --- /dev/null +++ b/docker/entrypoint.sh @@ -0,0 +1,176 @@ +#!/bin/sh +# ============================================================================= +# Authelia + Authelia-API Container Entrypoint +# +# Starts both services, monitors their health, and handles graceful shutdown. +# Authelia-API runs through a supervisor loop since it is the secondary service. +# ============================================================================= +set -e + +# --- Configuration defaults (overridable via env) --- +AUTHELIA_CONFIG="${AUTHELIA_CONFIG:-/config/configuration.yml}" +AUTHELIA_API_LISTEN="${AUTHELIA_API_LISTEN:-0.0.0.0:8080}" +AUTHELIA_API_DB="${AUTHELIA_API_DB:-/data/authelia-api.db}" +AUTHELIA_API_LOG_LEVEL="${AUTHELIA_API_LOG_LEVEL:-info}" +AUTHELIA_PORT="${AUTHELIA_PORT:-9091}" + +# --- Colors for logging --- +INFO="[INFO]" +WARN="[WARN]" +ERR="[ERROR]" + +echo "${INFO} ================================================" +echo "${INFO} Authelia + Authelia-API Container" +echo "${INFO} Authelia port: ${AUTHELIA_PORT}" +echo "${INFO} API listen: ${AUTHELIA_API_LISTEN}" +echo "${INFO} API database: ${AUTHELIA_API_DB}" +echo "${INFO} API log level: ${AUTHELIA_API_LOG_LEVEL}" +echo "${INFO} ================================================" + +# --- Signal handler --- +cleanup() { + echo "${INFO} Shutting down..." + kill -TERM "${AUTHELIA_PID}" 2>/dev/null || true + kill -TERM "${API_PID}" 2>/dev/null || true + wait "${AUTHELIA_PID}" 2>/dev/null || true + wait "${API_PID}" 2>/dev/null || true + echo "${INFO} Shutdown complete" + exit 0 +} +trap cleanup TERM INT + +# --- Helper: wait for a TCP port to be reachable --- +wait_for_port() { + local host="$1" port="$2" max_attempts="${3:-30}" interval="${4:-2}" + echo "${INFO} Waiting for ${host}:${port} to be ready..." + i=0 + while [ "${i}" -lt "${max_attempts}" ]; do + if nc -z "${host}" "${port}" 2>/dev/null; then + echo "${INFO} ${host}:${port} is ready (attempt $((i + 1)))" + return 0 + fi + i=$((i + 1)) + sleep "${interval}" + done + echo "${ERR} ${host}:${port} not reachable after ${max_attempts} attempts" + return 1 +} + +# ============================================================================= +# 1. Bootstrap required files +# ============================================================================= + +# Create empty users database if missing (Authelia requires it to exist) +if [ ! -f "/config/users_database.yml" ]; then + echo "${INFO} Creating empty users database at /config/users_database.yml" + echo 'users: {}' > /config/users_database.yml +fi + +# Create empty notifications file if missing +if [ ! -f "/config/notifications.yml" ]; then + echo "${INFO} Creating empty notifications file at /config/notifications.yml" + touch /config/notifications.yml +fi + +# ============================================================================= +# 2. Validate / generate configuration +# ============================================================================= +if [ ! -f "${AUTHELIA_CONFIG}" ]; then + echo "${WARN} No Authelia config found at ${AUTHELIA_CONFIG}" + echo "${WARN} Provide one via volume mount or set AUTHELIA_CONFIG env var" + echo "${WARN} Starting with a minimal configuration instead..." + + mkdir -p /tmp/authelia-config + cat > /tmp/authelia-config/configuration.yml << EOF +######################################## +# Authelia minimal config — replace me +######################################## +server: + address: tcp://0.0.0.0:${AUTHELIA_PORT} +log: + level: info +identity_validation: + reset_password: + jwt_secret: changeme_changeme_changeme_changeme_changeme +default_redirection_url: https://auth.example.com +totp: + issuer: authelia +authentication_backend: + file: + path: /config/users_database.yml +access_control: + default_policy: two_factor + rules: + - domain: example.com + policy: bypass +session: + name: authelia_session + secret: changeme_changeme_changeme_changeme_changeme + expiration: 1h + inactivity: 5m + remember_me: 1M + domain: example.com +regulation: + max_retries: 5 + find_time: 2m + ban_time: 5m +storage: + encryption_key: changeme_changeme_changeme_changeme_changeme + local: + path: /config/db.sqlite3 +notifier: + filesystem: + filename: /config/notifications.yml +EOF + AUTHELIA_CONFIG="/tmp/authelia-config/configuration.yml" +fi + +# ============================================================================= +# 3. Start Authelia +# ============================================================================= +echo "${INFO} Starting Authelia..." +authelia --config "${AUTHELIA_CONFIG}" & +AUTHELIA_PID=$! +echo "${INFO} Authelia started (PID: ${AUTHELIA_PID})" + +wait_for_port "127.0.0.1" "${AUTHELIA_PORT}" 30 2 || { + echo "${ERR} Authelia failed to start within timeout" + echo "${ERR} Check logs above for configuration errors." + kill "${AUTHELIA_PID}" 2>/dev/null || true + exit 1 +} + +# ============================================================================= +# 4. Start Authelia-API +# ============================================================================= +echo "${INFO} Starting Authelia-API..." +authelia-api \ + -config "${AUTHELIA_CONFIG}" \ + -listen "${AUTHELIA_API_LISTEN}" \ + -db "${AUTHELIA_API_DB}" \ + -log-level "${AUTHELIA_API_LOG_LEVEL}" & +API_PID=$! +echo "${INFO} Authelia-API started (PID: ${API_PID})" + +echo "${INFO} ================================================" +echo "${INFO} Both services are running" +echo "${INFO} Authelia: http://0.0.0.0:${AUTHELIA_PORT}" +echo "${INFO} Authelia-API: http://0.0.0.0:${AUTHELIA_API_LISTEN##*:}" +echo "${INFO} ================================================" + +# ============================================================================= +# 5. Monitor loop — exit if either process dies +# ============================================================================= +while true; do + if ! kill -0 "${AUTHELIA_PID}" 2>/dev/null; then + echo "${ERR} Authelia (PID ${AUTHELIA_PID}) exited unexpectedly" + kill "${API_PID}" 2>/dev/null || true + exit 1 + fi + if ! kill -0 "${API_PID}" 2>/dev/null; then + echo "${ERR} Authelia-API (PID ${API_PID}) exited unexpectedly" + kill "${AUTHELIA_PID}" 2>/dev/null || true + exit 1 + fi + sleep 5 +done diff --git a/docker/users_database.yml b/docker/users_database.yml new file mode 100644 index 0000000..94cd4e4 --- /dev/null +++ b/docker/users_database.yml @@ -0,0 +1,14 @@ +# Authelia Users Database +# ======================== +# This file is managed by Authelia-API. +# Manual edits will be overwritten on next sync. +# +# Format: +# users: +# : +# displayname: "" +# password: "" +# email: "" +# groups: [] +# +users: {}