《树莓派4B家庭服务器搭建指南》刷Ubuntu Server 20.04,绑定公网域名,对公网提供http服务,SSH登录服务


title: 《树莓派4B家庭服务器搭建指南》刷Ubuntu Server 20.04,绑定公网域名,对公网提供http服务,SSH登录服务

前段时间我买了一块8GB内存的树莓派4B,接了个USB无线网卡当软路由 为树莓派4B安装OpenWrt镜像打造普通wifi转魔法wifi的便携路由器 https://www.v2fy.com/p/2021-07-04-openwrt-4b-1625383754000/, 但后面又感觉8GB的树莓派当软路由很浪费,于是这次把树莓派4B改装成一个公网可访问的服务器,用来跑一些内存消耗大的任务。

树莓派原生的系统不如Ubuntu的包丰富,于是本次烧录的镜像选Ubuntu Server 20.04长期支持版。

为了保证在公网,也能访问家中的树莓派服务器,我通过开源的frp内网穿透技术,为树莓派绑定了一个frp.v2fy.com的域名,公网访问https://frp.v2fy.com, 即可访问树莓派开启的http服务。然后,我又对树莓派,SSH做了映射,通过公网访问frp.v2fy.com 的 6000端口即可进行SSH登录。

原理结构图

结构
关于内网穿透的架构

浏览器对域名的请求默认是指向80(http)和443(https)端口,我先在服务器端安装了Nginx,占用80 和 443 端口,用于接收http 和 https请求,然后写一套规则,将针对frp.v2fy.com的请求,统统转发到8080端口,其中https的规则部分,还给frp.v2fy.com 配置了https证书(Nginx自动更新证书的操作可参考 零依赖!使用acme.sh设置nginx多个https证书自动更新,无限续期https证书 https://www.v2fy.com/p/2021-06-27-nginx-https-1624774964000/), 而8080端口被frp的服务端进程frps占用,frps将请求发送给frp在树莓派的客户端frpc, frpc将会把来自frpc的请求转发给树莓派运行在 8080 的http-server 服务; SSH转发规则与HTTP转发规则类似,从服务器的6000端口,转发到树莓派的22端口

前期准备

  1. 树莓派不可或缺套装:树莓派一个(二三四代皆可,我选的是树莓派4B),树莓派电源,8GB以上的SD卡(推荐16GB及以上)
  2. 两端水晶头完好的网线一根
  3. 一个联网的路由器,并有一个空闲可用的lan口
  4. 一个有固定IP的公网服务器
  5. 一个域名
  6. 一个32GB及以上的U盘或大容量硬盘,用来给树莓派服务器扩容(可选)

接下来正文开始…

使用SD Card Formatter格式化SD卡

SD Card Formatter下载地址 https://www.sdcard.org/downloads/formatter/

使用SD Card Formatter格式化SD卡

格式化完成后,分区合二为一,显示真实容量

下载镜像

https://ubuntu.com/download/raspberry-pi/thank-you?version=20.04.3&architecture=server-arm64+raspi 页面下载镜像

下载镜像

点击页面中download now后, 下载得到的文件为ubuntu-20.04.3-preinstalled-server-arm64+raspi.img

ubuntu-20.04.3-preinstalled-server-arm64+raspi.img

如果你浏览器经常下载失败,建议将https://cdimage.ubuntu.com/releases/20.04.3/release/ubuntu-20.04.3-preinstalled-server-arm64+raspi.img.xz 放入Free Download Manager直接下载(Free Download Manager是一款免费下载下载工具,而且有免费云端加速下载功能,对下载海外资源比较友好)

下载

使用balenaEtcher将镜像烧录到SD卡

balenaEtcher下载地址 https://www.balena.io/etcher/

按自己的系统,选择自己需要下载的版本,如果是windows系统,直接Download下图中第一个即可

按自己的系统,选择自己需要下载的版本

打开 Etcher , 选择镜像文件, 选择SD卡 , 开始烧录

开始烧录

这里图中用的8GB的SD卡,但有几次烧录失败了,后来我换了16GB的内存卡,一次刷成功,如果大家烧录一直失败,建议换一张SD卡试试。

将烧录好的SD卡放入树莓派,使用网线将树莓派与路由器lan口连接,通电开机

登录路由器后台,查看安装了ubuntu的树莓派被分配的ip

查看安装了ubuntu的树莓派被分配的ip

使用SSH登录树莓派服务器

使用SSH登录树莓派服务器

初始用户名,密码均为 ubuntu

第一次登录后,会强制要求改变默认密码

修改密码并重新登录

下面,我们通过frp内网穿透,给树莓派这个家庭服务器一个外网域名

内网穿透:服务端设置

首先将你的域名解析到你的服务器ip,接下来的步骤会用到服务器以下四个端口,为了方面后续的调试运行,请放开以下几个端口的安全策略, 80(Nginx接收http请求用), 443(Nginx接收https请求用), 6000(转发映射SSH服务用),8080(转发映射http服务用)端口

  • 配置Nginx,转发对frp.v2fy.com域名请求到8080端口(做这一步前,请先按照自己服务器的操作系统,自行安装nginx)

设置 /etc/nginx/nginx.conf

#user  nginx;
worker_processes  1;
load_module /usr/lib64/nginx/modules/ngx_stream_module.so;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;

stream {
    map $ssl_preread_server_name $backend_name {
        frp.v2fy.com        frp_v2fy_com;
        default web;
    }


   upstream frp_v2fy_com {
        server 127.0.0.1:8080;
   }

   upstream web {
        server 127.0.0.1:80;
   }

   server {
        listen       443 reuseport;
        listen  [::]:443 reuseport;
        proxy_pass   $backend_name;
        ssl_preread  on;
   }

}

events {
    worker_connections  1024;
}

http {

    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    charset utf-8,gbk;
    client_max_body_size 20m;

    set_real_ip_from 127.0.0.1;
    real_ip_header X-Forwarded-For;


    log_format  main  '$remote_addr  - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';
    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;
    keepalive_timeout  65;
    gzip  on;
    include /etc/nginx/conf.d/*.conf;
}

新建 /etc/nginx/conf.d/frp.v2fy.com.conf , 并在/etc/nginx/conf.d/frp.v2fy.com.conf 写入一下内容(frp.v2fy.com是我的域名, 请大家自行替换为自己的域名)

server {
    server_name      frp.v2fy.com;
    listen           80;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host:80;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}


server {
    listen       8080 ssl http2;
    listen       [::]:8080 ssl http2;
    server_name  frp.v2fy.com;

    location / {
        proxy_pass http://127.0.0.1:8080;
        proxy_set_header Host $host:443;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    ssl_certificate "/etc/nginx/ssl/frp.v2fy.com/fullchain.cer";
    ssl_certificate_key "/etc/nginx/ssl/frp.v2fy.com/frp.v2fy.com.key";
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout  10m;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Load configuration files for the default server block.
    include /etc/nginx/default.d/*.conf;

    error_page 404 /404.html;
        location = /40x.html {
    }

    error_page 500 502 503 504 /50x.html;
        location = /50x.html {
    }
}

重启nginx

nginx -t
nginx -s reload
  • 下载frp,并进行服务端设置

frp这个软件分为两部分,客户端为frpc, 服务端为frps

cd  /opt/
wget https://github.com/fatedier/frp/releases/download/v0.37.0/frp_0.37.0_linux_386.tar.gz
tar zxvf https://github.com/fatedier/frp/releases/download/v0.37.0/frp_0.37.0_linux_386.tar.gz

服务端frpc的配置文件为frpc.ini

服务端和客户端

我们需要修改服务端配置文件 frps.ini

修改服务端配置文件 frps.ini

[common]
bind_port = 7000
vhost_http_port = 8080

以上配置的意思是,服务端frp的名称为frps 运行在7000端口, 同时将指向8080端口的请求,转发到客户端 ;

  • 运行以下命令,开启frp的服务端程序
./frps -c frps.ini

开启程序,运行成功

frps默认前台运行,如果你想以后台守护进程运行, 可以使用node.js版的pm2进行守护

  • pm2 全局安装方式

首先安装Node.js(请根据自己服务器的操作系统,选择合适的Node.js版本), npm默认和Node.js一起安装, 然后通过npm安装 pm2

npm i pm2 -g

pm2的使用也很简单

首先将 ./frps -c frps.ini 存入名为 start_frps.sh 的文件

然后运行

pm2 start  /opt/frp_0.37.0_linux_arm64/start_frps.sh
pm2 save

即可以守护进程的方式运行frps !

此时运行 pm2 list, 可以看到脚本正在运行中…

脚本正在运行中…

内网穿透:客户端设置

  • 在树莓派内执行以下命令, 下载frp, 并解压
cd /opt/
sudo wget https://github.com/fatedier/frp/releases/download/v0.37.0/frp_0.37.0_linux_arm64.tar.gz
sudo tar zxvf  frp_0.37.0_linux_arm64.tar.gz

进入 /opt/frp_0.37.0_linux_arm64

备份客户端frpc的配置文件frpc.ini

sudo cp frpc.ini frpc.ini_backup
  • 编辑frpc.ini
sudo vim frpc.ini
  • 将以下配置放入frpc.ini
[common]
server_addr = (自己服务器的公网ip)
server_port = 7000

[web]
type = http
local_port = 8080
custom_domains = frp.v2fy.com

  • 使用浏览器从公网访问树莓派,验证内网穿透是否成功

内网穿透成功

安装Node.js (使用armv8版本的稳定版node.js)

我查了一下wiki对树莓派CPU架构的描述,树莓派三系及以后的版本都是ARMv8架构

架构

使用ARMv8版本的稳定版Node.js

使用ARMv8版本的稳定版Node.js

cd /opt/
sudo wget https://nodejs.org/dist/v14.18.0/node-v14.18.0-linux-arm64.tar.xz
sudo tar xvf node-v14.18.0-linux-arm64.tar.xz
  • 将Node.js添加到系统变量
sudo echo "export NODE_HOME=/opt/node-v14.18.0-linux-arm64" >> ~/.bashrc
sudo echo "export PATH=\$NODE_HOME/bin:\$PATH" >> ~/.bashrc
source ~/.bashrc

将Node.js添加到系统变量

安装http-server服务

npm install http-server -g

安装http-server服务

  • /opt 文件夹 新建 frp.v2fy.com 文件夹, 并创建hello.txt文件
sudo mkdir /opt/frp.v2fy.com
sudo chmod 777 -R  /opt/frp.v2fy.com
sudo touch /opt/frp.v2fy.com/hello.txt
sudo echo "Hello World! Success! " > /opt/frp.v2fy.com/hello.txt
  • 安装pm2
npm install pm2 -g
  • 使用pm2守护运行http-server服务
cd /opt/frp_0.37.0_linux_arm64 
sudo chmod 777 start_http_server.sh
sudo echo "http-server /opt/frp.v2fy.com -p 8080" > start_http_server.sh
pm2 start /opt/frp_0.37.0_linux_arm64/start_http_server.sh
pm2 save
  • 使用pm2守护运行frpc服务
sudo touch /opt/frp_0.37.0_linux_arm64/start_frpc.sh
sudo chmod 777 /opt/frp_0.37.0_linux_arm64/start_frpc.sh
sudo echo "/opt/frp_0.37.0_linux_arm64/frpc -c /opt/frp_0.37.0_linux_arm64/frpc.ini" > /opt/frp_0.37.0_linux_arm64/start_frpc.sh
cd /opt/frp_0.37.0_linux_arm64/
pm2 start  /opt/frp_0.37.0_linux_arm64/start_frpc.sh
pm2 save

pm2守护frpc和http-server服务成功

访问 https://frp.v2fy.com

页面显示

文件内容访问成功

这里可以通过公网顺利访问到家庭服务器的https服务。

添加ssh服务

  • 添加配置

在frpc.ini内添加ssh配置

[ssh]
type = tcp
local_ip = 127.0.0.1
local_port = 22
remote_port = 6000

配置的意思是,将树莓派的默认ssh的22号端口,映射到frp.v2fy.com的600端口

  • 重启frpc服务
cd /opt/frp_0.37.0_linux_arm64
pm2 restart start_frpc.sh
  • 通过公网frp.v2fy.com的6000端口进行ssh登录
ssh ubuntu@frp.v2fy.com -p 6000

登录成功

至此我们可以从互联网任何一台电脑,通过ssh访问我们j家里的树莓派服务器。

我们将pm2设置为开机启动,这样树莓派意外断电重启后,可以自动开启内网穿透

ubuntu@ubuntu:/opt/frp_0.37.0_linux_arm64$ pm2 startup
[PM2] Init System found: systemd
[PM2] To setup the Startup Script, copy/paste the following command:
sudo env PATH=$PATH:/opt/node-v14.18.0-linux-arm64/bin /opt/node-v14.18.0-linux-arm64/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
ubuntu@ubuntu:/opt/frp_0.37.0_linux_arm64$ sudo env PATH=$PATH:/opt/node-v14.18.0-linux-arm64/bin /opt/node-v14.18.0-linux-arm64/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu
[PM2] Init System found: systemd
Platform systemd
Template
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target

[Service]
Type=forking
User=ubuntu
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=/opt/node-v14.18.0-linux-arm64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/opt/node-v14.18.0-linux-arm64/bin:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=/home/ubuntu/.pm2
PIDFile=/home/ubuntu/.pm2/pm2.pid
Restart=on-failure

ExecStart=/opt/node-v14.18.0-linux-arm64/lib/node_modules/pm2/bin/pm2 resurrect
ExecReload=/opt/node-v14.18.0-linux-arm64/lib/node_modules/pm2/bin/pm2 reload all
ExecStop=/opt/node-v14.18.0-linux-arm64/lib/node_modules/pm2/bin/pm2 kill

[Install]
WantedBy=multi-user.target

Target path
/etc/systemd/system/pm2-ubuntu.service
Command list
[ 'systemctl enable pm2-ubuntu' ]
[PM2] Writing init configuration in /etc/systemd/system/pm2-ubuntu.service
[PM2] Making script booting at startup...
[PM2] [-] Executing: systemctl enable pm2-ubuntu...
[PM2] [v] Command successfully executed.
+---------------------------------------+
[PM2] Freeze a process list on reboot via:
$ pm2 save

[PM2] Remove init script via:
$ pm2 unstartup systemd
ubuntu@ubuntu:/opt/frp_0.37.0_linux_arm64$

运行pm2 startup, 然后运行弹出的一句命令 sudo env PATH=$PATH:/opt/node-v14.18.0-linux-arm64/bin /opt/node-v14.18.0-linux-arm64/lib/node_modules/pm2/bin/pm2 startup systemd -u ubuntu --hp /home/ubuntu

命令执行成功

为了验证开机自启,是否确实设置成功,我拔掉了树莓派的电源,果然http服务不可用了

image.png

连上树莓派的电源, frp.v2fy.com又可以访问了

可以访问了

自动恢复进程

为树莓派添加更大的容量(挂个32GB的大U盘)

我使用的内存卡只有16GB, 还是太小了,于是我往树莓派插了个32GB的U盘扩容容量,插入树莓派后,输入以下命令即可查看U盘有没有被识别

sudo fdisk -l

U盘识别成功

U盘设备的位置在 /dev/sda1

  • /dev/sda1 挂载到 /mnt/sda1
sudo mkdir /mnt/sda1
sudo mount /dev/sda1 /mnt/sda1

进入/mnt/sda1 , 即可往U盘内部读写文件了

访问扩容的U盘空间

我们也可以将U盘挂载到web服务文件夹

sudo mkdir /opt/frp.v2fy.com/sda1
sudo mount /dev/sda1 /opt/frp.v2fy.com/sda1

web文件夹

再次查看https://frp.v2fy.com, 通过https://frp.v2fy.com/sda1 可以访问U盘里所有的文件
frp.v2fy.com

有了服务器可以做什么?

  • 免费解锁网易云灰色歌曲 使用私人服务器,将网易云歌曲变亮,并分享给周围小伙伴 https://www.v2fy.com/p/2021-07-07-net-server-1625654857000/

  • 免费为超人气Makrdown编辑器Typora创建一个图床 元旦在家写代码,我完成了一个Markdown利器Typora私有化图床工具~ Windows, macOS,Linux均可运行 https://www.v2fy.com/p/2021-01-02-easytypora-1609587043000/

  • 免费建一个带数据库的满血版网站 《Nginx WordPress建站攻略》搭建一个高可玩的网站 https://www.v2fy.com/p/tips-000003-nginx-wordpress/

  • 免费建一个BBS论坛 给热心老哥搭个窝,2021年30分钟用Discourse搭建新一代BBS论坛站全攻略 https://www.v2fy.com/p/2021-06-12-discourse-2021-1623477573000/

  • 免费建一个VScode云端开发环境,随时随地可编程 将VSCode部署到服务器教程, 网页游戏上号!开始「云代码」!可作为ssh客户端使用~ https://www.v2fy.com/p/2021-07-12-vscode-1626075074000/

  • 免费部署自己的RSS爬虫服务器 私有化部署RSSHub全记录 https://www.v2fy.com/p/2021-09-07-rsshub-1631018903000/

小结

通过本次操作,我通过内网穿透,为家用树莓派提供了一个frp.v2fy.com域名,并可通过公网访问;通过配置ssh, 可以在互联网任何地方,使用frp.v2fy.com的6000端口进行ssh远程登录。

近期zhaoolee在研究K8S集群, 需要搞几台性能不错的主机,但内存和硬盘都太贵了,于是就把手头的树莓派4B利用了起来,有了内网穿透,就可以像一台真实的服务器,在互联网上提供服务。

在家里搭建自己的服务器,是每个男生的梦想,只要不断电,不断网,树莓派板子不爆炸,我们就能用极低的成本,获得性价比极高的服务器。

本文永久更新地址(欢迎来读留言,写评论):

https://www.v2fy.com/p/2021-10-01-pi-server-1633066843000