Hi!
I am preparing a Mag2 setup that will have about 1000 unique visitors per day.
I like simple setups, only tweak when needed but security and performance are important.
Ingredients so far:
- A 2GB VPS with SSD-cached IO
- Centos 7, with firewalld and SELinux enabled
- MariaDB 10, Apache 2.4, PHP 7.0 (all from the iuscommunity.org repository)
- Nginx in front of Apache to increase security, save memory, handle A+ grade SSL and cache static files
- Magento 2: running in default mode, no tweaks whatsoever
Config:
- DocumentRoot: magento2/pub during normal operations, magento2 when upgrading
- I lowered Apache MaxRequestWorkers to 15 (php running in prefork) to avoid memory thrashing
- SELinux switched off during upgrades, otherwise only allowing write access to /var, /app/etc, /pub/media and /pub/static
- MariaDB: max_allowed_packet=32M and query_cache_size also 32M
- Nginx caches static files for 1 month, but I will cleanup the cache directory with every Magento upgrade. Access is logged in Apache only
I am counting on that my nginx config will save the day and allow good performance on an el cheapo 2GB VPS, caching all static files using the built in proxy_cache. Apache is running on port 8008 (SELinux default for second http server).
Here is my nginx .conf file:
proxy_cache_path /usr/share/nginx/html.example/nginxcache levels=1:2 keys_zone=STATICS:120m inactive=1M max_size=10G; proxy_cache_key "$scheme$request_method$host$request_uri"; server { listen 80; listen [::]:80; server_name www.example.com example.com; location '/.well-known/acme-challenge' { default_type "text/plain"; root /usr/share/nginx/html.example/letsencrypt-auto; } location / { return 301 https://www.example.com$request_uri; } } server { listen *:443 ssl; listen [::]:443 ssl; server_name www.example.com; root /usr/share/nginx/html; access_log off; ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.1 TLSv1; ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES1 28-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE- DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SH A:!KRB5-DES-CBC3-SHA'; ssl_prefer_server_ciphers on; ssl_dhparam /etc/nginx/ssl/dhparams.pem; add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"; ssl_session_cache shared:SSL:20m; ssl_session_timeout 10m; location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 120; proxy_pass http://localhost:8008; proxy_cache STATICS; proxy_cache_valid 200 301 302 1M; proxy_cache_valid 404 1m; } location /static { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 120; proxy_pass http://localhost:8008; proxy_cache STATICS; proxy_cache_valid 200 301 302 1M; proxy_cache_valid 404 1m; proxy_ignore_headers Set-Cookie; proxy_ignore_headers "Cache-Control"; proxy_ignore_headers "Expires"; } location / { proxy_set_header X-Real-IP $remote_addr; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_read_timeout 120; proxy_pass http://localhost:8008; } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
Any input on how I can further improve this setup is highly appreciated. But I need to keep it simple, one of the reasons I use Letsencrypt SSL, do not use Varnish and run Magento 2 in default mode.
Hi there,
any reasons you do not use Varnish? there are more qualified people on this forum to review your setup but our server admins always configure client's Magento 2 stores with Varnish. I do not think there is any better way to have first-time byte of Magento 2 store under 0.15 sec. and this is the main server related parameter Google is monitoring for SEO and I would consider a successful Magento setup (after all your security is in place, of cause).
Thanks for your reply!
Just trying to keep things simple I guess, nginx can do both SSL and caching while Varnish is good for caching only, I have no need for load balancing (yet).
But I can see that Varnish is "best practice" and the setup with Magento seems to be very straight forward. Would Varnish still be helpful if media and static files are cached by a CDN?
Yes, caching system like Varnish or LiteMage Cache are still very useful even if the static files are cached by a CDN.
Ideally you should have both of them running and they shouldn't complicate your setup too much if configured properly.
if you really need to save resources and gain some speed and you have very small server, like up to 3 cores, and very low RAM
do not waste your time building too extraordinary configuration.
install HHVM as backend for Apache or Nginx (do not mix them together, there is no gain at all)
you will have some space to grow.