UP | HOME

☁️ Cloud Computing

Primary Services

Compute

Storage

Databases

Services Models

IaaS

  • Networking
  • Servers
  • Storage
  • Virtualization

Target Audience

  • DevOps Engineers

PaaS

  • Middleware
  • Operating System
  • Runtime

Target Audience

  • Software Engineers

SaaS

  • Applications
  • Data

Roles

Cloud Architect

  • Solutions architect of the cloud
  • Design cloud infrastructure based on business requirements

Security Engineer

  • Ensure data privacy of users and the organization is protected
  • Spec out technical security requirements based on regulations and business requirements

Further Reading

DevOps Engineer

  • Maintain infrastracture through code
  • Ensure reliability, availability, and scalability through automation
  • Experienced in software development and IT operations

Setup VPS / Ubuntu

Init / Update The VM

I assume you already create a new virtual machine and you have a fresh system available. I also assume your virtual machine runs Ubuntu.

Change the default root password to a new one:

passwd root

Update the system packages to the newest version:

apt update && apt -y upgrade

If you want, you can install a terminalmultiplexer like tmux. Sometimes it is easier to work with tmux on a remote machine. Also I like to use mosh instead of ssh, because mosh is less restrictive if the connection is lost.

apt install -y tmux mosh

Setup A Standard User

You will do this initial setup as the root user. All work after setting up a new user should be done by using the new user, not the root user.

Create a new user and add it to the sudo group. Do not manage the server with the root user! Later we will disable root login in the sshd config. So no one is able to log in with the root user by ssh.

useradd -G sudo -s /bin/bash -m marcus

useradd is a command in Linux that is used to add user accounts to your system. It is just a symbolic link to adduser command in Linux and the difference between both of them is that useradd is a native binary compiled with system whereas adduser is a Perl script which uses useradd binary in the background. It make changes to the following files:

/etc/passwd

/etc/shadow

/etc/group

/etc/gshadow

creates a directory for new user in /home

Set a good password for your new user:

passwd marcus

Verify that the user was created correctly:

id marcus
uid=1000(marcus) gid=1000(marcus) groups=1000(marcus),27(sudo)

You can get more detailed information of a user by using the finger tool:

apt install -y finger
finger marcus
Login: marcus         			Name:
Directory: /home/marcus             	Shell: /bin/bash
On since Sun Aug 28 07:04 (UTC) on pts/0 from 2003:ca:1f1e:7700:751a:6940:4e3b:3f49
   1 minute 7 seconds idle
On since Sun Aug 28 07:01 (UTC) on pts/1 from 2003:ca:1f1e:7700:751a:6940:4e3b:3f49
   1 second idle
     (messages off)
No mail.
No Plan.

Send the public ssh key from your local machine to the remote machine to be able to log in via ssh with your new created user.

(I assume you only have one public key in your ~/.ssh directory)

ssh-copy-id marcus@u1.metaebene.dev

Automatic systems are constantly scanning the internet for open services and ports. This is a normal thing.

As a security action, using one of the following user names should be avoided:

ubuntu, oracle, rust, rustserver, kubernetes, vagrant, admin, account, pgsql, deploy, hadoop, ansible, user, pi, test, guest, support, xbmc, nagios, debian, minecraft, cisco, www, wwwrun, ftpuser, centos, joomla, puppet, docker, glassfish, bugzilla, wpuser, ts3, ts3server, postgres, jenkins, web, solarwinds, codenvy, mcserver, chef, deployer, ftpadmin, tomcat, wordpress, git, mysql, ec2-user, cloud, csgoserver, csgo, odoo, samsung, apple, acer, systems, maria, centos, cirros, mcserver, mcsrv, es

The following tasks should be done by using the new created user and not the root user.

SSHD Configuration

To be able to secure connect and work on the virtual machine you need to configure and setup sshd.

In simple terms, SSH (Secure Shell) is a protocol used to securely access remote computers over a network. It allows users to log in to a remote system and execute commands as if they were using a local terminal, but with the added security of encryption and authentication to protect the communication from eavesdropping, tampering, and other security threats. SSH also supports file transfers and port forwarding, making it a versatile tool for remote system management and access.

Create the sshd_config

Include /etc/ssh/sshd_config.d/*.conf

Disable login using root

Disabling root login in the sshd_config file makes it harder for attackers to gain unauthorized access to your server, and reduces the risk of accidental damage to the system. Root accounts have powerful access, and disabling their direct login forces attackers to use other accounts and adds an additional layer of security.

PermitRootLogin no
UsePAM no

In general, it is recommended to disable challenge-response authentication, as it is less secure than other methods of authentication, such as public key authentication or password authentication.

ChallengeResponseAuthentication no

Disable password based login

PasswordAuthentication no

The AuthenticationMethods publickey setting allows only public key authentication for SSH connections, which is more secure than other methods of authentication like password authentication. It involves generating a key pair and providing the public key to the server, limiting the methods of authentication that an attacker can use to gain unauthorized access to the system.

AuthorizedKeysFile .ssh/authorized_keys
AuthenticationMethods publickey
PubkeyAuthentication yes

Limit Users’ ssh access

AllowUsers marcus
DenyUsers root

Disable empty passwords

PermitEmptyPasswords no

Configure idle log out timeout interval

ClientAliveInterval 300
ClientAliveCountMax 0

The X11 protocol is not security oriented. If you don’t need it, you should disable the X11 forwarding in SSH.

X11Forwarding no

But still enable TCP forwarding, we will use it to secure connect to the lisp machine.

AllowTcpForwarding yes

Default configs

Subsystem       sftp    /usr/lib/openssh/sftp-server
AcceptEnv LANG LC_*
PrintMotd no

“KexAlgorithms curve25519-sha256@libssh.org” is a cryptographic setting that specifies the use of a key exchange algorithm called “curve25519-sha256” to securely establish a connection between the SSH client and server.

KexAlgorithms curve25519-sha256@libssh.org

“Ciphers chacha20-poly1305@openssh.com” is a cryptographic setting that specifies the use of a cipher algorithm called “chacha20-poly1305” to secure data during data exchange.

Ciphers chacha20-poly1305@openssh.com

“MACs hmac-sha2-512-etm@openssh.com” is a cryptographic setting that specifies the use of a MAC (Message Authentication Code) algorithm called “hmac-sha2-512-etm” to ensure data integrity during data exchange.

MACs hmac-sha2-512-etm@openssh.com

Copy the sshd_config to the remote maschine

On your remote machine first create a copy of the default sshd_config:

cp /etc/ssh/sshd_config ~/sshd_config.bak

Copy the newely created sshd_config to your remote machine into the /etc/ssh directory and restart the sshd server:

scp sshd_config marcus@u1.metaebene.dev:~/sshd_config
sudo cp ~/sshd_config /etc/ssh/sshd_config
sudo systemctl restart sshd

Cloud Init

#cloud-config
#Make sure to check the cloud-init logs (/var/log/cloud-init.log and /var/log/cloud-init-output.log)
locale: en_US.UTF-8
keyboard:
  layout: us
timezone: Europe/Berlin

groups:
  - nginxgroup

users:
  - name: nginxuser
    system: true
    shell: /usr/sbin/nologin
    groups: nginxgroup
    sudo: null
  # Create a new user named 'marcus'
  - name: marcus
    # Add the user to the 'users' and 'admin' groups
    groups: users, admin
    # Allow the user to execute any command with sudo without entering a password
    sudo: ALL=(ALL) NOPASSWD:ALL
    # Set the user's default shell to /bin/bash
    shell: /bin/bash
    # Add the user's public SSH key for key-based authentication
    ssh_authorized_keys:
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIA+46Y3AHPLJgz8KK61doqH3jBX2TL3TJvZsJrB9Km03 visua@xps-8930
      - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMIHJ5qpMIKL7N3nC0GG1O4ygtkqOlQuZReoik6xGBxn marcus@XPS-13-9380.local

packages:
  - fail2ban
  - ufw
  - unattended-upgrades
  - sbcl
  - mosh
  - tmux
  - git
  - mercurial
  - nginx
  - certbot
  - python3-certbot-nginx
  - libev4
  - build-essential
  - sqlite3
  - emacs-nox
  - python3-pip
  - python3-pandas
  - python3-matplotlib

package_update: true
package_upgrade: true

write_files:
  - path: /etc/apt/apt.conf.d/20auto-upgrades
    content: |
      APT::Periodic::Update-Package-Lists "1";
      APT::Periodic::Download-Upgradeable-Packages "1";
      APT::Periodic::AutocleanInterval "7";
      APT::Periodic::Unattended-Upgrade "1";

  - path: /etc/ssh/sshd_config
    content: |
      # Include additional configuration files from the specified directory
      Include /etc/ssh/sshd_config.d/*.conf
      # Set the maximum number of authentication attempts allowed per connection
      MaxAuthTries 3
      # Specifies the file containing public keys for user authentication
      AuthorizedKeysFile .ssh/authorized_keys
      # Disables password authentication
      PasswordAuthentication no
      # Specifies the authentication method(s) to use (public key authentication in this case)
      AuthenticationMethods publickey
      # Enables public key authentication
      PubkeyAuthentication yes
      # Disables root login via SSH
      PermitRootLogin no
      # Disables keyboard-interactive authentication
      KbdInteractiveAuthentication no
      # Enables the Pluggable Authentication Module (PAM) for authentication
      UsePAM yes
      # Disables agent forwarding for SSH connections
      AllowAgentForwarding no
      # Enables TCP forwarding for SSH connections
      AllowTcpForwarding yes
      # Disables X11 forwarding for SSH connections
      X11Forwarding no
      # Disables printing of the message of the day (MOTD) when a user logs in
      PrintMotd no
      # Specifies the key exchange algorithms to use
      KexAlgorithms curve25519-sha256@libssh.org
      # Specifies the ciphers allowed for protocol version 2
      Ciphers chacha20-poly1305@openssh.com
      # Specifies the message authentication code (MAC) algorithms in order of preference
      MACs hmac-sha2-512-etm@openssh.com
      # Specifies environment variables sent by the client to the server
      AcceptEnv LANG LC_*
      # Specifies the command to use for the SFTP subsystem
      Subsystem sftp /usr/lib/openssh/sftp-server
      # Specifies the user(s) allowed to log in via SSH (in this case, only the user "marcus")
      AllowUsers marcus

  # Create a new filter for Nginx
  - path: /etc/fail2ban/filter.d/nginx-http-auth.conf
    content: |
      # Define the filter
      [Definition]
      # Regular expression to match unauthorized requests in Nginx logs
      failregex = ^<HOST> -.*"(GET|POST|HEAD).*HTTP.*" 401 .*
      # Regular expressions to ignore (none in this case)
      ignoreregex =

  # Add Nginx jail configuration
  - path: /etc/fail2ban/jail.d/nginx.conf
    content: |
      # Define the jail for Nginx
      [nginx-http-auth]
      # Enable the jail
      enabled = true
      # Specify the filter to use (created earlier)
      filter = nginx-http-auth
      # Define the action to take (using UFW)
      action = ufw
      # Specify the log file to monitor
      logpath = /var/log/nginx/error.log
      # Set the maximum number of failed attempts before banning
      maxretry = 6
      # Set the ban time in seconds (1 hour)
      bantime = 3600
      # Set the time window for failed attempts in seconds (10 minutes)
      findtime = 600

  - path: /etc/fail2ban/jail.local
    content: |
      [DEFAULT]
      # Ban time (in seconds) for an IP after reaching the max number of retries.
      bantime = 3600
      # Time window (in seconds) in which 'maxretry' failures must occur.
      findtime = 600
      # Maximum number of failed login attempts before an IP gets banned.
      maxretry = 3
      # Ban action to use (ufw in this case).
      banaction = ufw

      [sshd]
      # Enable the sshd jail.
      enabled = true
      # Specify the port for the sshd service.
      port = 22
      # Path to the log file for the sshd service.
      logpath = /var/log/auth.log

      [sshd-ddos]
      # Enable the sshd-ddos jail.
      enabled = true
      # Specify the port for the sshd service.
      port = ssh
      # Path to the log file for the sshd service.
      logpath = /var/log/auth.log
      # Maximum number of failed login attempts before an IP gets banned (for DDoS protection).
      maxretry = 5
      # Ban time (in seconds) for an IP after reaching the max number of retries (for DDoS protection).
      bantime = 600

  - path: /etc/nginx/nginx.conf
    content: |
      user nginxuser;
      worker_processes auto;
      pid /run/nginx.pid;
      include /etc/nginx/modules-enabled/*.conf;
      events {
        worker_connections 768;
        # multi_accept on;
      }
      http {
        ##
        # Basic Settings
        ##
        sendfile on;
        tcp_nopush on;
        types_hash_max_size 2048;
        # server_tokens off;
        # server_names_hash_bucket_size 64;
        # server_name_in_redirect off;
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
        ##
        # SSL Settings
        ##
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;
        ##
        # Logging Settings
        ##
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
        ##
        # Gzip Settings
        ##
        gzip on;
        # gzip_vary on;
        # gzip_proxied any;
        # gzip_comp_level 6;
        # gzip_buffers 16 8k;
        # gzip_http_version 1.1;
        # gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
        ##
        # Virtual Host Configs
        ##
        include /etc/nginx/conf.d/*.conf;
        include /etc/nginx/sites-enabled/*;
      }

  # Write reverse-proxy configuration file
  - path: /etc/nginx/sites-available/reverse-proxy.conf
    content: |
      # Listen on port 80
      server {
        listen 80;
        # Set your domain name
        server_name u1.metaebene.dev;
        # Redirect all requests to HTTPS
        return 301 https://$host$request_uri;
      }

      # Listen on port 443 with SSL
      server {
        listen 443 ssl;
        # Set your domain name
        server_name u1.metaebene.dev;

        # Include SSL certificate managed by Certbot
        ssl_certificate /etc/letsencrypt/live/u1.metaebene.dev/fullchain.pem;
        # Include SSL certificate key managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/u1.metaebene.dev/privkey.pem;
        # Include SSL options provided by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf;
        # Include DH parameters provided by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        # Proxy settings for the location
        location / {
          # Set backend server address and port
          proxy_pass http://localhost:8080;
          # Set Host header
          proxy_set_header Host $host;
          # Set X-Real-IP header
          proxy_set_header X-Real-IP $remote_addr;
          # Set X-Forwarded-For header
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          # Set X-Forwarded-Proto header
          proxy_set_header X-Forwarded-Proto $scheme;
        }
      }

      server {
        listen 80;
        # Set your domain name
        server_name docs.u1.metaebene.dev;
        # Redirect all requests to HTTPS
        return 301 https://$host$request_uri;
      }

      # Listen on port 443 with SSL
      server {
        listen 443 ssl;
        # Set your domain name
        server_name docs.u1.metaebene.dev;

        # Include SSL certificate managed by Certbot
        ssl_certificate /etc/letsencrypt/live/docs.u1.metaebene.dev/fullchain.pem;
        # Include SSL certificate key managed by Certbot
        ssl_certificate_key /etc/letsencrypt/live/docs.u1.metaebene.dev/privkey.pem;
        # Include SSL options provided by Certbot
        include /etc/letsencrypt/options-ssl-nginx.conf;
        # Include DH parameters provided by Certbot
        ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

        location / {
          root /home/marcus/www/u1/docs/public;
          index index.html;
        }
      }
runcmd:
  # Generate the en_US.UTF-8 locale
  - locale-gen en_US.UTF-8
  # Set the system's default locale to en_US.UTF-8
  - update-locale LANG=en_US.UTF-8
  # Set the system's timezone to Europe/Berlin
  - timedatectl set-timezone Europe/Berlin
  # Run Certbot to obtain SSL certificates and configure Nginx
  - certbot certonly --nginx -d u1.metaebene.dev --non-interactive --agree-tos --email marcus.kammer@mailbox.org --redirect
  - certbot certonly --nginx -d docs.u1.metaebene.dev --non-interactive --agree-tos --email marcus.kammer@mailbox.org --redirect
  # Download DHPARAM
  - curl https://ssl-config.mozilla.org/ffdhe2048.txt > /etc/letsencrypt/ssl-dhparam.pem
  # Create a symlink for the configuration file
  - ln -s /etc/nginx/sites-available/reverse-proxy.conf /etc/nginx/sites-enabled/
  # Remove default Nginx configuration
  - rm /etc/nginx/sites-enabled/default
  # Reload Nginx configuration
  - systemctl reload nginx
  # Allow Nginx Full (HTTP and HTTPS) through the firewall
  - ufw allow 'Nginx Full'
  # Set UFW firewall rules
  - ufw default deny incoming
  - ufw default allow outgoing
  - ufw allow 22/tcp
  - ufw allow mosh
  - ufw enable
  # Enable and start the fail2ban service
  - systemctl enable fail2ban && systemctl start fail2ban
  # Restart the SSH server to apply the new configuration
  - systemctl restart sshd
  - |
    sudo -u marcus git config --global user.email "marcus.kammer@mailbox.org"
    sudo -u marcus git config --global user.name "Marcus Kammer"
    sudo -u marcus git config --global init.defaultBranch main
  # Clone the SBCL repository for a specific branch and depth
  - sudo -u marcus git clone --depth 1 --branch sbcl-2.1.11 git://git.code.sf.net/p/sbcl/sbcl /home/marcus/sbcl
  # Clone the SLIME repository for a specific branch and depth
  - sudo -u marcus git clone --depth 1 --branch v2.28 https://github.com/slime/slime.git /home/marcus/slime
  # Download the Quicklisp installer
  - |
    curl https://beta.quicklisp.org/quicklisp.lisp -o /home/marcus/quicklisp.lisp
    chown marcus:marcus /home/marcus/quicklisp.lisp

Author: Marcus Kammer

Email: marcus.kammer@mailbox.org

Date: nil

Emacs 29.1.90 (Org mode 9.6.11)

License: CC BY-SA 3.0