Invision Community 4: SEO, prepare for v5 and dormant account notifications By Matt Monday at 02:04 PM
Popular Post Makoto Posted December 27, 2015 Popular Post Posted December 27, 2015 Nginx Server Installation Guide This is a guide for those interested in learning how to set up a secure, high performance Invision Power Suite installation using Nginx and PHP-FPM. Everything written here was done so with a focus on security, maintainability, and adherence to best practices. The information provided is the result of years of personal experience, research and testing. The steps listed have been tested to work on CentOS 7 and Debian Wheezy. If you run into any problems with your distribution, please submit as detailed of a report as you can below. Warning / Requirements This guide is intended for intermediate users and assumes you have at least a decent understanding of the Linux operating system. Please do not blindly attempt to run these commands on an active server. If you are replacing an existing Nginx installation, the easiest thing to do is make a backup of your configuration files, then purge/uninstall your existing Nginx installation before re-installing using the Nginx repository listed below.  Be responsible. Test locally before trying to set anything up in production. The information and resources below are provided "as is", with no guarantee of support, and without warranty of any kind. 1. Installing Nginx When installing Nginx on CentOS or Debian based systems, I recommend utilizing the official Nginx repository so you can keep up to date with the latest releases straight from the developers. Please follow the instructions on the official Nginx website to set this repository up on your system:http://nginx.org/en/linux_packages.html After importing the repository, go ahead and install Nginx. CentOS 7 yum install nginx Debian / Ubuntu apt-get update apt-get install nginx 2. Configuring Nginx Once you have Nginx up and running, you can move on to the configuration. Open /etc/nginx/nginx.conf and make sure it matches the following configuration, user nginx nginx; pid /var/run/nginx.pid; worker_processes auto; worker_priority -10; events { worker_connections 1024; } http { ## # Basic Settings ## default_type application/octet-stream; keepalive_timeout 30; sendfile on; tcp_nodelay on; tcp_nopush on; ## # Logging Settings ## log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; #access_log /var/log/nginx/access.log main; access_log off; error_log /var/log/nginx/error.log error; ## # Gzip Settings ## gzip on; gzip_disable "msie6"; 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/x-javascript text/xml application/xml application/xml+rss text/javascript; ## # Configuration Includes ## include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } Notice The "auto" worker_processes value is only supported in Nginx versions 1.2.5 (stable) / 1.3.8 (mainline) and up. If you are using an older version, you will need to manually specify a value instead. There are just a few things to note in detail here. First, we have changed our worker_processes from the default of 1 to auto. This will automatically assign workers equal to the number of cores your server has. Second, we have set the worker_priority of Nginx to -10. This is a small change that simply gives your web server higher CPU scheduling priority over other processes on your server. Finally, we have enabled the sendfile, tcp_nodelay and tcp_nopush directives to improve performance. 3. Structuring your Nginx configuration files If you're going to be managing your configuration files manually, it's particularly important to have a good, solid configuration structure in place. The default layout of your /etc/nginx directory may vary a bit depending on your distribution. I personally recommend setting up and using a basic structure like this: /etc/nginx/ ? conf.d - Global configuration directives to be loaded automatically when Nginx is started. ? mime_types.conf - Universal mime type associations for file extensions. ? includes - Common configuration snippets to be included in server or location blocks as needed. ? ips - Common configuration snippets designed for use on IPS installations. ? protect_upload_directories - Configuration include used to prevent execution of PHP scripts in writable upload directories. ? allow_only_admins - Configuration include used to restrict location block access to server administrators. ? cache_static_files - Contains a location block used to automatically apply cache headers to static resources. ? deny_dotfiles - Contains a location block used to deny requests to dotfiles (eg; .htpasswd). ? php_fastcgi_params - Basic FastCGI configuration for PHP-FPM. ? php_fpm_status - Contains a location block used for enabling admin only access to the php_fpm_status URI. ? stub_status - Contains a location block used for allowing admins to access basic information about the web server. ? ... - May also contain various other includes provided by Nginx and/or your distribution. ? scripts - Contains various helper scripts for common Nginx related tasks. ? create - Creates configuration and domain directories for a new virtual host. ? disable - Removes configuration symlinks for a single domain or a domain and all its subdomains. ? enable - Creates a configuration symlink for a specified domain. ? fixperms - Automatically sets/fixes file ACL permissions for a specified domain. ? provision - Run once after installing Nginx to rebuild the Nginx configuration directory. ? sites-available - Contains all available virtual host configurations. (Structure: sites-available/{domain}/{subdomain-or-root}.conf) ? default - Default/"localhost" configurations. ? root.conf - The default configuration used for unconfigured virtual hosts. ? sites-enabled - Contains symlinks to enabled virtual hosts in /etc/nginx/sites-available, (Structure: sites-available/{domain}) ? default -> /etc/nginx/sites-available/default/root.conf - Default virtual host. ? ssl - Contains SSL keys and certificates for virtual hosts. Keys should be owned by root:nginx with no public access (chmod 0640). ? nginx.conf - The primary Nginx configuration file. Info You won't need to reconfigure everything above manually. A helper script will be provided at the end which can automatically provision everything for you. If you've worked with Apache before, you should feel pretty at home with this setup. You store configurations for virtual hosts in sites-available, then create symlinks to those configuration files in sites-enabled to actually enable them. To provide a quick example, here is how you would enable a virtual host manually (you won't need to do this manually if you use the helper scripts, but you should still know how), $ ln -vs /etc/nginx/sites-available/example.org/root.conf /etc/nginx/sites-enabled/example.org $ ln -vs /etc/nginx/sites-available/example.org/foo.conf /etc/nginx/sites-enabled/foo.example.org In sites-available, every domain has its own directory. Inside those directories are the virtual host configurations relevant to that domain, which are named by their subdomains (or "root" for www/no subdomain). When symlinking configurations in sites-enabled, you just use the raw domain name for the symlinks filename. $ ls -l /etc/nginx/sites-enabled/ lrwxrwxrwx. 1 root nginx 44 Dec 20 11:23 example.org -> /etc/nginx/sites-available/example.org/root.conf lrwxrwxrwx. 1 root nginx 44 Dec 20 11:23 foo.example.org -> /etc/nginx/sites-available/example.org/foo.conf $ rm -i /etc/nginx/sites-enabled/foo.example.org rm: remove symbolic link `/etc/nginx/sites-enabled/foo.example.org'? y This way, you get the best of both worlds. When you want to see which domains are enabled, you can just list the /etc/nginx/sites-enabled directory and everything is displayed in one place. When you need to review the virtual hosts for a domain, your configuration files remain efficiently categorized for sorting. I've written a script that will automatically provision your Nginx directory using the above structure, so you shouldn't need to do any of this manually. To get things rolling, just run the following commands, cd /etc/nginx/ wget https://github.com/FujiMakoto/nginx-helpers/releases/download/v0.1/scripts.tar.gz tar -xzvf scripts.tar.gz rm -f scripts.tar.gz /etc/nginx/scripts/provision After running the provisioner, you should be left with a setup roughly identical to the one above. If you have vim installed prior to running the provisioner, you will also be prompted to automatically download and install syntax highlighting for Nginx configuration files. This is a very nice feature to have if you're a vim user. Once you have everything provisioned, go ahead and restart Nginx and try and access your servers IP address through your web browser. You should see a generic Nginx welcome page. If you don't / if you get an error when restarting nginx, make sure you've updated the nginx.conf configuration properly and try again. 4. Creating your first virtual host Now that you have a good configuration structure to work with, we can move on to creating our first IPS virtual host. To start, go ahead and set up a new directory for your domain name (naturally replacing yourdomain.com with your actual domain name), mkdir /etc/nginx/sites-available/yourdomain.com Next, go ahead and create a configuration file in the directory you made above. This should be named root.conf if your IPS installation is located on yourdomain.com / www.yourdomain.com, otherwise use the subdomain as the filename (for example, use community.conf for community.yourdomain.com). Inside of this file, insert the following configuration template, upstream php_backend { server unix:/var/run/php-fpm_webapp.sock; } server { # Basic server configuration listen 80; server_name yourdomain.com www.yourdomain.com; root /srv/http/yourdomain.com/root/html; index index.php; # Maximum allowed upload size client_max_body_size 100M; # Logging #access_log /srv/http/yourdomain.com/root/logs/access.log.gz combined gzip flush=5m; error_log /srv/http/yourdomain.com/root/logs/error.log error; # Friendly URL "rewrite" rules location / { try_files $uri $uri/ @ips; } # Configuration includes include /etc/nginx/includes/ips/protect_upload_directories; include /etc/nginx/includes/deny_dotfiles; include /etc/nginx/includes/stub_status; include /etc/nginx/includes/php_fpm_status; # Assign cache headers to static files location ~* ^.+\.(?:jpg|jpeg|gif|css|png|js|ico|xml|htm|swf|cur)$ { # If the static resource doesn't exist, pass off to IPS' 404 handler try_files $uri @ips404; access_log off; expires 2w; } # Lock down access to the AdminCP location ~ ^/admin/.+\.php$ { #allow 127.0.0.1; #deny all; #auth_basic "This page is restricted to administrators"; #auth_basic_user_file $document_root/admin/.htpasswd; try_files $uri @ips404; include /etc/nginx/includes/php_fastcgi_params; fastcgi_pass php_backend; } # Execute the requested PHP script if it exists, otherwise pass off to IPS location ~ \.php$ { try_files $uri @ips; include /etc/nginx/includes/php_fastcgi_params; fastcgi_pass php_backend; fastcgi_buffers 38 4k; fastcgi_buffer_size 16k; } # Pass off not found errors to IPS' 404 handler location @ips404 { include /etc/nginx/includes/php_fastcgi_params; fastcgi_pass php_backend; fastcgi_param SCRIPT_FILENAME $document_root/404error.php; fastcgi_param SCRIPT_NAME 404error.php; } # Send rewritten requests directly to IPS location @ips { include /etc/nginx/includes/php_fastcgi_params; fastcgi_pass php_backend; fastcgi_param SCRIPT_FILENAME $document_root/index.php; fastcgi_param SCRIPT_NAME /index.php; fastcgi_buffers 38 4k; fastcgi_buffer_size 16k; } } Virtual host configuration There are naturally some things you will need adjust here. We'll go through these in the order of which they appear. Once that's out of the way, we'll explain a bit how everything you see works. Server Name This one is obvious. Replace yourdomain.com with your actual domain name. If you are using a root level domain, be sure you add both the www/non-www variants. Root This, as you've probably already figured out, is the root path to your IPS installation. I recommend storing all of your applications in /srv/http and keeping to a/srv/http/{domain}/{subdomain} directory structure (similar to how our Nginx configuration files are managed). Client Max Body Size Self-explanatory. You should adjust this value to at least the maximum upload size you allow in IPS. You will need to remember to keep this value in sync with PHP's configured max_upload_size as well, otherwise your uploads will end up restricted to whichever setting is the lowest. AdminCP Location If you have renamed your AdminCP by following the instructions in the IPS security center, you will need to replace "admin" in the admin location block with the actual name of your admin directory. You can also enable IP based restrictions in this location block by uncommenting the allow and deny lines. You'll probably want to go ahead and add your local IP address as an allow line now if you do this. You can also set up .htpasswd based restrictions with the other two lines. For more information on how to do that, follow the instructions listed here.  "Rewrite" rules and named location blocks Quite often, when looking up guides or examples for Nginx PHP configurations online, you'll see examples that simply pass every request ending with .php to FastCGI/PHP-FPM and be done with it. Don't do this, it is really a bad way to configure your server. Most prominently because it opens the potential for a serious security vulnerability, and while modern releases of PHP-FPM protect against this vulnerability by default, it only exists as a protection for misconfigured web servers. You shouldn't rely on it. By taking full advantage of Nginx's named location blocks and try_files processing, we are able to provide a clean and elegant configuration layout that is both secure and fast. In order to really understand how everything here works in detail, you'll need to dig into Nginx's documentation and familiarize yourself with how the location and try_files configuration directives work. Configuration Includes When running the provisioner script provided above, you'll automatically download a few simple but useful include files for Nginx. You can also also access them directly online here, each include file provides a bit of documentation explaining what it's for. In summary, the four includes we use here provide IPS' "Protect Writeable Folders From Dangerous Files" security recommendation for Nginx, block browser access to dotfiles (which is very important if you store a .htpasswd file in your AdminCP directory for HTTP authentication), and finally enable access to the ngx_server_status and php_fpm_status pages for registered server administrators. 5. Setting up your web directory Now that we have a working virtual host for our IPS installation, it's time to set it up. As I mentioned above, I recommend storing your web files in /srv/http. Naturally, you don't have to do it that way. You are free to store your installations wherever you want, it will just require some additional work on your part to set everything up if you do use a different location. Why not /var/www? /var/www is a common place for http data to be stored, mostly because it is usually the default configured path for Nginx and Apache. However, while this is often the usual place for web data, it's not actually a standardized configuration. /var is best reserved (as its name implies) for variable files which change over time, such as log files. Why not /home/user/public_html? This setup is actually fine for shared hosting environments and may make the most sense in such a situation. However, there's no reason to use it outside of that. From a security perspective, I would also advise against hosting your IPS installation under your primary user account. In the absolute worst case scenario that your SSH credentials are compromised and you've followed this guides recommendations (also assuming you have a properly configured server), your installation files and data would still be protected. Why /srv/http? I personally use and recommend /srv/http as it is FHS compliant. The /srv directory is the only standardized directory specifically made for hosting service files like this. If you are already used to another way of doing things and don't want to change, you are again free to use whatever kind of configuration you like.  We can use another helper script to take care of constructing the web directories for us, but if you decide not to use the default /srv/http path, you will need to edit the script below and modify HTTP_BASEDIR accordingly. Once that's done, go ahead and copy your IPS installation files into the html directory. mkdir -p /srv/http /etc/nginx/scripts/create yourdomain.com root 6. Locking down access to your web directory Optional While strongly recommended, it is not required that you follow the steps listed here. If you prefer not to (or are for some reason unable to) take advantage of ACL's, you will simply be responsible for setting up and managing permissions on your own. While outdated, you can still use the old Nginx+PHP-FPM server guide here as a reference for setting up decently secure UNIX permissions. In this step, I will be explaining how to set up and configure ACL (Access Control List) permissions for your web directories. If this is new to you, it may be a bit difficult to grasp at first, but I recommend sticking with it. ACL's are an incredibly powerful tool to have and make managing secure file permissions a lot easier in the long run. Go ahead and make sure the ACL utilities are installed now, they should be available through the acl package on most distributions. Next, test to make sure acl is enabled on your filesystem, touch acl_test setfacl -m "u:nginx:r--" acl_test getfacl acl_test rm acl_test If all is well, the above commands should run without error and you should see "user:nginx:r--" in the output returned by getfacl. If you do get an error, you likely need to enable acl on your filesystem now. To do this, replace /dev/sdXY in the command below with your actual filesystem device (e.g. /dev/sda1) and then try repeating the previous commands after, mount -o remount,acl / tune2fs -o acl /dev/sdXY Once you've confirmed acl's are working, you can go ahead and set the permissions for your IPS installation. Again, as long as you've configured Nginx using the provisioner script above, you will have access to a helper script to assist in doing this, /etc/nginx/scripts/fixperms yourdomain.com root After running the above command, you will be asked to provide a user for file ownership in your web directory. You can use whatever makes most sense to you here, a shortened version of your IPS communities name is a good example choice. Unless you plan on setting up and running multiple web applications under different PHP-FPM pools, it's reasonable to leave the default for the PHP-FPM user. When prompted for files to grant PHP modification access to, you should input conf_global.php only if this is a new IPS installation. Otherwise, leave this blank. When prompted for directories to grant PHP recursive write access to, input applications/ datastore/ plugins/ uploads/ $ /etc/nginx/scripts/fixperms yourdomain.com root What user do you want to grant file ownership to? webapp What user does PHP-FPM run under for this virtual host? www-data Which individual files/directories should PHP be granted write access to? conf_global.php Which directories should PHP be granted recursive write access to? applications/ datastore/ plugins/ uploads/ Making sure all files and directories are owned by webapp Setting directory permissions to 0750 Setting file permissions to 0640 Setting default permissions for new files Granting Nginx user read-only access to all files and directories Granting PHP-FPM user read-only access to all files and directories Granting PHP-FPM user write access to conf_global.php Granting PHP-FPM user recursive write access in applications/ Granting PHP-FPM user recursive write access in datastore/ Granting PHP-FPM user recursive write access in plugins/ Granting PHP-FPM user recursive write access in uploads/ All site permissions updated successfully In the example above, first, we've set it so that everything in our web root is owned by the webapp user. Furthermore, permissions on all files and directories have been set in a way that completely prevents public access. This means that, at this point, no user other than webapp can see or read anything inside the web root. This is where we start using acl permissions. First, we run the following commands to grant the Nginx and PHP-FPM users read-only access to everything in our web directory, # Nginx setfacl -R -m "u:nginx:r-X" /srv/http/yourdomain.com/root setfacl -R -d -m "u:nginx:r-X" /srv/http/yourdomain.com/root # PHP-FPM setfacl -R -m "u:www-data:r-X" /srv/http/yourdomain.com/root setfacl -R -d -m "u:www-data:r-X" /srv/http/yourdomain.com/root The first commands (without the -d/--default flag) set the permissions on all existing files and directories. The second commands set the default permissions on all directories. This means any new files created inside your web directory will now automatically inherit the permissions you've configured. After that, we repeat the above commands for PHP-FPM (but with rwX permissions) in order to grant PHP write access to only the required files and directories. Note also that we use a capital X here when applying permissions recursively, that way only directories are made executable. With the following setup, you should never have a reason to use chmod 777 for anything. Furthermore, chmod 777 will also no longer work, as the ACL permissions for PHP-FPM will override it. You should instead use setfacl to set/remove permissions for PHP, # Make a file writable setfacl -m "u:www-data:rw-" conf_global.php # Make a file read-only setfacl -m "u:www-data:r--" conf_global.php # Recusrively make a directory and its contents writable setfacl -R -m "u:www-data:rwX" uploads/ setfacl -R -d -m "u:www-data:rwX" uploads/ # Recursively make a directory and its contents read-only setfacl -R -m "u:www-data:r-X" uploads/ setfacl -R -d -m "u:www-data:r-X" uploads/ For a good general overview of the acl utility commands and how they work, check out the Arch Wiki and Debian / CentOS documentation pages. For a more in-depth understanding of how setfacl works, read the manpages. 7. Installing and configuring PHP-FPM Finally, it's time to install and configure PHP-FPM. Go ahead and install the required packages now, CentOS 7 yum install php-fpm php-cli php-mysqlnd php-pdo php-gd php-mbstring php-xml # Only required if you use Imagick (which I recommend using over GD) yum install php-devel php-pear ImageMagick* pecl install Imagick echo "extension=imagick.so" > /etc/php.d/imagick.ini Debian / Ubuntu apt-get update apt-get install php5-fpm php5-cli php5-mysqlnd php5-curl php5-gd php5-imagick php5-json php5-mcrypt Afterwards, go ahead and delete the default PHP-FPM pool, as we will be replacing it with our own, CentOS 7 rm /etc/php-fpm.d/www.conf nano /etc/php-fpm.d/webapp.conf Debian / Ubuntu rm /etc/php5/fpm/pool.d/www.conf nano /etc/php5/fpm/pool.d/webapp.conf Inside of this file, insert the following configuration template, [webapp] ;;;;;;;;;;;;;;;;;;;;; ; FPM Configuration ; ;;;;;;;;;;;;;;;;;;;;; ; Basic settings prefix = /var/run user = www-data group = www-data listen = php-fpm_webapp.sock listen.owner = www-data listen.group = www-data listen.mode = 0660 ; Process manager configuration pm = dynamic pm.max_children = 8 pm.start_servers = 2 pm.min_spare_servers = 2 pm.max_spare_servers = 4 pm.max_requests = 500 pm.status_path = /php_fpm_status ; Log slow requests (used for performance tuning, 0 = Off) request_slowlog_timeout = 0 slowlog = /srv/http/yourdomain.com/root/logs/php_slow.log ; Terminate unresponsive requests, this should match PHP's max_execution_timeout at a minimum request_terminate_timeout = 30s ; Don't allow executing arbitrary files as PHP scripts. YOU SHOULD NEVER DISABLE THIS. security.limit_extensions = .php ;;;;;;;;;;;;;;;;;;;;; ; PHP Configuration ; ;;;;;;;;;;;;;;;;;;;;; ; Make sure errors are not displayed publicly, error logging can be enabled as needed php_flag[display_errors] = off php_admin_flag[log_errors] = off php_admin_value[error_log] = /srv/http/yourdomain.com/root/logs/php_error.log ; Set the maximum upload size, memory limit and execution timeout php_admin_value[upload_max_filesize] = 100M php_admin_value[post_max_size] = 100M php_admin_value[memory_limit] = 128M php_admin_value[max_execution_time] = 30 ; PHP security directives, adjust open_basedir appropriately php_admin_value[cgi.fix_pathinfo] = 0 php_admin_value[disable_functions] = exec,system,popen,proc_open,shell_exec php_admin_value[open_basedir] = /tmp/:/usr/bin/:/srv/http/yourdomain.com/root/html/ As usual, go ahead and replace all references to yourdomain.com accordingly. If you allow uploads larger than 100M, you'll also want to tweak the upload_max_filesize and post_max_size PHP values. The main thing we want to look at here is the process manager configuration. There are three ways you can configure the process manager; static, dynamic, and ondemand. You can use whichever makes the most sense to you, but you'll likely be needing to watch and tune these settings a bit no matter which you choose, so there's no harm in experimenting with different configurations. Regardless of which you use, it's very important you don't try and set pm.max_children to a higher value than your server can handle. In the brief amount of profiling I could perform on IPS4 prior to writing this guide, my tests indicated that the average pool memory consumption for a mostly stock IPS install was around 32M per process. With the above configuration, this means that with all 8 children in use, PHP would be utilizing approximately 256M of memory. So, when tuning this value, you need to factor in how much memory you have know you can dedicate entirely to PHP. In the above example, you would need to dedicate at least 256MB to PHP with a bit of margin for error. This is what you should be doing for everything on your server. Also consider that 32M is only an example, the actual average memory requirement will vary from setup to setup, so it would be a good idea to do a bit of profiling yourself. As a final note, even if you have massive amounts of memory on hand, you still shouldn't set this value absurdly high. It can do more harm than good. Memory restrictions aside, a good starting value would probably be the number of cores your server has * 2. So, for a quad core server, 8 children would probably be a good starting point. If your community hosts a lot of attachments and handles a lot of PHP file transfers, you'll probably want to increase this value. Finding an optimal value here will take a bit of trial and error.  So, what about Static? Good for very high traffic websites Static is the PM configuration I used for a long time. It's dead simple. With static, you don't need to specify start_servers, min_spare_servers or max_spare_servers. You just provide a number of child processes to spawn and they are all immediately spawned and kept alive and ready to handle requests at any moments notice. This sounds nice considering what I mentioned above. It offers better FPM performance, and since you're already dedicating that memory to PHP anyways, who cares if that memory is always in use? While there is a bit of truth to that, I probably would not recommend static for most installations anymore. I consider static particularly good for high traffic websites, or websites that receive a lot of very heavy intermittent traffic spikes. For most low to moderate traffic communities, I am more likely to recommend dynamic, and I explain why in more detail below.  So, what about Dynamic? Good for moderate and low traffic websites Dynamic is probably the most common configuration. It's the middle ground between static and ondemand. With this setup, PHP always keeps a set number of child processes spawned and ready to handle incoming traffic. New child processes are spawned as traffic increases, old processes are destroyed as traffic lowers again. This is great for most web applications, as it avoids wasting memory. While you still should always tune assuming all processes are in use, keeping the unused processes cleaned up gives more free memory to the server, which can in return be used for disk caching to improve overall server performance. Dynamic also helps better protect against memory leaks. As unused processes are killed off, there's naturally less risk of memory leaks eating away at your memory pool. pm.max_requests normally helps protect against this, but it becomes less effective the more processes you keep spawned.  So, what about Ondemand? Good for low traffic websites As its name implies, ondemand only spawns child processes on demand. This is similar to dynamic, however unlike with dynamic, ondemand does not keep any unused child processes active. When a request is made that spawns a new child process, a timeout is set. If no further requests are sent to that process within the timeout window, the process is destroyed. This could be beneficial for low traffic websites (particularly those on more memory constrained VPS'), but outside of that, there's probably not much of a reason to use it. Even for low traffic websites, keeping a small number of child processes spawned to handle new requests is usually good for performance.  Wrapping up Once you have PHP-FPM configured, it's finally time to test everything out. Go ahead and enable your new virtualhost now, /etc/nginx/scripts/enable yourdomain.com root systemctl restart {nginx,php-fpm} Assuming no errors are returned, try and visit your community in your web browser. If all has gone well, you're done! If not, check your error logs, review your configuration, make sure permissions are properly applied, and make sure you have all the required PHP packages installed. If you still have problems, don't be afraid to ask for help, just be sure to provide a detailed description of your problem and include any relevant error log entries when doing so! Did you find this guide useful? You can show your support by sending a small tip, or by buying and reviewing one of my marketplace submissions! If that's not an option for you, you can also just tell me I'm awesome or something. Prank, David.., Stirbu Daniel and 44 others 38 9
RevengeFNF Posted December 27, 2015 Posted December 27, 2015 (edited) @Makoto excellent tutorial, i give you my congratulations Just a quick note that i think you could add to this tutorial. If someone install's Centos 7 and then follows this tutorial, they will be installing PHP 5.4 which is currently EOL, and therefore no more security updates. Because this tut is all about security, i think the minimum version should be php 5.5. So, you could add the instructions for installing Epel and Remi repo(its stays disabled by default), for example, and then the Yum command would be instead: yum --enablerepo=remi,remi-php56 php-fpm php-cli php-mysqlnd php-pdo php-gd php-mbstring php-xml. If someone wants to try php 7.0, just change to remi-php70. With the Remi repo we can also install php-pecl-imagick instead of using the pecl install. Edited December 27, 2015 by RevengeFNF Skipy7, sofos and SJ77 1 2
MHPro Posted January 1, 2016 Posted January 1, 2016 Thanks for the big update! Hope it'll work now without problems.
icedream Posted January 7, 2016 Posted January 7, 2016 Thanks, how should I configure php session filepath and opcache filepath, I am not totally understanding about the acl. And if I add microcache for nginx, what permission should I set for cache_path and tmp_path?
Bliblou Posted January 26, 2016 Posted January 26, 2016 (edited) There is a tutorial for conf when forum is in directory ? Because, here, it's for website with only IPS4 ! Tks EDIT : Hum. It's maybe possible if you change Root line. hum my fault Edited January 26, 2016 by Bliblou
Sull5 Posted January 30, 2016 Posted January 30, 2016 Thanks for the guide very informative. I've run into a bit of a permission issue I'm hoping you can shed some light. If I run your fixperms script, all is good except when I go to upgrade an application, since the files and folders are owned by webapp:webapp I'll get a permission error. 0: Extraction from phar "/tmp/phpZ2rgSN.tar" failed: Cannot extract "Application.php" to "applications/cjmenu/Application.php", setting file permissions failed if I set the user:group recursively on applications/cjmenu to www-data:www-data the application will upgrade without a hitch. I thought we shouldn't have an issue since www-data has read and write access through acl ? here is the output from getfacl applications/ # file: applications/ # owner: webapp # group: webapp user::rwx user:www-data:rwx user:nginx:r-x group::r-x mask::rwx other::--- default:user::rwx default:user:www-data:rwx default:user:nginx:r-x default:group::r-x default:mask::rwx default:other::--- Please I'd really like to know why this is happening ? jpg 1
Makoto Posted January 30, 2016 Author Posted January 30, 2016 On 1/7/2016 at 1:05 AM, icedream said: Thanks, how should I configure php session filepath and opcache filepath, I am not totally understanding about the acl. And if I add microcache for nginx, what permission should I set for cache_path and tmp_path? Unless you have a reason to, there's really no reason you should need or want to change the default session/opcache filepaths. Regarding microcache, I haven't actually used that as of yet, but I imagine that's also something that is just written to tmp and is owned by Nginx on write? You'll have to review the documentation yourself on that one. On 1/26/2016 at 4:13 AM, Bliblou said: There is a tutorial for conf when forum is in directory ? I'm sorry, I have no idea what you are asking. If you still need help, can you please clarify what the problem / question is..? 17 hours ago, Sull5 said: If I set the user:group recursively on applications/cjmenu to www-data:www-data the application will upgrade without a hitch. I thought we shouldn't have an issue since www-data has read and write access through acl ? Are you upgrading using IPS4's FTP upgrader? Naturally, if you are using FTP, your FTP user will need read/write access to the files as well. Ideally, if you can, you should just set up an FTP account for the webapp user and utilize that account for upgrades.
Sull5 Posted January 30, 2016 Posted January 30, 2016 18 minutes ago, Makoto said: Unless you have a reason to, there's really no reason you should need or want to change the default session/opcache filepaths. Regarding microcache, I haven't actually used that as of yet, but I imagine that's also something that is just written to tmp and is owned by Nginx on write? You'll have to review the documentation yourself on that one. I'm sorry, I have no idea what you are asking. If you still need help, can you please clarify what the problem / question is..? Are you upgrading using IPS4's FTP upgrader? Naturally, if you are using FTP, your FTP user will need read/write access to the files as well. Ideally, if you can, you should just set up an FTP account for the webapp user and utilize that account for upgrades. I'm talking about upgrading 3rd party applications. not actually upgrading the suite.Â
Makoto Posted January 31, 2016 Author Posted January 31, 2016 Oh, it should work then, yes. What are the acl permissions on applications/cjmenu/Application.php? PHP-FPM is running as www-data as well, right?
Sull5 Posted January 31, 2016 Posted January 31, 2016 40 minutes ago, Makoto said: Oh, it should work then, yes. What are the acl permissions on applications/cjmenu/Application.php? PHP-FPM is running as www-data as well, right? getfacl on applications/cjmenu # file: applications/cjmenu # owner: webapp # group: webapp user::rwx user:www-data:rwx user:nginx:r-x group::r-x mask::rwx other::--- default:user::rwx default:user:www-data:rwx default:user:nginx:r-x default:group::r-x default:mask::rwx default:other::--- getfacl on applications/cjmenu/Application.php # owner: webapp # group: webapp user::rw- user:www-data:rw- user:nginx:r-- group::r-- mask::rw- other::rw- and yes php5-fpm is running under www-data Any application gives the same error. Except if I apply the owner:group to www-data recursively to applications/ Â
Sull5 Posted February 2, 2016 Posted February 2, 2016 On 1/31/2016 at 4:10 PM, Makoto said: Oh, it should work then, yes. What are the acl permissions on applications/cjmenu/Application.php? PHP-FPM is running as www-data as well, right? Thoughts on the issue ?
Makoto Posted February 3, 2016 Author Posted February 3, 2016 7 hours ago, Sull5 said: Thoughts on the issue ? I'm actually able to reproduce this, but I'm not sure if there's a solution. It only happens when upgrading applications, not installing. The error is caused because PHP is (intentionally) not allowed to change permissions on files it overwrites when they are not owned by www-data. This, in turn, causes PHP's Phar library to throw a fit and abort. It's actually irrelevant, ACL permissions make it where PHP doesn't need to handle permissions on its own, but PHP doesn't seem to care or offer any simple way to get around it that I can see. If it can't set permissions on files extracted with Phar, it will abort. The simple short term solution is to manually change the file ownership of the applications you're upgrading, I'll see if I can provide a more official workaround in the future however. jpg 1
Morgin Posted February 5, 2016 Posted February 5, 2016 @Makoto, this is kind of off-topic, but 1) Love this guide, and when I've got enough time set aside to test an upgrade and go through in production, I'm sure this will be super helpful as someone with (very) limited server admin experience (I followed enough guides to get a secure LAMP stack up to run IPB, but that's it). So first off, thanks for taking the time 2) Any chance you would be willing to do a short summary of what a dedicated IPS server might also have installed by way of mariadb (and version), php (and version), any specific thoughts on php functions to disable/enable, which php accelerator to use, etc etc etc. Kind of "hey, once you've followed a guide to setting up a VPS and followed the guides on securing your admin user and getting fail2ban and other recommended stuff installed to make it safe, here's your LEMP stack specifically tuned for IPS 4". That's a big ask, but you seem to be the active admin with tips around here, so figured I'd ask
BomAle Posted February 14, 2016 Posted February 14, 2016 @Makoto could you help me with rewrite url like: http://mysite.com/forum/forum/19-title-1/ http://mysite.com/forum/files/ http://mysite.com/forum/19-title-1/ don't touch this... this is ips4 url thing see @https://regex101.com/r/qY5lW3/4 onto nginx rules? Thanks for any replies #tested #1---------- location ~* ^/forum/(?![0-9]+\-.+).*$ { rewrite ^/forum/(?![0-9]+\-.+)(.*)$ /$1; } location / { try_files $uri $uri/ /index.php; } 2---------- location / { try_files @rules $uri $uri/ /index.php; } location @rules { rewrite ^/forum/(?![0-9]+\-.+)(.*)$ /$1 break; } not work for me
BomAle Posted February 20, 2016 Posted February 20, 2016 I have solved with rewrite ^/forum/(?![0-9]+\-.+)(.*)$ /$1 permanent; bye
yacenty Posted February 21, 2016 Posted February 21, 2016 is it possible to create a subdomain to graphic static files? to put there files like /forum/uploads? skins and so on? regards
btcdtc Posted February 28, 2016 Posted February 28, 2016 (edited) Great tutorial, thanks Edited February 28, 2016 by btcdtc
ASTRAPI Posted February 29, 2016 Posted February 29, 2016 Quote is it possible to create a subdomain to graphic static files? to put there files like /forum/uploads? skins and so on? Not flexible and it will not give any significant performance gain
twisted89 Posted March 1, 2016 Posted March 1, 2016 Could someone provide an example .conf for loading the forum under the /forum/ subdirectory I can't seem to get the rewrites working at all. Thanks.Â
Vinlockz Posted April 7, 2016 Posted April 7, 2016 Hello, I have read through all of this. I am unsure of what to pick out for my problem. I purchased a Dedicated Virtual Server from Media Temple. The rewrite refuses to work on NGINX :(. Everything, server wise, is all already set up and installed. I just need to know what extra to put into the Plesk 12.5 "Additional nginx directives". Image: My domain is www.pvpallday.com and my forum is at www.pvpallday.com/forum Please tell me the snippet that needs to go here. I tried pasting everything you put into there, i picked at it from what seemed like would redirect the clean URLs... I've looked all over, pasted and modified and edited and etc as much as I can. i even went as far as to use an onine convertor from htaccess to nginx, from the provided htaccess that IPB gives in the Admin CP... I am at a loss of ideas now. Please @Makoto or anyone, you seem to know what you're talking about better than any articles i have found online. Please help  Thank You.
jpg Posted April 13, 2016 Posted April 13, 2016 On 2/3/2016 at 1:21 PM, Makoto said: The simple short term solution is to manually change the file ownership of the applications you're upgrading, I'll see if I can provide a more official workaround in the future however. I don't really have any problem with this, is a minor temporary change to chown -R an application folder, and it's an extra layer of confirmation/security before upgrading an application.
Makoto Posted May 3, 2016 Author Posted May 3, 2016 5 hours ago, Jimmy Gavekort said: Offtopic, how did you make this fancy design? My guides are written using a template I purchased from ThemeForest a while back. You can find it here,http://themeforest.net/item/vsdocs-online-documentation-template/11418861 Eventually I'll have posts/guides like this compiled and posted somewhere online, instead of only available as post snippets here. This is also the template I use to write the readme's included with my newer applications, such as Bulk Downloader,https://www.makoto.io/docs/bulkdl/index.html tjk 1
Recommended Posts