Linux web services Part I
This is an introduction to a series of talks about setting up Linux servers. I’m going to make the assumptions that you already have some experience at the command line whether it is Mac or Windows so I will not be explaining basic commands in order to keep these talks with in a one-hour time frame. This talk will be done with the assumption you are using a Mac, but you can also follow along using cygwin on Windows.
Resources for this talk are available here https://github.com/icecreammatt/server-setup
Table of Contents
- Public Private Key Creation
- Instance Creation (DigitalOcean)
- SSH Connection
- Lockdown
- Update & Upgrade
- Software Installation
- Configuration & Debugging
- Shell Scripting
- Git
- Gotchas
Prerequisites
- OSX Terminal or Cygwin
- DigitalOcean hosting account or access to a fresh Ubuntu 14.04 install
Public Private Keys
To securely connect to a server we must not rely on passwords. So instead we use public/private key authentication. Using the same public keys that git uses for SSH we can also login to remote servers we configure to accept our key.
Key Generation
Before generating a key check to see if you don’t already have one.
If the output looks like below you can just use the existing public key to connect to the new server.
$ ls ~/.ssh
id_rsa id_rsa.pub
Otherwise generate a new public private key pair.
$ ssh-keygen -t rsa -C "name@example.com"
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/matt/.ssh/id_rsa): id_rsa_example
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa_example.
Your public key has been saved in id_rsa_example.pub.
The key fingerprint is:
e5:03:12:9c:40:7e:f3:f9:39:4c:1f:0b:07:04:7f:bd name@example.com
The key's randomart image is:
+--[ RSA 2048]----+
| .oo..... |
| . o. o . |
| . + . + . . |
| . + = o . |
| S = o E |
| + * o |
| = o |
| . |
| |
+-----------------+
$ ls
id_rsa_example id_rsa_example.pub
The command below is specific to OSX and will not work in Cygwin
Copy the contents of the public key to the clipboard
IMPORTANT! Be sure to copy the file that ends in “.pub”
$ pbcopy < id_rsa_example.pub
If using cygwin navigate to
C:\cygwin\home\username\.ssh\
Openid_rsa_example.pub
in a text editor to copy the contents
$ cat id_rsa_example.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDoROCEGpranbMr7Uj9Un3zPZAtYA4VgEqinTNSOnsJ5+oxpMrW0sV8/AUial3hxGVJK/UFsURmjGWg0liN9CGwNrnwGufDyG/SBpbRdFk8jwxLXQgiyTjbrNKlhhK0AWFTeajPsoXHE1jycEu4/G1oaewQ+se7055qsN3RIFLkpYj0VSsy/fjaZH5BPk+NtFQOc7yO7Nqs+x7nORsoLVyie2YhQSzzFBM23RMFmnf6qdrdARKwm98J8tpUqkILzCas9NG679fPxHMHGw/b2QPLr0I3LblE4c1IcIXIQPTniEm5lMjWkw7Ggf4AEg1PbWLcb5MvUwGuo8k6+ZsS1tYh name@example.com
Uploading Keys
- Login to DigitalOcean
- On the DigitalOcean dashboard select SSH Keys
- Add SSH Key
- Enter a name for it and paste the contents into the body.
- Create SSH Key
Instance Creation (Create Droplet)
DigitalOcean calls each server instance a “droplet”
- Click Create Droplet
- Enter a hostname for your server
- Select a size (I recommend 512MB RAM for starting)
- Select Region
- Select Image Ubuntu 14.04 x64 (LTS)
- Add your key, which was uploaded earlier
- Create Droplet
SSH Connection
Once the loading bar has completed and we have an IP address we are ready to connect to the server.
We can connect to the server using the ssh
command. Our public key has been automatically added to the server from the DigitalOcean control panel so our private key will work as the “password”.
$ ssh root@107.170.203.120
The authenticity of host '107.170.203.120 (107.170.203.120)' can't be established.
RSA key fingerprint is 5b:13:e0:0e:d9:44:5a:1a:49:b5:12:0e:3c:d4:0d:8d.
Are you sure you want to continue connecting (yes/no)?yes
After connecting you should see this.
Warning: Permanently added '107.170.203.120' (RSA) to the list of known hosts.
Welcome to Ubuntu 14.04 LTS (GNU/Linux 3.13.0-24-generic x86_64)
* Documentation: https://help.ubuntu.com/
System information as of Fri Jul 11 01:06:53 EDT 2014
System load: 0.0 Processes: 71
Usage of /: 6.1% of 19.56GB Users logged in: 0
Memory usage: 9% IP address for eth0: 107.170.203.120
Swap usage: 0%
Graph this data and manage this system at:
https://landscape.canonical.com/
root@setup-demo:~#
Lockdown
We are now logged into the server, which right now is almost wide open to the Internet. It is time to lock it down with the following steps:
User account creation
Create a sudo user account
username=YOUR_NAME_HERE
addgroup admin
adduser $username
usermod -a -G admin $username
Full output
root@setup-demo:~# username=matt
root@setup-demo:~# addgroup admin
Adding group `admin' (GID 1000) ...
Done.
root@setup-demo:~# adduser $username
Adding user `matt' ...
Adding new group `matt' (1001) ...
Adding new user `matt' (1000) with group `matt' ...
Creating home directory `/home/matt' ...
Copying files from `/etc/skel' ...
Enter new UNIX password:
Retype new UNIX password:
passwd: password updated successfully
Changing the user information for matt
Enter the new value, or press ENTER for the default
Full Name []: Matt Carrier
Room Number []:
Work Phone []:
Home Phone []:
Other []:
Is the information correct? [Y/n]
root@setup-demo:~# usermod -a -G admin $username
Copy over SSH public key to new account and set permissions to the owner
mkdir -p /home/$username/.ssh/
cp ~/.ssh/authorized_keys /home/$username/.ssh/authorized_keys
chmod -R 750 /home/$username
chown -R $username:$username /home/$username/
SSH Server lockdown
-
Disable password authentication
echo "PasswordAuthentication no" >> /etc/ssh/sshd_config
-
Disable root login
sed -i 's/PermitRootLogin without-password/PermitRootLogin no/g' /etc/ssh/sshd_config
sed -i 's/PermitRootLogin yes/PermitRootLogin no/g' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
- Only allow login from selected users
echo "AllowUsers $username" >> /etc/ssh/sshd_config
- Restart ssh server
service ssh restart
Firewall & fail2ban
- Setup ufw (Ubuntu Firewall)
# ufw (Ubuntu Firewall)
ufw default deny incoming
ufw default allow outgoing
# Open SSH
ufw allow ssh
# Open web ports
ufw allow 443/tcp
ufw allow 80/tcp
# Enable firewall and fail2ban
ufw --force enable
- Setup fail2ban
apt-get install -y fail2ban
- Confirm status
root@setup-demo:~# ufw status
Status: active
To Action From
-- ------ ----
22 ALLOW Anywhere
443/tcp ALLOW Anywhere
80/tcp ALLOW Anywhere
22 (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
root@setup-demo:~# service fail2ban status
* Status of authentication failure monitor
* fail2ban is running
- Ensure you can connect from a new terminal window before disconnecting
$ ssh YOUR_USERNAME@SERVER_IP
Updating & Upgrading
-
Set the time zone to your choice
NOTE: I had to run
$ tzconfig
before the above command would work for me.
$ dpkg-reconfigureĀ tzdata
-
Update server to latest software
apt-get update
will fetch all the latest updates.
apt-get upgrade
will apply updates.
$ apt-get update && apt-get upgrade -y
...
# Make sure you are able to reconnect from a new window before this step
$ shutdown -r now
Software Installation
Basic utilities to install
sudo apt-get install -y htop zsh tree git vim nginx nodejs make npm cmake python-dev
- htop - processor monitor
- tree - tree view directories
- git - the stupid content tracker
- vim - text editor
- nginx - web server / reverse proxy
- make - build tools
- cmake - more build tools
- python-dev - even more building tools
Configuration & Debugging
-
nginx -
sudo vim /etc/nginx/sites-enabled/default
sudo service nginx restart
-
ssh -
sudo vim /etc/ssh/sshd_config
sudo service ssh restart
-
logs
/var/log
sudo tail -f /var/log/nginx/access.log
Shell Scripting
#!/bin/bash
# This is a comment
echo "Hello World"
# make script executable
chmod a+x hello.sh
# execute script
./hello.sh
Git remote repository
On the remote machine
$ mkdir ~/web-project-name.git
$ git init --bare ~/web-project-name.git
From local machine
$ cd ~/projects/web-project
$ git remote add web-hostname YOUR_USERNAME@SERVER_IP:web-project-name.git
$ git push web-hostname master
- Githooks
- post-update for deployment
Challenge: Setup the git post-update hook to deploy website
Gotchas
- ctrl + z by accident?
- fg to foreground the application
NodeJS with Nginx
- Add a site config to
/etc/nginx/sites-available/site.conf
. - Soft link
ln -s /etc/nginx/sites-available/site.conf /etc/nginx/sites-enabled/
to enable the site. sudo service nginx reload
to apply the changes.- Change the port number from
3000
to whatever your node app is running on.
Next time
- Automation
- Ansible
- PaaS
- Docker
- Dokku
Future talk ideas
- Nginx Setup with NodeJS
- DNS
- Monitoring
- Automation deep dive
- AWS
- Basics
- Security Groups
- EC2
- Load Balancing
- etc…
- Continuous Integration