1. The problem I’m having:
I’m trying to use the tls ciphers directive to specify a list of allowed cipher suites. A customer wants to exclude CBC ciphers.
We realize it’s preferable not to change the defaults and we’ve advised our customer accordingly. However, we want to make sure we can disable the CBC ciphers if they insist.
2. Error messages and/or full log output:
root-web.1.ztu1dhvb9oba@ubuntu-s-8vcpu-16gb-intel-nyc3-01 | {"level":"info","ts":1680806830.4784403,"msg":"using provided configuration","config_file":"/tmpapp/CaddyfileForContainer","config_adapter":""}
root-web.1.ztu1dhvb9oba@ubuntu-s-8vcpu-16gb-intel-nyc3-01 | Error: adapting config using caddyfile: /tmpapp/CaddyfileForContainer:9: unrecognized directive: ciphers
3. Caddy version:
Built off commit f8b59e77f83c05da87bd5e3780fb7522b863d462 on master branch
4. How I installed and ran Caddy:
Built docker image containing executable mentioned above
a. System environment:
Alpine docker image
b. Command:
./caddy run --config /tmpapp/CaddyfileForContainer
c. Service/unit/compose file:
FROM alpine:3.16.4
ENV CADDYPATH=/tmpapp
ENV XDG_DATA_HOME=/tmpapp
ENV XDG_CONFIG_HOME=/tmpapp
WORKDIR /app
COPY . .
RUN set -eux && \
apk add --no-cache libcap nss-tools && \
adduser -u 10654 -g amag -s /bin/false --disabled-password amag && chown amag:amag -R /app && \
setcap CAP_NET_BIND_SERVICE=+eip /app/caddy
USER amag
EXPOSE 8080 8443
HEALTHCHECK --interval=5s --timeout=5s --start-period=5s --retries=3 CMD \
wget -S -q --spider http://localhost:8080/health-check || wget -S -q --spider http://localhost:8080/health-check 2>&1 | grep "308 Permanent Redirect" || exit 1
ENTRYPOINT ["/app/run.sh"]
d. My complete Caddy config:
# Header
{
debug
https_port 8443
http_port 8080
}
# CADDY Body
tls /run/secrets/rootweb_idm_pem /run/secrets/rootweb_idm_key {
ciphers TLS_RSA_WITH_AES_128_GCM_SHA256 TLS_RSA_WITH_AES_256_GCM_SHA384 TLS_AES_128_GCM_SHA256 TLS_AES_256_GCM_SHA384 TLS_CHACHA20_POLY1305_SHA256 TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256
}
# START InBody Customization
# END InBody Customization
encode gzip
log
file_server
header {
# Disallow the site to be rendered within a frame on different domain (clickjacking protection)
+X-Frame-Options "SAMEORIGIN"
-Server
-x-powered-by
+Access-Control-Allow-Headers Range
+Access-Control-Expose-Headers "Accept-Ranges, Content-Encoding, Content-Length, Content-Range"
#Implement Security Headers
X-Content-Type-Options "nosniff"
Strict-Transport-Security "max-age=31536000; includeSubDomains"
Content-Security-Policy "default-src data: https:; font-src data: https:; frame-src 'self' https: mailto: tel:; img-src data: https: http://localhost:1337 http://localhost:1338; script-src https: 'unsafe-inline' 'unsafe-eval'; style-src https: 'unsafe-inline'; connect-src https: ws://localhost:* wss: 'self' http://localhost:1337/* *.firebaseio.com"
Permissions-Policy "accelerometer=(), camera=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), interest-cohort=()"
Referrer-Policy "strict-origin-when-cross-origin"
}
# Enabling CORS for CDN Only
# The default Same-Origin Policy is enough for the web and apis
#######################################################################
# Set mime type for specific file as content sniffing is now disabled
# and browser needs to still behave as expected:
# - opening the file inside a tab as text or image for example,
# - downloading the file instead of opening it as text...
#######################################################################
@exe {
path *.exe
}
header @exe Content-Type application/octet-stream
@ttf {
path *.ttf
}
header @ttf Content-Type font/ttf
@woff {
path *.woff
}
header @woff Content-Type font/woff
@woff2 {
path *.woff2
}
header @woff2 Content-Type font/woff2
@mem {
path *.mem
}
header @mem Content-Type application/octet-stream
@ico {
path *.ico
}
header @ico Content-Type image/x-icon
@pk {
path *.pkpass
}
header @pk Content-Type application/vnd.apple.pkpass
#######################################################################
header /cdn* {
+Access-Control-Allow-Origin "*"
}
#mime .xlsx application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
@xlsx {
path *.xlsx
}
header @xlsx Content-Type application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
@txt {
path *.txt
}
header @txt Content-Disposition attachment
@csv {
path *.csv
}
header @csv Content-Disposition attachment
respond /health-check 200
#################################################
# Rewrite rules to eliminate case issues. Proxy
# routes are case sensitive
#################################################
redir /G4S.Portal.Web/ /AMAG.Auth
# rewrite /G4S.Portal.Web /AMAG.Portal - Above line used instead to bring new prospect signups to login screen vs Portal.
rewrite /Amag.Auth /AMAG.Auth
rewrite / /AMAG.Auth
rewrite /OneFacilityLoginWeb/Login/Login.mvc /AMAG.Auth
@amag-auth {
path /G4S.Portal.Web
path /Amag.Auth
path /AMAG.Auth
path /
path /OneFacilityLoginWeb/Login/Login.mvc
}
# CDN Image Resizer
@cdn_resize {
path /cdn/photos*
not query ""
not query random=*
}
rewrite @cdn_resize /display/resize/0x0{path}
reverse_proxy /display/* http://picfit:7319
# DOCUMENTATION
redir /documentation /documentation/
route /documentation/* {
uri strip_prefix /documentation
root * /app/cdn/documentation
file_server
}
# S3 CDN
##################################################
# Self hosted kestrel (.net core)
##################################################
reverse_proxy /AMAG.Auth* auth-web:7325
reverse_proxy /AMAG.Portal* portal-web:7326
reverse_proxy /amag.sso* sso-web:7328
## Below two proxies needed since JS points to old locations
#reverse_proxy /G4S.Portal.Web/public/ localhost:7326/AMAG.Portal/public/ {
# without /G4S.Portal.Web/public/
#}
reverse_proxy /G4S.Portal.Web/public* portal-web:7326
reverse_proxy /Amag.Login.Web/Login/Login* auth-web:7325
##################################################
# Self hosted React Apps (caddy)
##################################################
route /G4S.Registration.Web/* {
uri strip_prefix /G4S.Registration.Web
reverse_proxy registration-web:7320
}
@cac-web {
path /Amag.CAC.Web/*
path /AMAG.CAC.Web/*
}
route @cac-web {
uri strip_prefix /AMAG.CAC.Web
uri strip_prefix /Amag.CAC.Web
reverse_proxy cac-web:7323
}
route /G4S.IdentityManagement.Web/* {
uri strip_prefix /G4S.IdentityManagement.Web
reverse_proxy idm-web:7324
}
route /G4S.VMS.Web/* {
uri strip_prefix /G4S.VMS.Web
reverse_proxy vms-web:7327
}
##################################################
# Self hosted ReST APIs (servicestack)
##################################################
route /G4S.Registration.WebApi/api/* {
uri strip_prefix /G4S.Registration.WebApi/api
reverse_proxy registration-api:7120
}
route /AMAG.Symmetry.WebApi/api/* {
uri strip_prefix /AMAG.Symmetry.WebApi/api
reverse_proxy symmetry-api:7121
}
route /G4S.Core.WebApi/api/* {
uri strip_prefix /G4S.Core.WebApi/api
reverse_proxy core-api:7122
}
@cac-api {
path /Amag.CAC.WebApi/*
path /AMAG.CAC.WebApi/*
}
route @cac-api {
uri strip_prefix /AMAG.CAC.WebApi/api
uri strip_prefix /Amag.CAC.WebApi/api
reverse_proxy cac-api:7123
}
route /G4S.IdentityManagement.WebApi/api/* {
uri strip_prefix /G4S.IdentityManagement.WebApi/api
reverse_proxy idm-api:7124
}
route /G4S.VMS.WebApi/api/* {
uri strip_prefix /G4S.VMS.WebApi/api
reverse_proxy vms-api:7127
}
route /AMAG.Public/api/* {
uri strip_prefix /AMAG.Public/api
reverse_proxy public-api:7130
}
handle_path /G4S.VMS.WebSocketHub {
rewrite * /websockethub?{query}
reverse_proxy vms-websocket:5100
}
redir / /AMAG.Portal
#################################################
# IIS hosted applications
# NOTE: one entry can cover both web & webApi
#################################################
}