Налаштування робочого середовища для Magento 2.4
В нас ОС Debian 10.
ПІсля входу на вашу ВМ першим ділом закриваєм доступ по SSH root користувачу, Створюєм нового з правами sudo
useradd -m -U -s /bin/bash -G sudo hello
passwd hello
Змінюєм налаштування SSH nano /etc/ssh/sshd_config
Port 22123
PermitRootLogin noClientAliveInterval 300 ClientAliveCountMax 1
AllowUsers holu helloMaxAuthTries 2
Перевіряєм синтаксис сервісу: sshd -t та перезавантажуєм
systemctl restart sshd
Наспним кроком це встановлення Fail2Ban
apt install fail2ban
systemctl enable fail2ban
Налаштування Fail2Ban
cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local
nano /etc/fail2ban/jail.local
enabled = true
port = SELECTED_SSH_PORT
systemctl restart fail2ban
Установка PHP 7.4 / 7.3 / 7.2 / 7.1 на Debian 10
Оновлюєм репозиторії
sudo apt update
Встановіть наведені нижче пакети.
sudo apt install -y curl wget gnupg2 ca-certificates lsb-release apt-transport-https
Імпортуйте загальнодоступний за допомогою наведених нижче команд.
wget https://packages.sury.org/php/apt.gpg sudo apt-key add apt.gpg
Добавляєм в наші списки репозиторіїв
echo "deb https://packages.sury.org/php/ $ (lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/php7.list
Оновлюєм
sudo apt update
Встановіть PHP v7.4 наступною командою
sudo apt install -y php7.4 php7.4-cli php7.4-common php7.4-fpm
apt install -y php7.4-curl php7.4-bcmath php7.4-dom php7.4-gd php7.4-imagick php7.4-mbstring php7.4-xml php7.4-zip php7.4-xsl php7.4-mysqli php7.4-soap
Якщо вам потрібно встановити іншу версію то просто зміюєте версію php7.3, php7.2, php7.1. Після встановлення PHP перевірте версію.
php -v PHP 7.4.15 (cli) (built: Feb 23 2021 16:44:43) ( NTS ) Copyright (c) The PHP Group Zend Engine v3.4.0, Copyright (c) Zend Technologies with Zend OPcache v7.4.15, Copyright (c), by Zend Technologies
Встановлення Varnish 6.4
aptitude update aptitude install debian-archive-keyring aptitude install curl gnupg apt-transport-https curl -L https://packagecloud.io/varnishcache/varnish64/gpgkey | sudo apt-key add -
Додаєм в список репозиторія nano /etc/apt/sources.list
# varnish deb https://packagecloud.io/varnishcache/varnish64/debian/ buster main deb-src https://packagecloud.io/varnishcache/varnish64/debian/ buster main
Обновлюєм та встановлюєм
aptitude update aptitude install varnish=6.4.0-1~buster
varnishd -V
Змінюєм файл конфігурації
nano /lib/systemd/system/varnish.service
[Unit]
Description=Varnish HTTP accelerator
Documentation=https://www.varnish-cache.org/docs/6.4/ man:varnishd [Service]
Type=simple
LimitNOFILE=131072
LimitMEMLOCK=82000
ExecStart=/usr/sbin/varnishd -j unix,user=vcache -F -a :80 -T localhost:6082 -f /etc/varnish/default.vcl -S /etc/varnish/secret -s malloc,256m
ExecReload=/usr/share/varnish/varnishreload
ProtectSystem=full
ProtectHome=true
PrivateTmp=true
PrivateDevices=true [Install]
WantedBy=multi-user.target
systemctl daemon-reload
service varnish restart
Тепер змінюєм конфіг файл для Magento 2 nano /etc/varnish/default.vcl
# VCL version 5.0 is not supported so it should be 4.0 even though actually used Varnish version is 6 vcl 4.0; import std; # The minimal Varnish version is 6.4 # For SSL offloading, pass the following header in your proxy server or load balancer: 'X-Forwarded-Proto: https' backend default { .host = "localhost"; .port = "8080"; .first_byte_timeout = 600s; .probe = { .url = "/health_check.php"; .timeout = 2s; .interval = 5s; .window = 10; .threshold = 5; } } acl purge { "localhost"; } sub vcl_recv { if (req.restarts > 0) { set req.hash_always_miss = true; } if (req.method == "PURGE") { if (client.ip !~ purge) { return (synth(405, "Method not allowed")); } # To use the X-Pool header for purging varnish during automated deployments, make sure the X-Pool header # has been added to the response in your backend server config. This is used, for example, by the # capistrano-magento2 gem for purging old content from varnish during it's deploy routine. if (!req.http.X-Magento-Tags-Pattern && !req.http.X-Pool) { return (synth(400, "X-Magento-Tags-Pattern or X-Pool header required")); } if (req.http.X-Magento-Tags-Pattern) { ban("obj.http.X-Magento-Tags ~ " + req.http.X-Magento-Tags-Pattern); } if (req.http.X-Pool) { ban("obj.http.X-Pool ~ " + req.http.X-Pool); } return (synth(200, "Purged")); } if (req.method != "GET" && req.method != "HEAD" && req.method != "PUT" && req.method != "POST" && req.method != "TRACE" && req.method != "OPTIONS" && req.method != "DELETE") { /* Non-RFC2616 or CONNECT which is weird. */ return (pipe); } # We only deal with GET and HEAD by default if (req.method != "GET" && req.method != "HEAD") { return (pass); } # Bypass shopping cart, checkout and search requests if (req.url ~ "/checkout" || req.url ~ "/catalogsearch") { return (pass); } # Bypass health check requests if (req.url ~ "/health_check.php") { return (pass); } if (req.url ~ "/PrimeLab/handler.php") { return (pass); } # Set initial grace period usage status set req.http.grace = "none"; # normalize url in case of leading HTTP scheme and domain set req.url = regsub(req.url, "^http[s]?://", ""); # collect all cookies std.collect(req.http.Cookie); # Compression filter. See https://www.varnish-cache.org/trac/wiki/FAQ/Compression if (req.http.Accept-Encoding) { if (req.url ~ "\.(jpg|jpeg|png|gif|gz|tgz|bz2|tbz|mp3|ogg|swf|flv)$") { # No point in compressing these unset req.http.Accept-Encoding; } elsif (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } elsif (req.http.Accept-Encoding ~ "deflate" && req.http.user-agent !~ "MSIE") { set req.http.Accept-Encoding = "deflate"; } else { # unknown algorithm unset req.http.Accept-Encoding; } } # Remove all marketing get parameters to minimize the cache objects if (req.url ~ "(\?|&)(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=") { set req.url = regsuball(req.url, "(gclid|cx|ie|cof|siteurl|zanpid|origin|fbclid|mc_[a-z]+|utm_[a-z]+|_bta_[a-z]+)=[-_A-z0-9+()%.]+&?", ""); set req.url = regsub(req.url, "[?|&]+$", ""); } # Static files caching if (req.url ~ "^/(pub/)?(media|static)/") { # Static files should not be cached by default return (pass); # But if you use a few locales and don't use CDN you can enable caching static files by commenting previous line (#return (pass);) and uncommenting next 3 lines #unset req.http.Https; #unset req.http.X-Forwarded-Proto; #unset req.http.Cookie; } # Authenticated GraphQL requests should not be cached by default if (req.url ~ "/graphql" && req.http.Authorization ~ "^Bearer") { return (pass); } return (hash); } sub vcl_hash { if (req.http.cookie ~ "X-Magento-Vary=") { hash_data(regsub(req.http.cookie, "^.*?X-Magento-Vary=([^;]+);*.*$", "\1")); } # For multi site configurations to not cache each other's content if (req.http.host) { hash_data(req.http.host); } else { hash_data(server.ip); } # To make sure http users don't see ssl warning if (req.http.X-Forwarded-Proto) { hash_data(req.http.X-Forwarded-Proto); } if (req.url ~ "/graphql") { call process_graphql_headers; } } sub process_graphql_headers { if (req.http.Store) { hash_data(req.http.Store); } if (req.http.Content-Currency) { hash_data(req.http.Content-Currency); } } sub vcl_backend_response { set beresp.grace = 3d; if (beresp.http.content-type ~ "text") { set beresp.do_esi = true; } if (bereq.url ~ "\.js$" || beresp.http.content-type ~ "text") { set beresp.do_gzip = true; } if (beresp.http.X-Magento-Debug) { set beresp.http.X-Magento-Cache-Control = beresp.http.Cache-Control; } # cache only successfully responses and 404s if (beresp.status != 200 && beresp.status != 404) { set beresp.ttl = 0s; set beresp.uncacheable = true; return (deliver); } elsif (beresp.http.Cache-Control ~ "private") { set beresp.uncacheable = true; set beresp.ttl = 86400s; return (deliver); } # validate if we need to cache it and prevent from setting cookie if (beresp.ttl > 0s && (bereq.method == "GET" || bereq.method == "HEAD")) { unset beresp.http.set-cookie; } # If page is not cacheable then bypass varnish for 2 minutes as Hit-For-Pass if (beresp.ttl <= 0s || beresp.http.Surrogate-control ~ "no-store" || (!beresp.http.Surrogate-Control && beresp.http.Cache-Control ~ "no-cache|no-store") || beresp.http.Vary == "*") { # Mark as Hit-For-Pass for the next 2 minutes set beresp.ttl = 120s; set beresp.uncacheable = true; } return (deliver); } sub vcl_deliver { if (resp.http.X-Magento-Debug) { if (resp.http.x-varnish ~ " ") { set resp.http.X-Magento-Cache-Debug = "HIT"; set resp.http.Grace = req.http.grace; } else { set resp.http.X-Magento-Cache-Debug = "MISS"; } } else { unset resp.http.Age; } # Not letting browser to cache non-static files. if (resp.http.Cache-Control !~ "private" && req.url !~ "^/(pub/)?(media|static)/") { set resp.http.Pragma = "no-cache"; set resp.http.Expires = "-1"; set resp.http.Cache-Control = "no-store, no-cache, must-revalidate, max-age=0"; } unset resp.http.X-Magento-Debug; unset resp.http.X-Magento-Tags; unset resp.http.X-Powered-By; unset resp.http.Server; unset resp.http.X-Varnish; unset resp.http.Via; unset resp.http.Link; } sub vcl_hit { if (obj.ttl >= 0s) { # Hit within TTL period return (deliver); } if (std.healthy(req.backend_hint)) { if (obj.ttl + 300s > 0s) { # Hit after TTL expiration, but within grace period set req.http.grace = "normal (healthy server)"; return (deliver); } else { # Hit after TTL and grace expiration return (restart); } } else { # server is not healthy, retrieve from cache set req.http.grace = "unlimited (unhealthy server)"; return (deliver); } }
NGINX Встановлення
apt -y install nginx
systemctl status nginx systemctl enable nginx
apt install software-properties-common add-apt-repository universe add-apt-repository ppa:certbot/certbot apt update apt -y install python-certbot-nginx certbot --nginx -d domain.com -d www.domain.com certbot renew --dry-run certbot renew --dry-run
Також змінюєм налаштування NGINX для прослуховування 8080 порта
nano /etc/nginx/sites-available/my.conf
upstream fastcgi_backend { server unix:/var/run/php/php7.4-fpm.sock; } server { listen 8080 default_server; listen [::]:8080 default_server; error_log /var/log/nginx/example_error_log warn; error_log /var/log/nginx/example1.error_log crit; set $MAGE_ROOT /var/www/html; root $MAGE_ROOT/pub; index index.php; autoindex off; charset UTF-8; error_page 404 403 = /errors/404.php; #add_header "X-UA-Compatible" "IE=Edge"; # Deny access to sensitive files location /.user.ini { deny all; } location ~* ^/PrimeLab($|/) { root $MAGE_ROOT; location ~ ^/PrimeLab/handler.php { fastcgi_pass fastcgi_backend; fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=600"; fastcgi_read_timeout 600s; fastcgi_connect_timeout 600s; fastcgi_index handler.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } # PHP entry point for setup application location ~* ^/setup($|/) { root $MAGE_ROOT; location ~ ^/setup/index.php { fastcgi_pass fastcgi_backend; fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=600"; fastcgi_read_timeout 600s; fastcgi_connect_timeout 600s; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } location ~ ^/setup/(?!pub/). { deny all; } location ~ ^/setup/pub/ { add_header X-Frame-Options "SAMEORIGIN"; } } # PHP entry point for update application location ~* ^/update($|/) { root $MAGE_ROOT; location ~ ^/update/index.php { fastcgi_split_path_info ^(/update/index.php)(/.+)$; fastcgi_pass fastcgi_backend; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; include fastcgi_params; } # Deny everything but index.php location ~ ^/update/(?!pub/). { deny all; } location ~ ^/update/pub/ { add_header X-Frame-Options "SAMEORIGIN"; } } location / { try_files $uri $uri/ /index.php$is_args$args; } location /pub/ { # location ~ ^/pub/media/(downloadable|customer|import|theme_customization/.*\.xml) { # deny all; # } alias $MAGE_ROOT/pub/; add_header X-Frame-Options "SAMEORIGIN"; } location /static/ { # Uncomment the following line in production mode # expires max; # Remove signature of the static files that is used to overcome the browser cache location ~ ^/static/version { rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last; } location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2|json)$ { add_header Cache-Control "public"; add_header X-Frame-Options "SAMEORIGIN"; expires +1y; if (!-f $request_filename) { rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; } } location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { add_header Cache-Control "no-store"; add_header X-Frame-Options "SAMEORIGIN"; expires off; if (!-f $request_filename) { rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; } } if (!-f $request_filename) { rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last; } add_header X-Frame-Options "SAMEORIGIN"; } location /media/ { try_files $uri $uri/ /get.php$is_args$args; location ~ ^/media/theme_customization/.*\.xml { deny all; } location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ { add_header Cache-Control "public"; add_header X-Frame-Options "SAMEORIGIN"; expires +1y; try_files $uri $uri/ /get.php$is_args$args; } location ~* \.(zip|gz|gzip|bz2|csv|xml)$ { add_header Cache-Control "no-store"; add_header X-Frame-Options "SAMEORIGIN"; expires off; try_files $uri $uri/ /get.php$is_args$args; } add_header X-Frame-Options "SAMEORIGIN"; } location /media/customer/ { deny all; } location /media/downloadable/ { deny all; } location /media/import/ { deny all; } location /errors/ { location ~* \.xml$ { deny all; } } # PHP entry point for main application location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check)\.php$ { try_files $uri =404; fastcgi_pass fastcgi_backend; # fastcgi_buffers 1024 4k; fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; proxy_buffer_size 128k; proxy_buffers 4 256k; proxy_busy_buffers_size 256k; client_max_body_size 100m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffering on; fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off"; fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=18000"; fastcgi_read_timeout 600s; fastcgi_connect_timeout 600s; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } gzip on; gzip_disable "msie6"; gzip_comp_level 6; gzip_min_length 1100; gzip_buffers 16 8k; gzip_proxied any; gzip_types text/plain text/css text/js text/xml text/javascript application/javascript application/x-javascript application/json application/xml application/xml+rss image/svg+xml; gzip_vary on; # Banned locations (only reached if the earlier PHP entry point regexes don't match) location ~* (\.php$|\.phtml$|\.htaccess$|\.git) { deny all; } } server { server_name examle.com.ua; listen 443 ssl http2; error_log /var/log/nginx/example_error_log warn; error_log /var/log/nginx/example1.error_log crit; ssl on; # ssl_certificate /etc/letsencrypt/live/mysite/fullchain.pem; # ssl_certificate_key /etc/letsencrypt/live/mysite/privkey.pem; ssl_certificate /etc/letsencrypt/live/mysite/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/mysite/privkey.pem; location / { proxy_pass http://127.0.0.1; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-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 Ssl-Offloaded "1"; #proxy_hide_header X-Varnish; #proxy_hide_header Via; client_max_body_size 100m; client_body_buffer_size 128k; proxy_connect_timeout 90; proxy_send_timeout 90; proxy_read_timeout 90; proxy_buffering on; proxy_buffer_size 1024k; proxy_buffers 8 1024k; proxy_busy_buffers_size 1024k; proxy_set_header X-Forwarded-Proto $scheme; } }
Встановлення Elasticsearch 7
Добавляєм PGP ключі
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
Elasticsearch 7.x (Latest):
sudo apt -y install apt-transport-https
echo "deb https://artifacts.elastic.co/packages/oss-7.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-7.x.list
Elasticsearch 6.x:
sudo apt -y install apt-transport-https
echo "deb https://artifacts.elastic.co/packages/oss-6.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-6.x.list
Elasticsearch 5.x:
sudo apt -y install apt-transport-https
echo "deb https://artifacts.elastic.co/packages/oss-5.x/apt stable main" | sudo tee /etc/apt/sources.list.d/elastic-5.x.list
sudo apt update
sudo apt -y install elasticsearch-oss
Змінити налаштування nano /etc/elasticsearch/elasticsearch.yml
cluster.name: my-application
запускаєм та оновлюєм сервіси
sudo systemctl enable elasticsearch.service && sudo systemctl restart elasticsearch.service
Як встановити найновіший MySQL на Debian 10
На сервері клієнті встановлюємо клієнт apt install default-mysql-client
sudo apt update
sudo apt install gnupg
Після підтвердження встановлення apt встановить gnupgта його залежності.
cd /tmp wget https://dev.mysql.com/get/mysql-apt-config_0.8.13-1_all.deb
sudo dpkg -i mysql-apt-config*
sudo apt update
Після додавання сховища та оновлення нашого кешу пакунків тепер ми можемо використовувати aptдля встановлення останнього серверного пакету MySQL:
sudo apt install mysql-server
sudo systemctl status mysql
Захист MySQL mysql_secure_installation
Як дозволити віддалений доступ до MySQL
Однією з найпоширеніших проблем, з якою стикаються користувачі при спробі налаштування віддаленої бази даних MySQL, є те, що їх екземпляр MySQL налаштований лише на прослуховування локальних з'єднань. Це налаштування MySQL за замовчуванням, але воно не буде працювати для віддаленого налаштування бази даних, оскільки MySQL повинен мати можливість прослуховувати зовнішню IP-адресу, де можна отримати доступ до сервера. Щоб увімкнути це, відкрийте mysqld.cnfфайл:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld] pid-file = /var/run/mysqld/mysqld.pid socket = /var/run/mysqld/mysqld.sock datadir = /var/lib/mysql log-error = /var/log/mysql/error.log #localhost bind-address=127.0.0.1 #IP remote host bind-address=10.0.0.3
Можна налаштувати доступ з усіх ІР bind-address=0.0.0.0
sudo systemctl restart mysql
mysql -u root -p
В залежності від версії мускуля
# Створюжм нову БД CREATE DATABASE newdb character set utf8 collate utf8_bin; # Створюєм нового користувача з вказанням пароля CREATE USER 'bduser'@'10.0.0.2' IDENTIFIED BY 'hellomypass'; # або так CREATE USER 'bduser'@'10.0.0.2' IDENTIFIED WITH mysql_native_password BY 'hellomypass'; # всі права на БД користувачу GRANT ALL PRIVILEGES ON newdb.* TO 'bduser'@'10.0.0.2' WITH GRANT OPTION; GRANT CREATE, ALTER, DROP, INSERT, UPDATE, DELETE, SELECT, REFERENCES, RELOAD on *.* TO 'bduser'@'10.0.0.2' WITH GRANT OPTION; # обновити привілеї FLUSH PRIVILEGES; # якщо з віддаленого хоста не захоче приймати пасс тоді ALTER USER 'forsageu'@'10.0.0.2' IDENTIFIED WITH mysql_native_password BY 'hellomypass!';
Після чого з віддаленого сервера з IP 10.0.0.2 заходимо на віддалену БД *.0.3
mysql -u bduser -h 10.0.0.2 -p
Перевірити використовуючі порти netstat -lntp
Допоміжні статті magemastery.net devdocs.magento.com digitalocean computingforgeeks