This commit is contained in:
root
2021-10-03 14:45:56 +03:00
commit b060ba0580
29 changed files with 1586 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
DOMAIN=traefik.domain.ru
DOMAIN_API=traefik-api.domain.ru
ADMIN_TOKEN=123123

7
traefik-repo/traefik/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
acme.json
stdout.log
certs/*
api/logs/*
/logs/*
basic.auth
.env

View File

@@ -0,0 +1,3 @@
# admin \ admin
admin:$apr1$edqYaaX4$LcYGU242kPrNQVKBZpQ8x.

View File

@@ -0,0 +1,6 @@
http:
middlewares:
redirect-to-https:
redirectScheme:
scheme: https
permanent: true

View File

@@ -0,0 +1,15 @@
tcp:
routers:
pve:
entryPoints:
- https
rule: "HostSNI(`pve.domain.ru`)"
service: pve-service
tls:
certResolver: letsEncrypt
passthrough: true
services:
pve-service:
loadBalancer:
servers:
- address: 192.168.1.2:8006

View File

@@ -0,0 +1,32 @@
http:
routers:
rke:
entryPoints:
- https
rule: Host(`rke.domain.ru`)
service: rke-service
tls:
certResolver: letsEncrypt
services:
rke-service:
loadBalancer:
servers:
- url: http://192.168.9.200
passHostHeader: true
tcp:
routers:
rke-api:
entryPoints:
- k8s-api
rule: "HostSNI(`*`)"
service: rke-api-service
tls:
passthrough: true
services:
rke-api-service:
loadBalancer:
servers:
- address: 192.168.9.201:6443
- address: 192.168.9.202:6443
- address: 192.168.9.203:6443

View File

@@ -0,0 +1,20 @@
http:
routers:
s3-minio:
entryPoints:
- https
rule: Host(`s3.domain.ru`)
service: s3-minio-service
tls:
certResolver: letsEncrypt
services:
s3-minio-service:
loadBalancer:
healthCheck:
path: /health/live
scheme: http
servers:
- url: http://192.168.1.3:9000
- url: http://192.168.1.4:9000
- url: http://192.168.1.5:9000
- url: http://192.168.1.6:9000

View File

@@ -0,0 +1,54 @@
global:
checkNewVersion: true
# pilot:
# token: ""
serversTransport:
insecureSkipVerify: true
api:
dashboard: true
entryPoints:
http:
address: ":80"
https:
address: ":443"
# k8s-api:
# address: ":6443"
# metrics:
# address: ":8082"
# metrics:
# prometheus:
# entryPoint: metrics
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
# file:
# directory: /custom
# watch: true
# kubernetesIngress:
# endpoint: "https://rke.domain.ru/k8s/clusters/c-xxxxx"
# token: "" # Token from Rancher
# ingressClass: "traefik-lb"
# ingressEndpoint:
# ip: "" # you external IP
certificatesResolvers:
letsEncrypt:
acme:
email: vasyakrg@gmail.com
storage: acme.json
httpChallenge:
entryPoint: http
hetzner:
acme:
email: vasyakrg@gmail.com
storage: acme-hetzner.json
dnsChallenge:
provider: hetzner
delayBeforeCheck: 30

View File

@@ -0,0 +1,66 @@
version: '3.7'
services:
traefik:
image: traefik
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
ports:
- 80:80
- 443:443
# - 6443:6443
environment:
- HETZNER_API_KEY: ${HETZNER_API_KEY}
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
# - ./data/custom/:/custom/:ro
# - ./data/basic.auth:/basic.auth
labels:
- "traefik.enable=true"
- "traefik.http.routers.traefik.entrypoints=https"
- "traefik.http.routers.traefik.rule=Host(`${DOMAIN}`)"
- "traefik.http.routers.traefik.tls=true"
- "traefik.http.routers.traefik.tls.certresolver=letsEncrypt"
- "traefik.http.routers.traefik.service=api@internal"
- "traefik.http.services.traefik-traefik.loadbalancer.server.port=888"
# - "traefik.http.routers.traefik.middlewares=traefik-auth"
# - "traefik.http.middlewares.traefik-auth.basicAuth.usersFile=/basic.auth"
# global redirect to https
- "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
- "traefik.http.routers.http-catchall.entrypoints=http"
- "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
- "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"
networks:
- webproxy
# api:
# image: vasyakrg/traefik-api:latest
# container_name: traefik_api
# restart: unless-stopped
# labels:
# - "traefik.enable=true"
# - "traefik.http.routers.traefik-api.entrypoints=https"
# - "traefik.http.routers.traefik-api.rule=Host(`${DOMAIN_API}`)"
# - "traefik.http.routers.traefik-api.tls=true"
# - "traefik.http.routers.traefik-api.tls.certresolver=letsEncrypt"
# - "traefik.http.services.traefik-api-service.loadbalancer.server.port=80"
# - "traefik.docker.network=webproxy"
# environment:
# APP_DEBUG: "true"
# APP_ENV: "production"
# APP_URL: "${DOMAIN_API}"
# ADMIN_TOKEN: ${ADMIN_TOKEN}
# volumes:
# - ./logs:/var/log/apache2
# - ./certs:/etc/letsencrypt/live/
# networks:
# - webproxy
networks:
webproxy:
name: webproxy

View File

@@ -0,0 +1,30 @@
#!/bin/bash
FOLDER_EXPORT=${1:-certs}
# get name - .letsEncrypt.Certificates | .[0] | .domain.main
# get key - .letsEncrypt.Certificates | .[0] | .key
# get cert - .letsEncrypt.Certificates | .[0] | .certificate
ACME=data/acme.json
LENGTH=$(cat ${ACME} | jq '.letsEncrypt.Certificates | length')
mkdir -p ${FOLDER_EXPORT}
i=1
while [ $i != ${LENGTH} ]
do
name=$(cat ${ACME} | jq -r ".letsEncrypt.Certificates | .[${i}] | .domain.main")
key=$(cat ${ACME} | jq -r ".letsEncrypt.Certificates | .[${i}] | .key")
cert=$(cat ${ACME} | jq -r ".letsEncrypt.Certificates | .[${i}] | .certificate")
echo "export ${name}"
mkdir -p ${FOLDER_EXPORT}/${name}
echo $key | base64 --decode > ${FOLDER_EXPORT}/${name}/privkey.pem
echo $cert | base64 --decode > ${FOLDER_EXPORT}/${name}/cert.pem
echo "null" > ${FOLDER_EXPORT}/${name}/fullchain.pem
((i++))
done

6
traefik-repo/traefik/init.sh Executable file
View File

@@ -0,0 +1,6 @@
#!/bin/bash
[ ! -f .env ] && cp .env.example .env
touch data/acme.json
chmod 600 data/acme.json

View File

@@ -0,0 +1,22 @@
#!/bin/bash
DOMAIN=pve.domain.ru
PEM=pveproxy-ssl.pem
KEY=pveproxy-ssl.key
DEST_PATH=/etc/pve/local
SERVICE_RESTART=pveproxy
echo "[ START ] on $(date +'%d-%m-%Y_%H-%M')"
cp certs/${DOMAIN}/cert.pem ${DEST_PATH}/${PEM}
cp certs/${DOMAIN}/privkey.pem ${DEST_PATH}/${KEY}
SERVICE_RESTART=pveproxy
systemctl restart $SERVICE_RESTART
[[ ! $? -eq 0 ]] && echo "service not restarted, restart manually"
echo "[ END ] on $(date +'%d-%m-%Y_%H-%M')"
echo ""

View File

@@ -0,0 +1,135 @@
# Traefik server for docker
- поднимает траефик в докере
- позволяет выпускать наружу другие сервисы как в докере, так и из локальной сети подставляя валидные SSL сертификаты
- traefik-api умеет отдавать сертификаты по запросу через `токен`
## Настройка
- заполнить `.env` из `.env.example`
- запустить `./init.sh` (делается первый и единственный раз)
- запустить сервис
```
docker-compose up -d
```
- добавить в крон дампер, который из файла `acme.json` вытягивает и раскладывает сертификаты по папкам с названием доменов (нужно, что бы корректно работал `traefik-api`)
```
25 07 * *\1 * cd /srv/services/traefik/ && ./dumper.sh >> /var/log/traefik_api.log
```
**Внимание!**, что бы правильно работал `dumper.sh` в системе должна быть установлена утилита `jq`
```
apt install jq - для Debian\Ubuntu
brew install jq - для MacOS
```
## Внешняя защита
- Так как сам сервис trafik доступен из вне, его так же логично закрыть хотя бы basic auth
- в файле docker-compose.yml раскомментим строки:
```
- ./data/basic.auth:/basic.auth
- "traefik.http.middlewares.traefik-auth.basicAuth.usersFile=/basic.auth"
- "traefik.http.routers.traefik.middlewares=traefik-auth"
```
в папку `data` сгенерим файлик `basic.auth` c логином и паролем
```
htpasswd -c data/basic.auth admin
```
## Докерные сервисы
- запускаем нужный контейнер с правильно выставленными `лейблами`
- контейнер должен быть в том числе подключен к сети `webproxy`
**Пример**:
```
version: '3.7'
services:
grafana:
container_name: grafana
image: grafana/grafana:latest
restart: always
labels:
- "traefik.enable=true"
- "traefik.http.routers.grafana.entrypoints=https"
- "traefik.http.routers.grafana.rule=Host(`grafana.domain.ru`)"
- "traefik.http.routers.grafana.tls=true"
- "traefik.http.routers.grafana.tls.certresolver=letsEncrypt"
- "traefik.http.services.grafana-service.loadbalancer.server.port=3000"
- "traefik.docker.network=webproxy"
environment:
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
- GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
- GF_AUTH_ANONYMOUS_ENABLED=false
- GF_USERS_ALLOW_SIGN_UP=false
- GF_USERS_ALLOW_ORG_CREATE=false
volumes:
- grafana:/var/lib/grafana
expose:
- 3000
networks:
- grafana_net
- webproxy
```
## Кастомные сервисы
- примеры кастомных сервисов (читать - сервисы не в докере, а в локальной сети) лежат в папке `data/custom`
- файл должен иметь вид `name.yml` и содержать в себе правильный контекст (проверить ошибки применения можно через `docker log <traefik_container>`)
- перезапускать траефик, что бы применить новые файлы `не нужно!`
- если сервис больше не нужен, файл удаляется руками или переносится в папку disabled (опять же траефик применяет изменения налету)
## Traefik API
- Позволяет отдавать сертификаты в [traefik-api-client](../traefik-api-client/readme.MD) или по запросу
- В `.env` в переменной `ADMIN_TOKEN` указываем наш стойкий токен
### Методы для работы с API:
#### авторизация:
```
'headers' => [
'Authorization' => 'Bearer ' . $TOKEN,
]
```
#### проверка, что у traefik есть нужный домен:
```
curl -s --request POST 'https://traefik-api.domain.ru/api/v1/certman/getdomain' \
--header 'Authorization: Bearer <token>' \
--form 'domain=domain.ru'
```
#### запрос ключей:
```
curl -s --request POST 'https://traefik-api.domain.ru/api/v1/certman/getcerts' \
--header 'Authorization: Bearer <token>' \
--form 'domain=domain.ru'
```
#### корректный вывод будет такой:
```
{
"success": true,
"data": {
"crt": "-----BEGIN CERTIFICATE-----\\...\\-----END CERTIFICATE-----",
"key": "-----BEGIN PRIVATE KEY-----\\...\\-----END PRIVATE KEY-----",
"chain": "-----BEGIN CERTIFICATE-----\\...\\-----END CERTIFICATE-----"
},
"message": "OK"
}
```