Простой SSL сертификат на базе веб-сервера Caddy, Django и Gunicorn

В рамках учебного проекта мне потребовалось развернуть на одном сервере два приложения. Первое из них — классический Django Framework, который крутится с помощью Guncorn, файлы лежат прямо на сервере. Второе же хитрое — полностью докеризированная связка Nginx + Gunicorn + PostgreSQL.

Поднять незащищенное соединение совсем не сложно, у нас наружу светятся два порта, один от Gunicorn, один от Nginx из докера. Но как защитить все это дело? Если для серверного приложения с помощью Certbot это делается легко, то для докера настройки связки Certbot в контейнере и Nginx в контейнере — занятие не для слабонервных. А для того, чтобы сертификат заработал, нам потребовалось бы еще и пробрасывать 443 порт на докер, а сделать это можно двумя способами — либо не расшифровывая трафик через stream директиву Nginx, либо расшифровывая, но придется указать пути до ключей и, что самое сложное, понадобиться дать certbot положить файл в корневую директорию сайта для проверки соединения, а она у нас благодаря гуникорну не так-то просто достижима.

В качестве решения можно использовать сервер Caddy. Идея будет заключаться в том, что за все сертификаты будет отвечать только она, за ней уже пойдет незашифрованный трафик до нужных нам портов.

Установить Caddy просто, несколько команд в баше:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https 
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo apt-key add - 
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee -a /etc/apt/sources.list.d/caddy-stable.list 
sudo apt update sudo apt install caddy

Дальше необходимо создать конфиругацию. У кадди есть особенность, файл конфига может лежать где угодно. Я оставил его в домашней директории, он должен быть назван Caddyfile. Вот содержимое:

site-1-on-server.ru {
root * /home/user/site/
@notStatic {
not path /static/*
not path /media/*
}
reverse_proxy @notStatic 127.0.0.1:8000
file_server
}
site-2-in-docker.ru {
reverse_proxy localhost:8888
}

Этот конфиг позволяет запустить сайт1, который у нас лежит на сервере в указанной папке. Директива notStatic создает исключения для Кадди, эти файлы она не будет отправлять в Gunicorn и будет сама обслуживать. Обратный прокси — стандартная как для Ngnix, так и для Кадди операция, мы передаем все запросы дальше, на 8000 порт Гуникорна.

Вторая часть конфига не делает каких-либо исключений для статики, так как у нас в контейнерах крутится Nginx и он ответственный за статику.

А теперь немного магии от Кадди. Когда мы в директории, где у нас каддифайл лежит, запустим команду sudo caddy start, она автоматически выпустит SSL сертификаты для обоих доменов и будет их обновлять, проверяя оставшееся время каждые 10 дней. То есть самая сложная часть в случае с приложением, которое лежит на сервере — указать пути до статики, а если поднимается докеризированное приложение — то всего две строки и готово.