Head over to Hetzner and order one. Virtual servers (vServer) are OK if your hardware requirements are not so high. For this article, I'll use a CX20 with Debian 8.4 (minimal) OS. It comes with 50GB harddisk and 2GB RAM. Usually, it's a matter of minutes till your new server is online. You will receive an email telling you the IP address and the SSH password. You can then 'ssh' into your new account using a SSH client program (I like kitty a lot).
Somebody might have eavesdropped the email with the root password in it. Therefore you want to change it:
root:~# passwd Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully
Bring your system up-to-date:
root:~# apt-get update root:~# apt-get upgrade
Make a (normal) user account 'cv' for yourself (you don't want to be root all the time). You can chose any name you want.
root:~# useradd -d /home/cv -m -s /bin/bash cv root:~# passwd cv Enter new UNIX password: Retype new UNIX password: passwd: password updated successfully
A lot of SSH attacks probe the standard port (22), so let's chose a different port, 144 in this case. I usually also disallow SSH root login:
root:~# cat /etc/ssh/sshd_config ---[snip]--- [...] Port 144 [...] PermitRootLogin no [...] ---[snip]---
Add a firewall. Drop all incoming IPv4/v6 packets except ICMP (we still want ping to work) and SSH (port 144).
root:~# cat /etc/rc.local ---[snip]--- [...] /sbin/iptables -F /sbin/iptables -P INPUT DROP /sbin/iptables -A INPUT -p tcp -m tcp --dport 144 -j ACCEPT /sbin/iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT /sbin/iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT /sbin/iptables -A INPUT -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT /sbin/iptables -A INPUT -s 127.0.0.1 -j ACCEPT /sbin/iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT /sbin/iptables -P FORWARD DROP /sbin/iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT /sbin/iptables -P OUTPUT ACCEPT /sbin/ip6tables -F /sbin/ip6tables -P INPUT DROP /sbin/ip6tables -A INPUT -p tcp -m tcp --dport 144 -j ACCEPT /sbin/ip6tables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT /sbin/ip6tables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT /sbin/ip6tables -A INPUT -p icmp -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT /sbin/ip6tables -A INPUT -s ::1 -j ACCEPT /sbin/ip6tables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT /sbin/ip6tables -P FORWARD DROP /sbin/ip6tables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT /sbin/ip6tables -P OUTPUT ACCEPT exit 0 ---[snip]---
Reboot
root:~# reboot
Please note: From now on, you cannot login as root anymore, you have to login as a normal user and 'su' if required. Moreover, the SSH port is not 22 anymore, so use port 144 for future logins.
Unfortunately, we cannot download Oracle Java via wget/curl without some trickery, so we have to download it from their web page and 'scp' it to the server:
scp -P 144 server-jre-8u92-linux-x64.tar.gz cv@SERVER_IP:~
Over at the server:
cv:~# su root:/home/cv# cd /opt root:/opt# tar -xf /home/cv/server-jre-8u92-linux-x64.tar.gz root:/opt# ln -s /opt/jdk1.8.0_92/jre/bin/java /usr/bin/java root:/opt# exit cv:~# java -version java version "1.8.0_92" Java(TM) SE Runtime Environment (build 1.8.0_92-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.92-b14, mixed mode)
That depends heavily on how you did your web app (embedded http server, jetty, tomcat, etc.). So, I cannot describe this step. In the end, the web app must be reachable from within localhost, which you can check with curl:
cv:~# curl http://localhost:8080 > test-v4.html cv:~# curl -g -6 http://[::1]:8080 > test-v6.html
... must produce some valid html output in test-v4.html and test-v6.html.
Installation is easy
root:~# apt-get install nginx
Note: Debian is known for delivering pretty old releases. So, usually I install/upgrade nginx by hand. But for this tutorial, let's stick with what Debian gives us.
I don't like the 'sites-available'/'sites-enabled' stuff that debian-nginx is configured with out of the box, so let's change that:
root:~# cd /etc/nginx root:/etc/nginx# rm -rf sites-* root:/etc/nginx# vim nginx.conf ---[snip]--- ... # I don't like it # include /etc/nginx/sites-enabled/* ... ---[snip]--- root:/etc/nginx# cd conf.d root:/etc/nginx/conf.d# cp default.conf default.conf.original root:/etc/nginx/conf.d# vim default.conf ---[snip]--- server { listen 443 ssl; listen [::]:443 ssl; server_name www.myapp.de; ssl on; ssl_certificate /etc/nginx/conf.d/myapp.crt; ssl_certificate_key /etc/nginx/conf.d/myapp.key; charset utf-8; client_max_body_size 6m; client_body_buffer_size 2m; proxy_buffer_size 4K; proxy_buffers 8 32k; location / { proxy_pass http://127.0.0.1:8080; } } server { listen 80; listen 443; server_name myapp.de; return 301 https://www.myapp.de$request_uri; } ---[snip]---
This will tell nginx to listen on port 80 (http) and 443 (https) at the same
time. If a request comes in for port 80 (http), it will be redirected
(permanently) to its 443 (https) counterpart. If a request comes in for
'myapp.de' (without the 'www' subdomain), it will be redirected to the 'www'
subdomain. See http://www.yes-www.org/
for more information why this is what you want.
Whatever request comes in, nginx will proxy-forward it to
http://localhost:8080. This is where your web app is listening.
Right now, there is no app listening on port 8080, so nginx will report an
error back to a client.
You may have noticed the 'ssl_certificate' and 'ssl_certificate_key'
directives. This tells nginx where to find the SSL vertificate and the
private key file.
A note on SSL certificates: I'm not quite ready yet for Let's Encrypt (I don't want nobody mess with my server config..). So I still do the old-school way of paying for certificates and managing them myself. For this tutorial, let's pretend the certificate and its key is stored in the mayapp.crt/.key file. Let's also pretend the CN of the CERT is 'my-app.com', and 'www.my-app.com'
Let's protect the private key file, only root should be able to read it.
root:/etc/nginx/conf.d# chmod 600 myapp.key
Now restart nginx.
root:/etc/nginx/conf.d# service nginx restart
So, that's it. If all went well you should be able to access your web app from
the outside world via https://SERVER_IP/
. You might also register a
domain and tinker with its DNS A-record, so that you can access your web app
via https://www.my-app.com/
.