It’s not just the front-end ER-tormenting the server to arm itself.

clipboard.png

Preface

As a front-end development engineer, I am familiar with the concept of “front-end” when dealing with browsers and business codes every day. I can play with mainstream frameworks and tools, but I always feel that I have been confined in a small circle of so-called “front-end”-because other knowledge points are still relatively weak.

Later, I got a job rotation opportunity in the company, entered the operation and maintenance team to learn, and my vision was broadened. I also had a deeper understanding of my own level, and couldn’t wait to upgrade my skill tree other than “front-end knowledge”.

Since operation and maintenance teams often deal with servers, why don’t I just start with the servers and do it again?

I. purchasing servers

I have considered buying tengxunyun or ariyun and other domestic servers, but due to reasons well known in the country, many resources are either downloaded very slowly, or they just kneel down and switch sources at any time. At the same time, if addon domain has a domestic server, it will need to file it, which is really extremely troublesome. There is no doubt that I finally chose a foreign server, and the world was instantly clean …

Regarding the purchase of foreign servers, it is a matter of different opinions. I bought a 20G KVM server for a bricklayer at US$ 5/month. I bought it without loss and bought it without deception. Then I installed Centos 7 x86_64 bbr system, and then I could play happily.

clipboard.png

II. Purchase of Domain Names

It is good to set up any service, and one cannot let others memorize one’s own ip. It would be great to have a popular domain name. So I wentTen thousand nets, directly in their English namejrainlauI applied for onejrainlau.comDomain name, only 55 RMB a year, is really worth it

It is very simple to place an order and pay, then I have my own domain name, and then DNS resolution is carried out.

Enter ariyun’s console and findCloud resolution DNS, click in to see our domain name resolution information. Add two typesA, all pointing to the server’s ip address:

clipboard.png

III. Installation of Nginx

Within 10 minutes before the domain name resolution takes effect, it is enough for us to configure Nginx on the server.

First, ssh logs into the server:

ssh root@xxx.xxx.xxx.xxx -p yyyy

Enter the login password provided by the bricklayer and log in smoothly.

However, it is very painful to enter the password like a garbled code every time you log in to the server, so use ssh-key decisively to realize secret-free login.

  • The first step is to generate a secret key (this step can be omitted if the local machine already exists)

    ssh-keygen -t rsa

    Follow the prompts to select the directory where the key is stored (~/.ssh/),Password blankFinally, the generated secret key can be found in the set directory:

    clipboard.png

  • The second step is to upload the secret key to the server.

    ssh-copy-id root@xxx.xxx.xxx -p yyyy

    Then follow the prompts to enter the password again. In the future, if you want to log in to the server, you can directly log in without secret.

After completing the “branch task” just now, return to our main line of Nginx configuration.

According to the documentation on the official website of Nginx, it is very simple to install Nginx in CentOS:

yum install -y nginx

But in the actual operation, only to find that has been promptedNo package nginx available. After a search, the answer in Stack Overflow is probably not installed.epel, so immediately try it:

yum install -y epel-release

Strangely, the running result indicates that epel already exists, which is nothing to do. Then when I tried to install nginx, I found it was still no package nginx available. Trying to list all yum sources, foundThere is no epel at all.Source:

yum repolist
 
 Source ID Source Name Status
 base/7/x86_64                   CentOS-7 - Base                                                             9,590+1
 extras/7/x86_64                 CentOS-7 - Extras                                                               388
 updates/7/x86_64                CentOS-7 - Updates                                                          1,922+7

Later, after some ordeal, we found a solution:

# first enter/yum.repas.d directory
 cd /etc/yum.repos.d
 
 # Then edit the epel.repo file
 vi epel.repo
 
 [epel]
 name=Extra Packages for Enterprise Linux 7 - $basearch
 #baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch
 mirrorlist=https://mirrors.fedoraproject.org/metalink?  repo=epel-7&arch=$basearch
 failovermethod=priority
 enabled=0
 gpgcheck=1
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
 
 [epel-debuginfo]
 name=Extra Packages for Enterprise Linux 7 - $basearch - Debug
 #baseurl=http://download.fedoraproject.org/pub/epel/7/$basearch/debug
 mirrorlist=https://mirrors.fedoraproject.org/metalink?  repo=epel-debug-7&arch=$basearch
 failovermethod=priority
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
 gpgcheck=1
 
 [epel-source]
 name=Extra Packages for Enterprise Linux 7 - $basearch - Source
 #baseurl=http://download.fedoraproject.org/pub/epel/7/SRPMS
 mirrorlist=https://mirrors.fedoraproject.org/metalink?  repo=epel-source-7&arch=$basearch
 failovermethod=priority
 enabled=0
 gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-EPEL-7
 gpgcheck=1

As you can see,[epel]And[epel-source]insideenabledAll of them are 0. The solution is here. Just change 0 to 1 and save it to exit.

Now we are running againyum repolist, you will find epel source has been added:

Source ID Source Name Status
 base/7/x86_64                   CentOS-7 - Base                                                             9,590+1
 elrepo-kernel                    ELRepo.org Community Enterprise Linux Kernel Repository - el7                    37
 epel/x86_64                     Extra Packages for Enterprise Linux 7 - x86_64                               12,277
 epel-source/x86_64              Extra Packages for Enterprise Linux 7 - x86_64 - Source                           0
 extras/7/x86_64                 CentOS-7 - Extras                                                               388
 nodesource/x86_64               Node.js Packages for Enterprise Linux 7 - x86_64                                 22
 updates/7/x86_64                CentOS-7 - Updates                                                          1,922+7
 repolist: 24,236

Re-executionyum install -y nginx, found that finally can be successfully installed!

nginx version: nginx/1.12.2

Next, nginx can be opened with only one command:

nginx

After the above ordeal, DNS resolution of the domain name has already taken effect. Enter the domain name and press Enter at this time to see the welcome page of nginx ~

clipboard.png

4. Use HTTPS

Seeing the three words “unsafe” in the upper left corner, I was very unhappy, so I immediately proceeded to the next step and went to HTTPS.

Since it is a personal server, a free certificate is enough. In addition, for convenience, I used it.certbotThis tool helps me upgrade the server to HTTPS.

First download and install via yumcertbot

yum install certbot

Since the certbot server will access a static file generated by certbot through HTTP when verifying the domain name, we must first configure it in nginx:

Enter/etc/nginx, and then editnginx.confInserverAdd the following two location rules:

location ^~ /.well-known/acme-challenge/ {
 default_type "text/plain";
 root     /usr/share/nginx/html;
 }
 
 location = /.well-known/acme-challenge/ {
 return 404;
 }

As you can see, the one aboverootI am pointing to/usr/share/nginx/htm, this directory can be arbitrarily specified, I write this completely to be lazy.

Once nginx is configured, certbot can be used to generate certificates:

# certbot certonly --webroot -w <root url> -d <hostname>
 
 certbot certonly --webroot -w /usr/share/nginx/html/ -d  xxxx.com

If you see the following output, the certificate has been successfully generated:

IMPORTANT NOTES:
 - Congratulations!  Your certificate and chain have been saved at
 /etc/letsencrypt/live/xxxx.com/fullchain.pem. Your cert
 will expire on 20XX-09-23. To obtain a new or tweaked version of
 this certificate in the future, simply run certbot again. To
 non-interactively renew *all* of your certificates, run "certbot
 renew"
 - If you like Certbot, please consider supporting our work by:
 
 Donating to ISRG / Let's Encrypt:    https://letsencrypt.org/donate
 Donating to EFF:                     https://eff.org/donate-le

The certificate is ready, and we need nginx’s support. Reopen/etc/nginx/nginx.conf, and then give comments off https server to comment back:

server {
 listen       443 ssl http2 default_server;
 listen       [::]:443 ssl http2 default_server;
 server_name   xxxx.com ;
 root         /home/www;
 
 ssl_certificate "/etc/letsencrypt/live/xxxx.com/fullchain.pem";
 ssl_certificate_key "/etc/letsencrypt/live/xxxx.com/privkey.pem";
 ssl_trusted_certificate /etc/letsencrypt/live/xxxx.com/chain.pem;
 
 # Load configuration files for the default server block.
 include /etc/nginx/default.d/*.conf;
 
 location / {
 }
 
 error_page 404 /404.html;
 location = /40x.html {
 }
 
 error_page 500 502 503 504 /50x.html;
 location = /50x.html {
 }
 }

Ps: I have configured the root above/home/wwwDirectory, which means that I can pass any static resource folder placed under this directory in the future.Https://xxx.com/ folder nameFor direct access, please refer to official documents for more information on nginx configuration.

Finally, restart nginx to check whether our page has been marked with a small green mark:

nginx -s reload

clipboard.png

Since the letsencrypt certificate used by certbot is only valid for 90 days, we need to update it automatically on a regular basis.

First simulate the update:

sudo certbot renew --dry-run
 
 # See the following output to prove that the simulation update was successful
 -------------------------------------------------------------------------------
 Processing /etc/letsencrypt/renewal/your.domain.com.conf
 -------------------------------------------------------------------------------
 ** DRY RUN: simulating 'certbot renew' close to cert expiry
 **          (The test certificates below have not been saved.)
 
 Congratulations, all renewals succeeded. The following certs have been renewed:
 /etc/letsencrypt/live/xxxx.com/fullchain.pem (success)
 ** DRY RUN: simulating 'certbot renew' close to cert expiry
 **          (The test certificates above have not been saved.)

Then it can be usedcrontab -eCommand to achieve automation:

sudo crontab -e
 
 # Add configuration and perform renew at 3: 00 a.m. every Monday:
 
 00 3 * * 1 /usr/bin/certbot renew  >> /var/log/le-renew.log

V. deploying static pages and Node.js projects

The server is ready, HTTPS is ready, then we can deploy our static page and nodejs project.

As can be seen from the previous nginx configuration, nginx has the following characteristics for domain namesxxxx.comThe request, will request to/home/wwwDirectory, so we place static resource objects in the/home/wwwJust under the directory. For example, minemarkcookProjects:

cd /home/www
 
 git clone  https://github.com/jrainlau/markcook -b gh-pages

Access at this timehttps://jrainlau.com/markcookYou can access the project’s page.

For the nodejs project, we use thepm2To guard the process and let the project run in the background. Nodejs needs to be installed before pm2:

curl -sL  https://rpm.nodesource.com/setup_9.x | bash -
 yum install nodejs
 
 npm i pm2 -g

The nodejs project is still placed on the/home/wwwDirectory, enter the directory and execute the following command:

npm i
 
 pm2 start index.js --name my-server
 
 ┌─────────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
 │ App name    │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user │ watching │
 ├─────────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
 │  my-server  │ 0  │ fork │ 2306 │ online │ 22      │ 7h     │ 0%  │ 46.2 MB   │ root │ disabled │
 └─────────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

In the endnginx.confAdd a proxy rule (assuming the node service port is 3000):

location /my-server/ {
 proxy_pass  http://localhost:3000
 }

In this way, can passhttps://xxxx.com/my-server/Visited nodejs Project.

Six, the use of travis-ci to achieve continuous deployment

The operation just now is only the initial deployment. If there is any code change in the future, we need to log into the server, enter the corresponding project directory, and execute it manually.git pull, and then restart the server manually (this step can be omitted if pm2 starts watch mode), which is quite troublesome. Can there be a way to automatically update the server code and restart the server when I submit the code?travis-ciIs to achieve this goal.

Travis-ci supportPublic projectsAndPrivate projectThrough.orgAnd.comSuffix. Take an open project of mine as an example, first enterhttps://travis-ci.org/Official website, log in to my github account, then you will see the following page:

clipboard.png

Find the project that needs to integrate travis-ci and click the switch in front of it.

clipboard.png

At this time, the operation on travis-ci has come to an end temporarily, but don’t turn off the page and put it aside first.

Next, we went back to the local development machine, throughgit cloneCommand to clone this project locally and add one under the root directory of the project..travis.ymlDocuments. This file is the key to travis-ci continuous integration. It defines all your continuous integration operations. For the sake of simplicity, we will only use it.Automated deployment

language: node_js
 node_js:
 - 9.3.0
 after_success:
 - ssh root@xxx.xxx.xxx.xxx -p yyy 'cd /home/www/taxi-server && git pull && pm2 restart taxi-server'

As you can see, I defined her operating environment asnode.js 9.3.0After the successful construction (in fact, nothing was built), the server was automatically logged in, the latest code was pulled, and the pm2 was restarted.

As we all know, login to the server requires a password. Even travis-ci helps us automate this step. However, since the steps of entering passwords are interactive and cannot be processed automatically, we also need to set up a “password-free login” for travis-ci. After the above ssh-key configuration, we already have this condition, but we still need a few more steps.

  1. InLocalviagemInstallationtravisCommand line tools (ruby is supported by macOS by default):

    gem install travis
  2. Log in using travis:

    travis login

    Then enter github’s account password.

  3. Encrypt local ssh-key and write automatically.travis.yml

    # --add parameter indicates that scripts are automatically added to the. travis.yml file
     travis encrypt-file ~/.ssh/id_rsa --add

You will see.travis.ymlOne more paragraphbefore_installContents of:

before_install:
 - openssl aes-256-cbc -K $encrypted_e65149523857_key -iv $encrypted_e65149523857_iv
 -in id_rsa.enc -out ~\/.ssh/id_rsa -d

Then put the last line of “\“The escape character is deleted, and the following two items are added to the top box of the line feed:

- chmod 600 ~/.ssh/id_rsa
 - echo -e "Host xxx.xxx.xxx.xxx\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config

Remember toxxx.xxx.xxx.xxxChange to the IP of your server.

Finally add.travis.ymlJust push to github.

Returning to travis-ci.org’s page and entering the project, you can see the effect of continuous integration:

clipboard.png

clipboard.png

At this time back to the server, runpm2 logs, will see the service has been automatically restarted log records, so far continuous integration and deployment function is perfect success!

The end

After this ordeal, I finally felt the knowledge of servers, station building, continuous deployment and so on. I also had some superficial opinions on these technology stack. There are more interesting things to explore next, after all, this is just the beginning, let’s encourage together ~