[{"data":1,"prerenderedAt":1586},["ShallowReactive",2],{"\u002Fchecklist\u002Fflask-https-and-domain-checklist":3},{"id":4,"title":5,"body":6,"description":1576,"extension":1577,"meta":1578,"navigation":56,"path":1582,"seo":1583,"stem":1584,"__hash__":1585},"content\u002Fchecklist\u002Fflask-https-and-domain-checklist.md","Flask HTTPS and Domain Checklist",{"type":7,"value":8,"toc":1565},"minimark",[9,13,17,22,25,154,161,165,168,187,190,194,894,898,972,976,979,1161,1164,1271,1279,1283,1418,1422,1446,1450,1461,1469,1480,1488,1499,1507,1518,1530,1542,1554,1558,1561],[10,11,5],"h1",{"id":12},"flask-https-and-domain-checklist",[14,15,16],"p",{},"If you're trying to validate domain and HTTPS setup for a Flask app in production, this guide shows you what to verify step-by-step. Use it to confirm DNS, Nginx, TLS, redirects, and certificate renewal are working before or after launch.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24],{},"Run these checks first:",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","dig +short yourdomain.com\n\ndig +short www.yourdomain.com\n\nsudo nginx -t && sudo systemctl reload nginx\n\nsudo certbot certificates\n\ncurl -I http:\u002F\u002Fyourdomain.com\ncurl -I https:\u002F\u002Fyourdomain.com\ncurl -Iv https:\u002F\u002Fyourdomain.com\n","bash","",[33,34,35,51,58,68,73,101,106,117,122,134,144],"code",{"__ignoreMap":31},[36,37,40,44,48],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sScJk","dig",[36,45,47],{"class":46},"sZZnC"," +short",[36,49,50],{"class":46}," yourdomain.com\n",[36,52,54],{"class":38,"line":53},2,[36,55,57],{"emptyLinePlaceholder":56},true,"\n",[36,59,61,63,65],{"class":38,"line":60},3,[36,62,43],{"class":42},[36,64,47],{"class":46},[36,66,67],{"class":46}," www.yourdomain.com\n",[36,69,71],{"class":38,"line":70},4,[36,72,57],{"emptyLinePlaceholder":56},[36,74,76,79,82,86,90,92,95,98],{"class":38,"line":75},5,[36,77,78],{"class":42},"sudo",[36,80,81],{"class":46}," nginx",[36,83,85],{"class":84},"sj4cs"," -t",[36,87,89],{"class":88},"sVt8B"," && ",[36,91,78],{"class":42},[36,93,94],{"class":46}," systemctl",[36,96,97],{"class":46}," reload",[36,99,100],{"class":46}," nginx\n",[36,102,104],{"class":38,"line":103},6,[36,105,57],{"emptyLinePlaceholder":56},[36,107,109,111,114],{"class":38,"line":108},7,[36,110,78],{"class":42},[36,112,113],{"class":46}," certbot",[36,115,116],{"class":46}," certificates\n",[36,118,120],{"class":38,"line":119},8,[36,121,57],{"emptyLinePlaceholder":56},[36,123,125,128,131],{"class":38,"line":124},9,[36,126,127],{"class":42},"curl",[36,129,130],{"class":84}," -I",[36,132,133],{"class":46}," http:\u002F\u002Fyourdomain.com\n",[36,135,137,139,141],{"class":38,"line":136},10,[36,138,127],{"class":42},[36,140,130],{"class":84},[36,142,143],{"class":46}," https:\u002F\u002Fyourdomain.com\n",[36,145,147,149,152],{"class":38,"line":146},11,[36,148,127],{"class":42},[36,150,151],{"class":84}," -Iv",[36,153,143],{"class":46},[14,155,156,157,160],{},"Replace ",[33,158,159],{},"yourdomain.com"," with the production domain. This validates DNS resolution, Nginx config syntax, certificate presence, and HTTP\u002FHTTPS response behavior.",[18,162,164],{"id":163},"whats-happening","What’s Happening",[14,166,167],{},"A working Flask HTTPS setup depends on four layers:",[169,170,171,175,181,184],"ol",{},[172,173,174],"li",{},"DNS points to the correct server",[172,176,177,178],{},"Nginx matches the correct ",[33,179,180],{},"server_name",[172,182,183],{},"A valid certificate is installed for the active hostnames",[172,185,186],{},"HTTP redirects cleanly to HTTPS",[14,188,189],{},"If any layer is wrong, users may see certificate warnings, the wrong site, redirect loops, timeouts, or plain HTTP.",[18,191,193],{"id":192},"step-by-step-guide","Step-by-Step Guide",[169,195,196,227,259,293,391,416,436,511,543,573,607,645,686,733,776,811,833,869],{},[172,197,198,202,223,226],{},[199,200,201],"strong",{},"Verify the domain resolves to the correct public IP",[26,203,205],{"className":28,"code":204,"language":30,"meta":31,"style":31},"dig +short yourdomain.com\ndig +short www.yourdomain.com\n",[33,206,207,215],{"__ignoreMap":31},[36,208,209,211,213],{"class":38,"line":39},[36,210,43],{"class":42},[36,212,47],{"class":46},[36,214,50],{"class":46},[36,216,217,219,221],{"class":38,"line":53},[36,218,43],{"class":42},[36,220,47],{"class":46},[36,222,67],{"class":46},[224,225],"br",{},"Confirm both records point to the intended server or CDN endpoint.",[172,228,229,232,234,235,256,258],{},[199,230,231],{},"Confirm DNS record types are correct",[224,233],{},"Use:",[236,237,238,244,250],"ul",{},[172,239,240,243],{},[33,241,242],{},"A"," for IPv4",[172,245,246,249],{},[33,247,248],{},"AAAA"," for IPv6",[172,251,252,255],{},[33,253,254],{},"CNAME"," only where appropriate",[224,257],{},"Remove stale records that still point to old servers.",[172,260,261,264,266,267,282,284,285,288,289,292],{},[199,262,263],{},"Verify the firewall allows HTTP and HTTPS",[224,265],{},"On Ubuntu with UFW:",[26,268,270],{"className":28,"code":269,"language":30,"meta":31,"style":31},"sudo ufw status\n",[33,271,272],{"__ignoreMap":31},[36,273,274,276,279],{"class":38,"line":39},[36,275,78],{"class":42},[36,277,278],{"class":46}," ufw",[36,280,281],{"class":46}," status\n",[224,283],{},"Confirm ports ",[33,286,287],{},"80"," and ",[33,290,291],{},"443"," are allowed.",[172,294,295,298,300,301,312,314,315],{},[199,296,297],{},"Check that Nginx has the correct domain names",[224,299],{},"Inspect the active site config and confirm:",[26,302,306],{"className":303,"code":304,"language":305,"meta":31,"style":31},"language-nginx shiki shiki-themes github-light github-dark","server_name yourdomain.com www.yourdomain.com;\n","nginx",[33,307,308],{"__ignoreMap":31},[36,309,310],{"class":38,"line":39},[36,311,304],{},[224,313],{},"Example HTTPS server block:",[26,316,318],{"className":303,"code":317,"language":305,"meta":31,"style":31},"server {\n    listen 443 ssl http2;\n    listen [::]:443 ssl http2;\n    server_name yourdomain.com www.yourdomain.com;\n\n    ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Ffullchain.pem;\n    ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Fprivkey.pem;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fgunicorn.sock;\n        include proxy_params;\n        proxy_redirect off;\n    }\n}\n",[33,319,320,325,330,335,340,344,349,354,358,363,368,373,379,385],{"__ignoreMap":31},[36,321,322],{"class":38,"line":39},[36,323,324],{},"server {\n",[36,326,327],{"class":38,"line":53},[36,328,329],{},"    listen 443 ssl http2;\n",[36,331,332],{"class":38,"line":60},[36,333,334],{},"    listen [::]:443 ssl http2;\n",[36,336,337],{"class":38,"line":70},[36,338,339],{},"    server_name yourdomain.com www.yourdomain.com;\n",[36,341,342],{"class":38,"line":75},[36,343,57],{"emptyLinePlaceholder":56},[36,345,346],{"class":38,"line":103},[36,347,348],{},"    ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Ffullchain.pem;\n",[36,350,351],{"class":38,"line":108},[36,352,353],{},"    ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Fprivkey.pem;\n",[36,355,356],{"class":38,"line":119},[36,357,57],{"emptyLinePlaceholder":56},[36,359,360],{"class":38,"line":124},[36,361,362],{},"    location \u002F {\n",[36,364,365],{"class":38,"line":136},[36,366,367],{},"        proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fgunicorn.sock;\n",[36,369,370],{"class":38,"line":146},[36,371,372],{},"        include proxy_params;\n",[36,374,376],{"class":38,"line":375},12,[36,377,378],{},"        proxy_redirect off;\n",[36,380,382],{"class":38,"line":381},13,[36,383,384],{},"    }\n",[36,386,388],{"class":38,"line":387},14,[36,389,390],{},"}\n",[172,392,393,396,410,412,413,415],{},[199,394,395],{},"Validate Nginx configuration before reload",[26,397,399],{"className":28,"code":398,"language":30,"meta":31,"style":31},"sudo nginx -t\n",[33,400,401],{"__ignoreMap":31},[36,402,403,405,407],{"class":38,"line":39},[36,404,78],{"class":42},[36,406,81],{"class":46},[36,408,409],{"class":84}," -t\n",[224,411],{},"Fix syntax errors, duplicate ",[33,414,180],{}," entries, and invalid certificate paths before continuing.",[172,417,418,421],{},[199,419,420],{},"Reload Nginx after changes",[26,422,424],{"className":28,"code":423,"language":30,"meta":31,"style":31},"sudo systemctl reload nginx\n",[33,425,426],{"__ignoreMap":31},[36,427,428,430,432,434],{"class":38,"line":39},[36,429,78],{"class":42},[36,431,94],{"class":46},[36,433,97],{"class":46},[36,435,100],{"class":46},[172,437,438,441,454,456,457,472,474,475],{},[199,439,440],{},"Confirm the HTTP virtual host works correctly",[26,442,444],{"className":28,"code":443,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002Fyourdomain.com\n",[33,445,446],{"__ignoreMap":31},[36,447,448,450,452],{"class":38,"line":39},[36,449,127],{"class":42},[36,451,130],{"class":84},[36,453,133],{"class":46},[224,455],{},"Expected result:",[236,458,459,469],{},[172,460,461,464,465,468],{},[33,462,463],{},"301"," or ",[33,466,467],{},"308"," redirect to HTTPS, or",[172,470,471],{},"temporary ACME challenge handling during certificate issuance",[224,473],{},"Example redirect block:",[26,476,478],{"className":303,"code":477,"language":305,"meta":31,"style":31},"server {\n    listen 80;\n    listen [::]:80;\n    server_name yourdomain.com www.yourdomain.com;\n\n    return 301 https:\u002F\u002F$host$request_uri;\n}\n",[33,479,480,484,489,494,498,502,507],{"__ignoreMap":31},[36,481,482],{"class":38,"line":39},[36,483,324],{},[36,485,486],{"class":38,"line":53},[36,487,488],{},"    listen 80;\n",[36,490,491],{"class":38,"line":60},[36,492,493],{},"    listen [::]:80;\n",[36,495,496],{"class":38,"line":70},[36,497,339],{},[36,499,500],{"class":38,"line":75},[36,501,57],{"emptyLinePlaceholder":56},[36,503,504],{"class":38,"line":103},[36,505,506],{},"    return 301 https:\u002F\u002F$host$request_uri;\n",[36,508,509],{"class":38,"line":108},[36,510,390],{},[172,512,513,516,529,531,532],{},[199,514,515],{},"Verify a certificate exists for the required hostnames",[26,517,519],{"className":28,"code":518,"language":30,"meta":31,"style":31},"sudo certbot certificates\n",[33,520,521],{"__ignoreMap":31},[36,522,523,525,527],{"class":38,"line":39},[36,524,78],{"class":42},[36,526,113],{"class":46},[36,528,116],{"class":46},[224,530],{},"Confirm:",[236,533,534,537,540],{},[172,535,536],{},"certificate name matches expected domain set",[172,538,539],{},"all required hostnames are listed",[172,541,542],{},"expiry date is valid",[172,544,545,548,550,551,288,554,557,558],{},[199,546,547],{},"Check certificate paths in Nginx",[224,549],{},"Confirm ",[33,552,553],{},"ssl_certificate",[33,555,556],{},"ssl_certificate_key"," point to active files:",[26,559,561],{"className":303,"code":560,"language":305,"meta":31,"style":31},"ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Ffullchain.pem;\nssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Fprivkey.pem;\n",[33,562,563,568],{"__ignoreMap":31},[36,564,565],{"class":38,"line":39},[36,566,567],{},"ssl_certificate \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Ffullchain.pem;\n",[36,569,570],{"class":38,"line":53},[36,571,572],{},"ssl_certificate_key \u002Fetc\u002Fletsencrypt\u002Flive\u002Fyourdomain.com\u002Fprivkey.pem;\n",[172,574,575,578,591,531,593],{},[199,576,577],{},"Test HTTPS directly",[26,579,581],{"className":28,"code":580,"language":30,"meta":31,"style":31},"curl -Iv https:\u002F\u002Fyourdomain.com\n",[33,582,583],{"__ignoreMap":31},[36,584,585,587,589],{"class":38,"line":39},[36,586,127],{"class":42},[36,588,151],{"class":84},[36,590,143],{"class":46},[224,592],{},[236,594,595,598,601,604],{},[172,596,597],{},"TLS negotiation succeeds",[172,599,600],{},"certificate hostname matches",[172,602,603],{},"certificate is not expired",[172,605,606],{},"response comes from the expected host",[172,608,609,612,634,636,637],{},[199,610,611],{},"Verify HTTP redirects to HTTPS consistently",[26,613,615],{"className":28,"code":614,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002Fyourdomain.com\ncurl -I http:\u002F\u002Fwww.yourdomain.com\n",[33,616,617,625],{"__ignoreMap":31},[36,618,619,621,623],{"class":38,"line":39},[36,620,127],{"class":42},[36,622,130],{"class":84},[36,624,133],{"class":46},[36,626,627,629,631],{"class":38,"line":53},[36,628,127],{"class":42},[36,630,130],{"class":84},[36,632,633],{"class":46}," http:\u002F\u002Fwww.yourdomain.com\n",[224,635],{},"Confirm both hostnames either:",[236,638,639,642],{},[172,640,641],{},"redirect to their HTTPS equivalent, or",[172,643,644],{},"canonicalize intentionally to one preferred hostname",[172,646,647,650,672,674,675],{},[199,648,649],{},"Verify HTTPS serves the correct site",[26,651,653],{"className":28,"code":652,"language":30,"meta":31,"style":31},"curl -I https:\u002F\u002Fyourdomain.com\ncurl -I https:\u002F\u002Fwww.yourdomain.com\n",[33,654,655,663],{"__ignoreMap":31},[36,656,657,659,661],{"class":38,"line":39},[36,658,127],{"class":42},[36,660,130],{"class":84},[36,662,143],{"class":46},[36,664,665,667,669],{"class":38,"line":53},[36,666,127],{"class":42},[36,668,130],{"class":84},[36,670,671],{"class":46}," https:\u002F\u002Fwww.yourdomain.com\n",[224,673],{},"Confirm you are not hitting:",[236,676,677,680,683],{},[172,678,679],{},"the default Nginx site",[172,681,682],{},"an old certificate",[172,684,685],{},"another application on the same server",[172,687,688,691,693,694,708,456,710],{},[199,689,690],{},"Confirm the Flask app works behind HTTPS",[224,692],{},"Test a known route:",[26,695,697],{"className":28,"code":696,"language":30,"meta":31,"style":31},"curl -I https:\u002F\u002Fyourdomain.com\u002Fhealth\n",[33,698,699],{"__ignoreMap":31},[36,700,701,703,705],{"class":38,"line":39},[36,702,127],{"class":42},[36,704,130],{"class":84},[36,706,707],{"class":46}," https:\u002F\u002Fyourdomain.com\u002Fhealth\n",[224,709],{},[236,711,712,724],{},[172,713,714,717,718,721,722],{},[33,715,716],{},"200",", ",[33,719,720],{},"204",", or intentional ",[33,723,463],{},[172,725,726,727,464,730],{},"not ",[33,728,729],{},"500",[33,731,732],{},"502",[172,734,735,738,740,741],{},[199,736,737],{},"Validate certificate renewal",[224,739],{},"Check timer or dry-run renewal:",[26,742,744],{"className":28,"code":743,"language":30,"meta":31,"style":31},"systemctl list-timers | grep certbot\nsudo certbot renew --dry-run\n",[33,745,746,764],{"__ignoreMap":31},[36,747,748,751,754,758,761],{"class":38,"line":39},[36,749,750],{"class":42},"systemctl",[36,752,753],{"class":46}," list-timers",[36,755,757],{"class":756},"szBVR"," |",[36,759,760],{"class":42}," grep",[36,762,763],{"class":46}," certbot\n",[36,765,766,768,770,773],{"class":38,"line":53},[36,767,78],{"class":42},[36,769,113],{"class":46},[36,771,772],{"class":46}," renew",[36,774,775],{"class":84}," --dry-run\n",[172,777,778,781,783,784,808,810],{},[199,779,780],{},"Check HSTS only after HTTPS is stable",[224,782],{},"If enabled, confirm the header is intentional:",[26,785,787],{"className":28,"code":786,"language":30,"meta":31,"style":31},"curl -I https:\u002F\u002Fyourdomain.com | grep -i strict-transport-security\n",[33,788,789],{"__ignoreMap":31},[36,790,791,793,795,798,800,802,805],{"class":38,"line":39},[36,792,127],{"class":42},[36,794,130],{"class":84},[36,796,797],{"class":46}," https:\u002F\u002Fyourdomain.com",[36,799,757],{"class":756},[36,801,760],{"class":42},[36,803,804],{"class":84}," -i",[36,806,807],{"class":46}," strict-transport-security\n",[224,809],{},"Do not force HSTS until all intended hostnames and subdomains behave correctly over HTTPS.",[172,812,813,816,818,819],{},[199,814,815],{},"Confirm there is no mixed content",[224,817],{},"Open the site in a browser and verify:",[236,820,821,824,827,830],{},[172,822,823],{},"CSS loads over HTTPS",[172,825,826],{},"JS loads over HTTPS",[172,828,829],{},"images load over HTTPS",[172,831,832],{},"API calls use HTTPS",[172,834,835,838,840,841,843,844],{},[199,836,837],{},"If using a proxy or load balancer, verify forwarded headers",[224,839],{},"Confirm TLS terminates where expected and headers are passed correctly.",[224,842],{},"Typical Nginx proxy settings:",[26,845,847],{"className":303,"code":846,"language":305,"meta":31,"style":31},"proxy_set_header Host $host;\nproxy_set_header X-Real-IP $remote_addr;\nproxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\nproxy_set_header X-Forwarded-Proto $scheme;\n",[33,848,849,854,859,864],{"__ignoreMap":31},[36,850,851],{"class":38,"line":39},[36,852,853],{},"proxy_set_header Host $host;\n",[36,855,856],{"class":38,"line":53},[36,857,858],{},"proxy_set_header X-Real-IP $remote_addr;\n",[36,860,861],{"class":38,"line":60},[36,862,863],{},"proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",[36,865,866],{"class":38,"line":70},[36,867,868],{},"proxy_set_header X-Forwarded-Proto $scheme;\n",[172,870,871,874,876,877],{},[199,872,873],{},"Record final validation results",[224,875],{},"Confirm these are all true:",[236,878,879,882,885,888,891],{},[172,880,881],{},"working DNS",[172,883,884],{},"valid certificate",[172,886,887],{},"correct redirect behavior",[172,889,890],{},"renewal status verified",[172,892,893],{},"successful Flask response over HTTPS",[18,895,897],{"id":896},"common-causes","Common Causes",[236,899,900,914,926,936,945,951,960,966],{},[172,901,902,905,906,908,909,908,911,913],{},[199,903,904],{},"DNS points to the wrong server"," → The domain resolves, but traffic reaches an old host or different service → Update ",[33,907,242],{},"\u002F",[33,910,248],{},[33,912,254],{}," records and wait for propagation.",[172,915,916,922,923,925],{},[199,917,918,919,921],{},"Nginx ",[33,920,180],{}," does not match the requested domain"," → Nginx serves the default site or wrong virtual host → Correct ",[33,924,180],{}," and reload Nginx.",[172,927,928,931,932,935],{},[199,929,930],{},"Certificate does not cover all hostnames"," → Browsers show a mismatch warning on ",[33,933,934],{},"www"," or apex → Reissue the certificate including every required hostname.",[172,937,938,941,942,944],{},[199,939,940],{},"Port 443 is blocked"," → HTTPS times out even though Nginx is configured → Open the firewall or cloud security group for ",[33,943,291],{},".",[172,946,947,950],{},[199,948,949],{},"HTTP-to-HTTPS redirect loop exists"," → Browser reports too many redirects → Fix redirect rules across Nginx, Flask, proxy headers, and CDN settings.",[172,952,953,956,957,944],{},[199,954,955],{},"Old or duplicate Nginx site configs are active"," → Requests hit the wrong certificate or wrong app → Remove stale configs and validate with ",[33,958,959],{},"nginx -T",[172,961,962,965],{},[199,963,964],{},"Certbot renewal is not working"," → HTTPS works initially but fails after certificate expiry → Fix renewal timer, challenge routing, or certificate permissions.",[172,967,968,971],{},[199,969,970],{},"Mixed-content assets remain on HTTP"," → Page loads with warnings or broken CSS\u002FJS → Update asset URLs, proxy handling, and HTTPS-aware URL generation.",[18,973,975],{"id":974},"debugging-section","Debugging Section",[14,977,978],{},"Check these systems in order:",[26,980,982],{"className":28,"code":981,"language":30,"meta":31,"style":31},"dig +short yourdomain.com\ndig +short www.yourdomain.com\ndig @1.1.1.1 yourdomain.com\nsudo ufw status\nsudo nginx -t\nsudo nginx -T\nsudo systemctl status nginx\nsudo systemctl reload nginx\nsudo certbot certificates\nsudo certbot renew --dry-run\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fletsencrypt\u002Fletsencrypt.log\ncurl -I http:\u002F\u002Fyourdomain.com\ncurl -I https:\u002F\u002Fyourdomain.com\ncurl -Iv https:\u002F\u002Fyourdomain.com\nopenssl s_client -connect yourdomain.com:443 -servername yourdomain.com\n",[33,983,984,992,1000,1009,1017,1025,1034,1045,1055,1063,1073,1089,1102,1115,1123,1132,1141],{"__ignoreMap":31},[36,985,986,988,990],{"class":38,"line":39},[36,987,43],{"class":42},[36,989,47],{"class":46},[36,991,50],{"class":46},[36,993,994,996,998],{"class":38,"line":53},[36,995,43],{"class":42},[36,997,47],{"class":46},[36,999,67],{"class":46},[36,1001,1002,1004,1007],{"class":38,"line":60},[36,1003,43],{"class":42},[36,1005,1006],{"class":46}," @1.1.1.1",[36,1008,50],{"class":46},[36,1010,1011,1013,1015],{"class":38,"line":70},[36,1012,78],{"class":42},[36,1014,278],{"class":46},[36,1016,281],{"class":46},[36,1018,1019,1021,1023],{"class":38,"line":75},[36,1020,78],{"class":42},[36,1022,81],{"class":46},[36,1024,409],{"class":84},[36,1026,1027,1029,1031],{"class":38,"line":103},[36,1028,78],{"class":42},[36,1030,81],{"class":46},[36,1032,1033],{"class":84}," -T\n",[36,1035,1036,1038,1040,1043],{"class":38,"line":108},[36,1037,78],{"class":42},[36,1039,94],{"class":46},[36,1041,1042],{"class":46}," status",[36,1044,100],{"class":46},[36,1046,1047,1049,1051,1053],{"class":38,"line":119},[36,1048,78],{"class":42},[36,1050,94],{"class":46},[36,1052,97],{"class":46},[36,1054,100],{"class":46},[36,1056,1057,1059,1061],{"class":38,"line":124},[36,1058,78],{"class":42},[36,1060,113],{"class":46},[36,1062,116],{"class":46},[36,1064,1065,1067,1069,1071],{"class":38,"line":136},[36,1066,78],{"class":42},[36,1068,113],{"class":46},[36,1070,772],{"class":46},[36,1072,775],{"class":84},[36,1074,1075,1077,1080,1083,1086],{"class":38,"line":146},[36,1076,78],{"class":42},[36,1078,1079],{"class":46}," tail",[36,1081,1082],{"class":84}," -n",[36,1084,1085],{"class":84}," 100",[36,1087,1088],{"class":46}," \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\n",[36,1090,1091,1093,1095,1097,1099],{"class":38,"line":375},[36,1092,78],{"class":42},[36,1094,1079],{"class":46},[36,1096,1082],{"class":84},[36,1098,1085],{"class":84},[36,1100,1101],{"class":46}," \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\n",[36,1103,1104,1106,1108,1110,1112],{"class":38,"line":381},[36,1105,78],{"class":42},[36,1107,1079],{"class":46},[36,1109,1082],{"class":84},[36,1111,1085],{"class":84},[36,1113,1114],{"class":46}," \u002Fvar\u002Flog\u002Fletsencrypt\u002Fletsencrypt.log\n",[36,1116,1117,1119,1121],{"class":38,"line":387},[36,1118,127],{"class":42},[36,1120,130],{"class":84},[36,1122,133],{"class":46},[36,1124,1126,1128,1130],{"class":38,"line":1125},15,[36,1127,127],{"class":42},[36,1129,130],{"class":84},[36,1131,143],{"class":46},[36,1133,1135,1137,1139],{"class":38,"line":1134},16,[36,1136,127],{"class":42},[36,1138,151],{"class":84},[36,1140,143],{"class":46},[36,1142,1144,1147,1150,1153,1156,1159],{"class":38,"line":1143},17,[36,1145,1146],{"class":42},"openssl",[36,1148,1149],{"class":46}," s_client",[36,1151,1152],{"class":84}," -connect",[36,1154,1155],{"class":46}," yourdomain.com:443",[36,1157,1158],{"class":84}," -servername",[36,1160,50],{"class":46},[14,1162,1163],{},"What to look for:",[236,1165,1166,1179,1200,1223,1240,1253],{},[172,1167,1168,1171],{},[199,1169,1170],{},"Nginx status",[236,1172,1173],{},[172,1174,1175,1176],{},"service is ",[33,1177,1178],{},"active (running)",[172,1180,1181,1184],{},[199,1182,1183],{},"Nginx error log",[236,1185,1186,1189,1192,1195],{},[172,1187,1188],{},"TLS errors",[172,1190,1191],{},"wrong certificate path",[172,1193,1194],{},"upstream failures",[172,1196,1197,1198],{},"duplicate ",[33,1199,180],{},[172,1201,1202,1205],{},[199,1203,1204],{},"Nginx access log",[236,1206,1207,1210],{},[172,1208,1209],{},"request hostnames",[172,1211,1212,717,1214,717,1216,717,1218,717,1221],{},[33,1213,463],{},[33,1215,467],{},[33,1217,716],{},[33,1219,1220],{},"404",[33,1222,732],{},[172,1224,1225,1229],{},[199,1226,1227],{},[33,1228,959],{},[236,1230,1231,1234,1237],{},[172,1232,1233],{},"duplicate site definitions",[172,1235,1236],{},"wrong default server",[172,1238,1239],{},"stale configs still loaded",[172,1241,1242,1245],{},[199,1243,1244],{},"Let’s Encrypt log",[236,1246,1247,1250],{},[172,1248,1249],{},"ACME challenge failures",[172,1251,1252],{},"renewal permission issues",[172,1254,1255,1260],{},[199,1256,1257],{},[33,1258,1259],{},"openssl s_client",[236,1261,1262,1265,1268],{},[172,1263,1264],{},"served certificate CN\u002FSAN values",[172,1266,1267],{},"full chain issues",[172,1269,1270],{},"expiry details",[14,1272,1273,1274,944],{},"If requests reach Nginx but fail upstream, validate Gunicorn and Flask separately before treating it as an HTTPS issue. For upstream failures, see ",[1275,1276,1278],"a",{"href":1277},"\u002Ffix-issues\u002Fflask-https-not-working-after-certbot","Flask HTTPS Not Working After Certbot",[18,1280,1282],{"id":1281},"checklist","Checklist",[236,1284,1287,1299,1308,1319,1328,1337,1343,1349,1355,1361,1370,1376,1382,1388,1394,1403,1412],{"className":1285},[1286],"contains-task-list",[172,1288,1291,1295,1296,1298],{"className":1289},[1290],"task-list-item",[1292,1293],"input",{"disabled":56,"type":1294},"checkbox"," ",[33,1297,159],{}," resolves to the correct production IP",[172,1300,1302,1295,1304,1307],{"className":1301},[1290],[1292,1303],{"disabled":56,"type":1294},[33,1305,1306],{},"www.yourdomain.com"," resolves correctly or intentionally redirects",[172,1309,1311,1313,1314,288,1316,1318],{"className":1310},[1290],[1292,1312],{"disabled":56,"type":1294}," Ports ",[33,1315,287],{},[33,1317,291],{}," are open on the server and firewall",[172,1320,1322,1324,1325,1327],{"className":1321},[1290],[1292,1323],{"disabled":56,"type":1294}," Nginx ",[33,1326,180],{}," matches the production domain names",[172,1329,1331,1295,1333,1336],{"className":1330},[1290],[1292,1332],{"disabled":56,"type":1294},[33,1334,1335],{},"sudo nginx -t"," passes without errors",[172,1338,1340,1342],{"className":1339},[1290],[1292,1341],{"disabled":56,"type":1294}," HTTP requests return the expected redirect or challenge response",[172,1344,1346,1348],{"className":1345},[1290],[1292,1347],{"disabled":56,"type":1294}," HTTPS certificate covers the active domain names",[172,1350,1352,1354],{"className":1351},[1290],[1292,1353],{"disabled":56,"type":1294}," Certificate is not expired",[172,1356,1358,1360],{"className":1357},[1290],[1292,1359],{"disabled":56,"type":1294}," Nginx certificate paths point to the current files",[172,1362,1364,1295,1366,1369],{"className":1363},[1290],[1292,1365],{"disabled":56,"type":1294},[33,1367,1368],{},"curl -Iv https:\u002F\u002Fyourdomain.com"," completes TLS successfully",[172,1371,1373,1375],{"className":1372},[1290],[1292,1374],{"disabled":56,"type":1294}," HTTP redirects to HTTPS for all intended hostnames",[172,1377,1379,1381],{"className":1378},[1290],[1292,1380],{"disabled":56,"type":1294}," HTTPS serves the correct Flask app, not the default Nginx site",[172,1383,1385,1387],{"className":1384},[1290],[1292,1386],{"disabled":56,"type":1294}," App routes return successful responses over HTTPS",[172,1389,1391,1393],{"className":1390},[1290],[1292,1392],{"disabled":56,"type":1294}," Static assets load over HTTPS without mixed-content warnings",[172,1395,1397,1295,1399,1402],{"className":1396},[1290],[1292,1398],{"disabled":56,"type":1294},[33,1400,1401],{},"certbot renew --dry-run"," succeeds or renewal timer is present",[172,1404,1406,1408,1409,1411],{"className":1405},[1290],[1292,1407],{"disabled":56,"type":1294}," Canonical redirect behavior between apex and ",[33,1410,934],{}," is intentional",[172,1413,1415,1417],{"className":1414},[1290],[1292,1416],{"disabled":56,"type":1294}," No redirect loop exists between Nginx, Flask, CDN, or proxy layers",[18,1419,1421],{"id":1420},"related-guides","Related Guides",[236,1423,1424,1430,1436,1440],{},[172,1425,1426],{},[1275,1427,1429],{"href":1428},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[172,1431,1432],{},[1275,1433,1435],{"href":1434},"\u002Fdeploy\u002Fflask-domain-and-dns-setup-for-production","Flask Domain and DNS Setup for Production",[172,1437,1438],{},[1275,1439,1278],{"href":1277},[172,1441,1442],{},[1275,1443,1445],{"href":1444},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1447,1449],{"id":1448},"faq","FAQ",[14,1451,1452,1458,1460],{},[199,1453,1454,1455,1457],{},"Q: Should both apex and ",[33,1456,934],{}," use HTTPS?",[224,1459],{},"\nA: Yes, if both are reachable. Either serve both with valid certificates or redirect one canonical host to the other over HTTPS.",[14,1462,1463,1466,1468],{},[199,1464,1465],{},"Q: Can I force HTTPS before the certificate is working?",[224,1467],{},"\nA: No. Confirm certificate issuance and HTTPS access first, then enforce redirects and HSTS.",[14,1470,1471,1474,1476,1477,1479],{},[199,1472,1473],{},"Q: Why does HTTPS work for one hostname but not another?",[224,1475],{},"\nA: The certificate, DNS, or Nginx ",[33,1478,180],{}," may not include the missing hostname.",[14,1481,1482,1485,1487],{},[199,1483,1484],{},"Q: Why does Certbot succeed but the browser still shows the old certificate?",[224,1486],{},"\nA: Nginx may not have been reloaded, the wrong server block may be active, or a proxy\u002FCDN is serving a different cert.",[14,1489,1490,1493,1495,1496,1498],{},[199,1491,1492],{},"Q: What should the first HTTPS test be?",[224,1494],{},"\nA: Use ",[33,1497,1368],{}," and inspect certificate validity, hostname match, and response headers.",[14,1500,1501,1504,1506],{},[199,1502,1503],{},"Q: Should I enable HSTS immediately?",[224,1505],{},"\nA: Only after HTTPS is fully working for all intended hostnames and redirects are stable.",[14,1508,1509,1515,1517],{},[199,1510,1511,1512,1514],{},"Q: Do I need separate certificates for apex and ",[33,1513,934],{},"?",[224,1516],{},"\nA: No. A single certificate can cover both if both names are included during issuance.",[14,1519,1520,1527,1529],{},[199,1521,1522,1523,1526],{},"Q: Why does ",[33,1524,1525],{},"nginx -t"," pass but HTTPS still fail?",[224,1528],{},"\nA: Syntax may be correct while DNS, firewall, certificate path, or certificate hostname coverage is still wrong.",[14,1531,1532,1535,1537,1538,1541],{},[199,1533,1534],{},"Q: How do I confirm certificate renewal is safe?",[224,1536],{},"\nA: Run ",[33,1539,1540],{},"sudo certbot renew --dry-run"," and confirm no challenge or permission errors occur.",[14,1543,1544,1547,1549,1550,1553],{},[199,1545,1546],{},"Q: What is the minimum validation before launch?",[224,1548],{},"\nA: Correct DNS, open ports ",[33,1551,1552],{},"80\u002F443",", valid certificate, working HTTPS response, and clean HTTP-to-HTTPS redirect behavior.",[18,1555,1557],{"id":1556},"final-takeaway","Final Takeaway",[14,1559,1560],{},"A production-ready Flask HTTPS setup is valid only when DNS, Nginx, certificate coverage, redirect behavior, and renewal all work together. Use this checklist to verify each layer before launch and after every domain or TLS change.",[1562,1563,1564],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":31,"searchDepth":53,"depth":53,"links":1566},[1567,1568,1569,1570,1571,1572,1573,1574,1575],{"id":20,"depth":53,"text":21},{"id":163,"depth":53,"text":164},{"id":192,"depth":53,"text":193},{"id":896,"depth":53,"text":897},{"id":974,"depth":53,"text":975},{"id":1281,"depth":53,"text":1282},{"id":1420,"depth":53,"text":1421},{"id":1448,"depth":53,"text":1449},{"id":1556,"depth":53,"text":1557},"Complete guide on flask https and domain checklist for Flask production environments.","md",{"ogTitle":5,"ogDescription":1576,"twitterCard":1579,"robots":1580,"canonical":1581},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Fchecklist\u002Fflask-https-and-domain-checklist","\u002Fchecklist\u002Fflask-https-and-domain-checklist",{"title":5,"description":1576},"checklist\u002Fflask-https-and-domain-checklist","HNjO5zWVd5fLqqi6O1P7vx4ffbNnJ3yiew3aKDMS8CQ",1776805766384]