Baştan Sona VPS Sunucu Optimizasyonu (Apache - MySQL - NGINX)

Sunucu optimizasyonu zor, uzun süren ve baş ağrıtıcı bir olaydır. 2 yıldır kullandığım sunucumu optimize etmekten artık yorulmuş durumdayım. Hala da acaba daha iyi olabilir mi diyerek yeni şeyler deniyorum. Bu denediklerimi de sizlerle paylaşmak istiyorum. Buraya paylaştıklarım hem sizlere hem de bana faydalı olacak diye düşünüyorum. Çok uzatmadan uyguladığım yöntemleri ve kaynakları paylaşayım. Ayrıca sizlerle Apache, MySQL (Benim için MariaDB ama fark etmez.) ve NGINX ayarlarımı da paylaşacağım. Hemen aşağıdaki VPS Kurulumu konusunda Türkiye’de ilk sırada çıkan ilgili yazımı da kesinlikle okumalısınız. Bu yazımda yaşadıklarımı bir günlük gibi de tutmaktayım.

VPS Optimizasyonu Nedir?

VPS Optimizasyonu özetle aşağıdaki adımlardan oluşur;

  1. Sunucu çekirdeğinin optimizasyonu (Swap alanı, network ile ilgili iyileştirmeler vb.)
  2. Sunucu üzerindeki servislerin optimizasyonu (Apache, MySQL, NGINX, fail2ban, Firewall vb.)
  3. Servisler üzerindeki dosyaların/verilerin optimizasyonu (Veritabanı, WordPress ya da özel yazılım siteler, scriptler vb.)

Optimizasyonu tam anlamıyla gerçekleştirmek için üç adıma da sağlam bir şekilde dokunmak gerekiyor. Ben bu yazımda ağırlıklı olarak 2. adımdaki servislere değindim. Diğer adımların optimizasyonlarına yukarıdaki söz konusu başlıklara tıklayarak ulaşabilirsiniz.

Not: Yazılarım biraz karışık ilerliyor sanki biliyorum ama düzeltmek için de bir çözümüm yok 🙂 zaten bu olaylar kendiliğinden karışık. Kurcalaya kurcalaya öğrenmek gerekiyor. Çok iyi bir anlatıcı da değilim bu arada kusura bakmayın 🙁

VPS Sunucu Sistemi ve Özellikleri

Öncelikle işletim sistemim CentOS 7 bunu belirteyim. Bu uyguladığım ayarlar 1 GB RAM ve 1 çekirdek CPU’ya sahip VPS’ler için uygundur. Daha yüksek RAM’e sahip sunucularda Apache ayarlarını arttırabiliriz. Hangi kısmı arttırabileceğinizi daha sonra detaylandıracağım burada. Yine de tabi siz aşağıdaki apache2buddy aracı ile arttırmanız gereken alanları görebilirsiniz.

Apache

apache2buddy

apache2buddy scripti sunucuda yüklü olan Apache sunucusunun pek çok alanına bakarak size optimizasyon önerileri sunar. Baktığı alanları özetlersem;

  • PHP RAM limitleri
  • Memcache
  • MaxClients
  • RAM kullanımı
  • Potansiyel maksimum RAM kullanımı
  • Toplam RAM’in yüzde kaçının Apache’ye ayrıldığı
  • MaxRequestWorkers

Bu aracın yukarıdakilere bakarak önerdiği ayarları gerçekleştirdiğimizde de sunucunun ciddi olarak hızlandığını hissedebiliyoruz.

Aracı aşağıdaki komut ile PuTTY aracıyla sunucuya bağlanarak kullanabiliriz.

curl -sL https://raw.githubusercontent.com/richardforth/apache2buddy/master/apache2buddy.pl | perl

Apache Ayarlarım

ServerRoot "/etc/httpd"
Include conf.modules.d/*.conf
User apache
Group apache
ServerAdmin root@localhost

<Directory />
    AllowOverride none
</Directory>

DocumentRoot "/var/www/html"
<Directory "/var/www">
    AllowOverride None
    Require all granted
</Directory>

<Directory "/var/www/html">
    Options FollowSymLinks
    #Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

DirectoryIndex index.php index.html

<Files ".ht*">
    Require all denied
</Files>

ErrorLog "logs/error_log"
LogLevel warn

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%b" bytes
CustomLog "logs/access_log" combined

TypesConfig /etc/mime.types
AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml
#AddHandler cgi-script .cgi

AddDefaultCharset UTF-8

<IfModule mime_magic_module>
    MIMEMagicFile conf/magic
</IfModule>

EnableSendfile on

<IfModule remoteip_module>
    RemoteIPHeader X-Real-IP
    LogFormat "%a %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%a %l %u %t \"%r\" %>s %b" common
</IfModule>

IncludeOptional conf.d/*.conf

<IfModule mpm_prefork_module>
    StartServers          1
    MinSpareServers       4
    MaxSpareServers      5
    ServerLimit         5
    MaxClients          5
    MaxRequestWorkers   5
    MaxRequestsPerChild 500
</IfModule>

<IfModule worker.c>
    ServerLimit         6
    StartServers          1
    MaxClients          8
    MinSpareThreads      4
    MaxSpareThreads      8
    ThreadsPerChild      8
    ThreadLimit          32
    MaxRequestWorkers   8
    ThreadStackSize      1048576
    MaxRequestsPerChild   500
</IfModule>

<IfModule event.c>
    ServerLimit           4
    MaxClients           4
    StartServers           1
    ThreadsPerChild       2
    ThreadLimit           8
    MinSpareThreads       1
    MaxSpareThreads      4
    MaxRequestsPerChild 500
    GracefulShutdownTimeout 8
    MaxRequestWorkers 2
</IfModule>

Timeout 45
KeepAlive On
KeepAliveTimeout 3
MaxKeepAliveRequests 100
HostnameLookups Off
ServerSignature Off
ServerName 127.0.0.1:80

MySQL

Ben MySQL optimizasyonu için birçok makale okudum. Fakat aşağıda paylaşacağım aracı kullanmanızı tavsiye ederim. Bu araç MySQL ayarlarınızı ve kullanım istatistiklerinizi tarayarak size tavsiyeler veriyor. Bu tavsiyelere uyarak veritabanı sunucunuzu güzel bir şekilde optimize edebilirsiniz. Tabi her önerdiği ayara da uymayın. Sonuçta VPS’lerinizin RAM miktarı kısıtlı.

MySQLTuner

MySQLTuner scripti de aynı apache2buddy scripti gibi bu sefer veritabanı sunucunuzun pek çok alanına bakarak size optimizasyon önerileri sunar. Bu aracı aşağıdaki şekilde kullanabilirsiniz. Size muhtemelen 1. seçenek uyacaktır.

“root” Şifreniz Aynıysa

curl -L https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl | perl

“root” Şifreniz Farklıysa

wget https://raw.githubusercontent.com/major/MySQLTuner-perl/master/mysqltuner.pl
chmod +x mysqltuner.pl
./mysqltuner.pl

MySQL Ayarlarım

[mysqld]

# GENERAL #
default-storage-engine         = InnoDB
socket                         = /var/lib/mysql/mysql.sock
symbolic-links                 = 0
local-infile                   = 0
skip-external-locking
skip-name-resolve

# SAFETY #
max-allowed-packet             = 16M
max-connect-errors             = 1000000

# MyISAM #
key-buffer-size                = 64M
myisam-recover-options         = FORCE,BACKUP

# DATA STORAGE #
datadir                        = /var/lib/mysql

# CACHES AND LIMITS #
bulk_insert_buffer_size        = 4M
sort_buffer_size               = 1M
read_buffer_size               = 1M
read_rnd_buffer_size           = 1M
thread_stack                   = 1M
thread_concurrency             = 2
tmp_table_size                 = 48M
max_heap_table_size            = 48M
thread_cache_size              = 64
join_buffer_size               = 2M
aria-pagecache-buffer-size     = 512K
query_cache_size               = 0
query_cache_type               = 0
query_cache_limit              = 512K
query_cache_min_res_unit       = 2K
myisam_sort_buffer_size        = 2M
performance_schema             = OFF
innodb_flush_log_at_trx_commit = 0
innodb_flush_method            = O_DIRECT
innodb_buffer_pool_size        = 48M
innodb_file_per_table          = 1
innodb_log_buffer_size         = 4M
innodb_stats_on_metadata       = OFF
innodb_buffer_pool_instances   = 1
innodb_log_file_size           = 6M
innodb-file-per-table          = 1
innodb_open_files              = 400
max_connections                = 30
max_user_connections           = 30
wait_timeout                   = 60
connect_timeout                = 15
interactive_timeout            = 40
open-files-limit               = 65535
table_open_cache               = 24
table-definition-cache         = 4096
table-open-cache               = 4096
log-error                      = /var/log/mariadb/mariadb.log
log_queries_not_using_indexes  = 0
long_query_time                = 3
slow_query_log                 = 1
slow_query_log_file            = /var/log/mariadb/mysql-slow-queries.log

[mysqld_safe]
log-error                      =/var/log/mariadb/mariadb.log
pid-file                       =/var/run/mariadb/mariadb.pid

[mysqldump]
quick max_allowed_packet       = 8M

!includedir /etc/my.cnf.d
 

NGINX

NGINX Ayarlarım

# Server globals
user                    nginx;
worker_processes        1;
error_log               /var/log/nginx/error.log;
pid                     /var/run/nginx.pid;


# Worker config
events {
        worker_connections          1024;
        use                         epoll;
        multi_accept                on;
}


http {
    # Main settings
    client_header_buffer_size       2k;
    client_max_body_size            64m;
    sendfile                        on;
    tcp_nopush                      on;
    tcp_nodelay                     on;
    client_header_timeout           45;
    client_body_timeout             45;
    client_body_buffer_size         256k;
    large_client_header_buffers     4 16k;
    send_timeout                    45;
    keepalive_timeout               60 60;
    reset_timedout_connection       on;
    server_tokens                   off;
    server_name_in_redirect         off;
    server_names_hash_max_size      512;
    server_names_hash_bucket_size   512;

    log_format  main    '$remote_addr - $remote_user [$time_local] $request '
                        '"$status" $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
    log_format  bytes   '$body_bytes_sent';
    #access_log          /var/log/nginx/access.log  main;
    access_log off;


    # Mime settings
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;


    # Compression
    gzip                on;
    gzip_vary           on;
    gzip_static         on;
    gzip_comp_level     6;
    gzip_min_length     512;
    gzip_disable        "MSIE [1-6]\.";

     gzip_buffers       16 8k;

    #gzip_proxied       expired no-cache no-store private auth;
     gzip_proxied       any;

     #gzip_types        text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml application/x-font-ttf font/opentype application/x-javascript;
     #gzip_types        text/plain application/x-javascript text/xml text/css application/xml;
     #gzip_types        text/plain text/html text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
      gzip_types
                        application/atom+xml
                        application/javascript
                        application/json
                        application/rss+xml
                        application/vnd.ms-fontobject
                        application/x-font-ttf
                        application/x-javascript
                        application/x-web-app-manifest+json
                        application/xhtml+xml
                        application/xml
                        font/opentype
                        image/svg+xml
                        image/x-icon
                        text/css
                        text/plain
                        text/javascript
                        text/x-component;

    # Proxy settings
    proxy_redirect          off;
    proxy_set_header        Host            $host;
    proxy_set_header        X-Real-IP       $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass_header       Set-Cookie;
    proxy_connect_timeout   240;
    proxy_send_timeout      600;
    proxy_read_timeout      600;
    proxy_buffers           4 256k;
    proxy_buffer_size       128k;
    proxy_busy_buffers_size 256k;
    proxy_buffering         on;

    #peer closed connection in SSL handshake" hatası için eklendi.
    proxy_ssl_server_name   on;

    # SSL PCI Compliance
    ssl_session_cache         shared:SSL:10m;
    ssl_protocols             TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_ciphers               "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";


    # Error pages
    error_page          403          /error/403.html;
    error_page          404          /error/404.html;
    error_page          502 503 504  /error/50x.html;


    # Cache
    proxy_cache_path /var/cache/nginx levels=2 keys_zone=cache:10m inactive=60m max_size=512m;
    proxy_temp_path  /var/cache/nginx/temp;
    proxy_cache_key "$host$request_uri $cookie_user";
    proxy_ignore_headers Expires Cache-Control;
    proxy_cache_use_stale error timeout invalid_header http_502;
    proxy_cache_valid any 3d;

    map $http_cookie $no_cache {
        default 0;
        ~SESS 1;
        ~wordpress_logged_in 1;
    }


    # Wildcard include
    include             /etc/nginx/conf.d/*.conf;
}

Veritabanı Optimizasyonu

Kısaca 3. adımdaki veritabanı optimizasyonundan da bahsedersem ben veritabanı optimizasyonunu WP-Optimize eklentisi ile gerçekleştiriyorum. Bunu da daha sonra detaylandırırız.

Sonuç

Sonuç olarak benim verdiğim ayarları kullandığınızda tam anlamıyla optimize bir sisteme sahip olacaksınız. Sistem gayet hızlı çalışacak. Bu yazıyı da sürekli güncel tutup daha da dallandırmayı düşünüyorum. Takipte kalın! Teşekkürler 🙂

Ayrıca bu optimizasyon ile birlikte aşağıdaki yazımı da uygulamanızı tavsiye ederim. Ayarları tam olarak 1 GB RAM’li sisteme göre yaptığımız için swap kısmına çok ihtiyacımız olmayacak. Swap yapacağız fakat aşırı değil. %100’e çok yaklaştığında sistem swap yapacak. Bu yüzden aşağıdaki gibi uygulayın ayarları.

Önemli Not

Evet biliyorum yazım hatta tüm yazılarım karışık. Fakat benim bunları öğrenmem (Ki tam öğrenebildiğim söylenemez. Sonu yok bu işin.) 2 senemi aldı. Bu 2 sene içinde sunucumu onlarca kez baştan kurdum. Bozdum, bozdum, düzelttim. Belki 1000’den fazla makale okudum. Bu yazı ve Baştan Sona VPS Kurulumu yazımı oluşturmam kolay olmadı. Bu yüzden en azından bu yazım ağır geliyorsa (Ağır derken anlayamadığınız yerleri tek tek Google’da araştırmanız lazım. Her şeyi burada anlatmadım ben.) direk 3 adet config dosyamı (Apache, MySQL ve NGINX) alın ve kullanın sorgulamadan. Sunucunuz benim sunucum gibiyse (Vesta Panel kullanıyorum bu yüzden sadece gerekli yerleri almanız gerekebilir.) direk kullanın geçin.

Kaynak: 
https://www.linode.com/docs/web-servers/apache-tips-and-tricks/tuning-your-apache-server/
Kaynak: 
https://lunarpages.com/5-ways-to-optimize-apache-performance/
Kaynak: 
https://www.tecmint.com/mysql-mariadb-performance-tuning-and-optimization/
Kaynak: 
https://www.linode.com/docs/databases/mysql/how-to-optimize-mysql-performance-using-mysqltuner/

4.2/5 - (8 votes)