Yuhang Zheng

增加Memos备忘录功能以及由frp穿透转为nginx反向代理

N 人看过

今天腾讯云通知我域名的SSL证书到期了,所以我自己又在腾讯云上重新申请了一年的免费的SSL证书。

突然意识到自己已经建站两年多了,也一直是处于自娱自乐佛系更新的阶段。没有像其他的大神一样通过博客交到很多志同道合的朋友,也没有遵从一开始建站的心愿好好记录一下生活或者是工作中易忘的知识,最终还是要慢慢的腐朽成一个空壳子么?

… 其他的感慨有时间再慢慢絮叨吧 … 今天的目的还是要好好记录一下最近的博客的更新变化呢。

第一部分:增加Memos备忘录网站

很久之前在微信关注了一个【逛逛Github】的订阅号,它会时不时推荐一些好玩的GitHub上的项目,最近我被一个Memos备忘录的项目吸引了,项目链接如下:https://github.com/usememos/memos

这个是干啥的还有搭建过程就不多说了,上面有很详细的介绍,就是可以实现一个类似QQ空间说说的功能,而且搭建直接使用docker也很简单,搭建好的端口默认运行在5230。

搭建好之后,除了在网页上可以直接访问之外,也有很多大神做了三方的客户端可以使用,比如iPhone上可以使用的Moe Memos,当然我就要下载下来试一下呀。可是在填写服务器地址的时候出了问题,Apple为了安全必须要https的地址,但是docker搭建的Memos的是http的呀,这可怎么办才好呢?

第二部分:由frp穿透转成Nginx反向代理

这个时候我就想起来之前给公司搭建知识分享博客的时候是使用的Nginx来搭建的,Nginx的反向代理功能好像非常适合解决这个问题。另外这个时候不得不提一下自己现在的网站的一个现状了。

现在我的这个博客运行在Raspberry pi 4上,而Raspberry pi 4在家庭网络下,联通给了一个动态的公网ip,之前家庭网络虽然封禁了80端口,但是一直还能用443端口,自己就负责搞好DDNS的动态域名映射和内网穿透就可以。但是后来连443也封了,我就在腾讯云买了一个三年的香港的服务器来做映射,之前以为内地访问应该差不太多,实际上买了之后体验发现还是慢一些,但是自己一个小博客搭着玩,也还能用,而且也省了备案的麻烦,也就一直在将就用着。

一直搭博客都用的Apache2,很经典的网站服务器,简单很多,所以当时买了香港的服务器之后,直接想当然的去运行了一个frp的穿透,把之前的443端口直接给穿出去解决了问题(其实也是懒得弄了 …)。另外Raspberry pi 4上运行了很多额外的小网络服务,都是直接靠端口直接访问解决的(确实丑很多啊~)。

虽然早有耳闻Nginx的强大,但是一直都没有去搞。中间也试着在香港服务器上搭建过Trojan科学上网,了解了一些Nginx的知识,再到后面 给公司搭建知识分享博客的时候是使用的Nginx来搭建,所以这次,决心舍弃frp的穿透的方案,直接靠香港服务器上Nginx反向代理来把这些新老旧账一起算一下。

经过了解之后,决定将博客主站放到resona.top域名,其他的各个之前靠端口访问的网络服务分别放到各自的子域名来访问。

话不多说,直接代码搞起。

首先是主站和Memos需要SSL证书来配置为https访问,证书存在位置为:/etc/nginx_key/ 目录下

ubuntu@VM-4-3-ubuntu:/etc/nginx_key$ tree
.
├── memos.resona.top_bundle.crt
├── memos.resona.top_bundle.pem
├── memos.resona.top.csr
├── memos.resona.top.key
├── resona.top_bundle.crt
├── resona.top_bundle.pem
├── resona.top.csr
└── resona.top.key

0 directories, 8 files

其次Nginx各项配置文件位置为:/etc/nginx 目录下

ubuntu@VM-4-3-ubuntu:/etc/nginx$ tree
.
├── conf.d
│   ├── jd.resona.top.conf
│   ├── memos.resona.top.conf
│   ├── net.resona.top.conf
│   └── resona.top.conf
├── fastcgi_params
├── mime.types
├── modules -> /usr/lib/nginx/modules
├── nginx.conf
├── nginx.conf.bak
├── scgi_params
└── uwsgi_params

2 directories, 10 files

nginx.conf为通用的配置,文件内容如下:

user www-data;
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;
        tcp_nodelay on;
        keepalive_timeout 65;
        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_min_length 1k;
        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/*;
}

/etc/nginx/conf.d/resona.top.conf 为主站的配置

server {
    listen 80;
    server_name resona.top;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name resona.top;

    client_max_body_size 1024m;

    ssl_certificate      /etc/nginx_key/resona.top_bundle.pem;
    ssl_certificate_key  /etc/nginx_key/resona.top.key;

    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        proxy_pass  http://example.com:port;
    }
}

/etc/nginx/conf.d/memos.resona.top.conf 为memos的配置

server {
    listen 80;
    server_name memos.resona.top;

    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;
    server_name memos.resona.top;

    client_max_body_size 1024m;

    ssl_certificate      /etc/nginx_key/memos.resona.top_bundle.pem;
    ssl_certificate_key  /etc/nginx_key/memos.resona.top.key;

    ssl_session_timeout  5m;

    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;

    location / {
        proxy_pass http://memos.example.com:port;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}

其他的就是很多小http服务的配置了,这个就简单了很多

server {
    listen 80;
    server_name net.resona.top;

    location / {
        proxy_pass http://net.example.com:port;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

}

做完了这些配置,然后就是在阿里云的域名解析上,将这些子域名的解析全部做到腾讯云服务器的IP上,这样当我们在访问不同的域名的时候,Nginx就可以通过域名去区分提供不同的网络服务啦!(还是要感叹一下Nginx还是很厉害了,仅仅了解一个皮毛就可以实现这么强大的功能)。

另外在nginx.conf通用配置里面开启了gzip压缩,以提高网站的访问速度(虽然效果可能并不明显)

        gzip on;

        gzip_min_length 1k;
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;

额外内容:配置反向代理时常用的配置含义

在配置文件中location字段内容为:

    location / {
        proxy_pass http://example.com:port;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

字段中的后四行设置传递给后端服务器的请求头

 proxy_set_header       Host $host;
 proxy_set_header       X-Forwarded-Proto  $scheme;
 proxy_set_header       X-Real-IP $remote_addr;
 proxy_set_header       X-Forwarded-For $proxy_add_x_forwarded_for;

在使用Nginx做反向代理的时候,proxy_set_header HOST功能可以设置反向代理后的http header中的host,也就是上面代码段中的第一行

其后面的值可以有$host,$http_host,$proxy_host,那么这几个有什么区别呢?

Nginx的官网文档中说下面这两条是做反代时默认的,所以$proxy_host 自然是 proxy_pass后面跟着的host了

proxy_set_header Host       $proxy_host;
proxy_set_header Connection close;

所有可用的参数的解释如下:

1)$host:它的值等于“Host”请求标头字段中的服务器名称或主服务器名称(如果该字段不存在):即将当前location块的server_name指令填充到Host头
2)$http_host:传递未更改的“Host”请求标头字段,即客户端原生的请求,以访问memos子站为例,即memos.resona.top
3)$proxy_host:代理服务器请求的host,即后端服务器/源站的IP,后端服务器有可能还是代理服务器。以访问memos子站为例,即memos.example.com:port
4)$host:$proxy_port:此外,服务器名称可以与后端服务器的端口一起传递:

具体更详细的内容可以参考Nginx的官方文档

http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_set_header

第二行中其实可以取三个不同的值

proxy_set_header X-Forwarded-Proto http;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Proto  $scheme;

nginx嵌入式变量:scheme。请求协议,http或https。

第三行中

proxy_set_header X-Real-IP $remote_addr;
$remote_addr的值为客户端的ip,即可以使后端服务器看见用户真实的ip,也就是客户端的真实ip

第四行中其实可以取两个不同的值

proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
当只有一层代理服务器的情况下,两者的X-Forwarded-For值一致,都是用户的真实IP。
但是区别在于,如果有两层代理的情况下,$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开,这个地方不再详细说明。

遇到的一些问题

在完成上面这些配置之后,测试和的时候发现有时候网站会出现打不开或者图片出不来的问题,尤其是网站静态资源较大或者图片比较大的时候更容易出现。网上查了一下可能的原因有:

  • 磁盘满了

  • nginx的临时目录(/proxy_temp)过大或没有权限写入缓存文件

    //当代理文件大小超过配置的proxy_temp_file_write_size值时,nginx会将文件写入到临时目录下(默认为/proxy_temp)。
    //如果nginx中/proxy_temp过大或者没有写权限,缓存文件就写不进去了。
    //直接删除Nginx缓存文件;
    rm -rf  /usr/local/nginx/proxy_temp
    
    //设置Nginx的缓存过期时间;
    //调整/proxy_temp权限为配置nginx的那个用户;
    sudo chown -R www-data:root /var/cache/nginx/proxy_temp/
  • nginx的缓冲区(Proxy Buffer)设置较小

    //修改nginx
    proxy_buffer_size 1024k;
    proxy_buffers 16 1024k;
    proxy_busy_buffers_size 2048k;
    proxy_temp_file_write_size 2048k;

通过查看nginx错误日志位置:/var/log/nginx/error.log,可以看到以下信息:

nginx /usr/local/nginx/proxy_temp/7/00/0000000007" failed (13: Permission denied) 

所以确定应该是权限问题导致,解决方法:

ubuntu@VM-4-3-ubuntu:/etc/nginx$ sudo ls -l /var/cache/nginx/proxy_temp/
total 40
drwx------ 3 nginx nginx 4096 Mar 16  2022 0
drwx------ 4 nginx nginx 4096 Mar 16  2022 1
drwx------ 4 nginx nginx 4096 Mar 16  2022 2
drwx------ 4 nginx nginx 4096 Mar 16  2022 3
drwx------ 4 nginx nginx 4096 Mar 16  2022 4
drwx------ 3 nginx nginx 4096 Mar 15  2022 5
drwx------ 3 nginx nginx 4096 Mar 15  2022 6
drwx------ 3 nginx nginx 4096 Mar 16  2022 7
drwx------ 3 nginx nginx 4096 Mar 16  2022 8
drwx------ 3 nginx nginx 4096 Mar 16  2022 9
ubuntu@VM-4-3-ubuntu:/etc/nginx$ sudo chown -R www-data:root /usr/local/nginx/proxy_temp