From 6e43a72f29b58e3bbc1a24987d35be7afd7f2b07 Mon Sep 17 00:00:00 2001 From: kencho Date: Wed, 6 Aug 2025 11:22:21 +0800 Subject: [PATCH 01/10] feat: try to implement single level subdomain A records --- .../nginx-conf/sites/nginx.target_deployment.http.conf.dist | 2 +- .../nginx-conf/sites/nginx.target_deployment.https.conf.dist | 2 +- ops/scripts/setup_cert.sh | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist index 13abc9ad3c..1373fa4b86 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist @@ -60,7 +60,7 @@ server { listen 80; listen [::]:80; - server_name portainer.$SERVER_HOSTNAME; + server_name portainer-$SERVER_HOSTNAME; root /var/www; index index.php index.html index.htm; diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist index 92d21bf236..fca8ae3ca0 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist @@ -115,7 +115,7 @@ server { add_header Access-Control-Allow-Headers '*'; - server_name portainer.$SERVER_HOSTNAME; + server_name portainer-$SERVER_HOSTNAME; root /var/www; index index.php index.html index.htm; diff --git a/ops/scripts/setup_cert.sh b/ops/scripts/setup_cert.sh index 3d70b16d6b..008c4cf7a4 100755 --- a/ops/scripts/setup_cert.sh +++ b/ops/scripts/setup_cert.sh @@ -90,7 +90,7 @@ fetch_cert_from_gitlab() { make_new_cert() { echo "Running certbot to make new cert" - $DOCKER_COMPOSE run --rm certbot certonly -d $REMOTE_HOSTNAME -d portainer.$REMOTE_HOSTNAME + $DOCKER_COMPOSE run --rm certbot certonly -d $REMOTE_HOSTNAME -d portainer-$REMOTE_HOSTNAME echo "Read content of files" $DOCKER_COMPOSE run --rm config mkdir -vp /etc/letsencrypt/archive/$REMOTE_HOSTNAME $DOCKER_COMPOSE run --rm config mkdir -vp /etc/letsencrypt/live/$REMOTE_HOSTNAME From 2a6b3e0a016704b9f97c699c9bfb4e1e9d515d21 Mon Sep 17 00:00:00 2001 From: kencho Date: Thu, 7 Aug 2025 10:36:18 +0800 Subject: [PATCH 02/10] refactor: update the ssl block for portainer --- .../sites/nginx.target_deployment.https.conf.dist | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist index fca8ae3ca0..865331f4bf 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist @@ -148,12 +148,12 @@ server { ssl_dhparam /etc/ssl/nginx/dhparam.pem; # intermediate configuration. tweak to your needs. - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS'; - ssl_prefer_server_ciphers on; + 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_prefer_server_ciphers off; # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) - add_header Strict-Transport-Security max-age=15768000; + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; # OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them From 2961fa02c884cf4a440c8d50f3cfa721d9053334 Mon Sep 17 00:00:00 2001 From: kencho Date: Thu, 7 Aug 2025 12:16:26 +0800 Subject: [PATCH 03/10] refactor: redirect all HTTP traffic to HTTPS --- .../nginx.target_deployment.http.conf.dist | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist index 1373fa4b86..65875a9326 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist @@ -61,28 +61,9 @@ server { listen [::]:80; server_name portainer-$SERVER_HOSTNAME; - root /var/www; - index index.php index.html index.htm; - - location ~* (common\.css|datatables\.css|pager\.css)$ { - expires -1; - } - - location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { - expires 365d; - } location / { - try_files $uri $uri/ /index.php$is_args$args; - } - - location ~ /\.ht { - deny all; - } - - location /.well-known/acme-challenge/ { - root /var/www/.le/; - log_not_found off; + return 301 https://$host$request_uri; } } From 1b1a39ad6b7a08fc8b90a38267e933e6eec64899 Mon Sep 17 00:00:00 2001 From: kencho Date: Thu, 7 Aug 2025 13:35:39 +0800 Subject: [PATCH 04/10] refactor: fix failed to validate Origin or Referer error --- ops/deployment/docker-compose.production-envs.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ops/deployment/docker-compose.production-envs.yml b/ops/deployment/docker-compose.production-envs.yml index 7a04660564..169f21c3d9 100644 --- a/ops/deployment/docker-compose.production-envs.yml +++ b/ops/deployment/docker-compose.production-envs.yml @@ -302,6 +302,8 @@ services: volumes: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data + environment: + - TRUSTED_ORIGINS=https://portainer-$REMOTE_HOSTNAME ports: - 9009:9000 - 8000:8000 From 9576727cbe5745e90aec14ed76c18c0daf6e3323 Mon Sep 17 00:00:00 2001 From: kencho Date: Thu, 7 Aug 2025 15:51:41 +0800 Subject: [PATCH 05/10] refactor: try to fix host not found in upstream error --- .../nginx.target_deployment.https.conf.dist | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist index 865331f4bf..e0831bef3e 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist @@ -100,6 +100,9 @@ server { listen 443 ssl http2; listen [::]:443 ssl http2; + resolver 127.0.0.11 valid=30s; + + server_name portainer-$SERVER_HOSTNAME; # Security headers add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; @@ -114,22 +117,21 @@ server { add_header Access-Control-Allow-Methods '*'; add_header Access-Control-Allow-Headers '*'; - - server_name portainer-$SERVER_HOSTNAME; - root /var/www; - index index.php index.html index.htm; - location / { proxy_http_version 1.1; proxy_set_header Connection ""; - proxy_pass http://portainer:9000; + + set $upstream_portainer http://portainer:9000; + proxy_pass $upstream_portainer; } location /api/websocket/ { proxy_http_version 1.1; proxy_set_header Connection "upgrade"; proxy_set_header Upgrade $http_upgrade; - proxy_pass http://portainer:9000/api/websocket; + + set $upstream_portainer_ws http://portainer:9000/api/websocket; + proxy_pass $upstream_portainer_ws; } location ~ /\.ht { @@ -152,9 +154,6 @@ server { 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; - # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months) - add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; - # OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; From 586dba5457753df99d16ff4118ddd0035c8d4fa2 Mon Sep 17 00:00:00 2001 From: kencho Date: Thu, 7 Aug 2025 21:38:58 +0800 Subject: [PATCH 06/10] refactor: update the trusted origins url --- ops/deployment/docker-compose.production-envs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ops/deployment/docker-compose.production-envs.yml b/ops/deployment/docker-compose.production-envs.yml index 169f21c3d9..2996031d0d 100644 --- a/ops/deployment/docker-compose.production-envs.yml +++ b/ops/deployment/docker-compose.production-envs.yml @@ -303,7 +303,7 @@ services: - /var/run/docker.sock:/var/run/docker.sock - portainer_data:/data environment: - - TRUSTED_ORIGINS=https://portainer-$REMOTE_HOSTNAME + - TRUSTED_ORIGINS=portainer-$REMOTE_HOSTNAME ports: - 9009:9000 - 8000:8000 From 6921f4e7262b208e434590831154236800abe241 Mon Sep 17 00:00:00 2001 From: kencho Date: Thu, 7 Aug 2025 23:19:15 +0800 Subject: [PATCH 07/10] doc: update change log --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92ebd588f9..873142df1e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## Unreleased +- Fix #2393: Make Portainer accessible behind Cloudflare proxy + ## v4.4.16 - 2025-08-15 - 6e04c0b9e - - Fix #2428: AdminUserController should target AdminUserController when validating or rejecting a claim From cb35de5035814f4bcb776919419341aa16fb9759 Mon Sep 17 00:00:00 2001 From: kencho Date: Tue, 12 Aug 2025 00:13:47 +0800 Subject: [PATCH 08/10] feat: make lets encrypt access the temporary challenge files --- .../sites/nginx.target_deployment.http.conf.dist | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist index 65875a9326..077a613576 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist @@ -60,7 +60,14 @@ server { listen 80; listen [::]:80; - server_name portainer-$SERVER_HOSTNAME; + # Listen on both hostnames that need certificates. + server_name $SERVER_HOSTNAME portainer-$SERVER_HOSTNAME; + + # Handle the challenge requests. + location /.well-known/acme-challenge/ { + root /var/www/.le/; + log_not_found off; + } location / { return 301 https://$host$request_uri; From 38b06411261a5c842f9bd492e21f8bf82f0271f1 Mon Sep 17 00:00:00 2001 From: kencho Date: Tue, 12 Aug 2025 10:27:51 +0800 Subject: [PATCH 09/10] refactor: remove conflicting server name error --- .../nginx.target_deployment.http.conf.dist | 47 +++++++++---------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist index 077a613576..9309ea2426 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.http.conf.dist @@ -3,7 +3,27 @@ server { listen 80; listen [::]:80; - server_name $SERVER_HOSTNAME web gigadb.dev gigadb.test; + # Listen on both hostnames that need certificates. + server_name $SERVER_HOSTNAME portainer-$SERVER_HOSTNAME; + + # Handle the challenge requests. + location /.well-known/acme-challenge/ { + root /var/www/.le/; + log_not_found off; + } + + location / { + return 301 https://$host$request_uri; + } + +} + +server { + + listen 80; + listen [::]:80; + + server_name web gigadb.dev gigadb.test; root /var/www; index index.php index.html index.htm; @@ -48,30 +68,5 @@ location /search { deny all; } - location /.well-known/acme-challenge/ { - root /var/www/.le/; - log_not_found off; - } - -} - -server { - - listen 80; - listen [::]:80; - - # Listen on both hostnames that need certificates. - server_name $SERVER_HOSTNAME portainer-$SERVER_HOSTNAME; - - # Handle the challenge requests. - location /.well-known/acme-challenge/ { - root /var/www/.le/; - log_not_found off; - } - - location / { - return 301 https://$host$request_uri; - } - } From 4262bfda9d39e32ca98c7c2bb3ac5d00032d93ab Mon Sep 17 00:00:00 2001 From: kencho Date: Fri, 15 Aug 2025 13:42:43 +0800 Subject: [PATCH 10/10] feat: let application know the connection is secure --- .../sites/nginx.target_deployment.https.conf.dist | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist index e0831bef3e..d4db19fd3b 100644 --- a/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist +++ b/ops/configuration/nginx-conf/sites/nginx.target_deployment.https.conf.dist @@ -48,7 +48,8 @@ server { fastcgi_send_timeout 600; fastcgi_connect_timeout 600; include fastcgi_params; - include phplimit.conf; + include phplimit.conf; + fastcgi_param HTTPS on; } location /search { @@ -121,6 +122,9 @@ server { proxy_http_version 1.1; proxy_set_header Connection ""; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-Proto https; + set $upstream_portainer http://portainer:9000; proxy_pass $upstream_portainer; }