Digital Ocean
Table of Contents
- Set Up SSH Keys
- Setting up a new user
- SFTP and SCP
- Security
- How To Add Swap on Ubuntu 12.04
- How To Install Linux, nginx, MySQL, PHP (LEMP) stack on Ubuntu 12.04
- Migrate Wordpress to Nginx
- MySQL Tips
- How To Create a SSL Certificate on nginx for Ubuntu 12.04
- Nginx and PHP5-FPM Configuration and Optimizing Tips
- update issues
Set Up SSH Keys
Create the RSA key pair on the client machine
ssh-keygen -t rsa
Enter file in which to save the key (/home/demo/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Copy the Public Key
#1 use ssh-copy-id command ssh-copy-id user@123.45.56.78 #2 use SSH cat ~/.ssh/id_rsa.pub | ssh user@123.45.56.78 "cat >> ~/.ssh/authorized_keys"
[Optional] Disable the Password for Root Login
sudo nano /etc/ssh/sshd_config #fine the line that includes PermitRootLogin and modify it PermitRootLogin without-password reload ssh
Setting up a new user1
Create a New User
adduser demo
add Root Privileges to the New User
visudo # User privilege specification root ALL=(ALL:ALL) ALL #Under there, add the following line, granting all the permissions to your new user demo ALL=(ALL:ALL) ALL
Configure SSH (OPTIONAL)
nano /etc/ssh/sshd_config Port 25000 Protocol 2 PermitRootLogin no
PermitRootLogin: change this from yes to no to stop future root login. You will now only be logging on as the new user.
Add these lines to the bottom of the document, replacing demo in the AllowUsers line with your username. (AllowUsers will limit login to only the users on that line. To avoid this, skip this line):
UseDNS no AllowUsers demo
Reload and Done
reload ssh ssh -p 25000 demo@123.45.67.890
SFTP and SCP
SCP
scp ~/Downloads/backup_db.sql.gz username@server_ip_address:
SFTP
sftp username@remote_hostname_or_IP #download files from our remote host get remoteFile #Transferring files to the remote system put localFile
Security
How To Protect SSH with fail2ban on Ubuntu 12.042
How To Install DenyHosts on Ubuntu 12.043
How To Add Swap on Ubuntu 12.044
Check for Swap Space
sudo swapon -s #An empty list will confirm that you have no swap files enabled: Filename Type Size Used Priority
Create and Enable the Swap File
1024*512k=512M swap space
sudo dd if=/dev/zero of=/swapfile bs=1024 count=512k sudo mkswap /swapfile #The results display: Setting up swapspace version 1, size = 262140 KiB no label, UUID=103c4545-5fc5-47f3-a8b3-dfbdb64fd7eb #Finish up by activating the swap file: sudo swapon /swapfile #You will then be able to see the new swap file when you view the swap summary. swapon -s Filename Type Size Used Priority /swapfile file 262140 0 -1 #the swap is permanent by adding it to the fstab file sudo nano /etc/fstab #Paste in the following line: /swapfile none swap sw 0 0
More Setting
Swappiness in the file should be set to 0. Skipping this step may cause both poor performance, whereas setting it to 0 will cause swap to act as an emergency buffer, preventing out-of-memory crashes.
You can do this with the following commands:
echo 0 | sudo tee /proc/sys/vm/swappiness echo vm.swappiness = 0 | sudo tee -a /etc/sysctl.conf
To prevent the file from being world-readable, set up the correct permissions on the swap file:
sudo chown root:root /swapfile sudo chmod 0600 /swapfile
How To Install Linux, nginx, MySQL, PHP (LEMP) stack on Ubuntu 12.045
Update Apt-Get
sudo apt-get update
Install MySQL
sudo apt-get install mysql-server mysql-client
- configuration
Once you have installed MySQL, we should activate it with this command:
sudo mysql_install_db
Finish up by running the MySQL set up script:
sudo /usr/bin/mysql_secure_installation
It’s easiest just to say Yes to all the options. At the end, MySQL will reload and implement the new changes.
By default, a MySQL installation has an anonymous user, allowing anyone to log into MySQL without having to have a user account created for them. This is intended only for testing, and to make the installation go a bit smoother. You should remove them before moving into a production environment. Remove anonymous users? [Y/n] y ... Success! Normally, root should only be allowed to connect from 'localhost'. This ensures that someone cannot guess at the root password from the network. Disallow root login remotely? [Y/n] y ... Success! By default, MySQL comes with a database named 'test' that anyone can access. This is also intended only for testing, and should be removed before moving into a production environment. Remove test database and access to it? [Y/n] y - Dropping test database... ... Success! - Removing privileges on test database... ... Success! Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? [Y/n] y ... Success! Cleaning up...
Install nginx
sudo apt-get install nginx
start nginx
sudo service nginx start
You can confirm that nginx has installed an your web server by directing your browser to your IP address. You can run the following command to reveal your VPS's IP address.
ifconfig eth0 | grep inet | awk '{ print $2 }'
Install PHP
sudo apt-get install php5-fpm sudo apt-get install php5-mysql php5-gd php5-xdebug php-apc
php5-gd: This package provides a module for handling graphics directly from PHP scripts. It supports the PNG, JPEG, XPM formats as well as Freetype/ttf fonts.
More:
- APC (php-pecl-apc) – APC caches and optimizes PHP intermediate code
- CLI (php-cli) – Command-line interface for PHP
- PEAR (php-pear) – PHP Extension and Application Repository framework
- PDO (php-pdo) – A database access abstraction module for PHP applications
- MySQL (php-mysqlnd) – A module for PHP applications that use MySQL databases
- PostgreSQL (php-pgsql) – A PostgreSQL database module for PHP
- MongoDB (php-pecl-mongo) – PHP MongoDB database driver
- SQLite (php-sqlite) – Extension for the SQLite V2 Embeddable SQL Database Engine
- Memcache (php-pecl-memcache) – Extension to work with the Memcached caching daemon
- Memcached (php-pecl-memcached) – Extension to work with the Memcached caching daemon
- GD (php-gd) – A module for PHP applications for using the gd graphics library
- XML (php-xml) – A module for PHP applications which use XML
- MBString (php-mbstring) – A module for PHP applications which need multi-byte string handling
- MCrypt (php-mcrypt) – Standard PHP module provides mcrypt library support
Configure php
sudo nano /etc/php5/fpm/php.ini cgi.fix_pathinfo=0
Find the line, cgi.fix_pathinfo=1
, and change the 1 to 0.
If this number is kept as 1, the php interpreter will do its best to process the file that is as near to the requested file as possible. This is a possible security risk. If this number is set to 0, conversely, the interpreter will only process the exact file path—a much safer alternative.
We need to make another small change in the php5-fpm configuration.
sudo nano /etc/php5/fpm/pool.d/www.conf
listen = /var/run/php5-fpm.sock
sudo service php5-fpm restart
Configure nginx
sudo nano /etc/nginx/sites-available/default server { listen 80; root /usr/share/nginx/www; index index.html index.htm index.php; server_name yourdomain.com www.yourdomain.com; location / { #try to find the requested uri or redirect to index.php with request args try_files $uri $uri/ /index.php?$args; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/www; } # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000 # location ~ \.php$ { fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; } }
Create a php Info Page for Test[option]
sudo nano /usr/share/nginx/www/info.php #Add in the following line: <?php phpinfo(); ?> #Restart nginx sudo service nginx restart #visiting http://youripaddress/info.php
Migrate Wordpress to Nginx6, 7
Restore Database
mysql -u root -p CREATE DATABASE wordpress; CREATE USER wordpressuser@localhost; SET PASSWORD FOR wordpressuser@localhost= PASSWORD("password"); GRANT ALL PRIVILEGES ON wordpress.* TO wordpressuser@localhost; FLUSH PRIVILEGES; mysql -h localhost -u wordpressuser -p wordpress < ./wordpress.sql
Basic NGINX Optimization
Increase or decrease the number of workers depending on your system's specs:
sudo nano /etc/nginx/nginx.conf worker_processes 1; #NGINX limits the number of connections that a worker can maintain at one time, if your websites have many visitors you might want to increase the limit of connections worker_connections 768; #Enabling Gzip gzip on; gzip_types text/css text/x-component application/x-javascript application/javascript text/javascript text/x-js text/richtext image/svg+xml text/plain text/xsd text/xsl text/xml image/x-icon;
Files can be compressed using Gzip to accelerate WordPress, the smaller the data size requested by the user, the faster the response. Think about CSS files & HTML files, they have many similar strings, repeated text and white spaces.
Creating NGINX .conf files
create 3 files that will hold our configurations:
- common.conf: Configurations applicable to all sites.
- wordpress.conf: Configurations applicable to all WordPress sites.
- multisite.conf: Special configurations for WordPress multisite with sub-directories.
- create the dir
sudo mkdir /etc/nginx/global cd /etc/nginx/global
- common.conf file
sudo nano common.conf # Global configuration file. # ESSENTIAL : Configure Nginx Listening Port listen 80; # ESSENTIAL : Default file to serve. If the first file isn't found, index index.php index.html index.htm; # ESSENTIAL : no favicon logs location = /favicon.ico { log_not_found off; access_log off; } # ESSENTIAL : robots.txt location = /robots.txt { allow all; log_not_found off; access_log off; } # ESSENTIAL : Configure 404 Pages error_page 404 /404.html; # ESSENTIAL : Configure 50x Pages error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/www; } # SECURITY : Deny all attempts to access hidden files .abcde location ~ /\. { deny all; } # PERFORMANCE : Set expires headers for static files and turn off logging. location ~* ^.+\.(js|css|swf|xml|txt|ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { access_log off; log_not_found off; expires 30d; }
location = /robots.txt {allow all;}
allows the access to robots.txt, if you want to specify another directory for the robots.txt you can add an alias:location /robots.txt { alias /var/www/example.com/public/sample_robots.txt; }
location ~ /\. {deny all;}
in the Linux operating system a hidden file begins with a ".", access to some hidden files, such as.htaccess
, should be blocked for security reasons.location ~* ^.+\.(js|css|swf...
expires headers tell the browser whether they should request a specific file from the server or whether they should grab it from the browser's cache. With expires 30d we are telling the browser to store static files such as pictures for 30 days. - wordpress.conf file
sudo nano wordpress.conf # WORDPRESS : Rewrite rules, sends everything through index.php and keeps the appended query string intact location / { try_files $uri $uri/ /index.php?q=$uri&$args; } # SECURITY : Deny all attempts to access PHP Files in the uploads directory location ~* /(?:uploads|files)/.*\.php$ { deny all; } # REQUIREMENTS : Enable PHP Support location ~ \.php$ { # SECURITY : Zero day Exploit Protection try_files $uri =404; # ENABLE : Enable PHP, listen fpm sock fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; include fastcgi_params; }
try_files $uri $uri/ /index.php?q=$uri&$args
rewrite rule required to allow you to choose your custom permalink structure on WordPress.location ~* /(?:uploads|files)/.*\.php$ {deny all;}
this will prevent malicious code from being uploaded and executed from the WordPress media directory.location ~ \.php$ {...}
since WordPress is a php site, we need to tell NGINX how to a pass our php scripts to PHP5.try_files $uri =404;
this is a security rule, you only want to either serve a determined php file or go to a 404 error. - multisite.conf file
sudo nano multisite.conf # Rewrite rules for WordPress Multi-site. if (!-e $request_filename) { rewrite /wp-admin$ $scheme://$host$uri/ permanent; rewrite ^/[_0-9a-zA-Z-]+(/wp-.*) $1 last; rewrite ^/[_0-9a-zA-Z-]+(/.*\.php)$ $1 last; }
Creating Server Blocks
Have two blogs: blog.dreamrunner.org
and other.dreamrunner.org
.
#disable the default server block: sudo rm /etc/nginx/sites-enabled/default #And create a server block file: sudo nano /etc/nginx/sites-available/dreamrun
Add:
server { server_name blog.dreamrunner.org; root /home/shougang/www/laogangzhi; access_log /var/log/nginx/blog.dreamrunner.org.access.log; error_log /var/log/nginx/blog.dreamrunner.org.error.log; include global/common.conf; include global/wordpress.conf; include global/multisite.conf; } server { server_name other.dreamrunner.org; root /home/shougang/www/dreamrunner; access_log /var/log/nginx/other.dreamrunner.org.access.log; error_log /var/log/nginx/other.dreamrunner.org.error.log; include global/common.conf; include global/wordpress.conf; include global/multisite.conf; }
server_name
: Determine which server block is used for a given URL.root
: The path where your site is stored.access log & error log
: Set the paths for your logs
Restore Wordpress Files
Copy the Wordpress files to /home/username/www/
and upzip;
sudo chown www-data:www-data * -R sudo usermod -a -G www-data [username] #in the wp-config.php file add define( 'FS_METHOD', 'direct' )
MySQL Tips
list MySQL user
SELECT User FROM mysql.user;
Create and Delete a MySQL Database
SHOW DATABASES; CREATE DATABASE database name; DROP DATABASE database name;
Access a MySQL Database
USE events; SHOW tables;
Create a MySQL Table
CREATE TABLE potluck (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20), food VARCHAR(30), confirmed CHAR(1), signup_date DATE); #the table’s organization with this command: DESCRIBE potluck;
Add Information to a MySQL Table
INSERT INTO `potluck` (`id`,`name`,`food`,`confirmed`,`signup_date`) VALUES (NULL, "John", "Casserole","Y", '2012-04-11'); SELECT * FROM potluck;
Update Information in the Table
UPDATE `potluck` SET `confirmed` = 'Y' WHERE `potluck`.`name` ='Sandy';
Add and Delete a Column
ALTER TABLE potluck ADD email VARCHAR(40); # place that column in a specific spot in the table ALTER TABLE potluck ADD email VARCHAR(40) AFTER name; ALTER TABLE potluck DROP email;
Delete a Row
DELETE from [table name] where [row name]=[field text];
How To Create a SSL Certificate on nginx for Ubuntu 12.04
Create a Directory for the Certificate
The SSL certificate has 2 parts main parts: the certificate itself and the public key.
sudo mkdir /etc/nginx/ssl
cd /etc/nginx/ssl
Create the Server Key and Certificate Signing Request
Start by creating the private server key. During this process, you will be asked to enter a specific passphrase. Be sure to note this phrase carefully, if you forget it or lose it, you will not be able to access the certificate.
sudo openssl genrsa -des3 -out server.key 1024 #Follow up by creating a certificate signing request: sudo openssl req -new -key server.key -out server.csr
This command will prompt terminal to display a lists of fields that need to be filled in.
The most important line is "Common Name". Enter your official domain name here or, if you don't have one yet, your site's IP address. Leave the challenge password and optional company name blank.
Remove the Passphrase
However, it would serve us to remove the passphrase. Although having the passphrase in place does provide heightened security, the issue starts when one tries to reload nginx. In the event that nginx crashes or needs to reboot, you will always have to re-enter your passphrase to get your entire web server back online.
sudo cp server.key server.key.org sudo openssl rsa -in server.key.org -out server.key
Sign your SSL Certificate
Keep in mind that you can specify how long the certificate should remain valid by changing the 365 to the number of days you prefer. As it stands this certificate will expire after one year.
sudo openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
Set Up the Certificate for Test [option]
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/example sudo nano /etc/nginx/sites-available/example # HTTPS server server { listen 443; server_name example.com; root /usr/share/nginx/www; index index.html index.htm; ssl on; ssl_certificate /etc/nginx/ssl/server.crt; ssl_certificate_key /etc/nginx/ssl/server.key; }
Activate the Virtual Host
sudo ln -s /etc/nginx/sites-available/example /etc/nginx/sites-enabled/example sudo service nginx restart
Nginx and PHP5-FPM Configuration and Optimizing Tips
high memory of php5-fpm
搬移到512M的digitalocean, Nginx + PHP5-FPM + Wordpress, 发现PHP5-FPM 的memory占用很高。
$ ps -A --sort -rss -o comm,pmem,pcpu | uniq -c | head -15 1 COMMAND %MEM %CPU 1 php5-fpm 21.2 0.0 1 php5-fpm 21.1 0.0 1 php5-fpm 19.3 0.0 1 php5-fpm 17.9 0.0 1 php5-fpm 17.4 0.0 1 php5-fpm 16.4 0.0 1 bash 1.5 4.2 1 php5-fpm 0.6 0.0 1 rsyslogd 0.6 0.0 1 nginx 0.5 0.0 1 init 0.2 0.0 1 sshd 0.2 0.1 1 whoopsie 0.2 0.0 1 nginx 0.2 0.0 $ free total used free shared buffers cached Mem: 502740 476344 26396 0 1120 50460 -/+ buffers/cache: 424764 77976 Swap: 524284 0 524284
Nginx
- Organize Nginx Configuration Files
## Main configuration file ## /etc/nginx/nginx.conf ## Virtualhost configuration files on ## /etc/nginx/sites-available/ /etc/nginx/sites-enabled/ ## Other config files on (if needed) ## /etc/nginx/conf.d/
nginx.conf
worker_processes [number of processor cores]; cat /proc/cpuinfo |grep processor processor : 0 worker_processes 1;
- under
/etc/nginx/conf.d/
create
user.conf
:#The charset directive will not only cause Nginx to re-encode #anything that is not in the defined character set, #it will also add it to the Content-Type HTTP header so browsers know. charset utf-8; #The default Nginx client_max_body_size is 1mb. #That’s too small for most everything these days client_max_body_size 32m; client_body_buffer_size 128k; #Hide Nginx Server Tokens / Hide Nginx version number server_tokens off;
create
ssl.conf
# we want to enable ssl session resumption to avoid # having to start the handshake from scratch each page load # so first we enable a shared cache, named SSL (creative!) that is 10mb large ssl_session_cache shared:SSL:10m; # save things in the cache for 3 minutes # if you're not making a request at least every 3 minutes, this isn't going # to accomplish anything anyway ssl_session_timeout 3m; # now we're going to change a bunch related to SSL ciphers and protocol # the primary goal here is to be more secure, and i've generally tried to # go with things that comply with the Federal Information Processing Standard (FIPS) # set by the US government for non-military government use # we don't want to support SSLv3, it's known to be insecure # FIPS 140-2 compliance, TLS1+ only ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # now we go through a couple different options for the SSL ciphers to support, mainly just to # give you a bunch of options to pick from # this is a very concise definition of ciphers that don't allow anonymous DH or MD5 - the big weaknesses # per: https://calomel.org/nginx.html #ssl_ciphers HIGH:!ADH!MD5:@STRENGTH; # this is a very (not so) short list of very secure ciphers that may be incompatible with older browsers # per: https://calomel.org/nginx.html #ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:AES256-GCM-SHA384:AES256-SHA256:AES256-SHA:AES128-SHA; # this excludes insecure ciphers and sorts the others by strength # it is BEAST-resistant, prioritizing RC4 # per: http://groups.drupal.org/node/179344 #ssl_ciphers !aNULL:!LOW:!MD5:!EXP:RC4:CAMELLIA:AES128:3DES:SEED:AES256@STRENGTH; # this is a combination of everything above and openssl docs - very secure, FIPS-compliant, ordered by strength ssl_ciphers !aNULL:!eNULL:FIPS@STRENGTH; # don't let the client decide what ciphers to use, we've told the server which to allow ssl_prefer_server_ciphers on;
PHP5-FPM
- the Configuration Files
## Main configuration file ## /etc/php5/fpm/php-fpm.conf ## last line of php-fpm.conf:include=/etc/php5/fpm/pool.d/*.conf ## Other config files on (if needed) ## /etc/php5/fpm/pool.d/
pool.d/www.conf
pm.max_children = 5 pm.start_servers = 2 pm.min_spare_servers = 1 pm.max_spare_servers = 3 listen = /var/run/php5-fpm.socket
update issues
The page you are looking for is temporarily unavailable.
After update the linux server, has the following issue:
“The page you are looking for is temporarily unavailable. Please try again later”
uncommenting the following lines in /etc/php5/fpm/pool.d/www.conf
and
restart php5-fpm
listen.owner = www-data listen.group = www-data listen.mode = 0660