Traefik известен тем, что автоматически выпускает сертификаты через ACME. Но иногда вам нужно использовать собственный сертификат — выданный сервисом GetHTTPS, корпоративным/внутренним CA или wildcard-сертификат, которым вы управляете в другом месте. Это руководство покажет, как именно это сделать в Traefik v3.
Главное, что нужно понять сразу: вы не можете подключить файл сертификата через метку Docker. Метки Traefik управляют маршрутизацией и включают TLS, но сам сертификат должен поступать от файлового провайдера в виде динамической конфигурации. На этом спотыкается почти каждый в первый раз. Мы сделаем всё правильно.
Если у вас ещё нет сертификата, получите его бесплатно за 5 минут.
Когда это использовать (вместо автоматического ACME в Traefik)
| Автоматический ACME (Let’s Encrypt) | Собственный сертификат (это руководство) |
|---|---|
| Публичный сайт, доступный из интернета | Внутренний сервис/интранет (без публичного DNS) |
| Стандартного DV-сертификата достаточно | Нужен конкретный CA, wildcard или сертификат OV/EV |
| Traefik может пройти HTTP/DNS-проверку | Изолированный или закрытый файрволом хост |
| Вы хотите нулевое управление сертификатами | У вас уже есть сертификат от GetHTTPS или из другого источника |
Если автоматический ACME вам подходит, то certificatesResolvers в Traefik проще. Это руководство для случая «у меня уже есть fullchain.pem + privkey.pem, и нужно, чтобы Traefik их обслуживал».
Предварительные требования
- Traefik v3, запущенный как контейнер Docker (в конфигурации ниже используется Docker, но часть с динамической конфигурацией применима к любой установке)
- Файлы вашего сертификата — их два:
fullchain.pem— ваш сертификат + промежуточная цепочкаprivkey.pem— ваш приватный ключ
- Домен, указывающий на хост (или локальная запись в hosts-файле для внутреннего использования)
Какие файлы нужны Traefik? Traefik ожидает полную цепочку в
certFileи ключ вkeyFile. Если вы используетеcert.pemтолько с конечным сертификатом, клиенты получат ошибки «неполная цепочка» — Traefik не добавляет промежуточные сертификаты автоматически для сертификатов файлового провайдера. Используйтеfullchain.pem. Форматы сертификатов объяснены →
Как разделена конфигурация Traefik
В Traefik есть два вида конфигурации, и сертификаты находятся во втором из них:
- Статическая конфигурация — задаётся при запуске (entrypoints, провайдеры). Её изменение требует перезапуска. Она прописывается в
traefik.ymlили в командных флагах контейнера. - Динамическая конфигурация — перезагружается на лету без перезапуска (routers, сервисы, TLS-сертификаты). Именно её читает файловый провайдер.
Ваш сертификат — это динамическая конфигурация. Вот почему метка не может его нести: метки читаются из провайдера Docker, а tls.certificates — это концепция файлового провайдера.
Шаг 1: Разместите файлы сертификата
Поместите файлы в каталог, который вы смонтируете в контейнер:
mkdir -p ./traefik/certs
cp fullchain.pem ./traefik/certs/
cp privkey.pem ./traefik/certs/
# Ограничьте доступ к приватному ключу
chmod 600 ./traefik/certs/privkey.pem
chmod 644 ./traefik/certs/fullchain.pem
Шаг 2: Напишите динамическую конфигурацию
Создайте ./traefik/dynamic/certs.yml. Именно здесь вы объявляете свой сертификат:
# ./traefik/dynamic/certs.yml (динамическая конфигурация — файловый провайдер)
tls:
certificates:
- certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
# Необязательно: сделать этот сертификат сертификатом по умолчанию для любого хоста,
# который не соответствует более конкретному сертификату (например, wildcard или внутренний CA).
stores:
default:
defaultCertificate:
certFile: /certs/fullchain.pem
keyFile: /certs/privkey.pem
Пути (/certs/...) — это пути внутри контейнера, мы смонтируем их на следующем шаге. Traefik выбирает нужный сертификат для каждого запроса с помощью SNI, сопоставляя SAN сертификата с запрашиваемым именем хоста. defaultCertificate — это запасной вариант, когда ничего другого не подходит.
Шаг 3: Настройте Traefik (статическая конфигурация + монтирование)
Вот полный docker-compose.yml. Entrypoints и файловый провайдер — это статическая конфигурация (передаётся в виде командных флагов); сертификат загружается из динамического файла, который вы только что написали.
services:
traefik:
image: traefik:v3.3
container_name: traefik
restart: unless-stopped
command:
# ─── Entrypoints ───────────────────────────────
- "--entrypoints.web.address=:80"
- "--entrypoints.websecure.address=:443"
# Перенаправлять весь HTTP → HTTPS на уровне entrypoint
- "--entrypoints.web.http.redirections.entrypoint.to=websecure"
- "--entrypoints.web.http.redirections.entrypoint.scheme=https"
- "--entrypoints.web.http.redirections.entrypoint.permanent=true"
# ─── Providers ─────────────────────────────────
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
# Файловый провайдер следит за каталогом динамической конфигурации
- "--providers.file.directory=/dynamic"
- "--providers.file.watch=true"
ports:
- "80:80"
- "443:443"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
- "./traefik/certs:/certs:ro"
- "./traefik/dynamic:/dynamic:ro"
# ─── Пример бэкенд-сервиса ──────────────────────
whoami:
image: traefik/whoami
container_name: whoami
labels:
- "traefik.enable=true"
# Router: сопоставить хост, обслуживать на HTTPS-entrypoint
- "traefik.http.routers.whoami.rule=Host(`example.com`)"
- "traefik.http.routers.whoami.entrypoints=websecure"
# Включить TLS на этом router — сертификат берётся из
# динамической конфигурации, а НЕ из метки.
- "traefik.http.routers.whoami.tls=true"
Критически важная строка — traefik.http.routers.whoami.tls=true. Она сообщает Traefik «обслуживать этот router по TLS». Затем Traefik выбирает подходящий сертификат из хранилища файлового провайдера по SNI. Нет метки вроде tls.certfile — для routers она не существует.
Шаг 4: Запуск и проверка
docker compose up -d
docker compose logs -f traefik
Следите за загрузкой вашего сертификата файловым провайдером. Вы не должны видеть ошибок TLS. Затем проверьте:
Проверка в браузере
Откройте https://example.com. Нажмите на значок замка:
- Кем выдан — ваш CA (Let’s Encrypt для GetHTTPS или ваш внутренний CA)
- Действителен — даты начала и окончания
- Домен — соответствует URL
Проверка из командной строки
# Убедитесь, что Traefik обслуживает ВАШ сертификат, а не свой самоподписанный по умолчанию
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
| openssl x509 -noout -subject -issuer -dates
Если вы видите CN=TRAEFIK DEFAULT CERT, значит Traefik вернулся к своей встроенной заглушке — ваш сертификат не был загружен. Смотрите раздел Устранение неполадок ниже.
Шаг 5 (необязательно): Усиление TLS
Чтобы управлять версиями протоколов и шифрами, добавьте блок параметров TLS в вашу динамическую конфигурацию и сошлитесь на него из router. Добавьте в certs.yml:
tls:
options:
modern:
minVersion: VersionTLS12
sniStrict: true
Затем в метке router:
- "traefik.http.routers.whoami.tls.options=modern@file"
Суффикс @file сообщает Traefik, что этот набор параметров берётся из файлового провайдера. Это ограничивает вас TLS 1.2 и 1.3 и отклоняет соединения без подходящего SNI.
HSTS: Добавьте заголовок
Strict-Transport-Securityчерез middlewareheadersв Traefik, когда убедитесь, что HTTPS работает везде. Руководство по HSTS →
Как обновить сертификат
Traefik не обновляет автоматически сертификаты, которые вы предоставляете сами, — это плата за использование собственного сертификата. Когда срок действия вашего сертификата подходит к концу (60-й день из 90 для Let’s Encrypt):
- Получите новый сертификат от GetHTTPS (или с помощью вашего инструмента обновления).
- Перезапишите файлы на месте:
cp new-fullchain.pem ./traefik/certs/fullchain.pem cp new-privkey.pem ./traefik/certs/privkey.pem - Больше ничего. Поскольку установлен
--providers.file.watch=true, Traefik обнаруживает изменение файла и горячо перезагружает сертификат — без перезапуска, без простоя. Это одно из самых приятных свойств Traefik для пользовательских сертификатов.
Полное руководство по обновлению →
Устранение неполадок
Traefik обслуживает «TRAEFIK DEFAULT CERT» вместо моего сертификата
Причина: Traefik не смог загрузить ваш сертификат, поэтому вернулся к своей самоподписанной заглушке. Почти всегда это проблема с путём или монтированием.
Решение:
# 1. Убедитесь, что файлы существуют ВНУТРИ контейнера по ожидаемому пути
docker compose exec traefik ls -l /certs
# 2. Убедитесь, что динамический файл смонтирован и доступен для чтения
docker compose exec traefik cat /dynamic/certs.yml
# 3. Проверьте логи на наличие реальной причины
docker compose logs traefik | grep -i "certificate\|tls\|error"
Пути certFile/keyFile в certs.yml должны соответствовать путям внутри контейнера (/certs/...), а не путям на вашем хосте.
«unable to find certificate for domain» / обслуживается неправильный сертификат
Причина: Ни один SAN сертификата не соответствует запрашиваемому имени хоста, и не задан defaultCertificate.
Решение: Либо добавьте имя хоста в ваш сертификат, либо задайте defaultCertificate в блоке stores.default (Шаг 2), чтобы у Traefik был запасной вариант.
Router возвращает 404, сертификат даже не проверяется
Причина: Правило router не совпадает, или сервис не открыт. TLS не имеет значения, пока маршрутизация не совпадёт.
Решение:
# Убедитесь, что router существует и включён
docker compose exec traefik wget -qO- http://localhost:8080/api/http/routers 2>/dev/null | grep whoami
Убедитесь, что traefik.enable=true указан на бэкенд-контейнере и правило Host() соответствует тестируемому домену.
Изменения в certs.yml не вступают в силу
Причина: Файловый провайдер не следит за изменениями, или вы отредактировали статическую конфигурацию (которая требует перезапуска).
Решение: Убедитесь, что --providers.file.watch=true присутствует в статической конфигурации. Помните: entrypoints/провайдеры — это статика (требуется перезапуск); routers и tls.certificates — это динамика (горячая перезагрузка).
«x509: certificate signed by unknown authority» от клиентов
Причина: Неполная цепочка — вы использовали cert.pem только с конечным сертификатом в certFile вместо fullchain.pem.
Решение: Укажите в certFile полную цепочку. Если у вас есть только отдельные файлы, объедините их (сначала конечный, затем промежуточные):
cat cert.pem intermediate.pem > fullchain.pem
Часто задаваемые вопросы
Можно ли указать файл сертификата через метку Docker?
Нет. Это заблуждение №1. Метки задают traefik.http.routers.<name>.tls=true, чтобы включить TLS, но файлы сертификата должны быть объявлены в динамической конфигурации через файловый провайдер (tls.certificates). Нет метки router, которая указывала бы на файл .pem.
Нужен ли tls=true на router, если у меня есть сертификат?
Да. Объявление сертификата в tls.certificates делает его доступным, но каждому router всё равно нужен tls=true (или прослушивание entrypoint с включённым TLS), чтобы реально обслуживать запросы по HTTPS. Само по себе определение сертификата не переключает router на TLS.
Можно ли совмещать автоматический ACME и пользовательские сертификаты?
Да. Traefik может использовать certificatesResolver для одних routers и сертификаты файлового провайдера для других. Для каждого запроса явное совпадение tls.certificates по SNI имеет приоритет над ACME для этого имени хоста.
Куда помещаются сертификаты в Kubernetes?
Не в файловый провайдер — в Kubernetes вы предоставляете сертификаты как TLS Secrets и ссылаетесь на них из IngressRoute/Ingress. Подход с файловым провайдером из этого руководства предназначен для Docker и автономных (не-K8s) установок.
Обновляет ли Traefik мой пользовательский сертификат автоматически?
Нет. Автоматическое обновление применяется только к сертификатам, которые Traefik выпускает сам через ACME. Для ваших собственных сертификатов вы заменяете файлы — но благодаря --providers.file.watch=true Traefik горячо перезагружает их без простоя, как описано в разделе Как обновить сертификат выше.
Работает ли это с сертификатами ECDSA/ECC?
Да. Traefik обслуживает сертификаты ECDSA точно так же, как RSA, — с той же конфигурацией certFile/keyFile. GetHTTPS по умолчанию выпускает ECDSA P-256 для меньших по размеру и более быстрых рукопожатий.