Project

General

Profile

Support #622

Updated by Daniel Curtis almost 9 years ago

{{>toc}} 

 Here is a procedure to install a FreeBSD with Nginx, PostgreSQL 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 the following line: 
 <pre> 
 192.168.1.100                 www.example.com 
 </pre> 

 --- 

 h1. Install Nginx 

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

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

 h1. Install PHP 

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

 * Install PHP extensions and a few modules: 
 <pre> 
 portmaster lang/php5-extensions databases/php5-pgsql databases/php5-pdo_pgsql www/php5-session 
 </pre> 

 *NOTE*: There are many more PHP modules, to search for more PHP modules run: 
 <pre> 
 find /usr/ports/ -name "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-*" 
 </pre> 

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

 h2. 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> 

 * Start and enable PHP-FPM at boot: 
 <pre> 
 echo 'php_fpm_enable="YES"' >> /etc/rc.conf 
 service php-fpm start 
 </pre> 

 h3. Configure Nginx to use PHP-FPM: 

 * Create a configuration directory to make managing individual server blocks easier 
 <pre> 
 mkdir /usr/local/etc/nginx/conf.d 
 </pre> 

 * Edit the main nginx config file: 
 <pre> 
 vi /usr/local/etc/nginx/nginx.conf 
 </pre> 
 #* And strip down the config file and add the include statement at the end to make it easier to handle various server blocks: 
 <pre> 
 #user    nobody; 
 worker_processes    1; 
 error_log    /var/log/nginx-error.log; 

 events { 
   worker_connections    1024; 
 } 

 http { 
   include         mime.types; 
   default_type    application/octet-stream; 

   sendfile          on; 
   #tcp_nopush       on; 

   #keepalive_timeout    0; 
   keepalive_timeout    65; 

   #gzip    on; 

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

 } 
 </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_ 
 *NOTE*: Ruby capabilities can be further extended by using rubygem packages, to search for more packages run: 
 <pre> 
 find /usr/ports/ -name "rubygem-*" 
 </pre> 

 h3.    Configuring Nginx and Passenger 

 * Edit the main nginx config file: 
 <pre> 
 vi /usr/local/etc/nginx/nginx.conf 
 </pre> 
 #* And add the Passenger config parameters: 
 <pre> 
 #user    nobody; 
 worker_processes    1; 
 error_log    /var/log/nginx-error.log; 

 events { 
   worker_connections    1024; 
 } 

 http { 
   include         mime.types; 
   default_type    application/octet-stream; 

   sendfile          on; 
   #tcp_nopush       on; 

   #keepalive_timeout    0; 
   keepalive_timeout    65; 

   #gzip    on; 

   # Load Phusion Passenger module globally 
   passenger_root /usr/local/lib/ruby/gems/2.1/gems/passenger-5.0.6; 
   passenger_ruby /usr/local/bin/ruby21; 
   passenger_max_pool_size 15; 
   passenger_pool_idle_time 300; 

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

 } 
 </pre> 

 --- 

 h1. Setting Up Web Sites 

 h2. Default Static Website 

 Start by setting up a simple static website, no server-side stuff PHP or Ruby; just plain HTML, CSS, JavaScript, etc. 

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

 * Add a *default site server block*: 
 <pre> 
 vi /usr/local/etc/nginx/conf.d/default.conf 
 </pre> 
 #* Add the following: 
 <pre> 
   server { 
     listen         80 default_server; 
     server_name    www.example.com; 

     access_log    /var/log/www.example.com.log    main; 

     location / { 
       root     /usr/local/www/www.example.com; 
       index    index.html index.htm; 
     } 

     # redirect server error pages to the static page /50x.html 
     error_page     500 502 503 504    /50x.html; 
     location = /50x.html { 
       root     /usr/local/www/nginx-dist; 
     } 

   } 
 </pre> 

 h2. PHP Website 

 * Create a directory for the web application: 
 <pre> 
 mkdir /usr/local/www/phpapp.example.com 
 </pre> 

 * Add a *phpapp.example.com server block*: 
 <pre> 
 vi /usr/local/etc/nginx/conf.d/phpapp.example.com.conf 
 </pre> 
 #* Add the following: 
 <pre> 
 server { 
   listen         80; 
   server_name    phpapp.example.com; 
   root           /usr/local/www/phpapp.example.com; 
   access_log     /var/log/phpapp.example.com-access.log; 
   error_log      /var/log/phpapp.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/phpapp.example.com$fastcgi_script_name; 
     fastcgi_param PATH_INFO $fastcgi_script_name; 
     include fastcgi_params; # include extra FCGI params 
   } 

 } 
 </pre> 

 h2. Ruby Website 

 * Create a directory for the web application: 
 <pre> 
 mkdir /usr/local/www/rubyapp.example.com 
 </pre> 

 * Add a *rubyapp.example.com server block*: 
 <pre> 
 vi /usr/local/etc/nginx/conf.d/rubyapp.example.com.conf 
 </pre> 
 #* Add the following: 
 <pre> 
 server { 
   listen         80; 
   server_name    rubyapp.example.com; 
   root           /usr/local/www/rubyapp.example.com/public; 
   access_log     /var/log/rubyapp.example.com-access.log; 
   error_log      /var/log/rubyapp.example.com-error.log 

   passenger_enabled on; 
   passenger_user      www; 
   passenger_group     www; 

 } 
 </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 SSL 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> 

 * 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> 

 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. Install PostgreSQL 9.4 

 * Install PostgreSQL: 
 <pre> 
 portmaster databases/postgresql94-server 
 </pre> 

 * Enable PostgreSQL at boot: 
 <pre> 
 echo 'postgresql_enable="YES"' >> /etc/rc.conf 
 </pre> 

 * Initialize the database: 
 <pre> 
 service postgresql initdb 
 </pre> 

 * Start PostgreSQL: 
 <pre> 
 service postgresql start 
 </pre> 

 h3. Create a new user 

 * Switch to the postgresql user: 
 <pre> 
 su - pgsql 
 </pre> 
 #* And add a new user 
 <pre> 
 create user -sdrP bob 
 </pre> 

 * When finished exit: 
 <pre> 
 exit 
 </pre> 

 * And wrap up by restarting the nginx and postgresql servers: 
 <pre> 
 service nginx restart 
 service postgresql restart 
 </pre> 

 h2. Resources 

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

Back