Skip to content

Instantly share code, notes, and snippets.

  • Save nguyenducdev/70b7b2868b16775e6f150e68944261b2 to your computer and use it in GitHub Desktop.
Save nguyenducdev/70b7b2868b16775e6f150e68944261b2 to your computer and use it in GitHub Desktop.
Set up EC2 Ubuntu server: Nginx + PHP 71 + Composer 2017

1. Commons

Reset ssh know host for remote ip:

ssh-keygen -R hostname [-f known_hosts_file]

ssh to server, and run as root user using command,

sudo su

2. Update & upgrade packages

apt-get update
apt-get upgrade
apt-get dist-upgrade

3 Setup admin user but not root user

If you don't have ubuntu user like EC2 did - Add new user as admin group, and also to handle for websites hosting

https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-16-04

adduser wwwadmin

##add wwwadmin to sudo group
usermod -aG sudo wwwadmin

Then log out and ssh again by new admin account to setup other things.

On local machine:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
cat ~/.ssh/id_rsa.pub

ssh into remote machine as wwwadmin, then paste public key into authorized_keys

mkdir ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys

# paste public key 

chmod 600 ~/.ssh/authorized_keys

Noted: Remember to add authorized_keys for root if wwwadmin is not sudoer

3.1 Only allow login using key

sudo nano /etc/ssh/sshd_config

Set options:

PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no


# make client auto disconnected after 5 mins of no response
ClientAliveInterval 60
ClientAliveCountMax 5

Then reload sshd

sudo systemctl reload sshd

3.2 Using ssh to login with wwwadmin

Install other things.

ssh wwwadmin@ip
mkdir setup

# make www dir as the html_root for all of future websites
mkdir www

cd setup

4 Install Nginx

  • Download key [root]

Ref: http://nginx.org/en/linux_packages.html#mainline (nginx document)

wget http://nginx.org/keys/nginx_signing.key
apt-key add nginx_signing.key
nano /etc/apt/sources.list
  • Enter new 2 lines at end of file sources.list:
deb http://nginx.org/packages/mainline/ubuntu/ codename nginx
deb-src http://nginx.org/packages/mainline/ubuntu/ codename nginx

codename = name of ubuntu server version codename

  • save the file and run commands to install nginx :
apt-get update
apt-get install nginx


# add wwwadmin to www-data group
sudo usermod -aG www-data wwwadmin
  • Path to configuration file:
/etc/nginx/

Ref: http://nginx.org/en/docs/beginners_guide.html

5. Install PHP 7.1 [root]

sudo apt-get install -y python-software-properties
add-apt-repository -y ppa:ondrej/php
apt-get update
apt-cache pkgnames | grep php7.1
apt-get install -y php7.1 php7.1-fpm php7.1-cli php7.1-mbstring php7.1-mysql php7.1-zip php7.1-opcache php7.1-json php7.1-xmlrpc php7.1-curl php7.1-intl php7.1-common php7.1-gd php7.1-xml php7.1-mcrypt php7.1-pgsql php7.1-tidy php7.1-sybase php7.1-readline php7.1-soap

Path to the configuration files:

Configuration File (php.ini) Path => /etc/php/7.1/cli
Loaded Configuration File => /etc/php/7.1/cli/php.ini
Scan this dir for additional .ini files => /etc/php/7.1/cli/conf.d

PHP-FPM sock

listen = /run/php/php7.1-fpm.sock

Update max upload file size:

sudo nano /etc/php/7.1/fpm/php.ini

Restart php-fpm

sudo /etc/init.d/php7.1-fpm stop
sudo /etc/init.d/php7.1-fpm start

5.1 ImageMagick

sudo apt install libmagickwand-dev imagemagick php-dev
sudo pecl install imagick

The result should be

Build process completed successfully
Installing '/usr/include/php/20160303/ext/imagick/php_imagick_shared.h'
Installing '/usr/lib/php/20160303/imagick.so'
install ok: channel://pecl.php.net/imagick-3.4.3
configuration option "php_ini" is not set to php.ini location
You should add "extension=imagick.so" to php.ini

Now edit php-fpm ini to enable extension as guided and restart fpm service.

6. Setup firewall

sudo ufw app list
sudo ufw allow OpenSSH
sudo ufw allow "Nginx HTTP"
sudo ufw allow "Nginx HTTPS"
sudo ufw allow "Postfix"
sudo ufw allow "Postfix SMTPS"
sudo ufw allow "Nginx Full"
sudo ufw allow 80
# sudo ufw allow http
sudo ufw allow 443
# sudo ufw allow https
sudo ufw enable
sudo ufw status

7. Install http2 [root]

7.1 Install nghttp2 ad tools (C library for http2):

# Get build requirements
# Some of these are used for the Python bindings
# this package also installs
apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config \
  zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev \
  libjemalloc-dev cython python3-dev python-setuptools
  
  
# Build nghttp2 from source
git clone https://github.com/tatsuhiro-t/nghttp2.git
cd nghttp2
autoreconf -i
automake
autoconf
./configure
make
make install

7.2 Upgrade to latest curl:

Ref: go to https://curl.haxx.se/download.html to got the newest stable version

cd ..
apt-get build-dep curl
wget https://curl.haxx.se/download/curl-7.56.1.tar.bz2
tar -xvjf curl-7.56.1.tar.bz2
cd curl-7.56.1

./configure --with-nghttp2=/usr/local --with-ssl
make
make install
ldconfig

# run command again to test http2
curl --http2 -I https://nghttp2.org/

Or check php info:

php -i > phpinfo.txt
nano phpinfo.txt

8. Install MySQL

https://www.digitalocean.com/community/tutorials/how-to-install-the-latest-mysql-on-ubuntu-16-04

curl -OL https://dev.mysql.com/get/mysql-apt-config_0.8.3-1_all.deb
sudo apt-get update
rm mysql-apt-config*
sudo apt-get install mysql-server
systemctl status mysql
mysql_secure_installation
mysqladmin -u root -p version

8.1 Allow root to remote from internet (not secure) [root]

#1. login using root local password 
mysql -u root -p

#2. run command to privilege for root remote host account
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'root_user_password' WITH GRANT OPTION;
mysql>  FLUSH PRIVILEGES;


#3. rebind local address by
nano /etc/mysql/mysql.conf.d/mysqld.cnf
#find and comment out 
bind-address = 127.0.0.1 => to: #bind-address = 127.0.0.1

# restart mysql service
service mysql restart


9. Install LetsEncrypt free ssl service

https://letsencrypt.org/getting-started/

https://certbot.eff.org/#ubuntuxenial-nginx

Setup to request certificate for nginx config:

# install
sudo apt-get update
sudo apt-get install software-properties-common
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx 

# this will help us to reconfig to apply ssl
sudo certbot --nginx

# this to generate only cert
sudo certbot --nginx certonly

Cronjob to auto renew certificate daily: [root]

crontab -e


# enter
0 1 * * * root certbot renew --pre-hook "nginx -s quit" --post-hook "nginx"

10. Note:

10.1 - Error 502 because of php-fpm permission

Edit user of nginx to match with user of php-fpm

sudo nano /etc/nginx/nginx.conf

user www-data

11. Install composer [root]

install root and use as global

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

11.1 Laravel / Lumen directory permissions set

Move to laravel root directory

Most folders should be normal "755" and files, "644"

Laravel requires some folders to be writable for the web server user. You can use this command on *nix based OSs.

sudo chgrp -R www-data storage bootstrap/cache
sudo chmod -R ug+rwx storage bootstrap/cache

12. Setup post-fix to send email out

Ref: https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-postfix-as-a-send-only-smtp-server-on-ubuntu-16-04

sudo apt-get update

# run this command for all need utils
sudo apt install mailutils

# sudo apt-get install postfix

# config; After modifying main.cf, be sure to run '/etc/init.d/postfix reload'
sudo nano /etc/postfix/main.cf

Config laravel to be send email using postfix .env file:

MAIL_DRIVER=sendmail
MAIL_HOST=localhost
MAIL_PORT=587

Please note, add define for server ip in the DNS record:

TXT @ "v=spf1 ip4:34.231.41.136 include:spf.mailjet.com -all"

example using goolge.com

TXT @ "v=spf1 ip4:ip_server_trusted include:_spf.google.com ~all"

Tool test

http://www.kitterman.com/spf/validate.html

13. Enable SFTP via ssh for wwwadmin

Ref: https://www.digitalocean.com/community/tutorials/how-to-enable-sftp-without-shell-access-on-ubuntu-16-04

13.1 Create sftpuser to allow sftp file handle only

sudo adduser sftpuser
cd /home/sftpuser
su sftpuser

mkdir ~/.ssh
chmod 700 ~/.ssh
nano ~/.ssh/authorized_keys

# paste public key 
chmod 600 ~/.ssh/authorized_keys

13.2 Set up directory structure for sftp transfer file [root]

Make directory structure to handle sftp file transfer upload to web

# 1. Create directory for sftp access
sudo mkdir -p /var/sftp/www

# 2. Set the owner of /var/sftp to root
sudo chown root:root /var/sftp

# 3. Give root write permissions to the same directory, and give other users only read and execute rights.
sudo chmod 755 /var/sftp

# 4. Change the ownership on the www directory to sftpuser.
sudo chown sftpuser:sftpuser /var/sftp/www

13.3 Restricting SFTP Access to One Directory [root]

nano /etc/ssh/sshd_config


# - scroll down to bottom and add these lines
# sftp settings
Match User sftpuser
ForceCommand internal-sftp
PasswordAuthentication yes
ChrootDirectory /var/sftp
PermitTunnel no
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no

# - save and close; restart sshd
sudo systemctl restart sshd

13.4 Mount folder for sfpt upload [root]

  • we will mount directory /user/wwwadmin/www into /var/sftp/www So everytime, sfptuser login and upload to that directory will also into /user/wwwadmin/www
nano /etc/fstab

# enter new line:
/var/sftp/www /home/wwwadmin/www none defaults,bind 0 0

# restart server
shutdown -r 0

13.5 set www-data is a user of sftpuser group

sudo usermod -aG sftpuser www-data
sudo usermod -aG sftpuser wwwadmin

From now, use sftp to upload website and update nginx config to load config file from www folder

use filezilla to upload new 1 folder servers into /www folder

sudo nano /etc/nginx/nginx.conf

# add line:
include /var/sftp/www/servers/*.conf;

14 Setup Firewall

14.1 Ban some know hackers IP:

They are from: china, poland, russia, hongkong

sudo ufw deny from 164.52.0.141 to any  
sudo ufw deny from 89.248.171.38 to any  
sudo ufw deny from 223.105.4.250 to any  
sudo ufw deny from 78.10.254.8 to any  
sudo ufw deny from 87.105.112.71 to any  
sudo ufw deny from 95.213.177.124 to any 

Ban by nginx:

https://support.hypernode.com/knowledgebase/blocking-allowing-ip-addresses-in-nginx/

To deny all access from certain addresses, create a file in the nginx-directory in your homedir named server.blacklist, with the following contents:

# deny 1.2.3.4;     # To deny a single server
# deny 5.6.7.0/24;  # To deny a complete network

deny 164.52.0.141;
deny 89.248.171.38;
deny 223.105.4.250;
deny 78.10.254.8;
deny 87.105.112.71;
deny 95.213.177.124;

14.2 Essential firewall rules

https://www.digitalocean.com/community/tutorials/ufw-essentials-common-firewall-rules-and-commands

sudo ufw allow 3306

Aditional list of IP maybe hackers,

Install fail2ban please to quicker setup process

186.139.86.192 194.25.8.139 71.6.202.198 162.158.166.115 174.139.109.122 177.35.246.147

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment