Init
This commit is contained in:
@@ -0,0 +1,4 @@
|
|||||||
|
certbot/letsencrypt/*
|
||||||
|
certbot/www/*
|
||||||
|
!certbot/letsencrypt/.gitkeep
|
||||||
|
!certbot/www/.gitkeep
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
FROM nginx:stable
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN apt-get update \
|
||||||
|
&& apt-get install -y --no-install-recommends certbot cron tzdata \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
|
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|
||||||
@@ -0,0 +1,237 @@
|
|||||||
|
# Nginx + Certbot Ingress
|
||||||
|
|
||||||
|
Этот каталог содержит автономный ingress-модуль в одном контейнере:
|
||||||
|
|
||||||
|
- `nginx` как reverse proxy
|
||||||
|
- `certbot` для выпуска и обновления сертификатов Let's Encrypt
|
||||||
|
- `cron` внутри контейнера для автообновления сертификатов
|
||||||
|
|
||||||
|
## Структура
|
||||||
|
|
||||||
|
```text
|
||||||
|
.
|
||||||
|
├── docker-compose.yml
|
||||||
|
├── Dockerfile
|
||||||
|
├── docker-entrypoint.sh
|
||||||
|
├── renew.sh
|
||||||
|
├── nginx.conf
|
||||||
|
├── conf.d/
|
||||||
|
│ └── registry.lesha.spb.ru.conf
|
||||||
|
└── certbot/
|
||||||
|
├── letsencrypt/
|
||||||
|
└── www/
|
||||||
|
```
|
||||||
|
|
||||||
|
## Что делает контейнер
|
||||||
|
|
||||||
|
После старта контейнер:
|
||||||
|
|
||||||
|
1. запускает `cron`
|
||||||
|
2. запускает `nginx` в foreground
|
||||||
|
3. два раза в день вызывает `renew.sh`
|
||||||
|
|
||||||
|
Скрипт [renew.sh](/Users/alex/Dev_projects_v2/apps/ingress/renew.sh) выполняет:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
certbot renew --webroot -w /var/www/certbot --quiet
|
||||||
|
nginx -s reload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Первый запуск
|
||||||
|
|
||||||
|
Перейти в каталог:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /opt/apps/nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
Локально в этом репозитории аналогичный путь:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /Users/alex/Dev_projects_v2/apps/ingress
|
||||||
|
```
|
||||||
|
|
||||||
|
Собрать и запустить контейнер:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up -d --build
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверить, что `nginx` поднялся:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose ps
|
||||||
|
docker logs nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
После первого старта `nginx` уже отвечает на `80` и обслуживает путь:
|
||||||
|
|
||||||
|
```text
|
||||||
|
/.well-known/acme-challenge/
|
||||||
|
```
|
||||||
|
|
||||||
|
Это нужно для выпуска сертификата через `webroot`.
|
||||||
|
|
||||||
|
## Выпуск сертификата для существующего домена
|
||||||
|
|
||||||
|
Текущий конфиг домена лежит в [conf.d/registry.lesha.spb.ru.conf](/Users/alex/Dev_projects_v2/apps/ingress/conf.d/registry.lesha.spb.ru.conf).
|
||||||
|
|
||||||
|
Выпуск сертификата:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it nginx certbot certonly \
|
||||||
|
--webroot -w /var/www/certbot \
|
||||||
|
-d registry.lesha.spb.ru \
|
||||||
|
--email you@example.com \
|
||||||
|
--agree-tos \
|
||||||
|
--no-eff-email
|
||||||
|
```
|
||||||
|
|
||||||
|
Сертификаты будут сохранены в:
|
||||||
|
|
||||||
|
```text
|
||||||
|
./certbot/letsencrypt
|
||||||
|
```
|
||||||
|
|
||||||
|
Они переживают рестарты контейнера, потому что каталог подключён как volume.
|
||||||
|
|
||||||
|
## Включение HTTPS после выпуска сертификата
|
||||||
|
|
||||||
|
В файле [conf.d/registry.lesha.spb.ru.conf](/Users/alex/Dev_projects_v2/apps/ingress/conf.d/registry.lesha.spb.ru.conf) уже есть готовый HTTPS-блок в комментарии.
|
||||||
|
|
||||||
|
Нужно:
|
||||||
|
|
||||||
|
1. раскомментировать блок `server { listen 443 ssl; ... }`
|
||||||
|
2. при необходимости включить редирект с HTTP на HTTPS
|
||||||
|
3. перезагрузить `nginx`
|
||||||
|
|
||||||
|
Перезагрузка:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec nginx nginx -s reload
|
||||||
|
```
|
||||||
|
|
||||||
|
## Автообновление сертификатов
|
||||||
|
|
||||||
|
Cron создаётся в контейнере автоматически при старте.
|
||||||
|
|
||||||
|
Расписание по умолчанию:
|
||||||
|
|
||||||
|
- `03:17`
|
||||||
|
- `15:17`
|
||||||
|
|
||||||
|
Проверить cron-задачу внутри контейнера:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec nginx cat /etc/cron.d/certbot-renew
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверить ручной запуск renewal:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec nginx /usr/local/bin/renew.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Добавление нового домена
|
||||||
|
|
||||||
|
Для нового домена нужно создать отдельный файл в `conf.d`.
|
||||||
|
|
||||||
|
Пример для `example.com`:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name example.com;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
auth_basic off;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# После выпуска сертификата:
|
||||||
|
# server {
|
||||||
|
# listen 443 ssl;
|
||||||
|
# http2 on;
|
||||||
|
# server_name example.com;
|
||||||
|
#
|
||||||
|
# ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
|
||||||
|
# ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
|
||||||
|
#
|
||||||
|
# location / {
|
||||||
|
# proxy_pass http://app:8080;
|
||||||
|
# proxy_set_header Host $http_host;
|
||||||
|
# proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# proxy_set_header X-Forwarded-Proto https;
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
```
|
||||||
|
|
||||||
|
Дальше порядок такой:
|
||||||
|
|
||||||
|
1. создать новый конфиг в `conf.d/<domain>.conf`
|
||||||
|
2. проверить имя upstream, например `app:8080`
|
||||||
|
3. перезагрузить `nginx`
|
||||||
|
4. выпустить сертификат через `certbot certonly --webroot`
|
||||||
|
5. включить HTTPS-блок
|
||||||
|
6. снова перезагрузить `nginx`
|
||||||
|
|
||||||
|
Команда выпуска сертификата для нового домена:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec -it nginx certbot certonly \
|
||||||
|
--webroot -w /var/www/certbot \
|
||||||
|
-d example.com \
|
||||||
|
--email you@example.com \
|
||||||
|
--agree-tos \
|
||||||
|
--no-eff-email
|
||||||
|
```
|
||||||
|
|
||||||
|
## Где менять backend
|
||||||
|
|
||||||
|
Для `registry.lesha.spb.ru` upstream сейчас задан так:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
proxy_pass http://registry:5000;
|
||||||
|
```
|
||||||
|
|
||||||
|
Если backend доступен по другому имени контейнера, DNS-алиасу или порту, измените это значение в [conf.d/registry.lesha.spb.ru.conf](/Users/alex/Dev_projects_v2/apps/ingress/conf.d/registry.lesha.spb.ru.conf).
|
||||||
|
|
||||||
|
## Полезные команды
|
||||||
|
|
||||||
|
Проверка итогового compose:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose config
|
||||||
|
```
|
||||||
|
|
||||||
|
Просмотр логов:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker logs nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
Проверка конфига `nginx`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec nginx nginx -t
|
||||||
|
```
|
||||||
|
|
||||||
|
Перезапуск контейнера:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose restart
|
||||||
|
```
|
||||||
|
|
||||||
|
## Важные замечания
|
||||||
|
|
||||||
|
- Модуль использует один контейнер, без отдельного `certbot`-сервиса.
|
||||||
|
- Выпуск сертификатов выполняется только через `webroot`.
|
||||||
|
- Путь `/var/www/certbot` должен совпадать в `nginx`, `certbot` и `renew.sh`.
|
||||||
|
- На первом старте HTTPS не включён специально, чтобы `nginx` не падал без сертификата.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name registry.lesha.spb.ru;
|
||||||
|
|
||||||
|
location /.well-known/acme-challenge/ {
|
||||||
|
root /var/www/certbot;
|
||||||
|
auth_basic off;
|
||||||
|
try_files $uri =404;
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
return 404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Enable this block after the certificate has been issued.
|
||||||
|
# If you want HTTP -> HTTPS redirect after issuance, replace the HTTP
|
||||||
|
# `location / { return 404; }` above with `return 301 https://$host$request_uri;`.
|
||||||
|
#
|
||||||
|
# server {
|
||||||
|
# listen 443 ssl;
|
||||||
|
# http2 on;
|
||||||
|
# server_name registry.lesha.spb.ru;
|
||||||
|
#
|
||||||
|
# client_max_body_size 1024m;
|
||||||
|
# proxy_read_timeout 900;
|
||||||
|
# proxy_connect_timeout 10s;
|
||||||
|
#
|
||||||
|
# ssl_certificate /etc/letsencrypt/live/registry.lesha.spb.ru/fullchain.pem;
|
||||||
|
# ssl_certificate_key /etc/letsencrypt/live/registry.lesha.spb.ru/privkey.pem;
|
||||||
|
#
|
||||||
|
# location /v2/ {
|
||||||
|
# proxy_pass http://registry:5000;
|
||||||
|
# proxy_set_header Host $http_host;
|
||||||
|
# proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
# proxy_set_header X-Forwarded-Proto https;
|
||||||
|
# add_header Docker-Distribution-Api-Version registry/2.0 always;
|
||||||
|
# }
|
||||||
|
#
|
||||||
|
# location / {
|
||||||
|
# return 404;
|
||||||
|
# }
|
||||||
|
# }
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
services:
|
||||||
|
nginx:
|
||||||
|
container_name: nginx
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Moscow
|
||||||
|
ports:
|
||||||
|
- "80:80"
|
||||||
|
- "443:443"
|
||||||
|
volumes:
|
||||||
|
- ./nginx.conf:/etc/nginx/nginx.conf:ro
|
||||||
|
- ./conf.d:/etc/nginx/conf.d:ro
|
||||||
|
- ./certbot/letsencrypt:/etc/letsencrypt
|
||||||
|
- ./certbot/www:/var/www/certbot
|
||||||
|
- ./renew.sh:/usr/local/bin/renew.sh:ro
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
CRON_FILE="/etc/cron.d/certbot-renew"
|
||||||
|
CRON_SCHEDULE="${CERTBOT_RENEW_SCHEDULE:-17 3,15 * * *}"
|
||||||
|
|
||||||
|
mkdir -p /var/www/certbot
|
||||||
|
chmod +x /usr/local/bin/renew.sh
|
||||||
|
|
||||||
|
cat > "$CRON_FILE" <<EOF
|
||||||
|
SHELL=/bin/sh
|
||||||
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
||||||
|
TZ=${TZ:-UTC}
|
||||||
|
|
||||||
|
${CRON_SCHEDULE} root /usr/local/bin/renew.sh >> /var/log/cron.log 2>&1
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod 0644 "$CRON_FILE"
|
||||||
|
touch /var/log/cron.log
|
||||||
|
|
||||||
|
cron
|
||||||
|
|
||||||
|
exec nginx -g 'daemon off;'
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
user nginx;
|
||||||
|
worker_processes auto;
|
||||||
|
|
||||||
|
error_log /var/log/nginx/error.log notice;
|
||||||
|
pid /run/nginx.pid;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
include /etc/nginx/mime.types;
|
||||||
|
default_type application/octet-stream;
|
||||||
|
|
||||||
|
sendfile on;
|
||||||
|
keepalive_timeout 65;
|
||||||
|
ssl_session_cache shared:SSL:10m;
|
||||||
|
|
||||||
|
access_log /var/log/nginx/access.log;
|
||||||
|
|
||||||
|
include /etc/nginx/conf.d/*.conf;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user