Merge pull request #1880 from SkynetLabs/certbot

replace caddy with certbot
This commit is contained in:
Karol Wypchło 2022-03-22 13:02:53 +01:00 committed by GitHub
commit f72043c732
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 79 additions and 1205 deletions

View File

@ -20,10 +20,6 @@ updates:
directory: "/packages/website" directory: "/packages/website"
schedule: schedule:
interval: weekly interval: weekly
- package-ecosystem: docker
directory: "/docker/caddy"
schedule:
interval: weekly
- package-ecosystem: docker - package-ecosystem: docker
directory: "/docker/nginx" directory: "/docker/nginx"
schedule: schedule:

View File

@ -39,21 +39,19 @@ services:
expose: expose:
- 9980 - 9980
caddy: certbot:
build: image: certbot/dns-route53:v1.25.0
context: ./docker/caddy entrypoint: sh /entrypoint.sh
dockerfile: Dockerfile container_name: certbot
container_name: caddy
restart: unless-stopped restart: unless-stopped
logging: *default-logging logging: *default-logging
env_file: env_file:
- .env - .env
environment:
- CERTBOT_ARGS=--dns-route53
volumes: volumes:
- ./docker/data/caddy/data:/data - ./docker/certbot/entrypoint.sh:/entrypoint.sh
- ./docker/data/caddy/config:/config - ./docker/data/certbot:/etc/letsencrypt
networks:
shared:
ipv4_address: 10.10.10.20
nginx: nginx:
build: build:
@ -70,7 +68,7 @@ services:
- ./docker/data/nginx/logs:/usr/local/openresty/nginx/logs - ./docker/data/nginx/logs:/usr/local/openresty/nginx/logs
- ./docker/data/nginx/skynet:/data/nginx/skynet:ro - ./docker/data/nginx/skynet:/data/nginx/skynet:ro
- ./docker/data/sia/apipassword:/data/sia/apipassword:ro - ./docker/data/sia/apipassword:/data/sia/apipassword:ro
- ./docker/data/caddy/data:/data/caddy:ro - ./docker/data/certbot:/etc/letsencrypt
networks: networks:
shared: shared:
ipv4_address: 10.10.10.30 ipv4_address: 10.10.10.30
@ -79,7 +77,6 @@ services:
- "80:80" - "80:80"
depends_on: depends_on:
- sia - sia
- caddy
- handshake-api - handshake-api
- dnslink-api - dnslink-api
- website - website
@ -174,5 +171,3 @@ services:
- STATE_DIR=/usr/app/state - STATE_DIR=/usr/app/state
expose: expose:
- 3100 - 3100
depends_on:
- caddy

View File

@ -1,18 +0,0 @@
FROM caddy:2.4.6-builder AS caddy-builder
# available dns resolvers: https://github.com/caddy-dns
RUN xcaddy build --with github.com/caddy-dns/route53
FROM caddy:2.4.6-alpine
COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy
# bash required for mo to work (mo is mustache templating engine - https://github.com/tests-always-included/mo)
RUN apk add --no-cache bash
COPY caddy.json.template mo /etc/caddy/
CMD [ "sh", "-c", \
"/etc/caddy/mo < /etc/caddy/caddy.json.template > /etc/caddy/caddy.json ; \
caddy run --config /etc/caddy/caddy.json" \
]

View File

@ -1,38 +0,0 @@
{
"apps": {
"tls": {
"certificates": {
"automate": [
{{#PORTAL_DOMAIN}}
"{{PORTAL_DOMAIN}}", "*.{{PORTAL_DOMAIN}}", "*.hns.{{PORTAL_DOMAIN}}"
{{/PORTAL_DOMAIN}}
{{#PORTAL_DOMAIN}}{{#SERVER_DOMAIN}},{{/SERVER_DOMAIN}}{{/PORTAL_DOMAIN}}
{{#SERVER_DOMAIN}}
"{{SERVER_DOMAIN}}", "*.{{SERVER_DOMAIN}}", "*.hns.{{SERVER_DOMAIN}}"
{{/SERVER_DOMAIN}}
]
},
"automation": {
"policies": [
{
"issuers": [
{
"module": "acme",
"email": "{{EMAIL_ADDRESS}}",
"challenges": {
"dns": {
"provider": {
"name": "route53"
}
}
}
}
]
}
]
}
}
}
}

File diff suppressed because it is too large Load Diff

55
docker/certbot/entrypoint.sh Executable file
View File

@ -0,0 +1,55 @@
#!/bin/bash
# Portal domain requires 3 domain certificates:
# - exact portal domain, ie. example.com
# - wildcard subdomain on portal domain, ie. *.example.com
# used for skylinks served from portal subdomain
# - wildcard subdomain on hns portal domain subdomain, ie. *.hns.example.com
# used for resolving handshake domains
DOMAINS=${PORTAL_DOMAIN},*.${PORTAL_DOMAIN},*.hns.${PORTAL_DOMAIN}
# Add server domain when it is not empty and different from portal domain
if [ ! -z "${SERVER_DOMAIN}" ] && [ "${PORTAL_DOMAIN}" != "${SERVER_DOMAIN}" ]; then
# In case where server domain is not covered by portal domain's
# wildcard certificate, add server domain name to domains list.
# - server-001.example.com is covered by *.example.com
# - server-001.servers.example.com or server-001.example-severs.com
# are not covered by any already requested wildcard certificates
#
# The condition checks whether server domain does not match portal domain
# with exactly one level of subdomain (portal domain wildcard cert):
# (start) [anything but the dot] + [dot] + [portal domain] (end)
if ! printf "${SERVER_DOMAIN}" | grep -q -E "^[^\.]+\.${PORTAL_DOMAIN}$"; then
DOMAINS=${DOMAINS},${SERVER_DOMAIN}
fi
# Server domain requires the same set of domain certificates as portal domain.
# Exact server domain case is handled above.
DOMAINS=${DOMAINS},*.${SERVER_DOMAIN},*.hns.${SERVER_DOMAIN}
fi
# The "wait" will prevent an exit from the script while background tasks are
# still active, so we are adding the line below as a method to prevent orphaning
# the background child processe. The trap fires when docker terminates the container.
trap exit TERM
while :; do
# Execute certbot and generate or maintain certificates for given domain string.
# --non-interactive: we are running this as an automation so we cannot be prompted
# --agree-tos: required flag marking agreement with letsencrypt tos
# --cert-name: output directory name
# --email: required for generating certificates, used for communication with CA
# --domains: comma separated list of domains (will generate one bundled SAN cert)
# Use CERTBOT_ARGS env variable to pass any additional arguments, ie --dns-route53
certbot certonly \
--non-interactive --agree-tos --cert-name skynet-portal \
--email ${EMAIL_ADDRESS} --domains ${DOMAINS} ${CERTBOT_ARGS}
# Run a background sleep process that counts down given time
# Certbot docs advise running maintenance process every 12 hours
sleep 12h &
# Await execution until sleep process is finished (it's a background process)
# Syntax explanation: ${!} expands to a pid of last ran process
wait ${!}
done

View File

@ -18,5 +18,6 @@ CMD [ "bash", "-c", \
./mo < /etc/nginx/conf.d.templates/server.api.conf > /etc/nginx/conf.d/server.api.conf; \ ./mo < /etc/nginx/conf.d.templates/server.api.conf > /etc/nginx/conf.d/server.api.conf; \
./mo < /etc/nginx/conf.d.templates/server.hns.conf > /etc/nginx/conf.d/server.hns.conf; \ ./mo < /etc/nginx/conf.d.templates/server.hns.conf > /etc/nginx/conf.d/server.hns.conf; \
./mo < /etc/nginx/conf.d.templates/server.skylink.conf > /etc/nginx/conf.d/server.skylink.conf ; \ ./mo < /etc/nginx/conf.d.templates/server.skylink.conf > /etc/nginx/conf.d/server.skylink.conf ; \
while :; do sleep 6h & wait ${!}; /usr/local/openresty/bin/openresty -s reload; done & \
/usr/local/openresty/bin/openresty '-g daemon off;'" \ /usr/local/openresty/bin/openresty '-g daemon off;'" \
] ]

View File

@ -18,9 +18,6 @@
return "{{SERVER_DOMAIN}}" return "{{SERVER_DOMAIN}}"
} }
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{PORTAL_DOMAIN}}/wildcard_.{{PORTAL_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{PORTAL_DOMAIN}}/wildcard_.{{PORTAL_DOMAIN}}.key;
include /etc/nginx/conf.d/server/server.account; include /etc/nginx/conf.d/server/server.account;
} }
{{/PORTAL_DOMAIN}} {{/PORTAL_DOMAIN}}
@ -37,9 +34,6 @@
server { server {
server_name account.{{SERVER_DOMAIN}}; # example: account.eu-ger-1.siasky.net server_name account.{{SERVER_DOMAIN}}; # example: account.eu-ger-1.siasky.net
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{SERVER_DOMAIN}}/wildcard_.{{SERVER_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{SERVER_DOMAIN}}/wildcard_.{{SERVER_DOMAIN}}.key;
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }

View File

@ -17,9 +17,6 @@ server {
return "{{SERVER_DOMAIN}}" return "{{SERVER_DOMAIN}}"
} }
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/{{PORTAL_DOMAIN}}/{{PORTAL_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/{{PORTAL_DOMAIN}}/{{PORTAL_DOMAIN}}.key;
include /etc/nginx/conf.d/server/server.api; include /etc/nginx/conf.d/server/server.api;
} }
{{/PORTAL_DOMAIN}} {{/PORTAL_DOMAIN}}
@ -36,9 +33,6 @@ server {
server { server {
server_name {{SERVER_DOMAIN}}; # example: eu-ger-1.siasky.net server_name {{SERVER_DOMAIN}}; # example: eu-ger-1.siasky.net
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/{{SERVER_DOMAIN}}/{{SERVER_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/{{SERVER_DOMAIN}}/{{SERVER_DOMAIN}}.key;
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }

View File

@ -17,9 +17,6 @@ server {
return "{{SERVER_DOMAIN}}" return "{{SERVER_DOMAIN}}"
} }
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.hns.{{PORTAL_DOMAIN}}/wildcard_.hns.{{PORTAL_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.hns.{{PORTAL_DOMAIN}}/wildcard_.hns.{{PORTAL_DOMAIN}}.key;
proxy_set_header Host {{PORTAL_DOMAIN}}; proxy_set_header Host {{PORTAL_DOMAIN}};
include /etc/nginx/conf.d/server/server.hns; include /etc/nginx/conf.d/server/server.hns;
} }
@ -37,9 +34,6 @@ server {
server { server {
server_name *.hns.{{SERVER_DOMAIN}}; # example: *.hns.eu-ger-1.siasky.net server_name *.hns.{{SERVER_DOMAIN}}; # example: *.hns.eu-ger-1.siasky.net
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.hns.{{SERVER_DOMAIN}}/wildcard_.hns.{{SERVER_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.hns.{{SERVER_DOMAIN}}/wildcard_.hns.{{SERVER_DOMAIN}}.key;
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }

View File

@ -17,9 +17,6 @@ server {
return "{{SERVER_DOMAIN}}" return "{{SERVER_DOMAIN}}"
} }
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{PORTAL_DOMAIN}}/wildcard_.{{PORTAL_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{PORTAL_DOMAIN}}/wildcard_.{{PORTAL_DOMAIN}}.key;
include /etc/nginx/conf.d/server/server.skylink; include /etc/nginx/conf.d/server/server.skylink;
} }
{{/PORTAL_DOMAIN}} {{/PORTAL_DOMAIN}}
@ -39,9 +36,6 @@ server {
set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_portal_domain { return "{{SERVER_DOMAIN}}" }
set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" } set_by_lua_block $skynet_server_domain { return "{{SERVER_DOMAIN}}" }
ssl_certificate /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{SERVER_DOMAIN}}/wildcard_.{{SERVER_DOMAIN}}.crt;
ssl_certificate_key /data/caddy/caddy/certificates/acme-v02.api.letsencrypt.org-directory/wildcard_.{{SERVER_DOMAIN}}/wildcard_.{{SERVER_DOMAIN}}.key;
include /etc/nginx/conf.d/server/server.skylink; include /etc/nginx/conf.d/server/server.skylink;
set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") } set_by_lua_block $server_alias { return string.match("{{SERVER_DOMAIN}}", "^([^.]+)") }

View File

@ -1,7 +1,10 @@
# https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1d&hsts=false&ocsp=false&guideline=5.6 # https://ssl-config.mozilla.org/#server=nginx&version=1.17.7&config=intermediate&openssl=1.1.1d&hsts=false&ocsp=false&guideline=5.6
ssl_certificate /etc/letsencrypt/live/skynet-portal/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/skynet-portal/privkey.pem;
ssl_session_timeout 1d; ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off; ssl_session_tickets off;
# curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam # curl https://ssl-config.mozilla.org/ffdhe2048.txt > /path/to/dhparam
@ -11,3 +14,13 @@ ssl_dhparam /etc/nginx/conf.d/dhparam.pem;
ssl_protocols TLSv1.2 TLSv1.3; ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384; ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off; ssl_prefer_server_ciphers off;
# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
# verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /etc/letsencrypt/live/skynet-portal/chain.pem;