edgecase_datafeed 118 2019-09-29 This is the date at the time of creation of this datafeed article. A checkpoint article containing a hash of this datafeed article may be created on this date or at a later date. 106 8 2019-04-27 bitcoin cd3f7f4c5d2b44dd03ad0ad59109376aaabe13d81acdac1700d374086fc920c0 573429 1HtwyqFWNVDoSEVqZwjBRRAV2oEsi8aQXr 16awNgyNAoqjhVjenPGZY8QZtKQKHgzwJa
Hello_World_on_a_server_(DigitalOcean,_Nginx,_Gunicorn,_Python) stjohn_piano 2019-09-29 yes GOAL Set up an online server and get it to return "Hello World" in response to an HTTP request. Components: DigitalOcean (a cloud server provider), Nginx (a web server), Gunicorn (a Python WSGI web server), and Python (a programming language). CONTENTS - Goal - Contents - Brief Summary - Summary - Notes - Project Log BRIEF SUMMARY Hello World achieved. Encountered some difficulty configuring Nginx to a) serve a static file containing "hello world" b) to connect to Gunicorn, both of which turned out to be mainly due to SELinux permission settings. SUMMARY Hello World achieved. Encountered some difficulty configuring Nginx to a) serve a static file containing "hello world" b) to connect to Gunicorn, both of which turned out to be mainly due to SELinux permission settings. Steps taken: - Studied the utility of using Nginx as a reverse proxy in front of Gunicorn. Essentially, this utility is the fact that Nginx handles the slow client problem by buffering requests until they're completed. - Created a new VPS (running CentOS 7.6 x64) on DigitalOcean, with ssh access from my local workstation Shovel. I set the domain edgecasesystems.com to point to this VPS. - Studied some of the main differences between Apache and Nginx. - Using the Yum package manager: -- I installed the CentOS 7 EPEL repository (version 7-11). -- I installed Nginx (version 1.12.2). --- This included integration with systemd, so that commands such as systemctl start nginx work. I enabled Nginx via systemctl enable nginx and confirmed that it starts on boot by power cycling the VPS. - I browsed to http://edgecasesystems.com, which displayed the default Nginx welcome page, located at /usr/share/nginx/html/index.html. - I chose: /srv/edgecase/www as my root directory for web content. - Studied some basics of Nginx configuration. -- The command nginx -t will check nginx.conf for syntax errors. -- I needed Nginx to load various new configurations. The command systemctl reload nginx did not work. The command systemctl restart nginx did. -- The access log and error log file paths are set in the Nginx configuration file /etc/nginx/nginx.conf. By default, they were /var/log/nginx/error.log and /var/log/nginx/access.log. I read the most recent error / access via tail e.g. tail -1 /var/log/nginx/error.log. - I created a text file containing "hello world" in /srv/edgecase/www and configured nginx to serve it (and to use it as an index page). However, when I browsed to http://edgecasesystems.com/test.txt, I got a 403 Forbidden error. Some research showed that it was probably due to a default SELinux restriction that prevents webservers accessing anything outside particular directories such as /var/www. - I created a text file containing "hello world" in /var/www/edgecase/basic to see if working from /var/www would solve the problem. I changed the Nginx configuration to match. However, I got the same 403 Forbidden error. - I used the command chcon -t httpd_sys_rw_content_t /var/www/ -R to change the SELinux permissions on the directory /var/www and its descendants. The setting httpd_sys_rw_content_t allows webserver ("httpd") services to read / write from /var/www. - I recalled that Nginx had originally been able to serve its default page at /usr/share/nginx/html/index.html. Using the command ls -Z /usr/share/nginx to check this directory's SELinux permissions, I could see that it only had the httpd_sys_content_t setting. Presumably, this is only read permission, not read / write permission, and I could have limited myself to that setting in the previous step. - I browsed to http://edgecasesystems.com and got "hello world". - I deleted /var/www/edgecase and moved back to working at /srv/edgecase. I changed the Nginx configuration to match. I changed the SELinux permission on /srv/edgecase/www to httpd_sys_content_t, using the command chcon -v --type=httpd_sys_content_t www -R. The command curl http://edgecasesystems.com/test.txt produced the result "hello world". - Using the Yum package manager, I installed pip 8.1.2. - Using the Pip package manager, I installed gunicorn (version 19.9.0). - I created an example test.py Python file for Gunicorn to serve, which returned "Hello, World!". - I was able to start the Gunicorn server manually (serving on localhost:8080) using the command gunicorn --bind=localhost:8080 --workers=1 test:app and curl "Hello, World!" from it. In this case, curl was run on the VPS i.e. the same machine as the running Gunicorn server. I found that Gunicorn could also serve to the wider net when started with the command gunicorn --bind=edgecasesystems.com:8080 --workers=1 test:app. - I configured Nginx to act as a proxy and pass all its requests to Gunicorn. I browsed to http://edgecasesystems.com and got "nginx error!". The Nginx error log showed "13: Permission denied". Disabling the SELinux setting "httpd_can_network_connect" allowed the Nginx server to connect to the Gunicorn server via HTTP. - I decided to switch to using a Unix socket instead of a network connection. I re-enabled the SELinux setting "httpd_can_network_connect". - I configured Gunicorn to use a socket located at /tmp/gunicorn.sock and started it using the command gunicorn --bind=unix:/tmp/gunicorn.sock --workers=1 test:app. I was able to curl "Hello, World!" from the socket using the commands curl --unix-socket /tmp/gunicorn.sock http://test or curl --unix-socket /tmp/gunicorn.sock h (but not curl --unix-socket /tmp/gunicorn.sock). - I configured Nginx to pass its requests to this socket. I browsed to http://edgecasesystems.com and got "nginx error!". The Nginx error log showed "2: No such file or directory". This was strange. I confirmed that the socket file existed at /tmp/gunicorn.sock. - I learned that sockets can't be placed in /tmp, as they can't be seen by other processes: Excerpt from: hyperlink http://serverfault.com/questions/463993/nginx-unix-domain-socket-error/464025#464025 serverfault.com/questions/463993/nginx-unix-domain-socket-error/464025#464025 You can't place sockets intended for interprocess communication in /tmp. For security reasons, recent versions of Fedora use namespaced temporary directories [ http://fedoraproject.org/wiki/Features/ServicesPrivateTmp ], meaning every service sees a completely different /tmp and can only see its own files in that directory. To resolve the issue, place the socket in a different directory, such as /run (formerly known as /var/run). answered Jan 8 '13 at 14:41 Michael Hampton - I changed the location of the socket from /tmp/gunicorn.sock to /run/gunicorn.sock. I changed the Nginx configuration to match. I browsed to http://edgecasesystems.com and got "nginx error!". The Nginx error log showed "13: Permission denied". The nginx server could now see the socket, but it didn't have permission to connect to it. - Disabling SELinux allowed Nginx to connect to the socket. Using curl to get "Hello, World!" from edgecasesystems.com worked. - I changed the SELinux label on /run/gunicorn.sock from "var_run_t" to "httpd_sys_content_t" using the command semanage fcontext -a -t httpd_sys_content_t /var/run/gunicorn.sock. This didn't work, but perhaps it allowed the next step to work. - I generated a new SELinux policy for nginx using the command grep nginx /var/log/audit/audit.log | audit2allow -M nginx. The -M flag caused this policy to be compiled and saved. The audit2allow tool takes in records of failed access attempts (stored in the SELinux log at /var/log/audit/audit.log) and uses them to generate the new policy. - I activated the policy using semodule -i nginx.pp and confirmed its inclusion using semodule -l | grep nginx. - I browsed to http://edgecasesystems.com and got "Hello, World!". The Notes section contains the following parts: - Acronyms - System details - Summary of an explanation of the slow client problem and how Nginx can handle it when used as a reverse proxy - Original and final Nginx configurations NOTES Parts - Acronyms - System details - Summary of an explanation of the slow client problem and how Nginx can handle it when used as a reverse proxy - Original and final Nginx configurations Acronyms HTTP = HyperText Transfer Protocol WSGI = Web Server Gateway Interface IP = Internet Protocol DNS = Domain Name System VPS = Virtual Private Server System details Local workstation details: - Name: Shovel - Specifications: HP 6005 Pro SFF. 3 GHz x86_64 processor (AMD II x4 B95 Quad Core), 4 GB RAM, 1 TB hard drive. Running CentOS 7.6.1810 (Core). - More information: article New_computer:_Shovel edgecase 81 New computer: Shovel - Installed items: GCC 4.8.5, Make 3.82, Vim 7.4, Python 2.7.5, Python 3.3.2, Gnome 3.28.2, gedit 3.28.1, GPG 1.4.10. DigitalOcean Droplet (VPS) details: - Distribution = CentOS 7.6 x64 - Choose a plan = Standard - Memory = 1 GB - vCPUS = 1 vCPU - SSD Disk = 25 GB - Transfer = 1000 GB - Price = $5/mo, $0.007/hr - Datacentre region = London - hostname = edgecase2 Summary of an explanation of the slow client problem and how Nginx can handle it when used as a reverse proxy I'll rewrite / summarise this source hyperlink http://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients Author: Brian Storti which explains the slow client problem and how to use a reverse proxy to handle it. Summary Some application servers, such as Unicorn (and Gunicorn), use a "forking model", which means that a new process is spawned in order to handle a new request. A "slow client" is a user accessing the application via a slow connection. This connection could actually be slow (e.g. a mobile network connection) or an attacker could artificially cause his client's responses to be slow. Scenario: A slow client tries to send a large request e.g. an upload of a 5MB file. The application server spawns a new process to handle this request. This process will be blocked, and remain idle, while the data is slowly received. Similarly, when the process sends a response back to the client, it will be blocked / idle while the client slowly receives the response data. There is a finite limit on the number of simultaneous server processes. When all of them are busy (perhaps just handling requests from slow clients), the entire application stops receiving new requests, even though it's not actually doing much work. A reverse proxy (e.g. Nginx) can be placed in front of the application server and be used as a buffering system. It can handle an enormous number of simultaneous requests and is not affected by slow clients. Nginx uses a non-blocking Evented I/O model, in which a read call (an I/O operation) is performed in order to handle a new request. The "wait until request is finished" job is passed to the operating system, and the Nginx process is immediately ready to handle a new request. When the read operation finishes, the operating system sends an event notification to Nginx, which will then pass the entire request to the application server. The application server never needs to wait for a slow request to be completed. Nginx buffers requests until they are finished, then passes them to the application server, which will process them and return a response. Nginx also buffers outgoing responses in the same way that it buffers incoming requests. End Summary Original and final Nginx configurations Original configuration: /etc/nginx/nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { 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; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. # # server { # listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; # server_name _; # root /usr/share/nginx/html; # # ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # # location / { # } # # error_page 404 /404.html; # location = /40x.html { # } # # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } } Final configuration: /etc/nginx/nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { 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; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://unix:/run/gunicorn.sock; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. # # server { # listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; # server_name _; # root /usr/share/nginx/html; # # ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # # location / { # } # # error_page 404 /404.html; # location = /40x.html { # } # # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } } The key section that has changed is this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://unix:/run/gunicorn.sock; } Notes: - Use spaces, not tabs, for nginx.conf spacing. - Use nginx -t to check nginx.conf for syntax errors. PROJECT LOG Components: DigitalOcean (a cloud server provider), Nginx (a web server), Gunicorn (a Python WSGI web server), and Python (a programming language). Let's go through these components. They form a series of layers, in this order: - DigitalOcean - Nginx - Gunicorn - Python [hello world application code] Here is the sequence of events (in my current understanding): - An HTTP request will be sent to a particular destination IP address by a client at a source IP address. - The destination IP address is linked to a particular server via the DNS system. The request will arrive at this server. In this project, the server will be a virtual machine running on the DigitalOcean cloud platform. - The HTTP request will be directed to port 80 on the server. The server will pass the request to the Nginx server, which will be listening at port 80. - The Nginx server will buffer HTTP requests and, when they are completely received, pass them to the Gunicorn server. In this case, the Nginx server is acting as a reverse proxy, preventing any slow clients from overloading the Gunicorn server. - The Gunicorn server will translate the HTTP request into a Python dictionary and pass the result to a pre-forked worker process, which will have already have the Python interpreter loaded up and ready to run. - The worker process will use the Python interpreter to execute the Python hello world application code, which will process the HTTP request data and produce a response. - The response will be passed back along the chain of components and sent back to the source IP address that originally made the HTTP request. Links: hyperlink http://www.fullstackpython.com/green-unicorn-gunicorn.html www.fullstackpython.com/green-unicorn-gunicorn.html hyperlink http://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients hyperlink http://docs.gunicorn.org/en/stable/deploy.html docs.gunicorn.org/en/stable/deploy.html hyperlink http://www.nginx.com/resources/wiki www.nginx.com/resources/wiki I'll rewrite / summarise this source hyperlink http://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients Author: Brian Storti which explains the slow client problem and how to use a reverse proxy to handle it. Summary Some application servers, such as Unicorn (and Gunicorn), use a "forking model", which means that a new process is spawned in order to handle a new request. A "slow client" is a user accessing the application via a slow connection. This connection could actually be slow (e.g. a mobile network connection) or an attacker could artificially cause his client's responses to be slow. Scenario: A slow client tries to send a large request e.g. an upload of a 5MB file. The application server spawns a new process to handle this request. This process will be blocked, and remain idle, while the data is slowly received. Similarly, when the process sends a response back to the client, it will be blocked / idle while the client slowly receives the response data. There is a finite limit on the number of simultaneous server processes. When all of them are busy (perhaps just handling requests from slow clients), the entire application stops receiving new requests, even though it's not actually doing much work. A reverse proxy (e.g. Nginx) can be placed in front of the application server and be used as a buffering system. It can handle an enormous number of simultaneous requests and is not affected by slow clients. Nginx uses a non-blocking Evented I/O model, in which a read call (an I/O operation) is performed in order to handle a new request. The "wait until request is finished" job is passed to the operating system, and the Nginx process is immediately ready to handle a new request. When the read operation finishes, the operating system sends an event notification to Nginx, which will then pass the entire request to the application server. The application server never needs to wait for a slow request to be completed. Nginx buffers requests until they are finished, then passes them to the application server, which will process them and return a response. Nginx also buffers outgoing responses in the same way that it buffers incoming requests. End Summary System details: - Name: Shovel - Specifications: HP 6005 Pro SFF. 3 GHz x86_64 processor (AMD II x4 B95 Quad Core), 4 GB RAM, 1 TB hard drive. Running CentOS 7.6.1810 (Core). - More information: article New_computer:_Shovel edgecase 81 New computer: Shovel - Installed items: GCC 4.8.5, Make 3.82, Vim 7.4, Python 2.7.5, Python 3.3.2, Gnome 3.28.2, gedit 3.28.1, GPG 1.4.10. Next: Create a new "droplet" (a virtual private server) on DigitalOcean. Log in to DigitalOcean. In DigitalOcean / Projects / edgecasesoftware, click Create, then Droplets. I now see the "Create Droplets" interface. Choose these droplet details: - Distribution = CentOS 7.6 x64 - Choose a plan = Standard - Memory = 1 GB - vCPUS = 1 vCPU - SSD Disk = 25 GB - Transfer = 1000 GB - Price = $5/mo, $0.007/hr - Datacentre region = London In the section "Add your SSH keys", choose "shovel" (the SSH key for my computer Shovel has already been uploaded to DigitalOcean). Set hostname to "edgecase2". Click Create Droplet. I now see the Project interface. New droplet is being created. New droplet finished. It has the IP address 46.101.86.226. I have a spare domain listed in this project: edgecasesystems.com Click it. The "Create new record" interface opens. It already has 3 Nameserver records pointing to the DigitalOcean nameservers. It also has an A record left over from a previous project. Edit the A record. Set it to point to "edgecase2". "TTL (Seconds)" is set to 3600. 3600 seconds = 1 hour. Click Save. Open a terminal. [spiano@localhost ~]$ ping 46.101.86.226 PING 46.101.86.226 (46.101.86.226) 56(84) bytes of data. 64 bytes from 46.101.86.226: icmp_seq=1 ttl=54 time=34.0 ms 64 bytes from 46.101.86.226: icmp_seq=2 ttl=54 time=22.9 ms 64 bytes from 46.101.86.226: icmp_seq=3 ttl=54 time=33.7 ms ^C --- 46.101.86.226 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2002ms rtt min/avg/max/mdev = 22.910/30.251/34.060/5.192 ms [spiano@localhost ~]$ ping edgecasesystems.com PING edgecasesystems.com (139.59.182.146) 56(84) bytes of data. 64 bytes from 139.59.182.146 (139.59.182.146): icmp_seq=1 ttl=54 time=20.3 ms 64 bytes from 139.59.182.146 (139.59.182.146): icmp_seq=2 ttl=54 time=19.7 ms 64 bytes from 139.59.182.146 (139.59.182.146): icmp_seq=3 ttl=54 time=19.5 ms 64 bytes from 139.59.182.146 (139.59.182.146): icmp_seq=4 ttl=54 time=20.8 ms ^C --- edgecasesystems.com ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3005ms rtt min/avg/max/mdev = 19.543/20.123/20.869/0.512 ms The IP addresses are different. The A record change has not yet propagated. time: 08:43 time: 09:23 ping edgecasesystems.com still hits 139.59.182.146. time: 09:59 ping edgecasesystems.com now hits 46.101.86.226. From Shovel, log in to VPS. [spiano@localhost ~]$ ssh root@edgecasesystems.com The authenticity of host 'edgecasesystems.com (46.101.86.226)' can't be established. ECDSA key fingerprint is SHA256:LKLzCfqqB7NQLA2qKNgkBcObeYd3qmCR7gbGXSXoPok. ECDSA key fingerprint is MD5:36:4d:35:df:54:5f:ce:de:ce:23:0b:16:ee:97:86:51. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'edgecasesystems.com,46.101.86.226' (ECDSA) to the list of known hosts. [root@edgecase2 ~]# Next: Install Nginx on edgecase2 VPS and test it. Links: hyperlink http://www.digitalocean.com/community/tutorials/nginx-essentials-installation-and-configuration-troubleshooting www.digitalocean.com/community/tutorials/nginx-essentials-installation-and-configuration-troubleshooting hyperlink http://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04 www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-16-04 hyperlink http://www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations hyperlink http://www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms www.digitalocean.com/community/tutorials/understanding-nginx-server-and-location-block-selection-algorithms Excerpts from: hyperlink http://www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations www.digitalocean.com/community/tutorials/apache-vs-nginx-practical-considerations Posted: January 28, 2015 Author: Justin Ellingwood In 2002, Igor Sysoev began work on Nginx as an answer to the C10K problem, which was a challenge for web servers to begin handling ten thousand concurrent connections as a requirement for the modern web. The initial public release was made in 2004, meeting this goal by relying on an asynchronous, events-driven architecture. Nginx has grown in popularity since its release due to its light-weight resource utilization and its ability to scale easily on minimal hardware. Nginx excels at serving static content quickly and is designed to pass dynamic requests off to other software that is better suited for those purposes. [...] Nginx came onto the scene after Apache, with more awareness of the concurrency problems that would face sites at scale. Leveraging this knowledge, Nginx was designed from the ground up to use an asynchronous, non-blocking, event-driven connection handling algorithm. Nginx spawns worker processes, each of which can handle thousands of connections. The worker processes accomplish this by implementing a fast looping mechanism that continuously checks for and processes events. Decoupling actual work from connections allows each worker to concern itself with a connection only when a new event has been triggered. Each of the connections handled by the worker are placed within the event loop where they exist with other connections. Within the loop, events are processed asynchronously, allowing work to be handled in a non-blocking manner. When the connection closes, it is removed from the loop. This style of connection processing allows Nginx to scale incredibly far with limited resources. Since the server is single-threaded and processes are not spawned to handle each new connection, the memory and CPU usage tends to stay relatively consistent, even at times of heavy load. [...] Nginx does not have any ability to process dynamic content natively. To handle PHP and other requests for dynamic content, Nginx must pass to an external processor for execution and wait for the rendered content to be sent back. The results can then be relayed to the client. For administrators, this means that communication must be configured between Nginx and the processor over one of the protocols Nginx knows how to speak (http, FastCGI, SCGI, uWSGI, memcache). This can complicate things slightly, especially when trying to anticipate the number of connections to allow, as an additional connection will be used for each call to the processor. However, this method has some advantages as well. Since the dynamic interpreter is not embedded in the worker process, its overhead will only be present for dynamic content. Static content can be served in a straight-forward manner and the interpreter will only be contacted when needed. [...] For administrators, one of the most readily apparent differences between these two pieces of software is whether directory-level configuration is permitted within the content directories. Apache Apache includes an option to allow additional configuration on a per-directory basis by inspecting and interpreting directives in hidden files within the content directories themselves. These files are known as .htaccess files. Since these files reside within the content directories themselves, when handling a request, Apache checks each component of the path to the requested file for an .htaccess file and applies the directives found within. This effectively allows decentralized configuration of the web server, which is often used for implementing URL rewrites, access restrictions, authorization and authentication, even caching policies. While the above examples can all be configured in the main Apache configuration file, .htaccess files have some important advantages. First, since these are interpreted each time they are found along a request path, they are implemented immediately without reloading the server. Second, it makes it possible to allow non-privileged users to control certain aspects of their own web content without giving them control over the entire configuration file. This provides an easy way for certain web software, like content management systems, to configure their environment without providing access to the central configuration file. This is also used by shared hosting providers to retain control of the main configuration while giving clients control over their specific directories. Nginx Nginx does not interpret .htaccess files, nor does it provide any mechanism for evaluating per-directory configuration outside of the main configuration file. This may be less flexible than the Apache model, but it does have its own advantages. The most notable improvement over the .htaccess system of directory-level configuration is increased performance. For a typical Apache setup that may allow .htaccess in any directory, the server will check for these files in each of the parent directories leading up to the requested file, for each request. If one or more .htaccess files are found during this search, they must be read and interpreted. By not allowing directory overrides, Nginx can serve requests faster by doing a single directory lookup and file read for each request (assuming that the file is found in the conventional directory structure). Another advantage is security related. Distributing directory-level configuration access also distributes the responsibility of security to individual users, who may not be trusted to handle this task well. Ensuring that the administrator maintains control over the entire web server can prevent some security missteps that may occur when access is given to other parties. [...] Nginx Nginx was created to be both a web server and a proxy server. Due to the architecture required for these two roles, it works primarily with URIs, translating to the filesystem when necessary. This can be seen in some of the ways that Nginx configuration files are constructed and interpreted. Nginx does not provide a mechanism for specifying configuration for a filesystem directory and instead parses the URI itself. For instance, the primary configuration blocks for Nginx are server and location blocks. The server block interprets the host being requested, while the location blocks are responsible for matching portions of the URI that comes after the host and port. At this point, the request is being interpreted as a URI, not as a location on the filesystem. For static files, all requests eventually have to be mapped to a location on the filesystem. First, Nginx selects the server and location blocks that will handle the request and then combines the document root with the URI, adapting anything necessary according to the configuration specified. [...] Parsing requests primarily as URIs instead of filesystem locations allows Nginx to more easily function in both web, mail, and proxy server roles. Nginx is configured simply by laying out how to respond to different request patterns. Nginx does not check the filesystem until it is ready to serve the request, which explains why it does not implement a form of .htaccess files. [...] Nginx also implements a module system, but it is quite different from the Apache system. In Nginx, modules are not dynamically loadable, so they must be selected and compiled into the core software. For many users, this will make Nginx much less flexible. This is especially true for users who are not comfortable maintaining their own compiled software outside of their distribution's conventional packaging system. While distributions' packages tend to include the most commonly used modules, if you require a non-standard module, you will have to build the server from source yourself. Nginx modules are still very useful though, and they allow you to dictate what you want out of your server by only including the functionality you intend to use. Some users also may consider this more secure, as arbitrary components cannot be hooked into the server. However, if your server is ever put in a position where this is possible, it is likely compromised already. Nginx modules allow many of the same capabilities as Apache modules. For instance, Nginx modules can provide proxying support, compression, rate limiting, logging, rewriting, geolocation, authentication, encryption, streaming, and mail functionality. [...] Administrators are also somewhat more likely to have experience working with Apache not only due to its prevalence, but also because many people start off in shared-hosting scenarios which almost exclusively rely on Apache due to the .htaccess distributed management capabilities. [...] Nginx is experiencing increased support as more users adopt it for its performance profile, but it still has some catching up to do in some key areas. In the past, it was difficult to find comprehensive English-language documentation regarding Nginx due to the fact that most of the early development and documentation were in Russian. As interest in the project grew, the documentation has been filled out and there are now plenty of administration resources on the Nginx site and through third parties. In regards to third-party applications, support and documentation is becoming more readily available, and package maintainers are beginning, in some cases, to give choices between auto-configuring for Apache and Nginx. Even without support, configuring Nginx to work with alternative software is usually straight-forward so long as the project itself documents its requirements (permissions, headers, etc). Using Apache and Nginx Together After going over the benefits and limitations of both Apache and Nginx, you may have a better idea of which server is more suited to your needs. However, many users find that it is possible to leverage each server's strengths by using them together. The conventional configuration for this partnership is to place Nginx in front of Apache as a reverse proxy. This will allow Nginx to to handle all requests from clients. This takes advantage of Nginx's fast processing speed and ability to handle large numbers of connections concurrently. For static content, which Nginx excels at, the files will be served quickly and directly to the client. For dynamic content, for instance PHP files, Nginx will proxy the request to Apache, which can then process the results and return the rendered page. Nginx can then pass the content back to the client. This setup works well for many people because it allows Nginx to function as a sorting machine. It will handle all requests it can and pass on the ones that it has no native ability to serve. By cutting down on the requests the Apache server is asked to handle, we can alleviate some of the blocking that occurs when an Apache process or thread is occupied. This configuration also allows you to scale out by adding additional backend servers as necessary. Nginx can be configured to pass to a pool of servers easily, increasing this configuration's resilience to failure and performance. [root@edgecase2 ~]# nginx -v -bash: nginx: command not found [root@edgecase2 ~]# yum search nginx [...] pcp-pmda-nginx.x86_64 : Performance Co-Pilot (PCP) metrics for the Nginx : Webserver [...] Excerpts from: hyperlink http://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-centos-7 www.digitalocean.com/community/tutorials/how-to-install-nginx-on-centos-7 Posted: July 22, 2014 Author: Mitchell Anicas This tutorial will teach you how to install and start Nginx on your CentOS 7 server. [...] Step One - Add Nginx Repository To add the CentOS 7 EPEL repository, open terminal and use the following command: sudo yum install epel-release Step Two - Install Nginx Now that the Nginx repository is installed on your server, install Nginx using the following yum command: sudo yum install nginx After you answer yes to the prompt, Nginx will finish installing on your virtual private server (VPS). Step Three - Start Nginx Nginx does not start on its own. To get Nginx running, type: sudo systemctl start nginx [...] You can do a spot check right away to verify that everything went as planned by visiting your server's public IP address in your web browser. [...] You will see the default CentOS 7 Nginx web page, which is there for informational and testing purposes. [...] Before continuing, you will probably want to enable Nginx to start when your system boots. To do so, enter the following command: sudo systemctl enable nginx [...] Server Root and Configuration If you want to start serving your own pages or application through Nginx, you will want to know the locations of the Nginx configuration files and default server root directory. Default Server Root The default server root directory is /usr/share/nginx/html. Files that are placed in there will be served on your web server. This location is specified in the default server block configuration file that ships with Nginx, which is located at /etc/nginx/conf.d/default.conf. Server Block Configuration Any additional server blocks, known as Virtual Hosts in Apache, can be added by creating new configuration files in /etc/nginx/conf.d. Files that end with .conf in that directory will be loaded when Nginx is started. Nginx Global Configuration The main Nginx configuration file is located at /etc/nginx/nginx.conf. This is where you can change settings like the user that runs the Nginx daemon processes, and the number of worker processes that get spawned when Nginx is running, among other things. [root@edgecase2 ~]# yum repolist Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.clouvider.net * extras: mirror.mhd.uk.as44574.net * updates: mirrors.clouvider.net repo id repo name status base/7/x86_64 CentOS-7 - Base 10,019 extras/7/x86_64 CentOS-7 - Extras 419 updates/7/x86_64 CentOS-7 - Updates 2,146 repolist: 12,584 [root@edgecase2 ~]# yum install epel-release Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.clouvider.net * extras: mirror.mhd.uk.as44574.net * updates: mirrors.clouvider.net Resolving Dependencies --\> Running transaction check ---\> Package epel-release.noarch 0:7-11 will be installed --\> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: epel-release noarch 7-11 extras 15 k Transaction Summary ================================================================================ Install 1 Package Total download size: 15 k Installed size: 24 k Is this ok [y/d/N]: y Downloading packages: warning: /var/cache/yum/x86_64/7/extras/packages/epel-release-7-11.noarch.rpm: Header V3 RSA/SHA256 Signature, key ID f4a80eb5: NOKEY Public key for epel-release-7-11.noarch.rpm is not installed epel-release-7-11.noarch.rpm | 15 kB 00:00 Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 Importing GPG key 0xF4A80EB5: Userid : "CentOS-7 Key (CentOS 7 Official Signing Key) \" Fingerprint: 6341 ab27 53d7 8a78 a7c2 7bb1 24c6 a8a7 f4a8 0eb5 Package : centos-release-7-6.1810.2.el7.centos.x86_64 (installed) From : /etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 Is this ok [y/N]: y ]Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : epel-release-7-11.noarch 1/1 Verifying : epel-release-7-11.noarch 1/1 Installed: epel-release.noarch 0:7-11 Complete! [root@edgecase2 ~]# yum search nginx Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile epel/x86_64/metalink | 25 kB 00:00 * base: mirrors.clouvider.net * epel: www.mirrorservice.org * extras: mirror.mhd.uk.as44574.net * updates: mirrors.clouvider.net epel | 5.4 kB 00:00 (1/3): epel/x86_64/group_gz | 88 kB 00:00 (2/3): epel/x86_64/updateinfo | 986 kB 00:00 (3/3): epel/x86_64/primary_db | 6.8 MB 00:00 ============================== N/S matched: nginx ============================== collectd-nginx.x86_64 : Nginx plugin for collectd munin-nginx.noarch : NGINX support for Munin resource monitoring nextcloud-nginx.noarch : Nginx integration for NextCloud nginx-all-modules.noarch : A meta package that installs all available Nginx : modules nginx-filesystem.noarch : The basic directory layout for the Nginx server nginx-mod-http-geoip.x86_64 : Nginx HTTP geoip module nginx-mod-http-image-filter.x86_64 : Nginx HTTP image filter module nginx-mod-http-perl.x86_64 : Nginx HTTP perl module nginx-mod-http-xslt-filter.x86_64 : Nginx XSLT module nginx-mod-mail.x86_64 : Nginx mail modules nginx-mod-stream.x86_64 : Nginx stream modules owncloud-nginx.noarch : Nginx integration for ownCloud pcp-pmda-nginx.x86_64 : Performance Co-Pilot (PCP) metrics for the Nginx : Webserver python2-certbot-nginx.noarch : The nginx plugin for certbot nginx.x86_64 : A high performance web server and reverse proxy server Name and summary matches only, use "search all" for everything. [root@edgecase2 ~]# yum install nginx Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.clouvider.net * epel: www.mirrorservice.org * extras: mirror.mhd.uk.as44574.net * updates: mirrors.clouvider.net Resolving Dependencies --\> Running transaction check ---\> Package nginx.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: nginx-all-modules = 1:1.12.2-3.el7 for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Processing Dependency: nginx-filesystem = 1:1.12.2-3.el7 for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Processing Dependency: nginx-filesystem for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Processing Dependency: libprofiler.so.0()(64bit) for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Running transaction check ---\> Package gperftools-libs.x86_64 0:2.6.1-1.el7 will be installed ---\> Package nginx-all-modules.noarch 1:1.12.2-3.el7 will be installed --\> Processing Dependency: nginx-mod-http-geoip = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-http-image-filter = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-http-perl = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-http-xslt-filter = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-mail = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-stream = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch ---\> Package nginx-filesystem.noarch 1:1.12.2-3.el7 will be installed --\> Running transaction check ---\> Package nginx-mod-http-geoip.x86_64 1:1.12.2-3.el7 will be installed ---\> Package nginx-mod-http-image-filter.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: gd for package: 1:nginx-mod-http-image-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libgd.so.2()(64bit) for package: 1:nginx-mod-http-image-filter-1.12.2-3.el7.x86_64 ---\> Package nginx-mod-http-perl.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: perl \>= 5.006001 for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(:MODULE_COMPAT_5.16.3) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(Exporter) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(XSLoader) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(constant) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(strict) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(warnings) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: libperl.so()(64bit) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 ---\> Package nginx-mod-http-xslt-filter.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: libxslt.so.1(LIBXML2_1.0.11)(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libxslt.so.1(LIBXML2_1.0.18)(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libexslt.so.0()(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libxslt.so.1()(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 ---\> Package nginx-mod-mail.x86_64 1:1.12.2-3.el7 will be installed ---\> Package nginx-mod-stream.x86_64 1:1.12.2-3.el7 will be installed --\> Running transaction check ---\> Package gd.x86_64 0:2.0.35-26.el7 will be installed --\> Processing Dependency: libjpeg.so.62(LIBJPEG_6.2)(64bit) for package: gd-2.0.35-26.el7.x86_64 packet_write_wait: Connection to 46.101.86.226 port 22: Broken pipe [spiano@localhost ~]$ ssh root@edgecasesystems.com Last login: Thu Jul 4 09:00:46 2019 from [deleted] [root@edgecase2 ~]# nginx -v -bash: nginx: command not found [root@edgecase2 ~]# yum list installed | grep epel epel-release.noarch 7-11 @extras [root@edgecase2 ~]# yum list installed | grep nginx [root@edgecase2 ~]# yum install nginx Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.clouvider.net * epel: www.mirrorservice.org * extras: mirror.mhd.uk.as44574.net * updates: mirrors.clouvider.net Resolving Dependencies --\> Running transaction check ---\> Package nginx.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: nginx-all-modules = 1:1.12.2-3.el7 for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Processing Dependency: nginx-filesystem = 1:1.12.2-3.el7 for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Processing Dependency: nginx-filesystem for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Processing Dependency: libprofiler.so.0()(64bit) for package: 1:nginx-1.12.2-3.el7.x86_64 --\> Running transaction check ---\> Package gperftools-libs.x86_64 0:2.6.1-1.el7 will be installed ---\> Package nginx-all-modules.noarch 1:1.12.2-3.el7 will be installed --\> Processing Dependency: nginx-mod-http-geoip = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-http-image-filter = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-http-perl = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-http-xslt-filter = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-mail = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch --\> Processing Dependency: nginx-mod-stream = 1:1.12.2-3.el7 for package: 1:nginx-all-modules-1.12.2-3.el7.noarch ---\> Package nginx-filesystem.noarch 1:1.12.2-3.el7 will be installed --\> Running transaction check ---\> Package nginx-mod-http-geoip.x86_64 1:1.12.2-3.el7 will be installed ---\> Package nginx-mod-http-image-filter.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: gd for package: 1:nginx-mod-http-image-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libgd.so.2()(64bit) for package: 1:nginx-mod-http-image-filter-1.12.2-3.el7.x86_64 ---\> Package nginx-mod-http-perl.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: perl \>= 5.006001 for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(:MODULE_COMPAT_5.16.3) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(Exporter) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(XSLoader) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(constant) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(strict) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: perl(warnings) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 --\> Processing Dependency: libperl.so()(64bit) for package: 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 ---\> Package nginx-mod-http-xslt-filter.x86_64 1:1.12.2-3.el7 will be installed --\> Processing Dependency: libxslt.so.1(LIBXML2_1.0.11)(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libxslt.so.1(LIBXML2_1.0.18)(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libexslt.so.0()(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 --\> Processing Dependency: libxslt.so.1()(64bit) for package: 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 ---\> Package nginx-mod-mail.x86_64 1:1.12.2-3.el7 will be installed ---\> Package nginx-mod-stream.x86_64 1:1.12.2-3.el7 will be installed --\> Running transaction check ---\> Package gd.x86_64 0:2.0.35-26.el7 will be installed --\> Processing Dependency: libjpeg.so.62(LIBJPEG_6.2)(64bit) for package: gd-2.0.35-26.el7.x86_64 --\> Processing Dependency: libjpeg.so.62()(64bit) for package: gd-2.0.35-26.el7.x86_64 --\> Processing Dependency: libfontconfig.so.1()(64bit) for package: gd-2.0.35-26.el7.x86_64 --\> Processing Dependency: libXpm.so.4()(64bit) for package: gd-2.0.35-26.el7.x86_64 --\> Processing Dependency: libX11.so.6()(64bit) for package: gd-2.0.35-26.el7.x86_64 ---\> Package libxslt.x86_64 0:1.1.28-5.el7 will be installed ---\> Package perl.x86_64 4:5.16.3-294.el7_6 will be installed --\> Processing Dependency: perl(Socket) \>= 1.3 for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Scalar::Util) \>= 1.10 for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl-macros for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(threads::shared) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(threads) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Time::Local) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Time::HiRes) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Storable) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Socket) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Scalar::Util) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Pod::Simple::XHTML) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Pod::Simple::Search) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Getopt::Long) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Filter::Util::Call) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(File::Temp) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(File::Spec::Unix) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(File::Spec::Functions) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(File::Spec) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(File::Path) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Cwd) for package: 4:perl-5.16.3-294.el7_6.x86_64 --\> Processing Dependency: perl(Carp) for package: 4:perl-5.16.3-294.el7_6.x86_64 ---\> Package perl-Exporter.noarch 0:5.68-3.el7 will be installed ---\> Package perl-constant.noarch 0:1.27-2.el7 will be installed ---\> Package perl-libs.x86_64 4:5.16.3-294.el7_6 will be installed --\> Running transaction check ---\> Package fontconfig.x86_64 0:2.13.0-4.3.el7 will be installed --\> Processing Dependency: fontpackages-filesystem for package: fontconfig-2.13.0-4.3.el7.x86_64 --\> Processing Dependency: dejavu-sans-fonts for package: fontconfig-2.13.0-4.3.el7.x86_64 ---\> Package libX11.x86_64 0:1.6.5-2.el7 will be installed --\> Processing Dependency: libX11-common \>= 1.6.5-2.el7 for package: libX11-1.6.5-2.el7.x86_64 --\> Processing Dependency: libxcb.so.1()(64bit) for package: libX11-1.6.5-2.el7.x86_64 ---\> Package libXpm.x86_64 0:3.5.12-1.el7 will be installed ---\> Package libjpeg-turbo.x86_64 0:1.2.90-6.el7 will be installed ---\> Package perl-Carp.noarch 0:1.26-244.el7 will be installed ---\> Package perl-File-Path.noarch 0:2.09-2.el7 will be installed ---\> Package perl-File-Temp.noarch 0:0.23.01-3.el7 will be installed ---\> Package perl-Filter.x86_64 0:1.49-3.el7 will be installed ---\> Package perl-Getopt-Long.noarch 0:2.40-3.el7 will be installed --\> Processing Dependency: perl(Pod::Usage) \>= 1.14 for package: perl-Getopt-Long-2.40-3.el7.noarch --\> Processing Dependency: perl(Text::ParseWords) for package: perl-Getopt-Long-2.40-3.el7.noarch ---\> Package perl-PathTools.x86_64 0:3.40-5.el7 will be installed ---\> Package perl-Pod-Simple.noarch 1:3.28-4.el7 will be installed --\> Processing Dependency: perl(Pod::Escapes) \>= 1.04 for package: 1:perl-Pod-Simple-3.28-4.el7.noarch --\> Processing Dependency: perl(Encode) for package: 1:perl-Pod-Simple-3.28-4.el7.noarch ---\> Package perl-Scalar-List-Utils.x86_64 0:1.27-248.el7 will be installed ---\> Package perl-Socket.x86_64 0:2.010-4.el7 will be installed ---\> Package perl-Storable.x86_64 0:2.45-3.el7 will be installed ---\> Package perl-Time-HiRes.x86_64 4:1.9725-3.el7 will be installed ---\> Package perl-Time-Local.noarch 0:1.2300-2.el7 will be installed ---\> Package perl-macros.x86_64 4:5.16.3-294.el7_6 will be installed ---\> Package perl-threads.x86_64 0:1.87-4.el7 will be installed ---\> Package perl-threads-shared.x86_64 0:1.43-6.el7 will be installed --\> Running transaction check ---\> Package dejavu-sans-fonts.noarch 0:2.33-6.el7 will be installed --\> Processing Dependency: dejavu-fonts-common = 2.33-6.el7 for package: dejavu-sans-fonts-2.33-6.el7.noarch ---\> Package fontpackages-filesystem.noarch 0:1.44-8.el7 will be installed ---\> Package libX11-common.noarch 0:1.6.5-2.el7 will be installed ---\> Package libxcb.x86_64 0:1.13-1.el7 will be installed --\> Processing Dependency: libXau.so.6()(64bit) for package: libxcb-1.13-1.el7.x86_64 ---\> Package perl-Encode.x86_64 0:2.51-7.el7 will be installed ---\> Package perl-Pod-Escapes.noarch 1:1.04-294.el7_6 will be installed ---\> Package perl-Pod-Usage.noarch 0:1.63-3.el7 will be installed --\> Processing Dependency: perl(Pod::Text) \>= 3.15 for package: perl-Pod-Usage-1.63-3.el7.noarch --\> Processing Dependency: perl-Pod-Perldoc for package: perl-Pod-Usage-1.63-3.el7.noarch ---\> Package perl-Text-ParseWords.noarch 0:3.29-4.el7 will be installed --\> Running transaction check ---\> Package dejavu-fonts-common.noarch 0:2.33-6.el7 will be installed ---\> Package libXau.x86_64 0:1.0.8-2.1.el7 will be installed ---\> Package perl-Pod-Perldoc.noarch 0:3.20-4.el7 will be installed --\> Processing Dependency: perl(parent) for package: perl-Pod-Perldoc-3.20-4.el7.noarch --\> Processing Dependency: perl(HTTP::Tiny) for package: perl-Pod-Perldoc-3.20-4.el7.noarch ---\> Package perl-podlators.noarch 0:2.5.1-3.el7 will be installed --\> Running transaction check ---\> Package perl-HTTP-Tiny.noarch 0:0.033-3.el7 will be installed ---\> Package perl-parent.noarch 1:0.225-244.el7 will be installed --\> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: nginx x86_64 1:1.12.2-3.el7 epel 531 k Installing for dependencies: dejavu-fonts-common noarch 2.33-6.el7 base 64 k dejavu-sans-fonts noarch 2.33-6.el7 base 1.4 M fontconfig x86_64 2.13.0-4.3.el7 base 254 k fontpackages-filesystem noarch 1.44-8.el7 base 9.9 k gd x86_64 2.0.35-26.el7 base 146 k gperftools-libs x86_64 2.6.1-1.el7 base 272 k libX11 x86_64 1.6.5-2.el7 base 606 k libX11-common noarch 1.6.5-2.el7 base 164 k libXau x86_64 1.0.8-2.1.el7 base 29 k libXpm x86_64 3.5.12-1.el7 base 55 k libjpeg-turbo x86_64 1.2.90-6.el7 base 134 k libxcb x86_64 1.13-1.el7 base 214 k libxslt x86_64 1.1.28-5.el7 base 242 k nginx-all-modules noarch 1:1.12.2-3.el7 epel 16 k nginx-filesystem noarch 1:1.12.2-3.el7 epel 17 k nginx-mod-http-geoip x86_64 1:1.12.2-3.el7 epel 23 k nginx-mod-http-image-filter x86_64 1:1.12.2-3.el7 epel 27 k nginx-mod-http-perl x86_64 1:1.12.2-3.el7 epel 36 k nginx-mod-http-xslt-filter x86_64 1:1.12.2-3.el7 epel 26 k nginx-mod-mail x86_64 1:1.12.2-3.el7 epel 54 k nginx-mod-stream x86_64 1:1.12.2-3.el7 epel 76 k perl x86_64 4:5.16.3-294.el7_6 updates 8.0 M perl-Carp noarch 1.26-244.el7 base 19 k perl-Encode x86_64 2.51-7.el7 base 1.5 M perl-Exporter noarch 5.68-3.el7 base 28 k perl-File-Path noarch 2.09-2.el7 base 26 k perl-File-Temp noarch 0.23.01-3.el7 base 56 k perl-Filter x86_64 1.49-3.el7 base 76 k perl-Getopt-Long noarch 2.40-3.el7 base 56 k perl-HTTP-Tiny noarch 0.033-3.el7 base 38 k perl-PathTools x86_64 3.40-5.el7 base 82 k perl-Pod-Escapes noarch 1:1.04-294.el7_6 updates 51 k perl-Pod-Perldoc noarch 3.20-4.el7 base 87 k perl-Pod-Simple noarch 1:3.28-4.el7 base 216 k perl-Pod-Usage noarch 1.63-3.el7 base 27 k perl-Scalar-List-Utils x86_64 1.27-248.el7 base 36 k perl-Socket x86_64 2.010-4.el7 base 49 k perl-Storable x86_64 2.45-3.el7 base 77 k perl-Text-ParseWords noarch 3.29-4.el7 base 14 k perl-Time-HiRes x86_64 4:1.9725-3.el7 base 45 k perl-Time-Local noarch 1.2300-2.el7 base 24 k perl-constant noarch 1.27-2.el7 base 19 k perl-libs x86_64 4:5.16.3-294.el7_6 updates 688 k perl-macros x86_64 4:5.16.3-294.el7_6 updates 44 k perl-parent noarch 1:0.225-244.el7 base 12 k perl-podlators noarch 2.5.1-3.el7 base 112 k perl-threads x86_64 1.87-4.el7 base 49 k perl-threads-shared x86_64 1.43-6.el7 base 39 k Transaction Summary ================================================================================ Install 1 Package (+48 Dependent packages) Total download size: 16 M Installed size: 50 M Is this ok [y/d/N]: y Downloading packages: (1/49): dejavu-fonts-common-2.33-6.el7.noarch.rpm | 64 kB 00:00 (2/49): fontconfig-2.13.0-4.3.el7.x86_64.rpm | 254 kB 00:00 (3/49): fontpackages-filesystem-1.44-8.el7.noarch.rpm | 9.9 kB 00:00 (4/49): dejavu-sans-fonts-2.33-6.el7.noarch.rpm | 1.4 MB 00:00 (5/49): gd-2.0.35-26.el7.x86_64.rpm | 146 kB 00:00 (6/49): libX11-common-1.6.5-2.el7.noarch.rpm | 164 kB 00:00 (7/49): libXau-1.0.8-2.1.el7.x86_64.rpm | 29 kB 00:00 (8/49): libX11-1.6.5-2.el7.x86_64.rpm | 606 kB 00:00 (9/49): libXpm-3.5.12-1.el7.x86_64.rpm | 55 kB 00:00 (10/49): libjpeg-turbo-1.2.90-6.el7.x86_64.rpm | 134 kB 00:00 (11/49): libxcb-1.13-1.el7.x86_64.rpm | 214 kB 00:00 (12/49): libxslt-1.1.28-5.el7.x86_64.rpm | 242 kB 00:00 (13/49): gperftools-libs-2.6.1-1.el7.x86_64.rpm | 272 kB 00:00 warning: /var/cache/yum/x86_64/7/epel/packages/nginx-1.12.2-3.el7.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID 352c64e5: NOKEY Public key for nginx-1.12.2-3.el7.x86_64.rpm is not installed (14/49): nginx-1.12.2-3.el7.x86_64.rpm | 531 kB 00:00 (15/49): nginx-all-modules-1.12.2-3.el7.noarch.rpm | 16 kB 00:00 (16/49): nginx-filesystem-1.12.2-3.el7.noarch.rpm | 17 kB 00:00 (17/49): nginx-mod-http-geoip-1.12.2-3.el7.x86_64.rpm | 23 kB 00:00 (18/49): nginx-mod-http-image-filter-1.12.2-3.el7.x86_64.r | 27 kB 00:00 (19/49): nginx-mod-http-perl-1.12.2-3.el7.x86_64.rpm | 36 kB 00:00 (20/49): nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64.rp | 26 kB 00:00 (21/49): nginx-mod-mail-1.12.2-3.el7.x86_64.rpm | 54 kB 00:00 (22/49): nginx-mod-stream-1.12.2-3.el7.x86_64.rpm | 76 kB 00:00 (23/49): perl-Exporter-5.68-3.el7.noarch.rpm | 28 kB 00:00 (24/49): perl-5.16.3-294.el7_6.x86_64.rpm | 8.0 MB 00:00 (25/49): perl-Carp-1.26-244.el7.noarch.rpm | 19 kB 00:00 (26/49): perl-File-Path-2.09-2.el7.noarch.rpm | 26 kB 00:00 (27/49): perl-File-Temp-0.23.01-3.el7.noarch.rpm | 56 kB 00:00 (28/49): perl-Getopt-Long-2.40-3.el7.noarch.rpm | 56 kB 00:00 (29/49): perl-Filter-1.49-3.el7.x86_64.rpm | 76 kB 00:00 (30/49): perl-HTTP-Tiny-0.033-3.el7.noarch.rpm | 38 kB 00:00 (31/49): perl-PathTools-3.40-5.el7.x86_64.rpm | 82 kB 00:00 (32/49): perl-Encode-2.51-7.el7.x86_64.rpm | 1.5 MB 00:00 (33/49): perl-Pod-Perldoc-3.20-4.el7.noarch.rpm | 87 kB 00:00 (34/49): perl-Pod-Usage-1.63-3.el7.noarch.rpm | 27 kB 00:00 (35/49): perl-Pod-Simple-3.28-4.el7.noarch.rpm | 216 kB 00:00 (36/49): perl-Scalar-List-Utils-1.27-248.el7.x86_64.rpm | 36 kB 00:00 (37/49): perl-Socket-2.010-4.el7.x86_64.rpm | 49 kB 00:00 (38/49): perl-Text-ParseWords-3.29-4.el7.noarch.rpm | 14 kB 00:00 (39/49): perl-Time-Local-1.2300-2.el7.noarch.rpm | 24 kB 00:00 (40/49): perl-Time-HiRes-1.9725-3.el7.x86_64.rpm | 45 kB 00:00 (41/49): perl-constant-1.27-2.el7.noarch.rpm | 19 kB 00:00 (42/49): perl-macros-5.16.3-294.el7_6.x86_64.rpm | 44 kB 00:00 (43/49): perl-parent-0.225-244.el7.noarch.rpm | 12 kB 00:00 (44/49): perl-podlators-2.5.1-3.el7.noarch.rpm | 112 kB 00:00 (45/49): perl-threads-1.87-4.el7.x86_64.rpm | 49 kB 00:00 (46/49): perl-threads-shared-1.43-6.el7.x86_64.rpm | 39 kB 00:00 (47/49): perl-Pod-Escapes-1.04-294.el7_6.noarch.rpm | 51 kB 00:00 (48/49): perl-Storable-2.45-3.el7.x86_64.rpm | 77 kB 00:00 (49/49): perl-libs-5.16.3-294.el7_6.x86_64.rpm | 688 kB 00:00 -------------------------------------------------------------------------------- Total 11 MB/s | 16 MB 00:01 Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 Importing GPG key 0x352C64E5: Userid : "Fedora EPEL (7) \" Fingerprint: 91e9 7d7c 4a5e 96f1 7f3e 888f 6a2f aea2 352c 64e5 Package : epel-release-7-11.noarch (@extras) From : /etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7 Is this ok [y/N]: y Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : fontpackages-filesystem-1.44-8.el7.noarch 1/49 Installing : dejavu-fonts-common-2.33-6.el7.noarch 2/49 Installing : dejavu-sans-fonts-2.33-6.el7.noarch 3/49 Installing : fontconfig-2.13.0-4.3.el7.x86_64 4/49 Installing : 1:perl-parent-0.225-244.el7.noarch 5/49 Installing : perl-HTTP-Tiny-0.033-3.el7.noarch 6/49 Installing : perl-podlators-2.5.1-3.el7.noarch 7/49 Installing : perl-Pod-Perldoc-3.20-4.el7.noarch 8/49 Installing : 1:perl-Pod-Escapes-1.04-294.el7_6.noarch 9/49 Installing : perl-Encode-2.51-7.el7.x86_64 10/49 Installing : perl-Text-ParseWords-3.29-4.el7.noarch 11/49 Installing : perl-Pod-Usage-1.63-3.el7.noarch 12/49 Installing : 4:perl-libs-5.16.3-294.el7_6.x86_64 13/49 Installing : 4:perl-macros-5.16.3-294.el7_6.x86_64 14/49 Installing : 4:perl-Time-HiRes-1.9725-3.el7.x86_64 15/49 Installing : perl-Exporter-5.68-3.el7.noarch 16/49 Installing : perl-constant-1.27-2.el7.noarch 17/49 Installing : perl-Time-Local-1.2300-2.el7.noarch 18/49 Installing : perl-Socket-2.010-4.el7.x86_64 19/49 Installing : perl-Carp-1.26-244.el7.noarch 20/49 Installing : perl-Storable-2.45-3.el7.x86_64 21/49 Installing : perl-PathTools-3.40-5.el7.x86_64 22/49 Installing : perl-Scalar-List-Utils-1.27-248.el7.x86_64 23/49 Installing : 1:perl-Pod-Simple-3.28-4.el7.noarch 24/49 Installing : perl-File-Temp-0.23.01-3.el7.noarch 25/49 Installing : perl-File-Path-2.09-2.el7.noarch 26/49 Installing : perl-threads-shared-1.43-6.el7.x86_64 27/49 Installing : perl-threads-1.87-4.el7.x86_64 28/49 Installing : perl-Filter-1.49-3.el7.x86_64 29/49 Installing : perl-Getopt-Long-2.40-3.el7.noarch 30/49 Installing : 4:perl-5.16.3-294.el7_6.x86_64 31/49 Installing : 1:nginx-filesystem-1.12.2-3.el7.noarch 32/49 Installing : libX11-common-1.6.5-2.el7.noarch 33/49 Installing : gperftools-libs-2.6.1-1.el7.x86_64 34/49 Installing : libXau-1.0.8-2.1.el7.x86_64 35/49 Installing : libxcb-1.13-1.el7.x86_64 36/49 Installing : libX11-1.6.5-2.el7.x86_64 37/49 Installing : libXpm-3.5.12-1.el7.x86_64 38/49 Installing : libxslt-1.1.28-5.el7.x86_64 39/49 Installing : libjpeg-turbo-1.2.90-6.el7.x86_64 40/49 Installing : gd-2.0.35-26.el7.x86_64 41/49 Installing : 1:nginx-mod-http-image-filter-1.12.2-3.el7.x86_64 42/49 Installing : 1:nginx-mod-mail-1.12.2-3.el7.x86_64 43/49 Installing : 1:nginx-mod-stream-1.12.2-3.el7.x86_64 44/49 Installing : 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 45/49 Installing : 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 46/49 Installing : 1:nginx-mod-http-geoip-1.12.2-3.el7.x86_64 47/49 Installing : 1:nginx-all-modules-1.12.2-3.el7.noarch 48/49 Installing : 1:nginx-1.12.2-3.el7.x86_64 49/49 Verifying : 1:nginx-all-modules-1.12.2-3.el7.noarch 1/49 Verifying : fontconfig-2.13.0-4.3.el7.x86_64 2/49 Verifying : perl-HTTP-Tiny-0.033-3.el7.noarch 3/49 Verifying : 1:nginx-mod-http-image-filter-1.12.2-3.el7.x86_64 4/49 Verifying : perl-threads-shared-1.43-6.el7.x86_64 5/49 Verifying : 4:perl-Time-HiRes-1.9725-3.el7.x86_64 6/49 Verifying : 1:perl-Pod-Escapes-1.04-294.el7_6.noarch 7/49 Verifying : perl-Exporter-5.68-3.el7.noarch 8/49 Verifying : perl-constant-1.27-2.el7.noarch 9/49 Verifying : perl-PathTools-3.40-5.el7.x86_64 10/49 Verifying : 1:nginx-1.12.2-3.el7.x86_64 11/49 Verifying : 1:nginx-mod-mail-1.12.2-3.el7.x86_64 12/49 Verifying : 1:nginx-mod-stream-1.12.2-3.el7.x86_64 13/49 Verifying : dejavu-fonts-common-2.33-6.el7.noarch 14/49 Verifying : fontpackages-filesystem-1.44-8.el7.noarch 15/49 Verifying : libjpeg-turbo-1.2.90-6.el7.x86_64 16/49 Verifying : 1:perl-parent-0.225-244.el7.noarch 17/49 Verifying : 1:nginx-mod-http-xslt-filter-1.12.2-3.el7.x86_64 18/49 Verifying : 4:perl-libs-5.16.3-294.el7_6.x86_64 19/49 Verifying : perl-File-Temp-0.23.01-3.el7.noarch 20/49 Verifying : 1:perl-Pod-Simple-3.28-4.el7.noarch 21/49 Verifying : perl-Time-Local-1.2300-2.el7.noarch 22/49 Verifying : libxcb-1.13-1.el7.x86_64 23/49 Verifying : 4:perl-macros-5.16.3-294.el7_6.x86_64 24/49 Verifying : perl-Socket-2.010-4.el7.x86_64 25/49 Verifying : libXpm-3.5.12-1.el7.x86_64 26/49 Verifying : 1:nginx-mod-http-perl-1.12.2-3.el7.x86_64 27/49 Verifying : perl-Carp-1.26-244.el7.noarch 28/49 Verifying : libxslt-1.1.28-5.el7.x86_64 29/49 Verifying : libX11-1.6.5-2.el7.x86_64 30/49 Verifying : perl-Storable-2.45-3.el7.x86_64 31/49 Verifying : dejavu-sans-fonts-2.33-6.el7.noarch 32/49 Verifying : perl-Scalar-List-Utils-1.27-248.el7.x86_64 33/49 Verifying : gd-2.0.35-26.el7.x86_64 34/49 Verifying : 1:nginx-mod-http-geoip-1.12.2-3.el7.x86_64 35/49 Verifying : perl-Pod-Usage-1.63-3.el7.noarch 36/49 Verifying : perl-Encode-2.51-7.el7.x86_64 37/49 Verifying : perl-Pod-Perldoc-3.20-4.el7.noarch 38/49 Verifying : perl-podlators-2.5.1-3.el7.noarch 39/49 Verifying : libXau-1.0.8-2.1.el7.x86_64 40/49 Verifying : perl-File-Path-2.09-2.el7.noarch 41/49 Verifying : perl-threads-1.87-4.el7.x86_64 42/49 Verifying : gperftools-libs-2.6.1-1.el7.x86_64 43/49 Verifying : libX11-common-1.6.5-2.el7.noarch 44/49 Verifying : perl-Filter-1.49-3.el7.x86_64 45/49 Verifying : perl-Getopt-Long-2.40-3.el7.noarch 46/49 Verifying : perl-Text-ParseWords-3.29-4.el7.noarch 47/49 Verifying : 4:perl-5.16.3-294.el7_6.x86_64 48/49 Verifying : 1:nginx-filesystem-1.12.2-3.el7.noarch 49/49 Installed: nginx.x86_64 1:1.12.2-3.el7 Dependency Installed: dejavu-fonts-common.noarch 0:2.33-6.el7 dejavu-sans-fonts.noarch 0:2.33-6.el7 fontconfig.x86_64 0:2.13.0-4.3.el7 fontpackages-filesystem.noarch 0:1.44-8.el7 gd.x86_64 0:2.0.35-26.el7 gperftools-libs.x86_64 0:2.6.1-1.el7 libX11.x86_64 0:1.6.5-2.el7 libX11-common.noarch 0:1.6.5-2.el7 libXau.x86_64 0:1.0.8-2.1.el7 libXpm.x86_64 0:3.5.12-1.el7 libjpeg-turbo.x86_64 0:1.2.90-6.el7 libxcb.x86_64 0:1.13-1.el7 libxslt.x86_64 0:1.1.28-5.el7 nginx-all-modules.noarch 1:1.12.2-3.el7 nginx-filesystem.noarch 1:1.12.2-3.el7 nginx-mod-http-geoip.x86_64 1:1.12.2-3.el7 nginx-mod-http-image-filter.x86_64 1:1.12.2-3.el7 nginx-mod-http-perl.x86_64 1:1.12.2-3.el7 nginx-mod-http-xslt-filter.x86_64 1:1.12.2-3.el7 nginx-mod-mail.x86_64 1:1.12.2-3.el7 nginx-mod-stream.x86_64 1:1.12.2-3.el7 perl.x86_64 4:5.16.3-294.el7_6 perl-Carp.noarch 0:1.26-244.el7 perl-Encode.x86_64 0:2.51-7.el7 perl-Exporter.noarch 0:5.68-3.el7 perl-File-Path.noarch 0:2.09-2.el7 perl-File-Temp.noarch 0:0.23.01-3.el7 perl-Filter.x86_64 0:1.49-3.el7 perl-Getopt-Long.noarch 0:2.40-3.el7 perl-HTTP-Tiny.noarch 0:0.033-3.el7 perl-PathTools.x86_64 0:3.40-5.el7 perl-Pod-Escapes.noarch 1:1.04-294.el7_6 perl-Pod-Perldoc.noarch 0:3.20-4.el7 perl-Pod-Simple.noarch 1:3.28-4.el7 perl-Pod-Usage.noarch 0:1.63-3.el7 perl-Scalar-List-Utils.x86_64 0:1.27-248.el7 perl-Socket.x86_64 0:2.010-4.el7 perl-Storable.x86_64 0:2.45-3.el7 perl-Text-ParseWords.noarch 0:3.29-4.el7 perl-Time-HiRes.x86_64 4:1.9725-3.el7 perl-Time-Local.noarch 0:1.2300-2.el7 perl-constant.noarch 0:1.27-2.el7 perl-libs.x86_64 4:5.16.3-294.el7_6 perl-macros.x86_64 4:5.16.3-294.el7_6 perl-parent.noarch 1:0.225-244.el7 perl-podlators.noarch 0:2.5.1-3.el7 perl-threads.x86_64 0:1.87-4.el7 perl-threads-shared.x86_64 0:1.43-6.el7 Complete! [root@edgecase2 ~]# yum repolist Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirrors.clouvider.net * epel: www.mirrorservice.org * extras: mirror.mhd.uk.as44574.net * updates: mirrors.clouvider.net repo id repo name status base/7/x86_64 CentOS-7 - Base 10,019 epel/x86_64 Extra Packages for Enterprise Linux 7 - x86_64 13,278 extras/7/x86_64 CentOS-7 - Extras 419 updates/7/x86_64 CentOS-7 - Updates 2,146 repolist: 25,862 [root@edgecase2 ~]# nginx --version nginx: invalid option: "-" [root@edgecase2 ~]# nginx -v nginx version: nginx/1.12.2 In the output of the first run of yum repolist, "epel" is not present. In the output of the second, it is. Browse to: http://edgecasesystems.com Result: {Unable to connect} [root@edgecase2 ~]# systemctl start nginx [root@edgecase2 ~]# systemctl status nginx [...] Active: active (running) since Thu 2019-07-04 10:06:29 UTC; 12s ago [...] Browse to: http://edgecasesystems.com Result: Welcome to nginx on Fedora! This page is used to test the proper operation of the nginx HTTP server after it has been installed. If you can read this page, it means that the web server installed at this site is working properly. Website Administrator This is the default index.html page that is distributed with nginx on Fedora. It is located in /usr/share/nginx/html. You should now put your content in a location of your choice and edit the root configuration directive in the nginx configuration file /etc/nginx/nginx.conf. Good. [root@edgecase2 ~]# systemctl enable nginx Created symlink from /etc/systemd/system/multi-user.target.wants/nginx.service to /usr/lib/systemd/system/nginx.service. Let's confirm that the nginx server starts on boot. Go to DigitalOcean / Manage / Droplets Click edgecase2 Click Power Click Power Cycle After a minute or so, a pop-up message confirms that power cycle has finished. Browse to: http://edgecasesystems.com Result: Welcome to nginx on Fedora! [...] Good. [root@edgecase2 ~]# packet_write_wait: Connection to 46.101.86.226 port 22: Broken pipe [spiano@localhost ~]$ ssh root@edgecasesystems.com Last login: Thu Jul 4 09:59:13 2019 from [deleted] [root@edgecase2 ~]# systemctl status nginx [...] Active: active (running) since Thu 2019-07-04 10:06:29 UTC; 12s ago [...] Next: Choose a location for the web application, put a "hello world" file there, and configure nginx to serve this file. [root@edgecase2 ~]# ls -1 /etc/nginx conf.d default.d fastcgi.conf fastcgi.conf.default fastcgi_params fastcgi_params.default koi-utf koi-win mime.types mime.types.default nginx.conf nginx.conf.default scgi_params scgi_params.default uwsgi_params uwsgi_params.default win-utf hyperlink http://serverfault.com/questions/144598/where-should-the-web-server-root-directory-go-in-linux serverfault.com/questions/144598/where-should-the-web-server-root-directory-go-in-linux hyperlink http://superuser.com/questions/635289/what-is-the-recommended-directory-to-store-website-content superuser.com/questions/635289/what-is-the-recommended-directory-to-store-website-content I choose: /srv/edgecase/www [root@edgecase2 html]# cd /srv [root@edgecase2 srv]# ls [root@edgecase2 srv]# mkdir -p edgecase/www [root@edgecase2 srv]# cd edgecase/www [root@edgecase2 www]# echo "hello world" \> test.txt [root@edgecase2 www]# cat test.txt hello world Next: Configure nginx to serve the hello world file. /etc/nginx/nginx.conf # For more information on configuration, see: # * Official English Documentation: http://nginx.org/en/docs/ # * Official Russian Documentation: http://nginx.org/ru/docs/ user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; # Load dynamic modules. See /usr/share/nginx/README.dynamic. include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } http { 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; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; # Load modular configuration files from the /etc/nginx/conf.d directory. # See http://nginx.org/en/docs/ngx_core_module.html#include # for more information. include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } } # Settings for a TLS enabled server. # # server { # listen 443 ssl http2 default_server; # listen [::]:443 ssl http2 default_server; # server_name _; # root /usr/share/nginx/html; # # ssl_certificate "/etc/pki/nginx/server.crt"; # ssl_certificate_key "/etc/pki/nginx/private/server.key"; # ssl_session_cache shared:SSL:1m; # ssl_session_timeout 10m; # ssl_ciphers HIGH:!aNULL:!MD5; # ssl_prefer_server_ciphers on; # # # Load configuration files for the default server block. # include /etc/nginx/default.d/*.conf; # # location / { # } # # error_page 404 /404.html; # location = /40x.html { # } # # error_page 500 502 503 504 /50x.html; # location = /50x.html { # } # } } Excerpts from: hyperlink http://nginx.org/en/docs/beginners_guide.html nginx.org/en/docs/beginners_guide.html An important web server task is serving out files (such as images or static HTML pages). You will implement an example where, depending on the request, files will be served from different local directories: /data/www (which may contain HTML files) and /data/images (containing images). This will require editing of the configuration file and setting up of a server block inside the http block with two location blocks. [...] Generally, the configuration file may include several server blocks distinguished by ports on which they listen to and by server names. Once nginx decides which server processes a request, it tests the URI specified in the request's header against the parameters of the location directives defined inside the server block. Notes (made from the entire linked document, not just the excerpts): - The location block's URI (in this case /) starts from the server block's root value (in this case /usr/share/nginx/html). So: In this case, the single location block handles all HTTP requests with URIs that start with /usr/share/nginx/html. Excerpt from: hyperlink http://docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files docs.nginx.com/nginx/admin-guide/basic-functionality/managing-configuration-files For HTTP traffic (the http context), each server directive controls the processing of requests for resources at particular domains or IP addresses. One or more location contexts in a server context define how to process specific sets of URIs. Excerpt from: hyperlink http://docs.nginx.com/nginx/admin-guide/web-server/web-server docs.nginx.com/nginx/admin-guide/web-server/web-server The server configuration block usually includes a listen directive to specify the IP address and port (or Unix domain socket and path) on which the server listens for requests. Both IPv4 and IPv6 addresses are accepted; enclose IPv6 addresses in square brackets (. The example below shows configuration of a server that listens on IP address 127.0.0.1 and port 8080: server { listen 127.0.0.1:8080; # The rest of server configuration } If a port is omitted, the standard port is used. Likewise, if an address is omitted, the server listens on all addresses. If the listen directive is not included at all, the "standard" port is 80/tcp and the "default" port is 8000/tcp, depending on superuser privileges. If there are several servers that match the IP address and port of the request, NGINX Plus tests the request's Host header field against the server_name directives in the server blocks. The parameter to server_name can be a full (exact) name, a wildcard, or a regular expression. A wildcard is a character string that includes the asterisk (*) at its beginning, end, or both; the asterisk matches any sequence of characters. NGINX Plus uses the Perl syntax for regular expressions; precede them with the tilde (~). This example illustrates an exact name. server { listen 80; server_name example.org www.example.org; ... } If several names match the Host header, NGINX Plus selects one by searching for names in the following order and using the first match it finds: 1. Exact name 2. Longest wildcard starting with an asterisk, such as *.example.org 3. Longest wildcard ending with an asterisk, such as mail.* 4. First matching regular expression (in order of appearance in the configuration file) If the Host header field does not match a server name, NGINX Plus routes the request to the default server for the port on which the request arrived. The default server is the first one listed in the nginx.conf file, unless you include the default_server parameter to the listen directive to explicitly designate a server as the default. server { listen 80 default_server; ... } Notes: - I think that these two lines in nginx.conf: listen 80 default_server; listen [::]:80 default_server; capture all requests on port 80 from any IP address. - This line: root /usr/share/nginx/html; sets the document root for these requests. - Any further settings should be placed in the location block: location / { } Excerpts from: hyperlink http://docs.nginx.com/nginx/admin-guide/web-server/serving-static-content docs.nginx.com/nginx/admin-guide/web-server/serving-static-content If a request ends with a slash, NGINX treats it as a request for a directory and tries to find an index file in the directory. The index directive defines the index file's name (the default value is index.html). [...] You can list more than one filename in the index directive. NGINX searches for files in the specified order and returns the first one it finds. location / { index index.$geo.html index.htm index.html; } The $geo variable used here here is a custom variable set through the geo directive. The value of the variable depends on the client's IP address. So, I can do this: location / { index test.txt index.htm index.html; } in order to direct the URI edgecasesystems.com to /test.txt. Ok. In order to set nginx to serve from /srv/edgecase/www, and to have test.txt be the default page, change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { index test.txt; } On the VPS, vi is present, but not vim. Use vi to edit nginx.conf to the desired state. Note: Use spaces, not tabs, for nginx.conf spacing. Use nginx -t to check nginx.conf for syntax errors. [root@edgecase2 nginx]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 nginx]# systemctl reload nginx Browse to: http://edgecasesystems.com Result: Welcome to nginx on Fedora! [...] [root@edgecase2 nginx]# systemctl restart nginx Browse to: http://edgecasesystems.com/test.txt Result: 403 Forbidden nginx/1.12.2 Hm. [root@edgecase2 nginx]# tail -1 /var/log/nginx/error.log 2019/07/05 11:14:29 [error] 8449#0: *1 open() "/srv/edgecase/www/test.txt" failed (13: Permission denied), client: [deleted], server: _, request: "GET /test.txt HTTP/1.1", host: "edgecasesystems.com" [reading and experimentation occurs here] Excerpt from: hyperlink http://unix.stackexchange.com/questions/285461/user-permissions-problem-in-centos-7-permission-denied unix.stackexchange.com/questions/285461/user-permissions-problem-in-centos-7-permission-denied answered Dec 1 '18 at 3:21 telcoM You're using CentOS 7, which has SELinux enabled by default. RHEL/CentOS has a default SELinux configuration that usually has a pretty negligible effect on regular user accounts, but it can place some strict limits on system services - like a web server, for example. Under SELinux, it is possible to restrict a process and all of its descendants from certain actions - independently from traditional Unix-style user/group/permissions system. Those restrictions can be configured to automatically "latch on" when certain binaries are executed, for certain system users, and on a multitude of other conditions. One of the default SELinux restrictions for a webserver is that access to anything outside specifically enabled directories like /var/www is blocked, unless specifically enabled using a SELinux boolean, a kind of switchable option in SELinux ruleset. I think this might be another thing stopping the web3 user from accessing the Drush application. If you want a web server (or any of its descendants, like a PHP interpreter) to access any content that is not under /var/www and is created by other users, you'll need to run this command: # setsebool -P httpd_read_user_content 1 On RHEL/CentOS, each system service has an additional man page, named like \_selinux, that contains information on SELinux restrictions and booleans for that specific service. Those man pages come in a RPM package named selinux-policy-doc: here's more information about that package [ http://centos.pkgs.org/7/centos-x86_64/selinux-policy-doc-3.13.1-192.el7.noarch.rpm.html ]. If you're using a system with SELinux enabled, you really should read those man pages for all the services you're planning to run: they make dealing with SELinux just so much easier. Of course, you may find on the internet a lot of suggestions on how to disable SELinux, but if you are planning to run a secure server, that might not be the best option. Hm. Ok. Let's try with /var/www/edgecase/basic instead of /srv/edgecase/www. [root@edgecase2 nginx]# ls /var/www ls: cannot access /var/www: No such file or directory [root@edgecase2 nginx]# mkdir -p /var/www/edgecase/basic [root@edgecase2 nginx]# echo "hello world" \> /var/www/edgecase/basic/test.txt [root@edgecase2 nginx]# ls /var/www/edgecase/basic test.txt change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /var/www/edgecase/basic; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { index test.txt; } [root@edgecase2 nginx]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 nginx]# systemctl restart nginx Browse to: http://edgecasesystems.com/test.txt Result: 403 Forbidden nginx/1.12.2 [root@edgecase2 nginx]# tail -1 /var/log/nginx/error.log 2019/07/05 11:39:31 [error] 8616#0: *4 open() "/var/www/edgecase/basic/test.txt" failed (13: Permission denied), client: [deleted], server: _, request: "GET /test.txt HTTP/1.1", host: "edgecasesystems.com" Excerpt from: hyperlink http://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls The [Filesystem Hierarchy Standard](https://en.wikipedia.org/wiki/Filesystem_Hierarchy_Standard "Filesystem Hierarchy Standard on WikiPedia") defines where data should exist. You should definitely read it. The short version is that you want your web content to exist in either /var/www/, /srv, /usr/share/www. Using the Default Document Root NGINX packages that exist in Ubuntu, Debian, or other operating systems, as an easy-to-install package will often provide a 'default' configuration file as an example of configuration methods, and will often include a document root to hold a basic HTML file. Most of these packaging systems do not check to see if files are modified or exist within the default document root, which can result in code loss when the packages are upgraded. Experienced system administrators know that there is no expectation of the data inside the default document root to remain untouched during upgrades. You should not use the default document root for any site-critical files. There is no expectation that the default document root will be left untouched by the system and there is an extremely high possibility that your site-critical data may be lost upon updates and upgrades to the NGINX packages for your operating system. [root@edgecase2 nginx]# namei -om /usr/share/nginx/html/index.html f: /usr/share/nginx/html/index.html dr-xr-xr-x root root / drwxr-xr-x root root usr drwxr-xr-x root root share drwxr-xr-x root root nginx drwxr-xr-x root root html -rw-r--r-- root root index.html [root@edgecase2 nginx]# namei -om /var/www/edgecase/basic/test.txt f: /var/www/edgecase/basic/test.txt dr-xr-xr-x root root / drwxr-xr-x root root var drwxr-xr-x root root www drwxr-xr-x root root edgecase drwxr-xr-x root root basic -rw-r--r-- root root test.txt Excerpts from: hyperlink http://introvertedengineer.com/2017/03/21/fixing-permission-denied-centos-selinux introvertedengineer.com/2017/03/21/fixing-permission-denied-centos-selinux Fixing Permission Denied on CentOS7 (SELinux) Date: March 21, 2017 Author: Said Ketchman You've configured your server, setup permissions properly, and still you get the frustrating error message: Permission denied in /var/www/... on line xyz. If you're using a newer linux based OS, chances are you've overlooked SELinux and need to also set the proper permissions for write access to your directory and files. If you have a WordPress, Joomla, Drupal, OpenCart, or any other CMS site and can't update your plugins automatically, chances are you have this issue. The fix is really simple, so that's good news! Allowing Read/Write Access via SELinux First thing is to check the current SELinux permissions for your website's home directory. You'll need to ssh into your server and then run the following command: ls -Z /path/to/website/root You will most likely see something like this: drwxrwsr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 mywebsite.com The key part to look at is the unconfined_u:object_r:httpd_sys_content_t:s0 portion. If you see httpd_sys_content_t then you know right away that your web server and application (Apache, PHP, etc.) will not be able to write to your directories. To allow for write access to your directories, you'll need to issue the following command: sudo chcon -t httpd_sys_rw_content_t mywebsite.com/ -R Note! This will make your entire website home directory writeable via SELinux, so you will probably want to selectively choose folders that you want your web server to be able to write to. Run the ls -Z command again and you should see the new attribute httpd_sys_rw_content_t instead of the previous httpd_sys_content_t. You should be all set at this point. SELinux is a security layer above the standard chmod permissions, so make sure both are set properly in order to have the permissions you need. Linux variations that implement SELinux: - Red Hat - CentOS/REHL - Fedora - Debian - Ubuntu - CoreOS [...] I'm beginning to see this issue pop up quite often as more and more people move towards hosting with a non-managed virtual private server. So it's always worth understanding the fundamentals. Ok. Let's try this. [root@edgecase2 nginx]# ls -Z /var/www drwxr-xr-x. root root unconfined_u:object_r:var_t:s0 edgecase [root@edgecase2 nginx]# chcon -t httpd_sys_rw_content_t /var/www/ -R [root@edgecase2 nginx]# ls -Z /var/www drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_rw_content_t:s0 edgecase [root@edgecase2 nginx]# systemctl restart nginx Browse to: http://edgecasesystems.com/test.txt Result: hello world Success. [root@edgecase2 nginx]# ls -Z /usr/share/nginx/ drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 html drwxr-xr-x. root root system_u:object_r:usr_t:s0 modules Looks like I only actually needed the httpd_sys_content_t permission (read-only permission?) on /var/www/edgecase/basic, not httpd_sys_rw_content_t permission (read/write permission). Browse to: http://edgecasesystems.com Result: hello world The index configuration works. Next: Delete /var/www/edgecase and move back to /srv/edgecase/www. Set SELinux read permission on /srv/edgecase/www. [root@edgecase2 edgecase]# cd /var/www [root@edgecase2 www]# ls edgecase [root@edgecase2 www]# rm -fr edgecase [root@edgecase2 www]# cd /srv/edgecase [root@edgecase2 edgecase]# ls www [root@edgecase2 edgecase]# ls -Z drwxr-xr-x. root root unconfined_u:object_r:var_t:s0 www [root@edgecase2 edgecase]# ls -Z www -rw-r--r--. root root unconfined_u:object_r:var_t:s0 404.html -rw-r--r--. root root unconfined_u:object_r:var_t:s0 50x.html -rw-r--r--. root root unconfined_u:object_r:var_t:s0 index.html -rw-r--r--. root root unconfined_u:object_r:var_t:s0 nginx-logo.png -rw-r--r--. root root unconfined_u:object_r:var_t:s0 poweredby.png -rw-r--r--. root root unconfined_u:object_r:var_t:s0 test.txt [root@edgecase2 edgecase]# chcon -t httpd_sys_r_content_t www -R chcon: failed to change context of 'test.txt' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument chcon: failed to change context of '404.html' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument chcon: failed to change context of '50x.html' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument chcon: failed to change context of 'index.html' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument chcon: failed to change context of 'nginx-logo.png' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument chcon: failed to change context of 'poweredby.png' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument chcon: failed to change context of 'www' to 'unconfined_u:object_r:httpd_sys_r_content_t:s0': Invalid argument [root@edgecase2 edgecase]# chcon -v --type=httpd_sys_content_t www changing security context of 'www' [root@edgecase2 edgecase]# ls -Z drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 www [root@edgecase2 edgecase]# chcon -v --type=httpd_sys_content_t www -R changing security context of 'www/test.txt' changing security context of 'www/404.html' changing security context of 'www/50x.html' changing security context of 'www/index.html' changing security context of 'www/nginx-logo.png' changing security context of 'www/poweredby.png' changing security context of 'www' [root@edgecase2 edgecase]# ls -Z www -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 404.html -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 50x.html -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.html -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 nginx-logo.png -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 poweredby.png -rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 test.txt Hm. Strange that chcon -t httpd_sys_r_content_t www -R didn't work, but chcon -v --type=httpd_sys_content_t www -R did. When searching / reading, I noted that the --type=httpd_sys_content_t option was used on this page: hyperlink http://wiki.centos.org/HowTos/SELinux wiki.centos.org/HowTos/SELinux change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { index test.txt; } [root@edgecase2 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 ~]# systemctl restart nginx [root@edgecase2 ~]# curl http://edgecasesystems.com/test.txt hello world [root@edgecase2 nginx]# tail -1 /var/log/nginx/access.log [deleted] - - [15/Sep/2019:15:38:12 +0000] "GET /test.txt HTTP/1.1" 200 12 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" "-" Excellent. Next: Install Gunicorn on edgecase2 VPS and test it. Excerpt from: hyperlink http://docs.gunicorn.org/en/stable/install.html docs.gunicorn.org/en/stable/install.html Requirements: Python 2.x \>= 2.6 or Python 3.x \>= 3.2 [root@edgecase2 ~]# pip --version -bash: pip: command not found [root@edgecase2 ~]# yum search pip [...] python-virtualenv-api.noarch : An API for virtualenv/pip python2-pip.noarch : A tool for installing and managing Python 2 packages python34-pip.noarch : A tool for installing and managing Python3 packages python36-pip.noarch : A tool for installing and managing Python3 packages [...] [root@edgecase2 ~]# python --version Python 2.7.5 [root@edgecase2 ~]# yum install pip Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile epel/x86_64/metalink | 30 kB 00:00:00 * base: mirror.sov.uk.goscomb.net * epel: mirrors.coreix.net * extras: mirror.mhd.uk.as44574.net * updates: mirror.mhd.uk.as44574.net base | 3.6 kB 00:00:00 epel | 5.3 kB 00:00:00 extras | 3.4 kB 00:00:00 updates | 3.4 kB 00:00:00 (1/4): epel/x86_64/updateinfo | 1.0 MB 00:00:00 (2/4): epel/x86_64/primary_db | 6.8 MB 00:00:00 (3/4): extras/7/x86_64/primary_db | 215 kB 00:00:00 (4/4): updates/7/x86_64/primary_db | 7.4 MB 00:00:00 No package pip available. Error: Nothing to do [root@edgecase2 ~]# yum install python2-pip.noarch Loaded plugins: fastestmirror Loading mirror speeds from cached hostfile * base: mirror.sov.uk.goscomb.net * epel: mirrors.coreix.net * extras: mirror.mhd.uk.as44574.net * updates: mirror.mhd.uk.as44574.net Resolving Dependencies --\> Running transaction check ---\> Package python2-pip.noarch 0:8.1.2-10.el7 will be installed --\> Finished Dependency Resolution Dependencies Resolved ==================================================================================== Package Arch Version Repository Size ==================================================================================== Installing: python2-pip noarch 8.1.2-10.el7 epel 1.7 M Transaction Summary ==================================================================================== Install 1 Package Total download size: 1.7 M Installed size: 7.2 M Is this ok [y/d/N]: y Downloading packages: python2-pip-8.1.2-10.el7.noarch.rpm | 1.7 MB 00:00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : python2-pip-8.1.2-10.el7.noarch 1/1 Verifying : python2-pip-8.1.2-10.el7.noarch 1/1 Installed: python2-pip.noarch 0:8.1.2-10.el7 Complete! [root@edgecase2 ~]# pip --version pip 8.1.2 from /usr/lib/python2.7/site-packages (python 2.7) [root@edgecase2 ~]# pip install gunicorn Collecting gunicorn Downloading https://files.pythonhosted.org/packages/8c/da/b8dd8deb741bff556db53902d4706774c8e1e67265f69528c14c003644e6/gunicorn-19.9.0-py2.py3-none-any.whl (112kB) 100% |________________________________| 122kB 5.4MB/s Installing collected packages: gunicorn Successfully installed gunicorn-19.9.0 You are using pip version 8.1.2, however version 19.2.3 is available. You should consider upgrading via the 'pip install --upgrade pip' command. [root@edgecase2 ~]# gunicorn --version gunicorn (version 19.9.0) [root@edgecase2 ~]# which gunicorn /usr/bin/gunicorn [root@edgecase2 ~]# file /usr/bin/gunicorn /usr/bin/gunicorn: Python script, ASCII text executable [root@edgecase2 ~]# cat /usr/bin/gunicorn #!/usr/bin/python2 # -*- coding: utf-8 -*- import re import sys from gunicorn.app.wsgiapp import run if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\\.pyw|\\.exe)?$', '', sys.argv[0]) sys.exit(run()) [some experimentation and reading occurs here, drawing mainly from the following links] hyperlink http://docs.gunicorn.org/en/stable/run.html docs.gunicorn.org/en/stable/run.html hyperlink http://docs.gunicorn.org/en/stable/deploy.html docs.gunicorn.org/en/stable/deploy.html Example test application: def app(environ, start_response): """Simplest possible application object""" data = 'Hello, World!\\n' status = '200 OK' response_headers = [ ('Content-type','text/plain'), ('Content-Length', str(len(data))) ] start_response(status, response_headers) return iter([data]) [root@edgecase2 ~]# vi test.py [paste in the example test application shown above] [root@edgecase2 ~]# gunicorn --bind=localhost:8080 --workers=2 test:app [2019-09-15 18:05:07 +0000] [29303] [INFO] Starting gunicorn 19.9.0 [2019-09-15 18:05:07 +0000] [29303] [INFO] Listening at: http://127.0.0.1:8080 (29303) [2019-09-15 18:05:07 +0000] [29303] [INFO] Using worker: sync [2019-09-15 18:05:07 +0000] [29308] [INFO] Booting worker with pid: 29308 [2019-09-15 18:05:07 +0000] [29309] [INFO] Booting worker with pid: 29309 [open another bash shell here and log in to edgecase2 VPS:] [root@edgecase2 ~]# curl localhost hello world [root@edgecase2 ~]# curl localhost:8080 Hello, World! [root@edgecase2 ~]# curl edgecasesystems.com:80 hello world [root@edgecase2 ~]# curl edgecasesystems.com:8080 curl: (7) Failed connect to edgecasesystems.com:8080; Connection refused [switch back to the original bash shell. press ctrl-C to stop the gunicorn process.] ^C[2019-09-15 18:06:07 +0000] [29303] [INFO] Handling signal: int [2019-09-15 18:06:07 +0000] [29308] [INFO] Worker exiting (pid: 29308) [2019-09-15 18:06:07 +0000] [29309] [INFO] Worker exiting (pid: 29309) [2019-09-15 18:06:07 +0000] [29303] [INFO] Shutting down: Master [root@edgecase2 ~]# gunicorn --bind=edgecasesystems.com:8080 --workers=1 test:app [2019-09-15 18:10:00 +0000] [29325] [INFO] Starting gunicorn 19.9.0 [2019-09-15 18:10:00 +0000] [29325] [INFO] Listening at: http://46.101.86.226:8080 (29325) [2019-09-15 18:10:00 +0000] [29325] [INFO] Using worker: sync [2019-09-15 18:10:00 +0000] [29330] [INFO] Booting worker with pid: 29330 [switch to second bash shell] [root@edgecase2 ~]# curl localhost hello world [root@edgecase2 ~]# curl localhost:80 hello world [root@edgecase2 ~]# curl localhost:8080 curl: (7) Failed connect to localhost:8080; Connection refused [root@edgecase2 ~]# curl edgecasesystems.com hello world [root@edgecase2 ~]# curl edgecasesystems.com:80 hello world [root@edgecase2 ~]# curl edgecasesystems.com:8080 Hello, World! [switch back to the original bash shell. press ctrl-C to stop the gunicorn process.] ^C[2019-09-15 18:35:22 +0000] [29325] [INFO] Handling signal: int [2019-09-15 18:35:22 +0000] [29330] [INFO] Worker exiting (pid: 29330) [2019-09-15 18:35:22 +0000] [29325] [INFO] Shutting down: Master Good. The gunicorn server is serving on the domain edgecasesystems.com on port 8080. Next: Configure nginx to pass all requests to the gunicorn server. In second bash shell, set gunicorn server process running: [root@edgecase2 ~]# gunicorn --bind=localhost:8080 --workers=1 test:app Switch to first bash shell: Change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://localhost:8080; } [root@edgecase2 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 ~]# systemctl restart nginx Browse to http://edgecasesystems.com: nginx error! [...] [root@edgecase2 ~]# tail -1 /var/log/nginx/error.log 2019/09/15 19:36:17 [crit] 29584#0: *1 connect() to [::1]:8080 failed (13: Permission denied) while connecting to upstream, client: 46.101.86.226, server: _, request: "GET / HTTP/1.1", upstream: "http://[::1]:8080/", host: "edgecasesystems.com" [experimentation + searching + reading occurs here] I'll follow some suggestions from: hyperlink http://stackoverflow.com/questions/23948527/13-permission-denied-while-connecting-to-upstreamnginx stackoverflow.com/questions/23948527/13-permission-denied-while-connecting-to-upstreamnginx [root@edgecase2 ~]# getsebool -a | grep httpd httpd_anon_write --\> off httpd_builtin_scripting --\> on httpd_can_check_spam --\> off httpd_can_connect_ftp --\> off httpd_can_connect_ldap --\> off httpd_can_connect_mythtv --\> off httpd_can_connect_zabbix --\> off httpd_can_network_connect --\> off httpd_can_network_connect_cobbler --\> off httpd_can_network_connect_db --\> off httpd_can_network_memcache --\> off httpd_can_network_relay --\> off httpd_can_sendmail --\> off httpd_dbus_avahi --\> off httpd_dbus_sssd --\> off httpd_dontaudit_search_dirs --\> off httpd_enable_cgi --\> on httpd_enable_ftp_server --\> off httpd_enable_homedirs --\> off httpd_execmem --\> off httpd_graceful_shutdown --\> on httpd_manage_ipa --\> off httpd_mod_auth_ntlm_winbind --\> off httpd_mod_auth_pam --\> off httpd_read_user_content --\> off httpd_run_ipa --\> off httpd_run_preupgrade --\> off httpd_run_stickshift --\> off httpd_serve_cobbler_files --\> off httpd_setrlimit --\> off httpd_ssi_exec --\> off httpd_sys_script_anon_write --\> off httpd_tmp_exec --\> off httpd_tty_comm --\> off httpd_unified --\> off httpd_use_cifs --\> off httpd_use_fusefs --\> off httpd_use_gpg --\> off httpd_use_nfs --\> off httpd_use_openstack --\> off httpd_use_sasl --\> off httpd_verify_dns --\> off [root@edgecase2 ~]# setsebool -P httpd_can_network_connect 1 [root@edgecase2 ~]# getsebool -a | grep httpd | grep network httpd_can_network_connect --\> on httpd_can_network_connect_cobbler --\> off httpd_can_network_connect_db --\> off httpd_can_network_memcache --\> off httpd_can_network_relay --\> off [root@edgecase2 ~]# curl edgecasesystems.com Hello, World! Cool. Works. Now remove the SELinux permission. I'll switch to using a Unix socket instead of a network connection. [root@edgecase2 ~]# setsebool -P httpd_can_network_connect 0 [root@edgecase2 ~]# getsebool -a | grep httpd | grep network httpd_can_network_connect --\> off httpd_can_network_connect_cobbler --\> off httpd_can_network_connect_db --\> off httpd_can_network_memcache --\> off httpd_can_network_relay --\> off Next: Configure nginx to pass requests to the gunicorn server via a Unix socket. First, stop the gunicorn server, then start it again, this time listening on a socket. [switch back to the second bash shell. press ctrl-C to stop the gunicorn process.] ^C[2019-09-15 19:45:34 +0000] [29379] [INFO] Handling signal: int [2019-09-15 19:45:34 +0000] [29384] [INFO] Worker exiting (pid: 29384) [2019-09-15 19:45:34 +0000] [29379] [INFO] Shutting down: Master [root@edgecase2 ~]# gunicorn --bind=unix:/tmp/gunicorn.sock --workers=1 test:app [2019-09-15 19:48:46 +0000] [29632] [INFO] Starting gunicorn 19.9.0 [2019-09-15 19:48:46 +0000] [29632] [INFO] Listening at: unix:/tmp/gunicorn.sock (29632) [2019-09-15 19:48:46 +0000] [29632] [INFO] Using worker: sync [2019-09-15 19:48:46 +0000] [29637] [INFO] Booting worker with pid: 29637 [switch to first bash shell] [root@edgecase2 ~]# curl --unix-socket /tmp/gunicorn.sock http://test Hello, World! [root@edgecase2 ~]# curl --unix-socket /tmp/gunicorn.sock curl: no URL specified! curl: try 'curl --help' or 'curl --manual' for more information [root@edgecase2 ~]# curl --unix-socket /tmp/gunicorn.sock http://test Hello, World! [root@edgecase2 ~]# curl --unix-socket /tmp/gunicorn.sock h Hello, World! Change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass unix:/tmp/gunicorn.sock; } [root@edgecase2 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 ~]# systemctl restart nginx Browse to http://edgecasesystems.com: nginx error! [...] [root@edgecase2 ~]# tail -1 /var/log/nginx/error.log 2019/09/15 19:58:42 [crit] 29730#0: *1 connect() to unix:/tmp/gunicorn.sock failed (2: No such file or directory) while connecting to upstream, client: 46.101.86.226, server: _, request: "GET / HTTP/1.1", upstream: "http://unix:/tmp/gunicorn.sock:/", host: "edgecasesystems.com" [root@edgecase2 ~]# ls -l /tmp total 0 srwxrwxrwx. 1 root root 0 Sep 15 19:48 gunicorn.sock drwx------. 3 root root 17 Jul 4 10:14 systemd-private-7f78a3d0bfb74fa89ef2a54f4a06856c-chronyd.service-ez5kpd drwx------. 3 root root 17 Sep 15 19:58 systemd-private-7f78a3d0bfb74fa89ef2a54f4a06856c-nginx.service-UzwWpy The socket file should allow the nginx user to write to it. hyperlink http://stackoverflow.com/questions/22272943/nginx-cannot-find-unix-socket-file-with-unicorn-no-such-file-or-directory stackoverflow.com/questions/22272943/nginx-cannot-find-unix-socket-file-with-unicorn-no-such-file-or-directory Excerpt from: hyperlink http://serverfault.com/questions/463993/nginx-unix-domain-socket-error/464025#464025 serverfault.com/questions/463993/nginx-unix-domain-socket-error/464025#464025 You can't place sockets intended for interprocess communication in /tmp. For security reasons, recent versions of Fedora use namespaced temporary directories [ http://fedoraproject.org/wiki/Features/ServicesPrivateTmp ], meaning every service sees a completely different /tmp and can only see its own files in that directory. To resolve the issue, place the socket in a different directory, such as /run (formerly known as /var/run). answered Jan 8 '13 at 14:41 Michael Hampton Change location of socket from /tmp/gunicorn.sock to /run/gunicorn.sock [switch back to the second bash shell. press ctrl-C to stop the gunicorn process.] ^C[2019-09-15 20:16:02 +0000] [29795] [INFO] Handling signal: int [2019-09-15 20:16:02 +0000] [29800] [INFO] Worker exiting (pid: 29800) [2019-09-15 20:16:02 +0000] [29795] [INFO] Shutting down: Master [root@edgecase2 ~]# gunicorn --bind=unix:/run/gunicorn.sock --workers=1 test:app [2019-09-15 20:16:06 +0000] [29813] [INFO] Starting gunicorn 19.9.0 [2019-09-15 20:16:06 +0000] [29813] [INFO] Listening at: unix:/run/gunicorn.sock (29813) [2019-09-15 20:16:06 +0000] [29813] [INFO] Using worker: sync [2019-09-15 20:16:06 +0000] [29818] [INFO] Booting worker with pid: 29818 [switch to first bash shell] Change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass unix:/run/gunicorn.sock; } [root@edgecase2 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 ~]# systemctl restart nginx [root@edgecase2 ~]# curl --unix-socket /run/gunicorn.sock h Hello, World! Browse to http://edgecasesystems.com: nginx error! [...] [root@edgecase2 ~]# tail -1 /var/log/nginx/error.log 2019/09/15 20:16:40 [crit] 29836#0: *1 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 46.101.86.226, server: _, request: "GET / HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/", host: "edgecasesystems.com" Ok, now the nginx server can see the socket, but it doesn't have permission to connect to it. Check SELinux log: [root@edgecase2 ~]# tail -2 /var/log/audit/audit.log type=CRYPTO_KEY_USER msg=audit(1568578956.471:1212622): pid=29844 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 msg='op=destroy kind=server fp=SHA256:ea:07:15:0d:68:e4:8b:bf:bd:20:b5:a2:83:df:af:c3:79:a7:2a:55:0c:b1:57:5a:7c:58:be:05:b8:eb:3a:74 direction=? spid=29844 suid=0 exe="/usr/sbin/sshd" hostname=? addr=? terminal=? res=success' type=USER_LOGIN msg=audit(1568578956.471:1212623): pid=29844 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:sshd_t:s0-s0:c0.c1023 msg='op=login acct="(unknown)" exe="/usr/sbin/sshd" hostname=? addr=103.17.53.148 terminal=ssh res=failed' Turn off SELinux: [root@edgecase2 ~]# setenforce 0 [root@edgecase2 ~]# curl edgecasesystems.com Hello, World! Ok, works if SELinux is disabled. [root@edgecase2 ~]# setenforce 1 [some days have passed - do a new runthrough] [Check current status of SELinux] [root@edgecase2 ~]# getenforce Enforcing [root@edgecase2 ~]# cat /etc/selinux/config # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=enforcing # SELINUXTYPE= can take one of three values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted Change this section of /etc/nginx/nginx.conf: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { } to this: server { listen 80 default_server; listen [::]:80 default_server; server_name _; root /srv/edgecase/www; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { proxy_pass http://unix:/run/gunicorn.sock; } Note: At some earlier point I changed unix:/run/gunicorn.sock to http://unix:/run/gunicorn.sock (I found it in the file when I opened it just now), but I'm not sure exactly when. Testing with proxy_pass unix:/run/gunicorn.sock: [root@edgecase2 ~]# systemctl restart nginx Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details. [root@edgecase2 ~]# nginx -t nginx: [emerg] invalid URL prefix in /etc/nginx/nginx.conf:48 nginx: configuration file /etc/nginx/nginx.conf test failed Switch back to proxy_pass http://unix:/run/gunicorn.sock. [root@edgecase2 ~]# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful [root@edgecase2 ~]# systemctl restart nginx [root@edgecase2 ~]# systemctl status nginx | grep Active Active: active (running) since Sat 2019-09-21 09:27:10 UTC; 10s ago [switch to a second bash shell] [root@edgecase2 ~]# gunicorn --bind=unix:/run/gunicorn.sock --workers=1 test:app [2019-09-21 09:28:03 +0000] [17502] [INFO] Starting gunicorn 19.9.0 [2019-09-21 09:28:03 +0000] [17502] [INFO] Listening at: unix:/run/gunicorn.sock (17502) [2019-09-21 09:28:03 +0000] [17502] [INFO] Using worker: sync [2019-09-21 09:28:03 +0000] [17507] [INFO] Booting worker with pid: 17507 [switch to a third bash shell] [root@edgecase2 ~]# curl --unix-socket /run/gunicorn.sock h Hello, World! Browse to http://edgecasesystems.com: nginx error! [...] [root@edgecase2 ~]# tail -1 /var/log/nginx/error.log 2019/09/21 09:29:36 [crit] 17494#0: *4 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: [deleted], server: _, request: "GET /favicon.ico HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/favicon.ico", host: "edgecasesystems.com" The nginx server can see the gunicorn socket, but it doesn't have permission to connect to it. Check SELinux log: [root@edgecase2 ~]# grep nginx /var/log/audit/audit.log type=SERVICE_STOP msg=audit(1569058030.240:1301773): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=nginx comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success' type=SERVICE_START msg=audit(1569058030.364:1301774): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=nginx comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success' type=AVC msg=audit(1569058175.985:1301787): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 type=SYSCALL msg=audit(1569058175.985:1301787): arch=c000003e syscall=42 success=no exit=-13 a0=c a1=559e009bb000 a2=6e a3=7fffdb49de30 items=0 ppid=17493 pid=17494 auid=4294967295 uid=997 gid=994 euid=997 suid=997 fsuid=997 egid=994 sgid=994 fsgid=994 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null) type=AVC msg=audit(1569058176.055:1301788): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 type=SYSCALL msg=audit(1569058176.055:1301788): arch=c000003e syscall=42 success=no exit=-13 a0=c a1=559e009bb000 a2=6e a3=7fffdb49de30 items=0 ppid=17493 pid=17494 auid=4294967295 uid=997 gid=994 euid=997 suid=997 fsuid=997 egid=994 sgid=994 fsgid=994 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null) type=AVC msg=audit(1569058176.082:1301789): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 type=SYSCALL msg=audit(1569058176.082:1301789): arch=c000003e syscall=42 success=no exit=-13 a0=d a1=559e009bb000 a2=6e a3=7fffdb49de30 items=0 ppid=17493 pid=17494 auid=4294967295 uid=997 gid=994 euid=997 suid=997 fsuid=997 egid=994 sgid=994 fsgid=994 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null) type=AVC msg=audit(1569058176.128:1301790): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 type=SYSCALL msg=audit(1569058176.128:1301790): arch=c000003e syscall=42 success=no exit=-13 a0=d a1=559e009bb000 a2=6e a3=7fffdb49de30 items=0 ppid=17493 pid=17494 auid=4294967295 uid=997 gid=994 euid=997 suid=997 fsuid=997 egid=994 sgid=994 fsgid=994 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null) After a look at: hyperlink http://nts.strzibny.name/allowing-nginx-to-use-a-pumaunicorn-unix-socket-with-selinux nts.strzibny.name/allowing-nginx-to-use-a-pumaunicorn-unix-socket-with-selinux I'll try using: grep nginx /var/log/audit/audit.log | audit2allow -m nginx The output of which is a suggested SELinux policy file. [root@edgecase2 ~]# grep nginx /var/log/audit/audit.log | audit2allow -m nginx module nginx 1.0; require { type unconfined_t; type httpd_t; class unix_stream_socket connectto; } #============= httpd_t ============== #!!!! The file '/run/gunicorn.sock' is mislabeled on your system. #!!!! Fix with $ restorecon -R -v /run/gunicorn.sock allow httpd_t unconfined_t:unix_stream_socket connectto; [root@edgecase2 ~]# restorecon -R -v /run/gunicorn.sock [root@edgecase2 ~]# ls -Z /run/gunicorn.sock srwxrwxrwx. root root unconfined_u:object_r:var_run_t:s0 /run/gunicorn.sock [root@edgecase2 ~]# grep nginx /var/log/audit/audit.log | audit2allow -m nginx module nginx 1.0; require { type unconfined_t; type httpd_t; class unix_stream_socket connectto; } #============= httpd_t ============== #!!!! The file '/run/gunicorn.sock' is mislabeled on your system. #!!!! Fix with $ restorecon -R -v /run/gunicorn.sock allow httpd_t unconfined_t:unix_stream_socket connectto; Excerpt from: hyperlink http://access.redhat.com/sites/default/files/attachments/what_is_selinux_trying_to_tell_me.pdf access.redhat.com/sites/default/files/attachments/what_is_selinux_trying_to_tell_me.pdf SELinux is all about labels. Every process, file, directory, and device on an SELinux system has a label. If these labels are wrong, SELinux will not function properly. If a file is mislabeled, a confined application might not be allowed access to the mislabeled file. If an executable is mislabeled, it may not transition to the correct label when executing, causing access violations and potentially causing it to mislabel files it creates. Excerpts from: hyperlink http://www.nginx.com/blog/using-nginx-plus-with-selinux www.nginx.com/blog/using-nginx-plus-with-selinux SELinux is enabled by default on modern RHEL and CentOS servers. Each operating system object (process, file descriptor, file, etc.) is labeled with an SELinux context that defines the permissions and operations the object can perform. In RHEL 6.6/CentOS 6.6 and later, NGINX is labeled with the httpd_t context. [...] The httpd_t context permits NGINX to listen on common web server ports, to access configuration files in /etc/nginx, and to access content in the standard docroot location (/usr/share/nginx). It does not permit many other operations, such as proxying to upstream locations or communicating with other processes through sockets. I'll use some commands and approaches suggested by hyperlink http://www.nginx.com/blog/using-nginx-plus-with-selinux www.nginx.com/blog/using-nginx-plus-with-selinux [root@edgecase2 ~]# grep nginx /var/log/audit/audit.log | audit2why type=AVC msg=audit(1569058175.985:1301787): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access. type=AVC msg=audit(1569058176.055:1301788): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access. type=AVC msg=audit(1569058176.082:1301789): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access. type=AVC msg=audit(1569058176.128:1301790): avc: denied { connectto } for pid=17494 comm="nginx" path="/run/gunicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 Was caused by: Missing type enforcement (TE) allow rule. You can use audit2allow to generate a loadable module to allow this access. [root@edgecase2 ~]# ls -Z /run/gunicorn.sock srwxrwxrwx. root root unconfined_u:object_r:var_run_t:s0 /run/gunicorn.sock [root@edgecase2 ~]# semanage fcontext -a -t httpd_sys_content_t /run/gunicorn.sock ValueError: File spec /run/gunicorn.sock conflicts with equivalency rule '/run /var/run'; Try adding '/var/run/gunicorn.sock' instead [root@edgecase2 ~]# semanage fcontext -a -t httpd_sys_content_t /var/run/gunicorn.sock [root@edgecase2 ~]# ls -Z /run/gunicorn.sock srwxrwxrwx. root root unconfined_u:object_r:var_run_t:s0 /run/gunicorn.sock [root@edgecase2 ~]# restorecon -v /run/gunicorn.sock restorecon reset /run/gunicorn.sock context unconfined_u:object_r:var_run_t:s0-\>unconfined_u:object_r:httpd_sys_content_t:s0 [root@edgecase2 ~]# ls -Z /run/gunicorn.sock srwxrwxrwx. root root unconfined_u:object_r:httpd_sys_content_t:s0 /run/gunicorn.sock Ok. /run/gunicorn.sock now has a label "httpd_sys_content_t" instead of "var_run_t". Hopefully, this means that an httpd process (e.g. nginx) can now access it. [root@edgecase2 ~]# grep nginx /var/log/audit/audit.log | audit2allow -m nginx module nginx 1.0; require { type unconfined_t; type httpd_t; class unix_stream_socket connectto; } #============= httpd_t ============== #!!!! The file '/run/gunicorn.sock' is mislabeled on your system. #!!!! Fix with $ restorecon -R -v /run/gunicorn.sock allow httpd_t unconfined_t:unix_stream_socket connectto; Hm. Still reported as mislabeled. [root@edgecase2 ~]# restorecon -R -v /run/gunicorn.sock [root@edgecase2 ~]# ls -Z /run/gunicorn.sock srwxrwxrwx. root root unconfined_u:object_r:httpd_sys_content_t:s0 /run/gunicorn.sock Browse to http://edgecasesystems.com: nginx error! [...] [root@edgecase2 ~]# tail -1 /var/log/nginx/error.log 2019/09/21 09:54:59 [crit] 17494#0: *17 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 82.11.184.184, server: _, request: "GET /poweredby.png HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/poweredby.png", host: "edgecasesystems.com", referrer: "http://edgecasesystems.com/" To generate a compiled policy, include the -M option: [root@edgecase2 ~]# grep nginx /var/log/audit/audit.log | audit2allow -M nginx ******************** IMPORTANT *********************** To make this policy package active, execute: semodule -i nginx.pp [root@edgecase2 ~]# semodule -i nginx.pp [Verify success] [root@edgecase2 ~]# semodule -l | grep nginx nginx 1.0 Browse to http://edgecasesystems.com: Hello, World! [root@edgecase2 ~]# tail -1 /var/log/nginx/error.log 2019/09/21 09:54:59 [crit] 17494#0: *17 connect() to unix:/run/gunicorn.sock failed (13: Permission denied) while connecting to upstream, client: 82.11.184.184, server: _, request: "GET /poweredby.png HTTP/1.1", upstream: "http://unix:/run/gunicorn.sock:/poweredby.png", host: "edgecasesystems.com", referrer: "http://edgecasesystems.com/" [root@edgecase2 ~]# tail -1 /var/log/nginx/access.log [deleted] - - [21/Sep/2019:09:59:14 +0000] "GET / HTTP/1.1" 200 14 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0" "-" [root@edgecase2 ~]# curl http://edgecasesystems.com/ Hello, World! Excellent. Cleanup: press ctrl-C to stop the gunicorn process. ^C[2019-09-21 10:24:14 +0000] [17502] [INFO] Handling signal: int [2019-09-21 10:24:14 +0000] [17507] [INFO] Worker exiting (pid: 17507) [2019-09-21 10:24:14 +0000] [17502] [INFO] Shutting down: Master Exit the bash shells. That's the end of this project. Changes from the original text: - I have not always preserved the format of any excerpts from webpages on other sites (e.g. not preserving the original bold/italic styles, changing the list structures, not preserving hyperlinks). - I have not always preserved the format of any computer output (e.g. from running bash commands). Examples: Setting input lines in bold text, adding/removing newlines in order to make a sequence of commands easier to read, using hyphens for lists and sublists instead of indentation, breaking wide tables into consecutive sections, replacing non-ASCII curled single quotation marks with ASCII straight single quotation marks, replacing Unicode black square characters with ASCII underline characters. - I have replaced instances of my IP address with "[deleted]".
iQIcBAABCgAGBQJdkOXqAAoJEC8RP+HmG9MXsCUQALxrhF8iM+bxFBdlXPT4pets WC00V34rPedYelw9QeBXa8cFLTPd5qOdCf3Ziy0ZUnY5QYIoQiI5YfLxLSfVknhF Sl7yDpByMUCp7l7XCc1BHm9Kh2XazATtjl19LgY1etRk5DsS1ZiVFz2fElC6oeZ1 bvbGH2LDfOeihQHknNOGHZC9n8Iu4AIL8Nmdro/0QubeeYgzLd8vGGW70ZiQ4SfC haD7FxsNb/+GHSyKpTeVauJMUTPNkctCFfAmmDVga6WSa9yyYQIWo+tOZKRC8V5q iFL2ioA8IqP00z2NEq1DyQqpZzhZAiKu6pSoEEC3StIeYZ0PKkkIO6boCSH1o4CJ 37kaUzCCXRB/OPAse1zZE+QQc1UfHp3ebFVnzMtADmhJfJzxm8mmIrLmqRyPE3Qp vAfrmGo5WzzItgzI5DVlbDopHM9Sp+VqqcWb2iwtNs+nZVwu/Ei44CWW2fYi9Iwm qCmjyIsQuC5P/bmAgPcma9AcRGjiCwasF6jX02jLex6zAVZCwKo/0dM2GAv1wYEo 2TqxjKmNe5yekyHVCFul1q336pcHVTCEr16taz7ww1odq8wL1mpm2ZZq/skasta1 k/mGKmO4oU4tsX0lTmNP5tyjhI1I2cCy4UKFTdA3eYrCHebbH7MvIrG0af3dIl4k tlHUp3LqKOev+0CF1PWo =5tZP
iQIcBAABCgAGBQJdkPGcAAoJECL1OzZgiBhwOeYP/jyuaRENIdM5bvNmLOdMzmyZ 0/4ArD4ETm2sH/WDApl/oxKHewZikbgpE9M7CoxXips5NjM4Z2H2ruRFda3JRZeJ vyMAd7H2cunu3xJ2IWxoRLKZA0DpKZ8uE90Bji595Ex9+41VvWtwjk/6To4UAiaH s7btJHqo0NS7CGngNwxJLn3aWUZm2yLDoyKPKm+AjIEMl89f+d7tSsHAwLGsLeoT XGitVNF7qN4L9XpbcI3eE1XdTGdRGiUGC62vMDXnGFaKJtF1TlIzpUHOTV6RGK7v QjHPt6W9KYtn1WS613AarAYhIpihpaiZBkyBknJlbVR3g2OoRNiFKg6nZl2dfUvR Fb+mRuNuTKpt6k2nuq2h574ntWw3W57Ss9BTqe70QEX3Oy4718k27XHRhXSWQvP/ TziK6GiEXKR7WoXBUcFgaS5duW4A6Uaj5R+xN2SSWa587PGyOZgFw82D08sj/C21 UF7dm+bVLhkiU9TkI6vcJnHB3t11cdqyn3GfZeeV2/+lKXHK62KEvNDnYJ5u9zn8 6Tabod6pii/BI7obGhJqvwcUuI+1Hc4jD8Cv59lvATiCh8yzBAcwTpZKzeeT79V9 2EgbUASu6JoUAGltdR07yHTZsqm0Dz3ReKGgF+3LVSwPePaBJmrfWUo+kkaMkgWJ ieR6fTNHspRKPAUFB0li =qcWU