It sometimes happens to setup development server for team with support many Docker environments.
Why is it Docker?
- It’s easy to setup.
- It’s easy to migrate.
- It’s easy to support.
- It’s just easy.
Update APT
As always, first as all, update and upgrade your APT.
# apt update
# apt upgrade
System settings
# echo fs.inotify.max_user_watches=582222 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
Change hostname using hostnamectl
# hostnamectl set-hostname dev.timebase.app
# hostnamectl
Static hostname: dev.timebase.app
Icon name: computer-vm
Chassis: vm
Machine ID: d2112e9bc476412b9e86f82930e22961
Boot ID: 3ce13f255d1846729ef6f51f31e4fdd5
Virtualization: kvm
Operating System: Ubuntu 20.04.2 LTS
Kernel: Linux 5.4.0-28-generic
Architecture: x86-64
Disable SSH password login on Linux to increase security
Assume you’ve just gotten access to a new server with a basic configuration with automatically generated root
password. It would be great to disable the possibility to connect to the server through SSH with password, instead you have to use a key pair.
Make sudo ask for the root password
To turn on the rootpw
flag, making sudo
ask for the root password, in /etc/sudoers
, add this line:
Defaults rootpw
Create a new sudo user account
You must create a regular user account and grant that user permission to gain root-level access via
su
command or NA command. Otherwise, you will be locked out of your server.
# useradd -m -s /bin/bash timebase
Set the user’s password using the passwd
command:
# passwd timebase
Add user to sudo (Ubuntu/Debian) group
# usermod -aG sudo timebase
The above command allows people in group wheel or sudo to run all commands. Verify it using the id command:
# su - timebase
$ id timebase
Sample outputs:
uid=1000(timebase) gid=1000(timebase) groups=1000(timebase),27(sudo)
Ctrl+D
to logout from a login shell.
Please note that you can add existing users to sudo
or wheel group too. No need to create a new user account:
# usermod -aG sudo userNameHere
Install your public key in remote server
Add your public key to remote server (don’t forget to change IP to yours)
$ ssh-copy-id -i ~/.ssh/id_rsa.pub timebase@80.65.78.198
Now open a new terminal and be sure that you can connect with your key just typing
$ timebase root@80.65.78.198
If you see the greeting message, everything is fine and you can go to the next step.
Ctrl+D
to logout from a login shell.
Disable the password based login on a server
Warning: Make sure you add yourself to sudoers files. Otherwise you will not able to login as root later on.
- Open the SSH configuration file
sshd_config
with the text editor vi:# vi /etc/ssh/sshd_config
- In the line
PermitRootLogin yes
replace the wordyes
with the wordno
:
PermitRootLogin no
- Find
ChallengeResponseAuthentication
and set tono
:
ChallengeResponseAuthentication no
- Next, find
PasswordAuthentication
set tono
too:
PasswordAuthentication no
- Finally look for
UsePAM
and set to no, too:
UsePAM no
- Save the file.
- Restart the service.
# systemctl restart sshd
Verification
Try to login as root
$ ssh root@80.209.229.183
root@80.209.229.183: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
Try to login as another user with password only
$ ssh timebase@80.209.229.183 -o PubkeyAuthentication=no
timebase@80.209.229.183: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).
Try to login as another user with public key
$ ssh timebase@80.209.229.183
Last login: Mon Jun 7 14:03:01 2021 from 78.98.52.223
Download and Install Docker
Set up the repository
- Update the
apt
package index and install packages to allowapt
to use a repository over HTTPS:# apt install apt-transport-https ca-certificates curl gnupg lsb-release make
- Add Docker’s official GPG key:
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
- Use the following command to set up the stable repository.
# echo \ "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Install Docker Engine
Enter the following command to download and install the Docker package.
apt update
apt install docker-ce docker-ce-cli containerd.io
Check Docker Version
You can check the version of Docker with the following command.
$ docker --version
Docker version 20.10.7, build f0df350
Launch Docker
Start Docker and enter the following command to enable it after every time the system reboots.
# systemctl enable --now docker
Synchronizing state of docker.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable docker
To disable it again, simply type in the following command.
# systemctl disable --now docker
Set User Privileges
This step will show you how to give privileges to any user with Docker. You can replace “timebase” with the user account you are giving permission.
$ sudo usermod -aG docker $USER
$ sudo gpasswd -a $USER docker
$ newgrp docker
Test Docker
Test Docker by running the following command, which will open a container to run the Hello World command.
# docker run hello-world
Install Docker Compose
-
Run this command to download the current stable release of Docker Compose:
# curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
To install a different version of Compose, substitute
1.29.2
with the version of Compose you want to use. -
Apply executable permissions to the binary:
# chmod +x /usr/local/bin/docker-compose
Note: If the command
docker-compose
fails after installation, check your path. You can also create a symbolic link to/usr/bin
or any other directory in your path. -
Test the installation.
$ docker-compose --version docker-compose version 1.29.2, build 5becea4c
Install AWS CLI
Install required packages
# apt-get install python3 python3-venv unzip mysql-client
Checking Python availability
Make sure phyton
command is available with:
$ python --version
Python 3.8.5
If you get an error like this /usr/bin/env: ‘python’: No such file or directory
instead. Check if Python 3 has been installed, run these commands:
# whereis python3
Then create a symlink to it:
# ln -s /usr/bin/python3 /usr/bin/python
AWS CLI installation
-
For the latest version of the AWS CLI, use the following command block:
# apt install # curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip" # unzip awscli-bundle.zip # ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws
-
Create new AWS CLI profile
$ aws configure --profile <your-name> AWS Access Key ID [None]: AK****************TY # change it with real ID AWS Secret Access Key [None]: Zk************************************ZE # change it with real key Default region name [None]: eu-central-1 Default output format [None]: json
-
Check if it’s saved correctly
$ cat ~/.aws/credentials [<your-name>] aws_access_key_id = AK****************TY aws_secret_access_key = Zk************************************ZE
-
Try to login with
$ $(aws ecr get-login --no-include-email --profile <your-name>)
Allow access to GitLab private repositories
-
Create the key pair on the server:
$ ssh-keygen -t rsa
-
Copy the new SSH key:
$ cat ~/.ssh/id_rsa.pub
-
Add the SSH key to GitLab:
Go to GitLab -> Preferences -> SSH Keys, past public key in the form and hitAdd key
button.
Configure a project
We need to create directory where all our project will be placed and directory for MySQL dumps. I’m going to setup the project from git repository. You can be free use any other repository.
-
Login with your non-root user and create directories.
$ cd ~ $ mkdir {docker,dump}
-
Clone your project
$ cd docker $ git clone https://gitlab.com/timebase/tb-web $ cd tb-web-tgs/
We have prepare
makefile
in our project that allows as to run the project as:$ make up
You can use native docker-compose command instead:
$ docker-compose up
-
Open your project in a browser
80.65.78.198:8081
.Note. Use the port number that you indicate in
.evn
ordocker-compose.yml
file.
But as you can notice it’s not comfortably to use IP and port, even more when the number of dev projects increase it’ll make a nightmare to remember who is who. To simplify our life we will install Nginx and apply reasonable names to our projects.
Install Nginx
# apt install nginx
-
Prepare a configuration file under:
# cat /etc/nginx/sites-available/tgs.timebase.app.conf server { server_name tgs.timebase.app; access_log /var/log/nginx/tgs.timebase.app.access.log; error_log /var/log/nginx/tgs.timebase.app.error.log; location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; proxy_pass http://localhost:8081/; } }
Make sure you indicate correct port number of your Docker container in
proxy_pass
config. -
Enable your project that Nginx can read this configuration:
# ln -s /etc/nginx/sites-available/tgs.timebase.app.conf /etc/nginx/sites-enabled/tgs.timebase.app.conf
-
Test Nginx configuration
# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Install Certbot
To make your project available on the Internet we have to configure Certbot to be able to connect through HTTPS.
-
Before to setup Certbot you must to add your domain to DNS.
-
Install Certbot and it’s Nginx plugin with
apt
:# apt install certbot python3-certbot-nginx
Certbot is now ready to use, but in order for it to automatically configure SSL for Nginx, we need to verify some of Nginx’s configuration.
-
Obtaining an SSL Certificate
Certbot provides a variety of ways to obtain SSL certificates through plugins. The Nginx plugin will take care of reconfiguring Nginx and reloading the config whenever necessary. To use this plugin, type the following:# certbot --nginx -d tgs.timebase.app -d www.tgs.timebase.app
This runs certbot with the --nginx
plugin, using -d
to specify the domain names we’d like the certificate to be valid for.
If this is your first time running certbot, you will be prompted to enter an email address and agree to the terms of service. After doing so, certbot will communicate with the Let’s Encrypt server, then run a challenge to verify that you control the domain you’re requesting a certificate for.
-
Verifying Certbot Auto-Renewal
# systemctl status certbot.timer ● certbot.timer - Run certbot twice daily Loaded: loaded (/lib/systemd/system/certbot.timer; enabled; vendor preset: enabled) Active: active (waiting) since Mon 2021-06-07 18:38:40 EEST; 10min ago Trigger: Tue 2021-06-08 10:57:25 EEST; 16h left Triggers: ● certbot.service Jun 07 18:38:40 dev.timebase.app systemd[1]: Started Run certbot twice daily.
-
Check your
/etc/nginx/sites-enabled/tgs.timebase.app.conf
:# cat /etc/nginx/sites-enabled/tgs.timebase.app.conf server { server_name tgs.timebase.app; access_log /var/log/nginx/tgs.timebase.app.access.log; error_log /var/log/nginx/tgs.timebase.app.error.log; location / { proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; proxy_connect_timeout 600; proxy_send_timeout 600; proxy_read_timeout 600; send_timeout 600; proxy_pass http://localhost:8081/; } listen 443 ssl; # managed by Certbot ssl_certificate /etc/letsencrypt/live/tgs.timebase.app/fullchain.pem; # managed by Certbot ssl_certificate_key /etc/letsencrypt/live/tgs.timebase.app/privkey.pem; # managed by Certbot include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot } server { if ($host = tgs.timebase.app) { return 301 https://$host$request_uri; } # managed by Certbot server_name tgs.timebase.app; listen 80; return 404; # managed by Certbot }
As you can see certbot added some configuration automatically. Now try to access
tgs.timebase.app
through your browser.