Skip to content

Instantly share code, notes, and snippets.

@marcuslilja
Last active January 30, 2020 23:28
Show Gist options
  • Star 32 You must be signed in to star a gist
  • Fork 22 You must be signed in to fork a gist
  • Save marcuslilja/99a989522ae546eebf98 to your computer and use it in GitHub Desktop.
Save marcuslilja/99a989522ae546eebf98 to your computer and use it in GitHub Desktop.
Server setup for Ubuntu 16.04 on Digital Ocean

Server setup for Ubuntu 16.04 on Digital Ocean

The setup installs the following software:

  • Nginx
  • MySQL
  • PHP
  • Node
  • Composer

Update system

apt-get update && apt-get dist-upgrade -y
apt-get autoremove -y

Add new user

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 "name@email.com"
cat ~/.ssh/id_rsa.pub

Install packages

apt-get install -y \
build-essential \
python-software-properties \
python \
g++ \
make \
fail2ban \
apache2-utils \
curl \
bc \
git \
htop \
ntp \
ntpdate

Set correct timezone

dpkg-reconfigure tzdata

Install firewall

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

Install NodeJS

curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
apt-get install -y nodejs

Update npm.

npm update -g

Install Composer

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

Create default htpasswd file

htpasswd -c /etc/default/htpasswd <htpasswd-username>

Install Nginx

add-apt-repository ppa:nginx/development
apt-get update && apt-get install nginx-full -y

Configure Nginx

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.

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;

keepalive_timeout 15;
send_timeout 10;
large_client_header_buffers 2 1k;

Restart Nginx.

service nginx restart

Configure Nginx vhost

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 <username>:<username> /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

Install PHP

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

Configure PHP

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 = Europe/Stockholm
mysql.default_socket = /var/run/mysqld/mysqld.sock

Enable mcrypt.

phpenmod mcrypt

Install MySQL

aptitude install -y \
mysql-server \
mysql-client
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment