Project

General

Profile

Support #433

Updated by Daniel Curtis over 9 years ago

{{>toc}} 

 Here is a procedure to install a FreeBSD with Nginx, MariaDB and PHP server stack. If any version of the packages needs to be changed, replace the versions in the commands accordingly. 

 h1. Pre-installation requirements 

 * Before installation of the components, make sure everything is up to date using the following command: 
 <pre> 
 pkg update -f && pkg upgrade 
 </pre> 

 * Install portmaster: 
 <pre> 
 cd /usr/ports/ports-mgmt/portmaster 
 make install clean 
 pkg2ng 
 </pre> 

 * Edit the @/etc/hosts@ file  
 <pre> 
 vi /etc/hosts 
 </pre> 
 #*And add/modify and add the following line: 
 <pre> 
 192.168.1.100 > 192.168.1.1                 www.example.com 
 </pre> 

 --- 

 h1. Install Nginx – Installation and Configuration 

 * Install Nginx 
 <pre> 
 portmaster www/nginx pkg install nginx 
 </pre> 

 * Start and enable Enable nginx to start at boot: 
 <pre> 
 echo 'nginx_enable="YES"' >> /etc/rc.conf 
 </pre> 

 * Start nginx: 
 <pre> 
 service nginx start 
 </pre> 

 h1. Install h2. PHP – Installation and Configuration 

 * Install PHP5 and other supporting packages: 
 <pre> 
 portmaster lang/php5 pkg install php5 
 </pre> 

 * 
 #* Install PHP extensions and a few modules: extensions: 
 <pre> 
 portmaster lang/php5-extensions databases/php5-mysql databases/php5-mysqli databases/php5-pdo_mysql www/php5-session pkg install php5-extensions 
 </pre> 
 #* Install MySQL support for PHP: 
 <pre> 
 pkg install php5-mysql php5-mysqli php5-pdo_mysql 
 </pre> 
 #* Install the php5-session package 
 <pre> 
 pkg install php5-session 
 </pre> 

 *NOTE*: There are many more PHP modules, to search for more PHP modules run: 
 <pre> 
 find /usr/ports/ -name "php5-*" pkg search php5 
 </pre> 

 *NOTE*: PHP capabilities can be further extended by using PECL packages, to search for more PECL packages run: 
 <pre> 
 find /usr/ports/ -name "pecl-*" pkg search pecl 
 </pre> 

 * Configure the default PHP settings 
 <pre> 
 cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini 
 </pre> 

 h2. h3. Configure PHP-FPM 

 * Edit @/usr/local/etc/php-fpm.conf@: 
 <pre> 
 vi /usr/local/etc/php-fpm.conf 
 </pre> 
 #* Make the following changes: 
 <pre> 
 events.mechanism = kqueue 
 listen = /var/run/php-fpm.sock 
 listen.owner = www 
 listen.group = www 
 listen.mode = 0666 
 </pre> 

 * Enable PHP-FPM to start at boot: 
 <pre> 
 echo 'php_fpm_enable="YES"' >> /etc/rc.conf 
 </pre> 

 * Start PHP-FPM: 
 <pre> 
 service php-fpm start 
 </pre> 

 h3. Configure Nginx to use PHP-FPM: 

 * Create a directory for a PHP web application or site: 
 <pre> 
 mkdir /usr/local/www/www.example.com 
 </pre> 

 * Edit @/usr/local/etc/nginx/nginx.conf@: 
 <pre> 
 vi /usr/local/etc/nginx/nginx.conf 
 </pre> 
 #* Add the following inside the @server{ }@ block: 
 <pre> 
 http { 
 ... 
   server { 
     listen         80; 
     server_name    localhost; 
     root           /usr/local/www/www.example.com; 
     access_log     /var/log/www.example.com-access.log; 
     error_log      /var/log/www.example.com-error.log 

     location / { 
         index    index.php index.html index.htm; 
     } 

     # For all PHP requests, pass them on to PHP-FPM via FastCGI 
     location ~ \.php$ { 
        fastcgi_pass unix:/var/run/php-fpm.sock; 
        fastcgi_param SCRIPT_FILENAME /usr/local/www/www.example.com$fastcgi_script_name; 
        fastcgi_param PATH_INFO $fastcgi_script_name; 
        include fastcgi_params; # include extra FCGI params 
     } 
   ... 
   } 
 ... 
 } 
 </pre> 

 The PHP support in FreeBSD is extremely modular so the base install is very limited. It is very easy to add support using the _lang/php5-extensions_ port. This port provides a menu driven interface to PHP extension installation. Alternatively, individual extensions can be installed using the appropriate port. 

 * Restart nginx: 
 <pre> 
 service nginx restart 
 </pre> 

 h1. Install Phusion Passenger 

 * Reinstall Nginx with Passenger support 
 <pre> 
 portmaster www/rubygem-passenger 
 </pre> 
 NOTE: Make sure to enable [X]NGINX when running make @config-recursive@ on _rubygem-passenger_ 
 NOTE: Make sure to enable [X]PASSENGER when running @make config@ on _nginx_ 

 * Configuring Nginx and Passenger 
 Edit the @/usr/local/etc/nginx/nginx.conf@ file to match: 
 <pre> 
 user    www www; 

 ## Change to match number of CPU cores 
 worker_processes 1; 

 error_log    /var/log/nginx/error.log notice; 
 pid          /var/run/nginx.pid; 

 events { 
     worker_connections    1024; 
 } 

 http { 
     passenger_root /usr/local/lib/ruby/gems/1.9/gems/passenger-4.0.29; 
     passenger_ruby /usr/local/bin/ruby; 
     passenger_max_pool_size 15; 
     passenger_pool_idle_time 300; 
     #passenger_spawn_method direct; # Uncomment on Ruby 1.8 h2. Enabling SSL for ENC to work 

     include         mime.types; 
     default_type    application/octet-stream; 
     sendfile        on; 
     tcp_nopush      on; 
     keepalive_timeout    65; 
     tcp_nodelay          on; 

     # Load config files from the /etc/nginx/conf.d directory 
     include /usr/local/etc/nginx/conf.d/*.conf; 

     server { 
         listen         80; 
         server_name    www.example.com; 

         passenger_enabled on; 
         passenger_user               www; 
         passenger_group              www; 

         access_log /var/log/nginx/dashboard_access.log; 
         root /usr/local/www/rubyapp/public; 
     } 

     server { 
         listen         443 ssl; 
         server_name    www.example.com; 

         passenger_enabled            on; 
         passenger_set_cgi_param      HTTP_X_CLIENT_DN $ssl_client_s_dn; 
         passenger_set_cgi_param      HTTP_X_CLIENT_VERIFY $ssl_client_verify; 
         passenger_user               www; 
         passenger_group              www; 

         access_log                   /var/log/nginx/puppet_access.log; 
         root                         /usr/local/www/rubyapp/public; 

         ssl_certificate              /var/puppet/ssl/certs/www.example.com.pem; 
         ssl_certificate_key          /var/puppet/ssl/private_keys/www.example.com.pem; 
         ssl_ciphers                  SSLv2:-LOW:-EXPORT:RC4+RSA; 
         ssl_prefer_server_ciphers    on; 
         ssl_session_cache            shared:SSL:128m; 
         ssl_session_timeout          5m; 
     } 
 } 
 </pre> 

 h1. Securing Nginx With SSL 

 * Install OpenSSL: 
 <pre> 
 portmaster security/openssl 
 </pre> 

 Enabling SSL in Nginx is simple. First add the ssl directive in the server listen option, then add the SSL certificate and key paths. 

 The basic server block should be look similar to the following: 
 <pre> 
     server { 
         listen                443 ssl; 
         server_name           www.example.com; 
         ssl_certificate       www.example.com.crt; 
         ssl_certificate_key www.example.com.key; 
         ... 
     } 
 </pre> 

 Some browsers may complain about a certificate signed by a well-known certificate authority, while other browsers may accept the certificate without issues. This occurs because the issuing authority has signed the server certificate using an intermediate certificate that is not present in the certificate base of well-known trusted certificate authorities which is distributed with a particular browser. In this case the authority provides a bundle of chained certificates which should be concatenated to the signed server certificate.  

 * The server certificate must appear before the chained certificates in the combined file: 
 <pre> 
 cat www.example.com.crt bundle.crt > www.example.com.chained.crt 
 </pre> 

 The resulting file should be used in the ssl_certificate directive: 
 <pre> 
     server { 
         listen                443 ssl; 
         server_name           www.example.com; 
         ssl_certificate       www.example.com.chained.crt; 
         ssl_certificate_key www.example.com.key; 
         ... 
     } 
 </pre> 

 h2. h3. Hardening Nginx with SSL 

 * Setup the Diffie-Hellman Key Exchange Parameters 
 <pre> 
 cd /usr/local/etc/nginx 
 openssl dhparam -out dhparam.pem 2048 
 </pre> 

 * Generate a strong SSL key and a CSR to send for signing by a CA: 
 <pre> 
 cd /usr/local/etc/nginx 
 openssl req -sha512 -out www.example.com.csr -new -newkey rsa:4096 -nodes -keyout www.example.com.key 
 </pre> 
 #* If the received SSL certificate requires additional bundle certificates, add them together like so: 
 <pre> 
 cd /usr/local/etc/nginx 
 cat www.example.com.crt www.example.com.bundle > www.example.com.chained.crt 
 </pre> 

 * Setup the Nginx configuration: 
 <pre> 
 vi /usr/local/etc/nginx/nginx.conf 
 </pre> 
 #* Then add or modify the configuration to look similar to the following: 
 <pre> 
 server { 

   listen 80;  
   listen 443 default ssl; 

   #ssl on; 
   ssl_certificate_key /etc/ssl/certs/www.example.com.pem; 
   ssl_certificate /etc/ssl/certs/ca-bundle.pem; 

   ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4'; 

   ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
   ssl_session_cache    builtin:1000    shared:SSL:10m; 
   ssl_stapling on; 
   ssl_stapling_verify on; 
   ssl_prefer_server_ciphers on; 
   ssl_dhparam /usr/local/etc/nginx/dhparam.pem; 

   add_header Strict-Transport-Security max-age=63072000; 
   add_header X-Frame-Options DENY; 
   add_header X-Content-Type-Options nosniff; 

   root /usr/local/www/; 
   index index.html index.htm; 
   autoindex on; 
   server_name www.example.com; 

   if ($scheme = http) { 
     return 301 https://$server_name$request_uri; 
   } 

 } 
 </pre> 

 h2. Install the Phusion Passenger module 

 * Reinstall Nginx with Passenger support 
 <pre> 
 portsnap fetch extract 
 cd /usr/ports/www/rubygem-passenger 
 make config-recursive 
 make install clean 
 cd /usr/ports/www/nginx 
 make config 
 make install clean 
 mkdir /usr/local/etc/nginx/conf.d 
 </pre> 
 NOTE: Make sure to enable [X]NGINX when running make @config-recursive@ on _rubygem-passenger_ 
 NOTE: Make sure to enable [X]PASSENGER when running @make config@ on _nginx_ 

 * Configuring Nginx and Passenger 
 Edit the @/usr/local/etc/nginx/nginx.conf@ file to match: 
 <pre> 
 user    www www; 

 ## Change to match number of CPU cores 
 worker_processes 1; 

 error_log    /var/log/nginx/error.log notice; 
 pid          /var/run/nginx.pid; 

 events { 
     worker_connections    1024; 
 } 

 http { 
     passenger_root /usr/local/lib/ruby/gems/1.9/gems/passenger-4.0.29; 
     passenger_ruby /usr/local/bin/ruby; 
     passenger_max_pool_size 15; 
     passenger_pool_idle_time 300; 
     #passenger_spawn_method direct; # Uncomment on Ruby 1.8 for ENC to work 

     include         mime.types; 
     default_type    application/octet-stream; 
     sendfile        on; 
     tcp_nopush      on; 
     keepalive_timeout    65; 
     tcp_nodelay          on; 

     # Load config files from the /etc/nginx/conf.d directory 
     include /usr/local/etc/nginx/conf.d/*.conf; 

     server { 
         listen         80; 
         server_name    www.example.com; 

         passenger_enabled on; 
         passenger_user               www; 
         passenger_group              www; 

         access_log /var/log/nginx/dashboard_access.log; 
         root /usr/local/www/rubyapp/public; 
     } 

     server { 
         listen         443 ssl; 
         server_name    www.example.com; 

         passenger_enabled            on; 
         passenger_set_cgi_param      HTTP_X_CLIENT_DN $ssl_client_s_dn; 
         passenger_set_cgi_param      HTTP_X_CLIENT_VERIFY $ssl_client_verify; 
         passenger_user               www; 
         passenger_group              www; 

         access_log                   /var/log/nginx/puppet_access.log; 
         root                         /usr/local/www/rubyapp/public; 

         ssl_certificate              /var/puppet/ssl/certs/www.example.com.pem; 
         ssl_certificate_key          /var/puppet/ssl/private_keys/www.example.com.pem; 
         ssl_ciphers                  SSLv2:-LOW:-EXPORT:RC4+RSA; 
         ssl_prefer_server_ciphers    on; 
         ssl_session_cache            shared:SSL:128m; 
         ssl_session_timeout          5m; 
     } 
 } 
 </pre> 

 --- 

 h1. Install MariaDB – Installation and Configuration 

 * Install MariaDB 5.5 server and client 
 <pre> 
 portmaster databases/mariadb55-server databases/mariadb55-client pkg install mariadb55-{server,client} 
 </pre> 

 h2. Configure MariaDB server 

 * Configure the MariaDB server 
 <pre> 
 cp /usr/local/share/mysql/my-small.cnf /usr/local/etc/my.cnf 
 </pre> 
 #* *my-small.cnf* - for systems with up to 64 Mb of RAM. 
 #* *my-medium.cnf* - for systems with up to 128 Mb of RAM (ideal for web servers). 
 #* *my-large.cnf* - for systems with 512 Mb of RAM (dedicated MySQL servers). 
 #* *my-huge.cnf* - for systems with 1-2 Gb of RAM (datacentres etc.). 

 * Enable MariaDB to start at boot: 
 <pre> 
 echo 'mysql_enable="YES"' >> /etc/rc.conf 
 </pre> 

 * Start MariaDB 
 <pre> 
 service mysql-server start 
 </pre> 

 * Set password for mysql using the following command 
 <pre> 
 mysqladmin -uroot password 
 </pre>  

 * Restart mysql using the following commands: 
 <pre> 
 service mysql-server restart 
 </pre> 

 h2. Install and configure phpMyAdmin 

 * Install phpmyadmin: 
 <pre> 
 pkg install phpmyadmin 
 </pre> 

 * Setup phpMyAdmin for nginx by adding the following to the server{ } block in /usr/local/etc/nginx/nginx.conf: 
 <pre> 
 ## phpMyAdmin 
 location ^~ /phpmyadmin { 
   access_log    off; 
   rewrite ^    /phpMyAdmin/ permanent; 
 } 
 
 location /phpMyAdmin { 
   root /usr/local/www/phpMyAdmin; 
   index index.php index.html; 

   ## Only Allow connections from localhost 
   allow 127.0.0.1; 
   deny all; 

     location ~ ^/phpMyAdmin/(.*\.php)$ { 
       root /usr/local/www/phpMyAdmin; 
       fastcgi_pass unix:/var/run/php-fpm.sock; 
       fastcgi_param SCRIPT_FILENAME /usr/local/www/phpMyAdmin$fastcgi_script_name; 
       fastcgi_param PATH_INFO $fastcgi_script_name; 
       include fastcgi_params; # include extra FCGI params 
     } 
 } 
 </pre> 

 Now its time to configure phpMyAdmin. Do this by creating the file @/usr/local/www/phpMyAdmin/config.inc.php@, the basic configuration file for phpMyAdmin. Traditionally, users have manually created or modified @/usr/local/www/phpMyAdmin/config.inc.php@, but now phpMyAdmin includes a nice setup script, making it much easier to create this file with the settings you want.  

 * Start by creating the directory /usr/local/www/phpMyAdmin/config and make it writable by the phpMyAdmin setup script: 
 <pre> 
 mkdir /usr/local/www/phpMyAdmin/config 
 chmod o+w /usr/local/www/phpMyAdmin/config 
 </pre> 

 * Then make @/usr/local/www/phpMyAdmin/config.inc.php@ readable by the phpMyAdmin setup script: 
 <pre> 
 chmod o+r /usr/local/www/phpMyAdmin/config.inc.php 
 </pre> 

 * Now open your web browser and navigate to http://www.example.com/phpmyadmin/setup where you will see the phpMyAdmin setup _Overview_ page.  

 * Select *New Server* and then select the *Authentication* tab.  
 *# Under the *Authentication type* choose +http+ from the drop-down list (using HTTP-Auth to sign-in into phpMyAdmin will avoid storing login/password credentials directly in config.inc.php) 
 *# And remove +root+ from the *User for config auth*. 

 * Now select *Apply* and you will be returned you to the Overview page where you should see a new server listed.  

 * Select *Save* again in the Overview page to save your configuration as @/usr/local/www/phpMyAdmin/config/config.inc.php@.  

 * Now let’s move that file up one directory to @/usr/local/www/phpMyAdmin@ where phpMyAdmin can make use of it. 
 <pre> 
 mv /usr/local/www/phpMyAdmin/config/config.inc.php /usr/local/www/phpMyAdmin   
 </pre>  

 * Now let’s try out phpMyAdmin to make sure it works. Point your web browser to http://www.example.com/phpmyadmin where you will be presented with a pop-up box requesting you to log in.  
 Use “root” and the MySQL password you set up previously, then you should be directed to the phpMyAdmin administration page.  

 * We no longer need the /usr/local/www/phpMyAdmin/config directory so let’s remove it, and the read permission we added previously to /usr/local/www/phpMyAdmin/config.inc.php: 
 <pre> 
 rm -r /usr/local/www/phpMyAdmin/config 
 chmod o-r /usr/local/www/phpMyAdmin/config.inc.php 
 </pre> 

 * And wrap up by restarting the nginx and MySQL servers: 
 <pre> 
 service nginx restart 
 service mysql-server restart 
 </pre> 

 h2. Resources 

 * http://www.bsdnow.tv/tutorials/nginx 
 * http://forums.freebsd.org/viewtopic.php?t=30268

Back