I’m new to security, so I maybe missed some knowledge. I’m trying to setup Https on my app but I’m stuck with a 502 error reported by cloudflare. I have many questions…
My app is dockerized, nestjs for the api, nextjs for the client, and Caddy as reverse proxy. On my local desktop everything is fine, Caddy does the job etc.
The difference with the production environment is Cloudflare.
I have 2 domains, suppose they are “mydomain.app” & “api.mydomaine.app”
I use cloudflare proxies for my domains, if I turn it off, many errors occured. I use cloudflare SSL Full strict mode.
I already went to cloudflare documentation to fix issues (about headers)
First questions:
I used the certificate generator from cloudflare to specify key & cert files to Caddy.
Should I use the same certificates for my NestJs App with the httpsOption ?
Does the api require to be in https too ? And should I use this certificates for the api ? Or others ?
Caddy code :
mydomain.app {
tls /etc/ssl/certs/cert.pem /etc/ssl/private/key.pem
reverse_proxy nextjs:3000
}
api.mydomain.app {
@cors_preflight {
method OPTIONS
}
respond @cors_preflight 204
header {
# Origin https://mydomain.app
# Access-Control-Allow-Origin https://mydomain.app
# Access-Control-Allow-Methods "GET,POST,OPTIONS,PATCH,PUT,DELETE"
# Access-Control-Allow-Headers "Content-Type,Authorization"
# Access-Control-Max-Age 86400
-X-Powered-By
-Server
# enable HSTS
Strict-Transport-Security max-age=31536000;
# disable clients from sniffing the media type
X-Content-Type-Options nosniff
# clickjacking protection
X-Frame-Options DENY
# XSS Protection
X-XSS-Protection "1; mode=block"
}
reverse_proxy nestjs:4000
}
NestJs code :
options.https = {
key: readFileSync('./certificates/key.pem'),
cert: readFileSync('./certificates/cert.pem'),
};
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(options)
);
Here is the error reported in Caddy’s log :
{
"level": "error",
"ts": 1738110651.6178956,
"logger": "http.log.error",
"msg": "EOF",
"request": {
"remote_ip": "172.71.172.133",
"remote_port": "47534",
"client_ip": "172.71.172.133",
"proto": "HTTP/2.0",
"method": "POST",
"host": "api.mydomain.app",
"uri": "/auth/login",
"headers": {
"Accept-Encoding": ["gzip, br"],
"Content-Type": ["application/json"],
"Sec-Ch-Ua": [
"\"Not A(Brand\";v=\"8\", \"Chromium\";v=\"132\", \"Google Chrome\";v=\"132\""
],
"Cf-Visitor": ["{\"scheme\":\"https\"}"],
"Sec-Fetch-Site": ["same-site"],
"Pragma": ["no-cache"],
"Cache-Control": ["no-cache"],
"X-Forwarded-Proto": ["https"],
"Cf-Connecting-Ip": ["81.254.47.103"],
"Referer": ["https://mydomain.app/"],
"X-Forwarded-For": ["81.254.47.103"],
"Sec-Fetch-Dest": ["empty"],
"Content-Length": ["67"],
"Cdn-Loop": ["cloudflare; loops=1"],
"Origin": ["https://mydomain.app"],
"Sec-Ch-Ua-Platform": ["\"Windows\""],
"Priority": ["u=1, i"],
"Sec-Ch-Ua-Mobile": ["?0"],
"Cf-Ray": ["90951db42ae13cc2-FRA"],
"Cf-Ipcountry": ["FR"],
"Dnt": ["1"],
"User-Agent": [
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36"
],
"Accept": ["application/json, text/plain, */*"],
"Accept-Language": ["fr-FR,fr;q=0.9,en-US;q=0.8,en;q=0.7"],
"Sec-Fetch-Mode": ["cors"]
},
"tls": {
"resumed": false,
"version": 772,
"cipher_suite": 4865,
"proto": "h2",
"server_name": "api.mydomain.app"
}
},
"duration": 0.00345099,
"status": 502,
"err_id": "nk4n4frc7",
"err_trace": "reverseproxy.statusError (reverseproxy.go:1373)"
}
I setup rules in Cloudflare because of a cors error : Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource.
My rule : (http.host eq “api.mydomain.app” and http.request.headers[“origin”][0] in {“https://mydomain.app”})
Define static : Access-Control-Allow-Headers = Content-Type,Authorization Define static : Access-Control-Allow-Origin = https://mydomain.app
I mainly followed this tutorial : https://www.youtube.com/watch?v=nKV5EKkChSU&list=PL99M1q5KDFQBGssxI0jRNKHFp_7Y3R39h&index=2
Some differences : I don’t serve files with caddy or the client or api.
I tried many things but I stuck since 4 days now…
Thanks for your answers per advance.