Skip to content

Instantly share code, notes, and snippets.

@colkito
Forked from dominikwilkowski/README.md
Created November 25, 2016 14:19
Show Gist options
  • Select an option

  • Save colkito/41a7a357823d51f686236b4765f68243 to your computer and use it in GitHub Desktop.

Select an option

Save colkito/41a7a357823d51f686236b4765f68243 to your computer and use it in GitHub Desktop.
Ubuntu 16.04 setup with NGINX http/2 and letsencrypt

BASICS

After creating the server (droplet on DigitalOcean) log in with

ssh root@[IP ADDRESS]

Once inside the machine set a password for root:

passwd

Update your package manager:

apt-get update
apt-get upgrade

Install fail2ban:

apt-get install fail2ban

Install vim:

apt-get install vim vim-scripts vim-doc vim-latexsuite vim-gui-common vim-gnome vim-gtk

Create a new user:

useradd deploy
mkdir /home/deploy
mkdir /home/deploy/.ssh
chmod 700 /home/deploy/.ssh

Give the new user a sudo password:

passwd deploy

Add your ssh key:

vim /home/deploy/.ssh/authorized_keys         #add your public ssh key here, copy your ssh key with: pbcopy < ~/.ssh/id_rsa.pub
chmod 400 /home/deploy/.ssh/authorized_keys   #permissions
chown deploy:deploy /home/deploy -R           #permissions

And add the user to the superuser group

visudo

Add into the file:

	root    ALL=(ALL) ALL
	deploy  ALL=(ALL) ALL

Disable root login and password authentication

vim /etc/ssh/sshd_config

Edit:

PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy@(your-ip) deploy@(another-ip-if-any)    #you can even whitelist IPs from where you connect from (optional)

Restart the ssh service

service ssh restart

Now test your login with the new user in a new shell:

ssh deploy@[ID ADDRESS]

If everything works with the deploy login, log out of you root session and close.


NOW LOGIN WITH DEPLOY AND INSTALL EVERYTHING WITH DEPLOY

Install unattended-upgrades

sudo apt-get install unattended-upgrades

Edit what is updated:

sudo vim /etc/apt/apt.conf.d/10periodic

Modify so you have:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Download-Upgradeable-Packages "1";
APT::Periodic::AutocleanInterval "7";
APT::Periodic::Unattended-Upgrade "1";

and specify what upgrades should be done:

sudo vim /etc/apt/apt.conf.d/50unattended-upgrades

The default here is often fine:

Unattended-Upgrade::Allowed-Origins {
        "${distro_id}:${distro_codename}-security";
};

Now install logwatch: (This will typically install postfix and ask you about your mail setup)

sudo apt-get install logwatch

Now edit what to do with the logs. I usually have them send to my email to sort them into a folder there:

sudo vim /etc/cron.daily/00logwatch

Modify so you have something like (change your@email.tld to your email):

/usr/sbin/logwatch --output mail --mailto your@email.tld --detail high

bash

I like to change the shell to bash as that's what I like.

sudo apt-get install csh
sudo chsh -s /bin/bash deploy

(see after reconnect)

firewall

First make sure you have IPv6 enabled:

sudo vim /etc/default/ufw

It should say:

IPV6=yes

Then make sure you are not locked out:

sudo ufw allow ssh

I would also usually do:

sudo ufw allow https
sudo ufw allow http
sudo ufw allow ftp

Then enable the firewall:

sudo ufw enable

And to make sure you have everything enabled and no useless ports open:

sudo ufw status

To reload the firewall you can:

sudo ufw reload

And to see the log you do:

sudo grep UFW /var/log/syslog

timezone

To set your correct timezone:

sudo dpkg-reconfigure tzdata

Install the time protocol daemon

sudo apt-get install ntp

swapfile

Now as we all have moved to SSD servers we don't need this anymore. :) For legacy reasons:

get memory with `free -m`
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
sudo sh -c 'echo "/swapfile none swap sw 0 0" >> /etc/fstab'

FTP

sudo apt-get install vsftpd

Edit the config:

sudo vim /etc/vsftpd.conf

Modify so you have:

anonymous_enable=NO
write_enable=YES

And restart your service:

sudo service vsftpd restart

(connection via SFTP)

git

Install git if it isn't already:

sudo apt-get install git

And set your account:

git config --global user.name "Your Name"
git config --global user.email "youremail@domain.com"

node

Install node and NPM:

sudo apt-get install nodejs
sudo apt-get install npm

Because there was a name clash in the package manager we have to add a symlink to get node working:

sudo ln -s /usr/bin/nodejs /usr/bin/node

nginx

Install your server of choice. NGINX is what I like:

sudo apt-get install nginx

For HTTP/2 to be supported you will need to check the version of NGINX and openSSL:

nginx -v
openssl version

NGINX needs to be at least 1.9.5 or above and OpenSSL needs to be at least 1.0.2 or above (for ALPN to work in chrome).

Create a symlink to get to your html folder quickly and give permission:

sudo ln -s /var/www/html/ /www
sudo chown deploy:deploy /var/www/html/ -R

And edit the NGINX config:

sudo vim /etc/nginx/sites-available/default

(I've attached my basic config that works for me below)

Restart the server with the new config:

sudo nginx -s reload

letsencrypt

Install letsencrypt because we want to add SSL to our website right?

cd /home/deploy/
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
./letsencrypt-auto --help
./letsencrypt-auto

If you are running NGINX and the loader is broken (as it is currently as of May 2016) run:

./letsencrypt-auto certonly --server https://acme-v01.api.letsencrypt.org/directory
# settings
#
server_tokens off;
# prevent clickjacking attacks
add_header X-Frame-Options SAMEORIGIN;
# disallow circumventing declared MIME types
add_header X-Content-Type-Options nosniff;
# X-XSS-Protection
add_header X-XSS-Protection '1; mode=block';
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security 'max-age=31536000; includeSubDomains;' always;
# CORS
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
# node proxy
#
server {
listen 8080;
server_name [YOUR IP]; #CHANGE THIS
access_log /var/log/nginx/nodeApp.log;
error_page 400 401 402 403 404 405 500 501 502 503 504 @error_page;
# fallback page when node app is off
#
location @error_page {
root /var/www/html/;
internal;
rewrite ^ [https://domain.tld/error.html]; #CHANGE THIS
break;
}
location / {
proxy_redirect off;
proxy_pass_header Server;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_connect_timeout 5;
proxy_read_timeout 240;
proxy_intercept_errors on;
proxy_pass http://127.0.0.1:1337; #the nodeApp is listening on port 1337 internally only (make sure port 1337 is denied by ufw)
}
}
# http to https redirect
#
server {
listen 80;
server_name [domain.tld]; #CHANGE THIS
return 301 https://$host$request_uri;
}
# ssl and http2 config
#
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name [domain.tld]; #CHANGE THIS
root /var/www/html/;
ssl on;
ssl_certificate /etc/letsencrypt/live/[domain.tld]/fullchain.pem; #CHANGE THIS
ssl_certificate_key /etc/letsencrypt/live/[domain.tld]/privkey.pem; #CHANGE THIS
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_dhparam /etc/nginx/ssl/dhparam.pem; #CHANGE THIS
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256'; #generate here: https://mozilla.github.io/server-side-tls/ssl-config-generator/
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
# root server
#
location / {
root /var/www/html/;
index index.html index.htm;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
}
@cinghaman
Copy link
Copy Markdown

Hi do you have a guide like this for apache on digital ocean too, I created a 1 click WordPress app which sets up an ubuntu/apache.
I did manually update/add HTTP/2 support but my ssl/domain still shows HTTP/1.1

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