Как отключить сжатие изображений?

Я управляю сайтом, где энтузиасты фотографии часто делятся своими работами, и я хочу отключить все сжатие изображений, но при этом включить удаление метаданных. Я внес следующие изменения:

Я установил максимальный размер изображения 40 МБ, максимальное количество мегапикселей — на максимально допустимое значение 150 МП и отключил оптимизацию изображений в редакторе сообщений.

Также я изменил настройки Nginx в контейнере.
Если коротко, я добавил:

client_header_timeout 1m;
client_body_timeout 1m;
proxy_connect_timeout 30s;
proxy_read_timeout 1m;
proxy_send_timeout 1m;

и изменил:

 # максимальный размер загружаемого файла (обновляйте при изменении соответствующей настройки на сайте)
  client_max_body_size 200m ;

в блоке server{} в файле /etc/nginx/nginx.conf.

Добавил:

        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;

в блок http{} в файле /etc/nginx/nginx.conf.

Вот конфигурации для /etc/nginx/nginx.conf и /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;

        ##
        # Базовые настройки
        ##

        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;

        ##
        # Настройки SSL
        ##

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Отключаем SSLv3, см. POODLE
        ssl_prefer_server_ciphers on;

        ##
        # Настройки логирования
        ##

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        ##
        # Настройки 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;

        ##
        # Конфигурации виртуальных хостов
        ##

        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
}


#mail {
#       # См. пример скрипта аутентификации по адресу:
#       # 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 
# Дополнительные MIME-типы, которые вы хотите обрабатывать в nginx, помещаются сюда
types {
    text/csv csv;
    application/wasm wasm;
}

upstream discourse { server 127.0.0.1:3000; }

# inactive означает, что мы храним данные в течение 1440 минут независимо от последнего доступа (1 неделя)
# levels означает, что это двухуровневая иерархия, так как у нас может быть много файлов
# max_size ограничивает размер кэша
proxy_cache_path /var/nginx/cache inactive=1440m levels=1:2 keys_zone=one:10m max_size=600m;

# Увеличено по сравнению со значением по умолчанию для поддержки больших куки во время потоков oAuth2
# например, в https://meta.discourse.org/t/x/74060 и больших заголовках CSP и Link (preload)
proxy_buffer_size 32k;
proxy_buffers 4 32k;

# Увеличено по сравнению со значением по умолчанию для поддержки большого объема куки в заголовках запроса
# Сам Discourse пытается минимизировать размер куки, но мы не можем контролировать другие куки, устанавливаемые другими инструментами на том же домене.
large_client_header_buffers 4 32k;

# Если вы собираетесь использовать Puma, используйте эти настройки:
#
# upstream discourse {
#   server unix:/var/www/discourse/tmp/sockets/puma.sock;
# }


# попытка сохранить протокол, должно быть в контексте 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"';

# Разрешить обход кэша с 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;

  # Раскомментируйте и настройте этот раздел для поддержки HTTPS
  # ПРИМЕЧАНИЕ: Поместите ваш SSL-сертификат в основную директорию конфигурации 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;

  # максимальный размер загружаемого файла (обновляйте при изменении соответствующей настройки на сайте)
  client_max_body_size 200m ;

  # путь к публичной директории Discourse
  set $public /var/www/discourse/public;

  # без слабых ETag мы не получаем никакой выгоды от ETag для динамически сжимаемого контента
  # кроме того, ETag основаны на файле в nginx, а не на хэше данных
  # используйте даты, это решает проблему нормально даже между серверами
  etag off;

  # предотвратить прямую загрузку резервных копий
  location ^~ /backups/ {
    internal;
  }

  # обход стека Rails с помощью дешевого 204 для запросов 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;
    }

    # здесь минимальное кэширование, чтобы мы не спрашивали постоянно
    # в долгосрочной перспективе, вероятно, стоит увеличить до 1 года
    location ~ ^/javascripts/ {
      expires 1d;
      add_header Cache-Control public,immutable;
      add_header Access-Control-Allow-Origin *;
    }

    location ~ ^/assets/(?<asset_path>.+)$ {
      expires 1y;
      # конвейер ресурсов включает это
      brotli_static on;
      gzip_static on;
      add_header Cache-Control public,immutable;
      # ВКЛЮЧЕНИЕ в расположение ресурсов (используется для расширяемости)
      # TODO, я не думаю, что этот break нужен, он просто выходит из rewrite
      break;
    }

    location ~ ^/plugins/ {
      expires 1y;
      add_header Cache-Control public,immutable;
      add_header Access-Control-Allow-Origin *;
    }

    # кэширование эмодзи
    location ~ /images/emoji/ {
      expires 1y;
      add_header Cache-Control public,immutable;
      add_header Access-Control-Allow-Origin *;
    }

    location ~ ^/uploads/ {

      # ПРИМЕЧАНИЕ: очень раздражает, что мы не можем просто определить заголовки
      # на верхнем уровне и наследовать их.
      #
      # proxy_set_header НЕ наследуется, по дизайну, мы должны повторять его,
      # иначе заголовки не будут установлены правильно
      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;

      ## опциональные правила защиты от хотлинкинга при загрузке
      #valid_referers none blocked mysite.com *.mysite.com;
      #if ($invalid_referer) { return 403; }

      # пользовательские CSS
      location ~ /stylesheet-cache/ {
          add_header Access-Control-Allow-Origin *;
          try_files $uri =404;
      }
      # это позволяет нам обходить Rails
      location ~* \.(gif|png|jpg|jpeg|bmp|tif|tiff|ico||avif)$ {
          add_header Access-Control-Allow-Origin *;
          try_files $uri =404;
      }
      # SVG требует дополнительного заголовка
      location ~* \.(svg)$ {
      }
      # миниатюры и оптимизированные изображения
      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;
    }

    # Этот большой блок необходим, чтобы мы могли выборочно включать
    # ускорение для резервных копий, аватаров, спрайтов и так далее.
    # см. примечание о повторении выше
    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;

      # если в ответе есть Set-Cookie, ничего не кэшируется
      # это двойной промах, так как мы не передаем last modified
      proxy_ignore_headers "Set-Cookie";
      proxy_hide_header "Set-Cookie";
      proxy_hide_header "X-Discourse-Username";
      proxy_hide_header "X-Runtime";

      # обратите внимание, x-accel-redirect нельзя использовать с 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;
    }

    # нам нужно отключить буферизацию для message bus
    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;
    }

    # это означает, что сначала пробуются все файлы в public
    try_files $uri @discourse;
  }

  location /downloads/ {
    internal;
    alias $public/;
  }

  location @discourse {
add_header Strict-Transport-Security 'max-age=31536000'; # запомнить сертификат на год и автоматически подключаться к HTTPS для этого домена  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;
  }

}

Несмотря на эти изменения, я всё ещё получаю ошибку «файл слишком большой» при загрузке изображений размером более 15 МБ, и при отключённой оптимизации изображений в редакторе сообщений загрузка изображений не удаётся.

Мог бы кто-нибудь подсказать, какие ещё настройки нужно изменить или есть ли проблема в моей конфигурации Nginx?

Я новичок в Nginx и полностью полагался на Google и ChatGPT при внесении этих изменений.

Здравствуйте… Кто-нибудь может помочь, пожалуйста?

Похоже, вы пытаетесь решить сразу две проблемы?

Отключение сжатия изображений выполняется путём изменения параметра «Качество пережатия исходных JPG» в разделе «Администрирование → Настройки → Файлы» на значение 100.

Другая проблема связана с максимальным размером загружаемого файла.

Не могли бы вы указать точную формулировку ошибки?

Работает ли это при включённой этой настройке?

Вам также нужно изменить значение client_max_body_size в конфигурации nginx внутри Docker-контейнера Discourse.