Administro un sitio web donde los entusiastas de la fotografía comparten frecuentemente sus obras, y quiero desactivar toda la compresión de imágenes mientras habilito el stripping de metadatos. He realizado los siguientes ajustes:
Establecí el tamaño máximo de imagen en 40 MB, configuré los megapíxeles máximos de imagen al valor máximo permitido de 150 MP y desactivé la optimización de imágenes de medios del compositor.
También ajusté la configuración de Nginx en el contenedor.
En resumen, agregué:
client_header_timeout 1m;
client_body_timeout 1m;
proxy_connect_timeout 30s;
proxy_read_timeout 1m;
proxy_send_timeout 1m;
y modifiqué:
# tamaño máximo de carga de archivo (mantener actualizado al cambiar la configuración del sitio correspondiente)
client_max_body_size 200m ;
en server{} en /etc/nginx/nginx.conf.
Agregué:
client_max_body_size 200m;
client_header_timeout 1m;
client_body_timeout 1m;
proxy_connect_timeout 60s;
proxy_read_timeout 1m;
proxy_send_timeout 1m;
en http{} en /etc/nginx/nginx.conf
Aquí están las configuraciones para /etc/nginx/nginx.conf y /etc/nginx/conf.d/discourse.conf:
root@iZj6cgi365ov99veqodfgnZ-app:/var/www/discourse# cat /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
daemon off;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 4000 ;
# multi_accept on;
}
http {
client_max_body_size 200m;
client_header_timeout 1m;
client_body_timeout 1m;
proxy_connect_timeout 60s;
proxy_read_timeout 1m;
proxy_send_timeout 1m;
##
# Configuración Básica
##
sendfile on;
tcp_nopush on;
types_hash_max_size 2048;
# server_tokens off;
# server_names_hash_bucket_size 64;
# server_name_in_redirect off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# Configuración SSL
##
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Eliminando SSLv3, ref: POODLE
ssl_prefer_server_ciphers on;
##
# Configuración de Registro
##
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
##
# Configuración Gzip
##
gzip on;
# gzip_vary on;
# gzip_proxied any;
# gzip_comp_level 6;
# gzip_buffers 16 8k;
# gzip_http_version 1.1;
# gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
##
# Configuraciones de Host Virtual
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
#mail {
# # Ver script de autenticación de ejemplo en:
# # http://wiki.nginx.org/ImapAuthenticateWithApachePhpScript
#
# # auth_http localhost/auth.php;
# # pop3_capabilities "TOP" "USER";
# # imap_capabilities "IMAP4rev1" "UIDPLUS";
#
# server {
# listen localhost:110;
# protocol pop3;
# proxy on;
# }
#
# server {
# listen localhost:143;
# protocol imap;
# proxy on;
# }
#}
root@iZj6cgi365ov99veqodfgnZ-app:/var/www/discourse# cat /etc/nginx/conf.d/discourse.conf
# Tipos MIME adicionales que deseas que nginx maneje van aquí
types {
text/csv csv;
application/wasm wasm;
}
upstream discourse { server 127.0.0.1:3000; }
# inactivo significa que mantenemos las cosas durante 1440m minutos independientemente del último acceso (1 semana)
# niveles significa que es una jerarquía de 2 niveles porque podemos tener muchos archivos
# max_size limita el tamaño de la caché
proxy_cache_path /var/nginx/cache inactive=1440m levels=1:2 keys_zone=one:10m max_size=600m;
# Aumentado desde el valor predeterminado para acomodar cookies grandes durante flujos oAuth2
# como en https://meta.discourse.org/t/x/74060 y encabezados CSP y Enlace (preload) grandes
proxy_buffer_size 32k;
proxy_buffers 4 32k;
# Aumentado desde el valor predeterminado para permitir un gran volumen de cookies en los encabezados de solicitud
# Discourse mismo intenta minimizar el tamaño de las cookies, pero no podemos controlar otras cookies establecidas por otras herramientas en el mismo dominio.
large_client_header_buffers 4 32k;
# Si vas a usar Puma, usa estos:
#
# upstream discourse {
# server unix:/var/www/discourse/tmp/sockets/puma.sock;
# }
# intentar preservar el protocolo, debe estar en el contexto http
map $http_x_forwarded_proto $thescheme {
default $scheme;
"~https$" https;
}
log_format log_discourse '[$time_local] "$http_host" $remote_addr "$request" "$http_user_agent" "$sent_http_x_discourse_route" $status $bytes_sent "$http_referer" $upstream_response_time $request_time "$upstream_http_x_discourse_username" "$upstream_http_x_discourse_trackview" "$upstream_http_x_queue_time" "$upstream_http_x_redis_calls" "$upstream_http_x_redis_time" "$upstream_http_x_sql_calls" "$upstream_http_x_sql_time"';
# Permitir omitir la caché desde localhost
geo $bypass_cache {
default 0;
127.0.0.1 1;
::1 1;
}
limit_req_zone $binary_remote_addr zone=flood:10m rate=12r/s;
limit_req_zone $binary_remote_addr zone=bot:10m rate=200r/m;
limit_req_status 429;
limit_conn_zone $binary_remote_addr zone=connperip:10m;
limit_conn_status 429;
server {
listen 80;
return 301 https://kongjiang.org$request_uri;
}
server {
access_log /var/log/nginx/access.log log_discourse;
listen 443 ssl http2;
listen [::]:443 ssl http2;
client_header_timeout 1m;
client_body_timeout 1m;
proxy_connect_timeout 30s;
proxy_read_timeout 1m;
proxy_send_timeout 1m;
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;
ssl_certificate /shared/ssl/kongjiang.org.cer;
ssl_certificate /shared/ssl/kongjiang.org_ecc.cer;
ssl_certificate_key /shared/ssl/kongjiang.org.key;
ssl_certificate_key /shared/ssl/kongjiang.org_ecc.key;
ssl_session_tickets off;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:1m;
gzip on;
add_header Strict-Transport-Security 'max-age=63072000';
if ($http_host != kongjiang.org) {
rewrite (.*) https://kongjiang.org$1 permanent;
}
gzip_vary on;
gzip_min_length 1000;
gzip_comp_level 5;
gzip_types application/json text/css text/javascript application/x-javascript application/javascript image/svg+xml application/wasm;
gzip_proxied any;
# Descomentar y configurar esta sección para soporte HTTPS
# NOTA: Coloca tu certificado SSL en tu directorio principal de configuración de nginx (/etc/nginx)
#
# rewrite ^/(.*) https://enter.your.web.hostname.here/$1 permanent;
#
# listen 443 ssl;
# ssl_certificate your-hostname-cert.pem;
# ssl_certificate_key your-hostname-cert.key;
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers HIGH:!aNULL:!MD5;
#
server_name _ ;
server_tokens off;
sendfile on;
keepalive_timeout 65;
# tamaño máximo de carga de archivo (mantener actualizado al cambiar la configuración del sitio correspondiente)
client_max_body_size 200m ;
# ruta al directorio público de Discourse
set $public /var/www/discourse/public;
# sin etags débiles no obtenemos ningún beneficio de los etags en contenido comprimido dinámicamente
# además los etags se basan en el archivo en nginx no en el hash sha de los datos
# usa fechas, resuelve el problema bien incluso entre servidores
etag off;
# prevenir descarga directa de copias de seguridad
location ^~ /backups/ {
internal;
}
# omitir la pila de Rails con un 204 barato para solicitudes de favicon.ico
location /favicon.ico {
return 204;
access_log off;
log_not_found off;
}
location / {
root $public;
add_header ETag "";
# auth_basic on;
# auth_basic_user_file /etc/nginx/htpasswd;
location ~ ^/uploads/short-url/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_pass http://discourse;
break;
}
location ~ ^/(secure-media-uploads/|secure-uploads)/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_pass http://discourse;
break;
}
location ~* (fonts|assets|plugins|uploads)/.*\.(eot|ttf|woff|woff2|ico|otf)$ {
expires 1y;
add_header Cache-Control public,immutable;
add_header Access-Control-Allow-Origin *;
}
location = /srv/status {
access_log off;
log_not_found off;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_pass http://discourse;
break;
}
# algo de caché mínima aquí para no seguir preguntando
# a largo plazo deberíamos aumentar probablemente a 1y
location ~ ^/javascripts/ {
expires 1d;
add_header Cache-Control public,immutable;
add_header Access-Control-Allow-Origin *;
}
location ~ ^/assets/(?<asset_path>.+)$ {
expires 1y;
# el pipeline de activos habilita esto
brotli_static on;
gzip_static on;
add_header Cache-Control public,immutable;
# GANCHO en la ubicación de activos (usado para extensibilidad)
# TODO No creo que este break sea necesario, solo sale del rewrite
break;
}
location ~ ^/plugins/ {
expires 1y;
add_header Cache-Control public,immutable;
add_header Access-Control-Allow-Origin *;
}
# cachear emojis
location ~ /images/emoji/ {
expires 1y;
add_header Cache-Control public,immutable;
add_header Access-Control-Allow-Origin *;
}
location ~ ^/uploads/ {
# NOTA: es realmente molesto que no podamos definir encabezados
# en el nivel superior e heredar.
#
# proxy_set_header NO hereda, por diseño, debemos repetirlo,
# de lo contrario los encabezados no se establecen correctamente
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
proxy_set_header X-Accel-Mapping $public/=/downloads/;
expires 1y;
add_header Cache-Control public,immutable;
## reglas opcionales de anti-hotlinking para carga
#valid_referers none blocked mysite.com *.mysite.com;
#if ($invalid_referer) { return 403; }
# CSS personalizado
location ~ /stylesheet-cache/ {
add_header Access-Control-Allow-Origin *;
try_files $uri =404;
}
# esto nos permite omitir Rails
location ~* \.(gif|png|jpg|jpeg|bmp|tif|tiff|ico||avif)$ {
add_header Access-Control-Allow-Origin *;
try_files $uri =404;
}
# SVG necesita un encabezado extra adjunto
location ~* \.(svg)$ {
}
# miniaturas e imágenes optimizadas
location ~ /_?optimized/ {
add_header Access-Control-Allow-Origin *;
try_files $uri =404;
}
proxy_pass http://discourse;
break;
}
location ~ ^/admin/backups/ {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_set_header X-Sendfile-Type X-Accel-Redirect;
proxy_set_header X-Accel-Mapping $public/=/downloads/;
proxy_pass http://discourse;
break;
}
# Este gran bloque es necesario para que podamos habilitar selectivamente
# la aceleración para copias de seguridad, avatares, sprites, etc.
# ver nota sobre repetición arriba
location ~ ^/(svg-sprite/|letter_avatar/|letter_avatar_proxy/|user_avatar|highlight-js|stylesheets|theme-javascripts|favicon/proxied|service-worker) {
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
# si Set-Cookie está en la respuesta nada se almacena en caché
# esto es doblemente malo porque no estamos pasando last modified
proxy_ignore_headers "Set-Cookie";
proxy_hide_header "Set-Cookie";
proxy_hide_header "X-Discourse-Username";
proxy_hide_header "X-Runtime";
# nota x-accel-redirect no puede usarse con proxy_cache
proxy_cache one;
proxy_cache_key "$scheme,$host,$request_uri";
proxy_cache_valid 200 301 302 7d;
proxy_cache_bypass $bypass_cache;
proxy_pass http://discourse;
break;
}
# necesitamos buffering desactivado para el bus de mensajes
location /message-bus/ {
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_http_version 1.1;
proxy_buffering off;
proxy_pass http://discourse;
break;
}
# esto significa que se prueba primero cada archivo en público
try_files $uri @discourse;
}
location /downloads/ {
internal;
alias $public/;
}
location @discourse {
add_header Strict-Transport-Security 'max-age=31536000'; # recordar el certificado durante un año y conectarse automáticamente a HTTPS para este dominio limit_conn connperip 20;
limit_req zone=flood burst=12 nodelay;
limit_req zone=bot burst=100 nodelay;
proxy_set_header Host $http_host;
proxy_set_header X-Request-Start "t=${msec}";
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $thescheme;
proxy_pass http://discourse;
}
}
A pesar de estos cambios, aún recibo un error de «archivo demasiado grande» al cargar imágenes mayores a 15 MB, y con la optimización de imágenes de medios del compositor desactivada, las imágenes no se cargan.
¿Podría alguien guiarme sobre qué otras configuraciones debería ajustar o si hay un problema con mi configuración de Nginx?
Soy nuevo en Nginx y he dependido completamente de Google y ChatGPT para estas modificaciones.