The setup installs the following software:
- Nginx
- MySQL
- PHP
- Node
- Composer
apt-get update && apt-get dist-upgrade -y
apt-get autoremove -y
Instead of using root as the user, we add a new one.
useradd -d /home/<username> -m -s /bin/bash <username>
usermod -a -G adm,cdrom,sudo,dip,plugdev <username>
If you provided your SSH key when creating the droplet, you can copy the authorized_keys to the new username
to skip needing a password when connecting.
mkdir /home/<username>/.ssh
cp /root/.ssh/authorized_keys /home/<username>/.ssh/
chmod 600 /home/<username>/.ssh/authorized_keys
chown -R <username>:<username> /home/<username>/.ssh
Run visudo
and add the following line at the end of the file.
<username> ALL=(ALL) NOPASSWD: ALL
Create and expose a SSH Key for the new user
ssh-keygen -t rsa -C "[email protected]"
cat ~/.ssh/id_rsa.pub
apt-get install -y \
build-essential \
software-properties-common \
python \
g++ \
make \
fail2ban \
apache2-utils \
curl \
bc \
git \
htop \
ntp \
ntpdate \
unzip \
aptitude
dpkg-reconfigure tzdata
sudo apt-get install ufw
Allow SSH, HTTP and HTTPS.
sudo ufw allow ssh
sudo ufw allow http
sudo ufw allow https
Enable firewall.
sudo ufw enable
Check the status of the firewall.
sudo ufw status verbose
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
apt-get install -y nodejs
Update npm.
npm update -g
curl -sS https://getcomposer.org/installer | php -- \
--install-dir=/usr/bin \
--filename=composer
htpasswd -c /etc/default/htpasswd <htpasswd-username>
add-apt-repository ppa:nginx/development
apt-get update && apt-get install nginx-full -y
Check number of cores to set worker_processes.
grep processor /proc/cpuinfo | wc -l
Check core limit for number of connections.
ulimit -n
Configure Nginx accordingly. Be careful not to duplicate any directives.
sudo nano /etc/nginx/nginx.conf
worker_processes <number-of-cores>;
worker_connections <core-limit>;
multi_accept on;
server_tokens off;
server_names_hash_bucket_size 64;
server_name_in_redirect off;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied any;
gzip_comp_level 2;
gzip_buffers 16 8k;
gzip_min_length 1100;
gzip_http_version 1.1;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/rss+xml text/javascript image/svg+xml application/x-font-ttf font/opentype application/vnd.ms-fontobject;
access_log off;
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 64m;
client_header_timeout 12;
client_body_timeout 12;
send_timeout 10;
large_client_header_buffers 2 1k;
Test Nginx Config and Restart Nginx if OK.
nginx -t
service nginx restart
Create config file for virtual host.
pico /etc/nginx/sites-available/<domain-name>.conf
server {
listen 80;
listen [::]:80;
root /var/www/<domain-name>/public/;
index index.php index.html;
server_name <domain-name>;
charset utf-8;
location ~* \.(?:manifest|appcache|html?|xml|json)$ {
expires -1;
}
location ~* \.(?:rss|atom)$ {
expires 1h;
add_header Cache-Control "public";
}
location ~* \.(?:jpg|jpeg|gif|png|ico|cur|gz|svg|svgz|mp4|ogg|ogv|webm|htc)$ {
expires 1M;
add_header Cache-Control "public";
}
location ~* \.(?:css|js)$ {
expires 1y;
add_header Cache-Control "public";
}
location ~* \.(?:ttf|ttc|otf|eot|woff|woff2)$ {
expires 1M;
add_header Cache-Control "public";
}
location / {
try_files $uri $uri/ /index.php?$query_string;
auth_basic "Restricted";
auth_basic_user_file /etc/default/htpasswd;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_intercept_errors on;
}
}
# Redirect www to non-www
server {
server_name www.<domain-name>;
return 301 http://<domain-name>$request_uri;
}
Create public directory in site folder.
mkdir -p /var/www/<domain-name>/public
Fix correct owner.
chown -R www-data:www-data /var/www/<domain-name>
sudo usermod -a -G www-data <username>
sudo chmod -R g+rw /var/www/<domain-name>
Enable vhost.
ln -s /etc/nginx/sites-available/<domain-name>.conf /etc/nginx/sites-enabled/<domain-name>.conf
Restart Nginx.
service nginx restart
apt-get -y install \
php7.0-fpm \
php7.0-mysql \
php7.0-curl \
php7.0-gd \
php7.0-intl \
php-pear \
php-imagick \
php7.0-imap \
php7.0-mcrypt \
php-memcache \
php7.0-pspell \
php7.0-recode \
php7.0-sqlite3 \
php7.0-tidy \
php7.0-xmlrpc \
php7.0-xsl \
php7.0-mbstring \
php-gettext
Adjustments for php-fpm is based on the 2GB Digital Ocean setup.
pico /etc/php/7.0/fpm/pool.d/www.conf
listen.owner = www-data
listen.group = www-data
pm.max_children = 16
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
pico /etc/php/7.0/fpm/php.ini
post_max_size = 64M
upload_max_filesize = 64M
date.timezone = America/New_York
mysql.default_socket = /var/run/mysqld/mysqld.sock
sed -i s/\;cgi\.fix_pathinfo\=1/cgi\.fix_pathinfo\=0/g /etc/php/7.0/fpm/php.ini;
Enable mcrypt.
phpenmod mcrypt
aptitude install -y \
mysql-server \
mysql-client
sudo add-apt-repository ppa:certbot/certbot
sudo apt-get update
sudo apt-get install python-certbot-nginx
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'
sudo certbot --nginx -d <domain-name> -d <domain-name>
apt-get update
apt-get -y install lsyncd
Now we need to setup the default files and directories for our logs and settings
sudo mkdir /var/log/lsyncd
touch /var/log/lsyncd/lsyncd.{log,status}
sudo mkdir /etc/lsyncd
sudo nano /etc/lsyncd/lsyncd.conf.lua
Here's the default settings for the lsyncd config file Install on the primary server, and list all the servers that you want to copy to in this one file.
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 20
}
servers = {
"<private-server-ip-to-copy-to>"
}
for _, server in ipairs(servers) do
sync {
default.rsyncssh,
source="/var/www/",
host=server,
targetdir="/var/www/",
rsync = {
archive = true,
acls = true,
verbose = true,
rsh = "/usr/bin/ssh -p 22 -o StrictHostKeyChecking=no"
},
}
end
apt-get update && apt-get dist-upgrade -y
apt-get autoremove -y
apt-get -y install mysql-server
mysql_secure_installation
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
bind-address = <REMOTE IP ADDRESS OR 0.0.0.0 FOR ALL>
save and exit
mysql
CREATE USER '<username>'@'<REMOTE IP ADDRESS OR % FOR ALL>' IDENTIFIED BY '<PASSWORD>';
GRANT ALL PRIVILEGES ON <DATABASENAME>.* TO '<username>'@'<REMOTE IP ADDRESS OR % FOR ALL>';
FLUSH PRIVILEGES;
exit
service mysql restart