Skip to content
Open
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -48,42 +68,5 @@ location /search {
deny all;
}

location /.well-known/acme-challenge/ {
root /var/www/.le/;
log_not_found off;
}

}

server {

listen 80;
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;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -100,6 +101,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";
Expand All @@ -114,22 +118,24 @@ 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;

proxy_set_header Host $host;
proxy_set_header X-Forwarded-Proto https;

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 {
Expand All @@ -148,12 +154,9 @@ 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;

# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
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;

# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
Expand Down
2 changes: 2 additions & 0 deletions ops/deployment/docker-compose.production-envs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,8 @@ services:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- portainer_data:/data
environment:
- TRUSTED_ORIGINS=portainer-$REMOTE_HOSTNAME
ports:
- 9009:9000
- 8000:8000
Expand Down
2 changes: 1 addition & 1 deletion ops/scripts/setup_cert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down