Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Caddy logo

Сервер Caddy с модулями replace-response и postauth-2fa

Note

Этот репозиторий является частью проекта "Феникс" и содержит конфигурацию для автоматической сборки Docker-образа веб-сервера Caddy с дополнительными модулями.

🔄 Автосборка

  • Образ автоматически пересобирается каждое 1-е число месяца, подтягивая свежую версию Caddy и обновленные зависимости.
  • Публикация происходит в GitHub Container Registryghcr.io/octohare/caddy:latest

📌 Описание

Образ ghcr.io/octohare/caddy:latest собран на базе официального caddy:latest с добавлением модулей:

Оба модуля входят в официальный реестр модулей на сайте продукта:

CaddyServer.com/Docs/Modules

❔ Зачем это нужно?

  • Модуль Replace-Response добавляет в Caddyfile поддержку директивы replace, которая позволяет подменять текст (HTML/JS/CSS/JSON) в теле ответов бэкенда на лету. Это необходимо для корректного проксирования сервисов по subpath (например, domain.com/subpath/), когда проксируемый сервис завязан на абсолютные пути (/static/, /api/) и не умеет работать с базовыми префиксами из коробки.
  • Модуль PostAuth-2FA добавляет в Caddyfile поддержку директивы postauth_2fa, которая добавляет возможность включить двухфакторную аутентификацию для любого проксируемого приложения.

📄 Пример использование

Important

Требования к окружению

Данная инструкция предполагает развертывание сервиса с помощью Stack в графической панели Portainer.
Для выполнения описанных шагов на сервере должны быть заранее установлены Docker и Portainer.

  1. Создаём каталоги для настроек и сертификатов:

    # Создаём каталоги
    
    # Для конфигурационного файла Caddy
    mkdir -p /etc/caddy
    
    # Для сертификатов
    mkdir -p /etc/caddy/data

  1. Модуль PostAuth-2FA требует секретный ключ не менее 32 байт для подписи JWT-токенов, генерируем Base64 ключ для подписи сессий:

    openssl rand -base64 32
    Вывод будет выглядеть примерно так: BgaZRtx8BcT0bcmPMJbAgNQH7363CcC7ydkw2xwJkq4=

  1. Для 2FA необходим секрет, генерируем Base32-секрет для пользователя:

    openssl rand 30 | base32 | tr --delete '='
    Вывод будет выглядеть примерно так: ZLUP2T66JIHV3OI3NSUOYJIPLTKM43FSPM2I6N3RTI72ILL7

  1. Необходимо передать секрет в ваше 2FA приложение, например Google Authenticator или любое другое. Есть два пути:

    • Ручной ввод. Скопируйте сам секрет и любым способом введите или вставьте его в 2FA приложение.
    • QR код. Для удобства можем превратить секрет в QR код прямо в консоле:

      Ставим приложение

      sudo apt install qrencode
      Запускаем команду с названием вашего приложения (MySecretAppName) и секретом secret=

      qrencode -t UTF8 "otpauth://totp/MySecretAppName?secret=ZLUP2T66JIHV3OI3NSUOYJIPLTKM43FSPM2I6N3RTI72ILL7"
      📱 Сканируем получившийся QR код через 2FA приложение
  2. Создаём файл с секретом для модуля PostAuth-2FA и скачиваем красивую форму ввода ключа:

    cat > /etc/caddy/totp_secrets.json << 'EOF'
    {
      "admin": {
        "totp_secret": "ZLUP2T66JIHV3OI3NSUOYJIPLTKM43FSPM2I6N3RTI72ILL7"
      }
    }
    EOF
    
    curl -fsSL https://raw.githubusercontent.com/steffenbusch/caddy-postauth-2fa/main/alternative-2fa-form.html -o /etc/caddy/alternative-2fa-form.html
  3. Создаём Caddyfile файл с конфигурацие для Caddy:

    cat > /etc/caddy/Caddyfile << 'EOF'
    {
    email your-email@example.com
    }
    
    example.com {
    
        handle_path /subpath/* {
    	    reverse_proxy 127.0.0.1:3030
        }
    
         handle_path /mysecretapp/* {
    	    reverse_proxy 127.0.0.1:4040
        }
    }
    EOF
  4. Далее для установки веб-сервера Caddy переходим в Portainer:

    • Раздел "Stacks"
    • Кнопка "+ Add stack" вверху справа
    • Задаём имя - Name: caddy
    • В поле Web editor вставляем:

    services:
      caddy:
        image: ghcr.io/octohare/caddy:latest
        container_name: caddy
        restart: unless-stopped
    
        network_mode: host
    
        volumes:
          - /etc/caddy:/etc/caddy
          - /etc/caddy/data:/data
          - caddy_config:/config
    
        healthcheck:
          test: ["CMD-SHELL", "curl -fI http://127.0.0.1:2019/metrics"]
          interval: 30s
          timeout: 5s
          retries: 3
          start_period: 10s
    
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: "2"
    
    volumes:
      caddy_config:
    • Кнопка "Deploy the stack" внизу слева
  5. Генерируем хеш пароля для Basic Auth:

    docker exec -it caddy caddy hash-password --plaintext 'y0uR_SeCrEt_P@s$w0rD'

    Вывод будет выглядеть примерно так: $2a$14$l8E4ux1gwzi4cxCnohyjNOFOGKzXhBz30kPbyDV02/LvXbIirGX2i

  6. Редактируем файл настроек Caddyfile:

    nano /etc/caddy/Caddyfile

    Пример файла конфигурации сервера Caddy в котором продемонстрированно использование новых доступных директив replace и postauth_2fa. В данном примере они применены условно к разным сайтам/сервисам, но их также можно применить и вместе к одному домену/порту/адресу.

    {
    email your-email@example.com
    }
    
    example.com {
    
        handle_path /subpath/* {
    
            reverse_proxy 127.0.0.1:3030 {
                header_up X-Forwarded-Prefix /subpath
            }
    
            replace {
                "href=\"/" "href=\"/subpath/"
                "src=\"/" "src=\"/subpath/"
                "fetch(\"/" "fetch(\"/subpath/"
                "\"/api/" "\"/subpath/api/"
                "EventSource(\"/" "EventSource(\"/subpath/"
            }
        }
    
        handle_path /mysecretapp/* {
    
            basic_auth {
                admin $2a$14$l8E4ux1gwzi4cxCnohyjNOFOGKzXhBz30kPbyDV02/LvXbIirGX2i
            }
    
            postauth_2fa {
                session_inactivity_timeout 12h
                secrets_file_path /etc/caddy/totp_secrets.json
                sign_key "BgaZRtx8BcT0bcmPMJbAgNQH7363CcC7ydkw2xwJkq4="
    			form_response_header X-2FA-Required true
    			form_template /etc/caddy/alternative-2fa-form.html
            }
    
            reverse_proxy 127.0.0.1:4040
        }
    
    }
  7. Применяем новые настройки:

    docker exec -it caddy caddy reload --config /etc/caddy/Caddyfile

Caddy server with replace-response and postauth-2fa modules

Note

This repository is part of the "Phoenix" project and contains the configuration for automated building of a Docker image of the Caddy web server with additional modules.

🔄 Autobuild

  • The image is automatically rebuilt on the 1st of every month, pulling the latest Caddy version and updated dependencies.
  • Published to GitHub Container Registryghcr.io/octohare/caddy:latest

📌 Description

The ghcr.io/octohare/caddy:latest image is built on top of the official caddy:latest with the following modules added:

Both modules are listed in the official module registry on the product website:

CaddyServer.com/Docs/Modules

❔ Why is this needed?

  • The Replace-Response module adds support for the replace directive in the Caddyfile, which allows on-the-fly text replacement (HTML/JS/CSS/JSON) in backend response bodies. This is necessary for correct proxying of services under a subpath (e.g., domain.com/subpath/), when the proxied service relies on absolute paths (/static/, /api/) and does not support base prefixes out of the box.
  • The PostAuth-2FA module adds support for the postauth_2fa directive in the Caddyfile, which enables two-factor authentication for any proxied application.

📄 Usage example

Important

Environment requirements

This guide assumes deployment of the service using a Stack in the Portainer graphical interface.
The server must have Docker and Portainer pre-installed to follow these steps.

  1. Create directories for configuration and certificates:

    # Create directories
    
    # For Caddy configuration file
    mkdir -p /etc/caddy
    
    # For certificates
    mkdir -p /etc/caddy/data

  1. The PostAuth-2FA module requires a secret key of at least 32 bytes to sign JWT tokens. Generate a Base64 key for session signing:

    openssl rand -base64 32
    The output will look something like: BgaZRtx8BcT0bcmPMJbAgNQH7363CcC7ydkw2xwJkq4=

  1. For 2FA you need a secret. Generate a Base32 secret for the user:

    openssl rand 30 | base32 | tr --delete '='
    The output will look something like: ZLUP2T66JIHV3OI3NSUOYJIPLTKM43FSPM2I6N3RTI72ILL7

  1. You need to transfer the secret to your 2FA app, such as Google Authenticator or any other. There are two ways:

    • Manual entry. Copy the secret itself and type or paste it into the 2FA app.
    • QR code. For convenience, we can turn the secret into a QR code directly in the terminal:

      Install the utility

      sudo apt install qrencode
      Run the command with your application name (MySecretAppName) and the secret= parameter

      qrencode -t UTF8 "otpauth://totp/MySecretAppName?secret=ZLUP2T66JIHV3OI3NSUOYJIPLTKM43FSPM2I6N3RTI72ILL7"
      📱 Scan the resulting QR code with your 2FA app
  2. Create the secrets file for the PostAuth-2FA module and download a nice key entry form:

    cat > /etc/caddy/totp_secrets.json << 'EOF'
    {
      "admin": {
        "totp_secret": "ZLUP2T66JIHV3OI3NSUOYJIPLTKM43FSPM2I6N3RTI72ILL7"
      }
    }
    EOF
    
    curl -fsSL https://raw.githubusercontent.com/steffenbusch/caddy-postauth-2fa/main/alternative-2fa-form.html -o /etc/caddy/alternative-2fa-form.html
  3. Create the Caddyfile configuration file for Caddy:

    cat > /etc/caddy/Caddyfile << 'EOF'
    {
    email your-email@example.com
    }
    
    example.com {
    
        handle_path /subpath/* {
    	    reverse_proxy 127.0.0.1:3030
        }
    
         handle_path /mysecretapp/* {
    	    reverse_proxy 127.0.0.1:4040
        }
    }
    EOF
  4. Next, to install the Caddy web server, go to Portainer:

    • "Stacks" section
    • "+ Add stack" button in the top right
    • Set name — Name: caddy
    • In the Web editor field paste:

    services:
      caddy:
        image: ghcr.io/octohare/caddy:latest
        container_name: caddy
        restart: unless-stopped
    
        network_mode: host
    
        volumes:
          - /etc/caddy:/etc/caddy
          - /etc/caddy/data:/data
          - caddy_config:/config
    
        healthcheck:
          test: ["CMD-SHELL", "curl -fI http://127.0.0.1:2019/metrics"]
          interval: 30s
          timeout: 5s
          retries: 3
          start_period: 10s
    
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: "2"
    
    volumes:
      caddy_config:
    • "Deploy the stack" button at the bottom left
  5. Generate a password hash for Basic Auth:

    docker exec -it caddy caddy hash-password --plaintext 'y0uR_SeCrEt_P@s$w0rD'

    The output will look something like: $2a$14$l8E4ux1gwzi4cxCnohyjNOFOGKzXhBz30kPbyDV02/LvXbIirGX2i

  6. Edit the Caddyfile configuration file:

    nano /etc/caddy/Caddyfile

    Example of a Caddy server configuration file demonstrating the use of the new replace and postauth_2fa directives. In this example they are applied conditionally to different sites/services, but they can also be used together on a single domain/port/address.

    {
    email your-email@example.com
    }
    
    example.com {
    
        handle_path /subpath/* {
    
            reverse_proxy 127.0.0.1:3030 {
                header_up X-Forwarded-Prefix /subpath
            }
    
            replace {
                "href=\"/" "href=\"/subpath/"
                "src=\"/" "src=\"/subpath/"
                "fetch(\"/" "fetch(\"/subpath/"
                "\"/api/" "\"/subpath/api/"
                "EventSource(\"/" "EventSource(\"/subpath/"
            }
        }
    
        handle_path /mysecretapp/* {
    
            basic_auth {
                admin $2a$14$l8E4ux1gwzi4cxCnohyjNOFOGKzXhBz30kPbyDV02/LvXbIirGX2i
            }
    
            postauth_2fa {
                session_inactivity_timeout 12h
                secrets_file_path /etc/caddy/totp_secrets.json
                sign_key "BgaZRtx8BcT0bcmPMJbAgNQH7363CcC7ydkw2xwJkq4="
    			form_response_header X-2FA-Required true
    			form_template /etc/caddy/alternative-2fa-form.html
            }
    
            reverse_proxy 127.0.0.1:4040
        }
    
    }
  7. Apply the new settings:

    docker exec -it caddy caddy reload --config /etc/caddy/Caddyfile

About

Custom Docker Image Caddy Server with Replace-Response and PostAuth-2FA modules. Docker образ Caddy сервера с дополнительными модуляи Replace-Response и PostAuth-2FA.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Packages

Contributors

Languages