After the blog website is developed, the last step is to deploy the blog website to the public network server and provide domain name access. The blog website that can be searched through the search engine is the real blog website.

Hello everyone, I am a lone duck of falling xia. After several weeks of hard work, we have finished the development of the blog. In this chapter we begin to deploy the blog site and access our blog site through a public network server and domain name.

First, preparation

In order for our website to be accessible by domain name, we need to have several conditions:

  1. To buy cloud server, you can choose to buy Ali, Tencent, Huawei and Baidu. Each platform has its own special discount, so you can choose a suitable platform for yourself.
  2. Install the operating system (OS) of the server. Generally, the server uses Linux, Ubuntu, Cent OS, and Debian
  3. To buy a domain name, you can use the domain name on the cloud server provider’s platform,.cn.comWill do.
  4. Purchase a domain name certificate. Only after a domain name certificate is obtained, the browser will not prompt you with security problems when you access the domain name.
  5. At present, there are two registration procedures for websites, one of which is ICP filing on the platform of the Ministry of Industry and Information Technology. After passing this filing, the public security Network filing needs to be completed.

Second, website deployment

After completing the preparatory work, we officially began to deploy our website.

2.1 the Python

Since our back-end code is written in Python, we need to install the Python runtime environment when we deploy it on the server.

The installation method here, I use the official website tutorial, version 3.7. Tutorial address: docs.python.org/zh-cn/3.7/u…

After the installation is complete, run the following command on the CLI to verify the installation

python -V
pip -V
Copy the code

2.2 Code Distribution

2.2.1 Front-end code

2.2.1.1 compilation

Since we are using a front-end written in Vue and TypeScript, we need to compile into native Javascript code before deploying.

Run the following command in the root directory of the front-end code

yarn build
Copy the code

After the execution is completed, the dist folder will be generated under the code path, which contains the compiled code. The file structure is shown as follows

2.2.1.2 upload

On the server, under the Home directory, create a folder “blog” and create “frontend” under “blog”.

cd ~
mkdir blog
cd blog
mkdir frontend
Copy the code

Then upload the front-end files in the local dist folder to the ~/blog/frontend path by FTP tool, and the front-end code is published.

2.2.2 Back-end code

Since Python is a scripting language, the code itself does not need to be compiled. You can simply upload the source code to the corresponding path on the server.

2.2.2.1 Dependent Installation

Python runs on a server that uses UWSGi, so you need to install dependencies on the server and run the following command

pip install uwsgi
Copy the code

After the installation, run commands to check whether the installation is successful

uwsgi --version
Copy the code
2.2.2.2 writeuwsgiThe configuration file

Create a file uwsgi.ini in the path of the back-end code project. We connect the back-end interface through socket and configure the following information:

[uwsgi]
socket = 127.0.0.1:8000
You can understand the absolute path to this file
chdir = ~/blog/backend/
# wsgi relative to chdir
wsgi-file = project/wsgi.py
processes = 4
# log
daemonize = ~/blog/backend/logs/uwsgi.log
pidfile = ~/blog/backend/uwsgi.pid
master = True
Copy the code

Create a new file uwsgi.param in the back-end code project path with the following contents

uwsgi_param  QUERY_STRING       $query_string;
uwsgi_param  REQUEST_METHOD     $request_method;
uwsgi_param  CONTENT_TYPE       $content_type;
uwsgi_param  CONTENT_LENGTH     $content_length;

uwsgi_param  REQUEST_URI        $request_uri;
uwsgi_param  PATH_INFO          $document_uri;
uwsgi_param  DOCUMENT_ROOT      $document_root;
uwsgi_param  SERVER_PROTOCOL    $server_protocol;
uwsgi_param  REQUEST_SCHEME     $scheme;
uwsgi_param  HTTPS              $https if_not_empty;

uwsgi_param  REMOTE_ADDR        $remote_addr;
uwsgi_param  REMOTE_PORT        $remote_port;
uwsgi_param  SERVER_PORT        $server_port;
uwsgi_param  SERVER_NAME        $server_name;
Copy the code
2.2.2.3 Upload code

In the ~/blog folder of the server, create the Backend folder

cd ~/blog
mkdir backend
Copy the code

Use an FTP tool to upload back-end code to the ~/blog/ Backend folder, including the uwsgi.ini file. In backend, create the logs folder for logging

mkdir logs
Copy the code

At this point, the back-end code is in place.

2.2.2.4 Starting and Stopping back-end services

Start the back-end code with a command

uwsgi --ini ~/blog/backend/uwsgi.ini
Copy the code

The test can view the server logs after startup through log files

tail -f ~/blog/backend/logs/uwsgi.log
Copy the code

The stop command is as follows:

uwsgi --stop ~/blog/backend/uwsgi.pid
Copy the code

If the back-end code is updated later, you need to stop the UWSGi service before starting the code update.

2.3 Nginx

In the current website deployment, Nginx as a reverse proxy server deployment site is the mainstream operation, has been a mature website deployment scheme.

Nginx has the following functions in web site deployment:

  1. Reverse proxy enables clients on the Internet to access the capabilities and data provided by the Intranet server.
  2. Load balancing to share the load of back-end servers
  3. HTTP server, Nginx itself is also a static resource server, and in the process of static resource request and response, better than the old Web server, better performance. Nginx enables the separation of dynamic and static deployment.

2.3.1 installation

There are a lot of tutorials on the Internet, so I will provide a reference tutorial for the installation of nginx under Linux.

2.3.2 Certificate File

In the preceding preparations, the domain name certificate is mentioned. In this case, download the certificate file provided by the domain name certificate provider platform, decompress it, and upload the Nginx certificate to the conf file in the Nginx installation path on the server.

2.3.3 Configuration Description

The Nginx configuration file is stored in the conf folder of the Nginx installation directory. The name of the Nginx configuration file is nginx.conf.

2.3.3.1 Static File Proxy

There are two parts of the static file, one is the front-end code file and the other is the media file obtained through the upload interface

location / {
   root ~/blog/frontend/dist;
   index index.html index.htm;
   if(! -e $request_filename) {rewrite^ / (. *) /index.html last; break; }}location /upload/ {
   root ~/blog/backend/;
   expires 24h;
}
Copy the code
2.3.3.2 Back-end interface proxy

There is critical in the location of two lines of configuration and include uwsgi_pass blog ~ / blog/backend/uwsgi param, clear is the way through the uwsgi agent Python interface

# server
    upstream blog{
       server 127.0.0.1:8000;
    }

location /api/ {
            uwsgi_pass blog;
            include ~/blog/backend/uwsgi.param;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header accept-encodeing 'gzip, deflate';
            proxy_set_header content-type 'application/json';
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header authorization $http_authorization;
            proxy_set_header accept '* / *';
            proxy_set_header x-bce-date $http_x_bce_date;
        }
Copy the code
2.3.3.3 Static FilesGzipThe compression

The reason for configuring Gzip compression is that a lot of content needs to be loaded on the first screen of a website when the front and back ends are separated. Therefore, you can reduce the file size during network transmission to speed up the loading of static files during the rendering of the first screen.

# Gzip
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 3;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_buffers 32 4k;
    gzip_http_version 1.0;
Copy the code
2.3.3.3 Domain Name Configuration
 server {
       listen 80;
       server_name www.longair.cn;
       rewrite^ (. *) $ https://${server_name}The $1 permanent;
    }

server {
        listen       443 ssl;
        server_name www.longair.cn;
        root html;
        index index.html index.htm;
}
Copy the code
2.3.3.3 HttpsCertificate File Configuration
ssl_certificate      /etc/nginx/longair.cn_nginx/server.crt;
ssl_certificate_key  /etc/nginx/longair.cn_nginx/server.key;
ssl_session_timeout  5m;
ssl_ciphersECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:! NULL:! aNULL:! MD5:! ADH:! RC4;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
Copy the code
2.3.3.3 HttpAutomatic transferHttps

When accessing port 80, redirect to port 433.

server {
       listen 80;
       server_name www.longair.cn;
       rewrite^ (. *) $ https://${server_name}The $1 permanent;
    }
Copy the code
2.3.3.3 Blog post details jump 404 Problem Configuration

Because we use Vue frame of the front end of the code, routing model USES is the history, the pattern of routing readable, but the article details page routing if, by means of a new page will appear 404 problem, so we need to do processing in this case, configuration principle is that the access path if it’s not the end of file, The page is automatically redirected to the home page. After entering index. HTML, you can change the route to enter the single-page application route, thus correctly rendering the details page. Vue – the router’s website documents: HTML 5 History model | Vue router (vuejs.org)

location / {
            root ~/blog/frontend/dist;
            index index.html index.htm;
            if(! -e $request_filename) {rewrite^ / (. *) /index.html last; break; }}Copy the code

2.3.4 Complete Configuration

The complete configuration is as follows:

user  root;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    keepalive_timeout  65;

    client_max_body_size 200M;

    # Gzip
    gzip on;
    gzip_min_length 1k;
    gzip_comp_level 3;
    gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png application/vnd.ms-fontobject font/ttf font/opentype font/x-woff image/svg+xml;
    gzip_vary on;
    gzip_disable "MSIE [1-6]\.";
    gzip_buffers 32 4k;
    gzip_http_version 1.0;

    # server
    upstream blog{
       server 127.0.0.1:8000;
    }

    # blog http
    server {
       listen 80;
       server_name www.longair.cn;
       rewrite^ (. *) $ https://${server_name}The $1 permanent;
    }

    server {
        listen* :80;
        listen* :443 ssl;
        listen[: :] :80;
        listen[: :] :443 ssl;
        server_name longair.cn;
        ssl_certificate      /etc/nginx/longair.cn_nginx/server.crt;
        ssl_certificate_key  /etc/nginx/longair.cn_nginx/server.key;
        return 301 https://www.longair.cn$request_uri;
    }

    # blog https
    server {
        listen       443 ssl;
        server_name www.longair.cn;
        root html;
        index index.html index.htm;

        ssl_certificate      /etc/nginx/longair.cn_nginx/server.crt;
        ssl_certificate_key  /etc/nginx/longair.cn_nginx/server.key;
        ssl_session_timeout  5m;
        ssl_ciphersECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:! NULL:! aNULL:! MD5:! ADH:! RC4;ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;

        location / {
            root ~/blog/frontend/dist;
            index index.html index.htm;
            if(! -e $request_filename) {rewrite^ / (. *) /index.html last; break; }}location /upload/ {
            root /blog/backend/;
            expires 24h;
        }
        location /api/ {
            uwsgi_pass blog;
            include ~/blog/backend/uwsgi.param;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $host;
            proxy_set_header accept-encodeing 'gzip, deflate';
            proxy_set_header content-type 'application/json';
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header authorization $http_authorization;
            proxy_set_header accept '* / *';
            proxy_set_header x-bce-date $http_x_bce_date;
        }

        error_page 500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
        location = /50x.html {
            root~/blog/frontend/dist; }}}Copy the code

Three, the maintenance of the website

3.1 Nginx maintenance

3.1.1 Start Commands

/usr/local/nginx/sbin/nginx -s start
Copy the code

3.1.2 Stop Command

/usr/local/nginx/sbin/nginx -s stop
Copy the code

3.3.3 Restart Command

/etc/nginx/sbin/nginx -s reload
Copy the code

3.3.4 Log View Commands

tail -f /etc/nginx/logs/access.log
tail -f /etc/nginx/logs/error.log
Copy the code

3.2 Maintenance of UWSGI

3.2.1 Start Commands

uwsgi --ini ~/blog/backend/uwsgi.ini
Copy the code

3.2.2 Stop Command

uwsgi --stop ~/blog/backend/uwsgi.pid
Copy the code

3.3.3 Log View Commands

uwsgi --stop ~/blog/backend/uwsgi.pid
Copy the code

Four, about the database

In the development stage, we use sqLite database is very convenient, but if the website is deployed to the server, then use SQLite will appear a lot of problems, such as data security problems, data update problems, so when we deploy the blog online, we need to switch to Mysql database.

4.1 MysqlThe installation

I use version 5.7, installation operation, please refer to your own operating system installation tutorial on the official website. MySQL :: MySQL 5.7 Reference Manual :: 2 Installing and Upgrading MySQL

4.2 Database Construction

On the server, the database is set up through the command line.

2 the root login

mysql -uroot -p
Copy the code

Then enter your password and press Enter to log in to the database.

4.2.2 Creating a Database

  1. Creating a database
create database blog character set utf8mb4;
Copy the code
  1. Create a user
create user 'blog'@The '%' identified by '12345678';
Copy the code
  1. User empowerment
grant all privileges on blog.* to 'blog'@The '%';
flush privileges;
Copy the code

4.3 Adjusting back-end Configurations

4.3.1 Isolation of production and development environments

In the development stage, through sqLite database, easy to debug, fast access, and production environment, using Mysql will be safer. So we want different database configurations for development and production environments.

Therefore, we use environment variables in the system to determine whether it is production or test, so that the code stays the same and does not need to be adjusted at deployment time.

You also need to adjust the host information that can be accessed.

4.3.2 Database Password Protection

As a result of our code may warehouse management through the code, if it is a lot of the warehouse, can will reveal your own database password, so we here by a single configuration file to record database account information, and then in Python by reading the database account configuration file to obtain information, so as to realize the database password protection.

4.3.3 configuration

4.3.3.1 project/settings.py
ALLOWED_HOSTS = ['www.longair.cn'.'127.0.0.1'.'localhost', ]

ENV_PROFILE = os.getenv("PYTHON_ENV")

if ENV_PROFILE == "production":
    import configparser

    cf = configparser.ConfigParser()
    cf.read('/blog/db.cnf')  The contents of this file will be created in the next step, as long as the file to be created in the next step is in the path written here
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql'.'NAME': cf.get('db'.'database'),
            'USER': cf.get('db'.'user'),  Get the database user name from the configuration file
            'PASSWORD': cf.get('db'.'password'),  Get the database password from the configuration file
            'HOST': 'localhost'.'PORT': '3306'
        }
    }
    DEBUG = False  Disable the debug mode in the production environment
else:
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3'.'NAME': os.path.join(BASE_DIR, 'data/db.sqlite3'),
        }
    }
    DEBUG = True
Copy the code
4.3.3.2 Configuring Environment Variables

To set the environment variables, enter vi ~/. Bashrc and add export PYTHON_ENV=production, press ESC and enter: :wq

Finally, enter source ~/.bashrc

4.3.3.3 Adding the Database Account Configuration File

Add vi db.cnf under ~/blog and add the following:

[db]
database = blog
user = blog
password = 12345678
default-character-set = utf8
Copy the code

The database, account, and password must be consistent with the preceding database information.

Congratulations, your blog site is now deployed and you can access your blog site by domain name.

In the next post, I will summarize the problems and solutions encountered during the entire blog development process.