# Install server

In this guide we will create a secure setup of a new Ubuntu (opens new window) server with Apache and Docker. This will be our base setup where we will install SenSeeAct later. There are of course many possible server configurations and you may already have a running Ubuntu server and web server. So chances are that you cannot follow this guide step by step and you might even skip most of it. But since this guide covers everything you need to set up a server, you may find some useful instructions that apply to your situation.

Before we start, we assume that you already have:

  • Access to an Ubuntu server. You may get it by launching an instance at AWS EC2 (Amazon Web Services - Elastic Compute Cloud), or renting a VPS (Virtual Private Server) from a hosting provider, or you may get it from your system administrator. You need to have:

    • The host name or IP address of your server.
    • The username and the private key or password of a user with sudo rights. On a clean installation of AWS EC2 or a VPS, you may only have the initial ubuntu or root user. We will create a normal user as soon as possible.
  • A domain name with the DNS set to resolve to the IP address of your server. If your domain is example.com, we assume that example.com and www.example.com resolve to your server.

  • An SSL certificate for your domain name (example.com and www.example.com). You can purchase a domain name and SSL certificate, or get it from your system administrator. For the certificate you should have three files like:

    • example_com.ca-bundle
    • example_com.crt
    • example_com.key
  • Access to an SMTP server to send email associated with your domain. Again, you can purchase email hosting from a hosting provider or get it from your system administrator.

# Connect

First you need to connect to your Ubuntu server from your workstation. Instructions:

# Create user

If you logged in with the initial ubuntu or root user, you should first create a normal user and give it sudo rights. You can also use the following instructions to create additional users.

  • Enter this command (sudo is not needed if you are root):
    $ sudo adduser <NEWUSER>
    
  • When asked, enter a password.
  • You are asked for further details, which are optional.
  • When the user is created, grant the sudo rights and add the user to relevant groups:
    $ sudo usermod -a -G sudo,adm,www-data <NEWUSER>
    

Then create an SSH key pair for the user if you don’t have one yet.

  • Open Terminal on your computer and enter:
    $ ssh-keygen
    
  • You are asked to enter the file in which to save the key. If you are creating a user for yourself, accept the default ~/.ssh/id_rsa. Otherwise enter something else, such as username_key.
  • When asked for the passphrase, just press Enter.
  • You should now have two files. If you chose the default ~/.ssh/id_rsa, you will have:
    • id_rsa: the private key
    • id_rsa.pub: the public key
  • Copy the files to a safe location so you can restore them if needed.

Upload the public key to the server.

  • Still in the terminal on your computer, enter this command:
    $ scp .ssh/id_rsa.pub <CURRENTUSER>@<HOSTNAME>:~
    
    At <CURRENTUSER> fill in the user that you are currently logged in with, not the new user that we are still setting up.
    You can change the public key path .ssh/id_rsa.pub if you chose a different location.
  • Now the public key is at your server. You can close the terminal on your computer.
  • Go back to your server connection.
  • Enter these commands:
    $ sudo mkdir -p /home/<NEWUSER>/.ssh
    $ cat id_rsa.pub | sudo tee -a /home/<NEWUSER>/.ssh/authorized_keys
    $ rm id_rsa.pub
    $ sudo chown -R <NEWUSER>:<NEWUSER> /home/<NEWUSER>/.ssh
    $ sudo chmod 700 /home/<NEWUSER>/.ssh
    $ sudo chmod 600 /home/<NEWUSER>/.ssh/authorized_keys
    
  • Close the connection with exit.

Now you can connect with the new user (Windows, Mac) using the new private key.

# Secure SSH access

You can further secure the SSH server by disabling SSH access for the root user and disabling access with a password, so a private key is required.

  • Connect to your server and edit sshd_config in nano:
    $ sudo nano /etc/ssh/sshd_config
    
  • Find the following options and change them to no:
    PermitRootLogin yes
    UsePAM yes
    PasswordAuthentication yes
    
  • Add this line:
    ChallengeResponseAuthentication no
    
  • Save the file with Ctrl+S and close the editor with Ctrl+X.
  • Restart the SSH server with:
    $ sudo service ssh restart
    
    IMPORTANT: Without your private key, you will no longer be able to connect to your server through SSH.

# Update

Run an update of the software. You need to repeat this from time to time to keep your server up-to-date.

  • Enter these commands:
    $ sudo apt update
    $ sudo apt upgrade
    
  • You may need to reboot after installing the updates:
    $ sudo reboot
    
  • This will close your connection. Reconnect later when the machine has rebooted.

# Firewall

The firewall should only allow the following inbound ports:

  • 22 (SSH): only your IP address
  • 80 (HTTP): anywhere
  • 443 (HTTPS): anywhere

Sometimes you, as a developer or administrator, will need access to other ports. Do not open such ports in your Firewall. You can access other ports through an SSH tunnel (Windows, Mac).

If you use AWS EC2, you can configure this in the security groups. Otherwise you can configure the firewall in Ubuntu.

# AWS EC2 Security Groups

  • From your EC2 dashboard, in the left-hand sidebar, choose Network & Security > Security Groups.
  • Click the security group ID that you are using.
  • Click Edit inbound rules.

Add the following rules:

Type Protocol Port range Source
HTTP TCP 80 Anywhere-IPv4: 0.0.0.0/0
HTTPS TCP 443 Anywhere-IPv4: 0.0.0.0/0
SSH TCP 22 Custom: <IP-ADDRESS>/32

You can add multiple SSH rules for all IP addresses or ranges that you want to allow.

# Ubuntu firewall

  • First allow access to port 22 (SSH). You can allow access from anywhere, or for extra security only from your IP address. For access from anywhere:

    $ sudo ufw allow 22
    

    For access from a certain IP address:

    $ sudo ufw allow from <IP-ADDRESS> to any port 22
    

    You can also use an IP mask like 192.168.1.0/24.

    IMPORTANT: You must configure this correctly before you activate the firewall in the next step. Otherwise you can no longer access your server through SSH. If you restrict access to your IP address, you will lose SSH access if your address changes.

  • Then allow the other ports from anywhere and activate the firewall:

    $ sudo ufw allow 80
    $ sudo ufw allow 443
    $ sudo ufw enable
    

# Apache

We will use Apache (opens new window) as a secure proxy in front of the applications that we install in Docker containers. First we will install Apache and create a general configuration for our server.

# Install

  • Enter this command:

    $ sudo apt install apache2
    
  • Enable modules:

    $ sudo a2enmod proxy
    $ sudo a2enmod proxy_ajp
    $ sudo a2enmod proxy_html
    $ sudo a2enmod proxy_http
    $ sudo a2enmod rewrite
    $ sudo a2enmod ssl
    
  • You can restart Apache any time to load your configuration changes:

    $ sudo service apache2 restart
    

# SSL certificate

Now you need to upload the certificate files from your computer to the server. Upload the three files like:

  • example_com.ca-bundle
  • example_com.crt
  • example_com.key

Instructions to upload files:

Upload the files to your home directory on the server. Then we move them to a secure location that is only accessible to Apache and to users in group www-data.

  • After uploading the files, enter the following commands. Use your domain instead of example_com.
    $ cd /etc/apache2
    $ sudo mkdir ssl
    $ sudo chown www-data:www-data ssl
    $ sudo chmod 750 ssl
    $ cd ssl
    $ sudo mv ~/example_com.* .
    $ sudo chown www-data:www-data *
    $ sudo chmod 640 *
    

We will load the certificate in Apache in the next section.

# Secure file access

By default Apache gives access to the files in /usr/share and /var/www. In our setup we serve everything through proxies to Docker containers, so we do not need public access to these files. It is best to deny access to files that are not needed. At least we recommend to deny access to /usr/share as this is used for developer applications such as stand-alone phpMyAdmin, which should be private. If you need those applications, you should configure Apache so that they are provided at an alternative port such as 8080 and access them through an SSH tunnel (see Firewall).

You can deny access to /usr/share and /var/www with the following steps.

  • Edit apache2.conf in nano:

    $ cd /etc/apache2
    $ sudo nano apache2.conf
    
  • Find these lines:

    <Directory />
        Options FollowSymLinks
        AllowOverride None
        Require all denied
    </Directory>
    
    <Directory /usr/share>
        AllowOverride None
        Require all granted
    </Directory>
    
    <Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    
  • Comment the following lines:

    # <Directory /usr/share>
    #     AllowOverride None
    #     Require all granted
    # </Directory>
    
    # <Directory /var/www/>
    #     Options Indexes FollowSymLinks
    #     AllowOverride None
    #     Require all granted
    # </Directory>
    
  • Save the file with Ctrl+S and close the editor with Ctrl+X.

# Sites

Sites are the applications and services that we want to make available. They can be public sites for end users, such as the SenSeeAct web application and API, or they can be private sites for administrators and developers, such as phpMyAdmin. Our applications and services will be provided by private Docker containers. For the ones that we want to make public, we will install sites in Apache as proxies to the Docker containers. The private ones are left as Docker containers. They can be accessed through an SSH tunnel (see Firewall).

In our configuration of Apache we consider that you can have additional sites of your own. If you install any private sites directly in Apache, we recommend to install them at an alternative port such as 8080 and access them through an SSH tunnel.

The Apache configuration allows for available sites that can be enabled and disabled indepedently. This is done in the directories /etc/apache2/sites-available and /etc/apache2/sites-enabled. We will set it up with these considerations:

  • We enable secure https:// by installing the SSL certificate.
  • Unsecure http:// is automatically redirected to secure https://.
  • We support specific subdomains such as myapp.example.com if you need them. Note that you need a wildcard SSL certificate for that.
  • Everything else defaults to https://www.example.com/.
  • You can enable or disable various sites under www.example.com.

We start with some defaults in /etc/apache2/sites-available. Note that the files will be imported in alphabetical order. This is significant because Apache will resolve incoming requests to the first match that it encounters.

  • Edit 000-default.conf in nano:
    $ cd /etc/apache2/sites-available
    $ sudo nano 000-default.conf
    
  • Replace the content with the following. Use your domain instead of example_com.
    <VirtualHost *:80>
        DocumentRoot /var/www/html
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    </VirtualHost>
    
    <VirtualHost *:443>
        DocumentRoot /var/www/html
    
        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined
    
        SSLEngine on
        SSLCertificateFile /etc/apache2/ssl/example_com.crt
        SSLCertificateKeyFile /etc/apache2/ssl/example_com.key
        SSLCertificateChainFile /etc/apache2/ssl/example_com.ca-bundle
    </VirtualHost>
    
  • Save the file with Ctrl+S and close the editor with Ctrl+X.

If you want to support any subdomains like myapp.example.com, configure them next, so they take precedence over the default www.example.com. Configure a subdomain with the following steps. You can skip this if you don’t use any subdomain.

  • Create file 001-myapp.conf in nano. Use your subdomain instead of myapp.
    $ sudo nano 001-myapp.conf
    
  • With the following content. Use your subdomain instead of myapp.example.com.
    <VirtualHost *:80>
        ServerName myapp.example.com
        RedirectPermanent / https://myapp.example.com/
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName myapp.example.com
        # Configure the site here
    </VirtualHost>
    
  • Save the file with Ctrl+S and close the editor with Ctrl+X.

After the custom subdomains, we get to the default www.example.com. We will set up an additional layer of sites that you can enable or disable independently within the domain of www.example.com. We create a directory www-available.

  • Enter these commands:
    $ sudo mkdir www-available
    
  • Create file 100-www-default.conf in nano.
    $ sudo nano 100-www-default.conf
    
  • With the following content. Use your domain instead of example.com.
    <VirtualHost *:80>
        # Redirect everything on http to https://www.example.com/
        ServerName www.example.com
        ServerAlias example.com
        ServerAlias *.example.com
        RedirectPermanent "/" "https://www.example.com/"
    </VirtualHost>
    
    <VirtualHost *:443>
        ServerName www.example.com
        IncludeOptional sites-enabled/www-enabled/*.conf
    </VirtualHost>
    
    <VirtualHost *:443>
        # Redirect everything remaining on https to https://www.example.com/
        # This section has to be after the previous section, so that we do not
        # redirect www.example.com to itself.
        ServerName example.com
        ServerAlias *.example.com
        RedirectPermanent / https://www.example.com/
    </VirtualHost>
    
  • Save the file with Ctrl+S and close the editor with Ctrl+X.

Finally set up the directory sites-enabled.

  • Enter these commands:
    $ cd /etc/apache2/sites-enabled
    $ sudo ln -sf ../sites-available/0*.conf ../sites-available/1*.conf .
    $ sudo mkdir www-enabled
    

We will install SenSeeAct in www-enabled later.

# Default site

When we install SenSeeAct, we will install the web application at one of these URLs:
https://www.example.com/ or https://www.example.com/senseeact/

And we install the API at:
https://www.example.com/servlets/senseeact/

If you choose to install the web application at https://www.example.com/senseeact/ and the user goes to https://www.example.com/, they will see a “forbidden” message. Below are some options to configure that URL.

Option 1: Redirect to SenSeeAct or another site

  • Edit 100-www-default.conf in nano:
    $ cd /etc/apache2/sites-available
    $ sudo nano 100-www-default.conf
    
  • Find this section:
    <VirtualHost *:443>
        ServerName www.example.com
        IncludeOptional sites-enabled/www-enabled/*.conf
    </VirtualHost>
    

To redirect to SenSeeAct:

  • Before </VirtualHost> add this line:
    RedirectMatch "(^/$)|(^/index.php.*$)|(^/index.html.*$)" "/senseeact/"
    

To redirect to another site:

  • Before </VirtualHost> add a line like this:
    RedirectMatch "(^/$)|(^/index.php.*$)|(^/index.html.*$)" "https://www.othersite.com/"
    

Finally save the file with Ctrl+S and close the editor with Ctrl+X.

Option 2: Install a default site in /var/www/html

If you disabled access to /var/www earlier, then re-enable it:

  • Edit apache2.conf in nano:
    $ cd /etc/apache2
    $ sudo nano apache2.conf
    
  • Enable this section:
    <Directory /var/www/>
        Options Indexes FollowSymLinks
        AllowOverride None
        Require all granted
    </Directory>
    
  • Save the file with Ctrl+S and close the editor with Ctrl+X.
  • Copy the files for the default site to /var/www/html.

# Restart Apache

We have finished the configuration of Apache. Now restart Apache to activate the changes.

  • Enter this command:
    $ sudo service apache2 restart
    

# Docker

https://www.docker.com/ (opens new window)

  • Install Docker with these commands:
    $ sudo apt update
    $ sudo apt install ca-certificates curl gnupg lsb-release
    $ sudo mkdir -p /etc/apt/keyrings
    $ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
    $ echo \
      "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
      $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
    $ sudo apt update
    $ sudo apt install docker-ce
    
  • Add your user to the docker group:
    $ sudo adduser $USER docker