أدير موقعًا ويب يشارك فيه هواة التصوير أعمالهم بشكل متكرر، وأرغب في تعطيل ضغط جميع الصور مع تمكين إزالة البيانات الوصفية. قمت بإجراء التعديلات التالية:
ضبطت الحد الأقصى لحجم الصورة على 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 دقيقة بغض النظر عن آخر وقت وصول (أسبوع واحد)
# 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;
# بدون weak etags لا نحصل على أي فائدة من etags على المحتوى المضغوط ديناميكيًا
# علاوة على ذلك، تعتمد etags على الملف في nginx وليس تجزئة sha للبيانات
# استخدم التواريخ، فهي تحل المشكلة بشكل جيد حتى عبر الخوادم
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;
}
# بعض التخزين المؤقت البسيط هنا حتى لا نظل نسأل
# على المدى الطويل يجب أن نزيد المدة ربما إلى 1y
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;
# HOOK في موقع الأصول (يُستخدم للتوسع)
# TODO لا أعتقد أن هذا الـ break مطلوب، فهو يكسر فقط خارج إعادة الكتابة
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;
}
# هذا يعني أن كل ملف في الدليل العام يتم تجربته أولاً
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 الخاصة بي؟
أنا جديد في Nginقاعدي اعتماد كلي على Google و ChatGPT لهذه التعديلات.