树莓派微型 web 服务器——正式设计报告

树莓派微型web服务器

摘要

这篇博客介绍了一个基于树莓派的轻量级服务器项目。树莓派是一款低成本、小型化的单板计算机,具有较低的功耗和良好的可扩展性。该项目利用树莓派搭建了一个功能简洁但性能稳定的服务器环境,适用于小型应用或个人使用。该轻量级服务器具有较低的能耗和占用空间,并提供基本的网站托管、文件存储与共享等功能。通过本论文的研究,可以为树莓派爱好者和需要搭建简单服务器的用户提供参考和指导。
This paper presents a lightweight server project based on Raspberry Pi. Raspberry Pi is a low-cost and compact single-board computer with low power consumption and excellent scalability. The project utilizes Raspberry Pi to create a simple yet stable server environment suitable for small-scale applications or personal use. The lightweight server offers low energy consumption, small footprint, and basic functionalities such as website hosting, file storage, and sharing. Through the research conducted in this paper, it provides references and guidance for Raspberry Pi enthusiasts and users in need of setting up a simple server.

关键词: Raspberry Pi 4 Model B;内网穿透;apache2;服务器搭建;网站托管;文件存储与共享;可扩展性;低成本;低功耗;小型化

Keywords: Raspberry Pi 4 Model B, port forwarding, apache2, server setup, website hosting, file storage and sharing, scalability, low cost, low power consumption, compact size



1. 项目简介

1.1 项目概述和目标

利用树莓派构建一个轻量级服务器,提供基本的网站托管、文件存储与共享等功能。树莓派是一款低成本、小型化的单板计算机,具有较低的功耗和良好的可扩展性。通过搭建树莓派服务器,可以实现简单的网络服务,并为用户提供可靠且经济高效的解决方案。

在这里插入图片描述

Image1 树莓派搭建web服务器的特点
  1. 通过合理配置树莓派和相关软件,确保服务器的稳定性和性能。
    提供基本的网站托管功能:支持部署简单的网站和应用程序,使用户能够在服务器上托管自己的网站或个人项目。
  2. 通过树莓派服务器,用户可以创建文件存储空间,并实现文件的共享和访问。
  3. 利用树莓派的特性,该项目具有低成本和低功耗的优势,适合个人用户或小型应用场景。
  4. 树莓派具有良好的可扩展性,用户可以根据需求添加更多的功能和扩展硬件,满足不同应用的需求。

1.2 项目背景

随着互联网的迅速发展和普及,越来越多的人需要搭建自己的服务器来托管网站、存储文件或提供其他网络服务。然而,传统的服务器往往价格昂贵、体积庞大、功耗高,对于个人用户或小型应用来说不太适合。在这样的背景下,树莓派(Raspberry Pi)作为一种低成本、小型化的单板计算机,成为了一个理想的选择。树莓派具有较低的功耗、良好的可扩展性和灵活性,能够满足个人用户或小型应用的需求。
基于树莓派的轻量级服务器项目应运而生。通过利用树莓派的性能和特性,可以搭建一个功能简洁但性能稳定的服务器环境,适用于个人用户、小型企业或教育机构等。这样的服务器不仅具有较低的能耗和占用空间,而且价格相对较低,为用户提供了一种经济高效的解决方案。在项目背景下,该轻量级服务器项目旨在利用树莓派的优势,为用户提供一个简单、稳定且经济高效的服务器搭建方案,满足他们在个人或小型应用中的基本需求。通过搭建树莓派服务器,用户可以实现网站托管、文件存储与共享等功能,并享受到树莓派的低成本和低功耗优势。

1.3 ngrok介绍

Ngrok 是一个用于创建安全隧道的工具,它可以将本地的服务器或应用程序暴露到公共互联网,从而使外部用户可以访问这些服务。
在这里插入图片描述

Image2 ngrok的logo

1.3.1 ngrok简介

Ngrok 是一款开源工具,由 Alan Shreve 开发,旨在简化本地开发和测试过程中与外部网络的连接。它提供了一种简单而强大的方式来公开本地服务器,并为开发人员和团队提供了更好的访问和调试本地应用程序的能力。

1.3.2 安全隧道

Ngrok 使用安全的隧道连接本地服务器和公共互联网,通过使用反向代理和加密通信来确保数据的安全传输。它采用了 TLS/SSL 加密来保护数据的传输,使用户可以在公共网络中安全地访问本地服务器。

1.3.3 跨平台支持

Ngrok 提供了跨平台的支持,可在 Windows、macOS 和 Linux 等操作系统上运行。这使得开发人员可以在不同的环境中使用 Ngrok,并轻松与不同平台的服务器进行交互。

1.3.4 操作简易

简单易用:Ngrok 具有简单易用的界面和命令行工具,使得设置和配置隧道变得非常简便。只需几个简单的命令或配置文件,即可将本地服务器暴露到公共互联网,无需进行复杂的网络设置或端口转发。

1.3.5 远程访问功能

通过 Ngrok,您可以在不同的网络环境中远程访问本地服务器。这对于与远程团队成员共享进展、进行演示、测试 API 等场景非常有用。
在这里插入图片描述

Image3 使用ngrok的页面图

1.3.6 调试和测试

Ngrok 提供了方便的调试和测试功能,可以轻松查看和分析传入和传出的请求、响应和日志。这对于开发人员进行本地开发、调试 API、测试微服务等非常有帮助。

1.4 apache2介绍

Apache2 是一款广泛使用的开源 Web 服务器软件,被广泛应用于构建和托管网站、Web 应用程序和服务。
在这里插入图片描述

Image4 apache的logo

1.4.1 apache2简介

Apache2 是 Apache 软件基金会开发的一款成熟稳定的 Web 服务器软件,它的前身是 Apache HTTP Server。Apache2 提供了一个可靠的平台,使用户能够在互联网上发布和管理自己的网站和应用程序。

1.4.2 高可靠性和稳定性

Apache2 经过多年的发展和测试,具有出色的稳定性和可靠性。它能够处理大量的并发连接,并具有强大的错误处理和恢复能力,确保网站和应用程序的稳定运行。

1.4.3 灵活的配置

Apache2 提供了灵活的配置选项,用户可以通过编辑配置文件来自定义服务器的行为和设置。这使得用户能够根据自己的需求进行高度定制,包括虚拟主机配置、SSL/TLS 加密、日志记录等。

1.4.4 文档和社区支持

Apache2 拥有丰富的官方文档和活跃的社区支持。用户可以从官方文档中获取详细的配置和使用指南,并参与社区讨论、获得帮助和解决问题。
在这里插入图片描述

Image5 apache2初始页面

2. 需求分析

2.1 功能需求

2.1.1 访问需求

  • 普通用户访问需求:
    普通用户可能有时候需要某一个特定的地方下载文件,比如学生从mystu上下载学习资料或者到ftp里面下载一些共享的文件,亦或者从邮箱上下载某些文件。在下载的时候会遇到种种问题,其中比较特别的就是离开了该局域网后就不能下载某个网站下的图片或者文件了,因此树莓派可以用作公网的微服务器来用于web的搭建、文件的传输、图片的下载…等等。
  • web开发者访问需求:
    对于web开发者,假如做出了一个vue或react或者其他简单的html的静态页面,想让公网的全部人都看到并且能够输入网站进入该页面,而不是只有localhost或者局域网内的用户能看到,那么树莓派+apache2+ngrok+内网穿透+vue build就能实现这一点。

2.1.2 自定义域名需求

其实对于静态网站的部署有很多办法,其中免费且稳定的方法就有GitHub Page,下图就是一个使用Github Page部署一个用Slidev构建的线上ppt的例子,使用https://hiddensharp429.github.io/slidev/1就可以访问这个部署在Github上的项目了。html项目、vue打包后的项目、react打包后的项目等等都可以直接部署在Github上面,但是这个.github.io这个二级域名你是不可以修改的,只有你购买的域名才有修改这个二级域名的权利。
由此就凸显了树莓派+ngrok的威力了,使用ngrok部署的项目可以自定义二级域名例如可以使用https://hiddensharppi.ap.ngrok.io \ https://hiddensharppi.in.ngrok.io/\ https://hiddensharppi.ngrok.com/等等域名,并且hiddensharppi这个字段是可以任意编辑的(例如我改成https://ilovestudy.ap.ngrok.io/完全可以)。
在这里插入图片描述

Image6 Github Page静态页面部署

在这里插入图片描述

Image7 Github Page部署Slidev项目

2.1.3 下载公共文件需求

假如有多个人需要相互之间传输下载文件,但是又不想使用微信等通讯工具来满足其需求,这时候树莓派就可以充当一个小型的文件服务器了,如果这几个人在同一个局域网内进行通讯就可以直接通过访问树莓派内存里面的文件夹share来进行文件的传输,该项目的注重的是在公网内用户如何达到这样的一个目的:“管理员上传相关的文件,来自不同局域网的用户通过输入网址来访问树莓派服务器,点击相关文件的url链接来下载他们所需要的文件”。

2.1.4 用户体验需求

用户使用树莓派的web服务器主要要求服务器具有如下特征:

  1. 域名友好的
  2. 服务稳定的
  3. 延迟较低的

对于第一点域名友好的,树莓派web服务器可以使用ngrok来进行二级域名和最大程度的域名自定义,由此可以实现第一点;

对于第二点服务稳定的,树莓派相对于电脑作为web服务器,树莓派本身机身小,不需要关机,连接简单,操作易上手等等特性使得其可以称得上是微型web服务器的最优选;

对于第三点延迟较低的,树莓派web服务器原本是用apache2进行局域网内的网址部署,但是利用了ngrok进行了内网穿透,使得本来只能局域网内访问的网址变成了在联网的情况上均可以访问的网址。

2.2 技术需求

2.2.1 操作系统指令

树莓派通常使用Raspbian作为默认操作系统,它是基于Linux的。同时也可以选择使用其他的操作系统,例如Ubuntu等,若想要完成这个项目,要求对Linux系统操作命令拥有一定的熟练度。

2.2.2 涉及的技术栈

本项目主要的涉及的技术栈有Raspbian、Apache2、Nginx、http\tcp\ip协议、ngrok、ssh、vue.js、node.js、html、css等,由于该项目的树莓派使用的内存是16G的,故没有涉及到后端开发,因此之前所搭建的个人ChatGPT网站和Midjourney网站就没有上传至树莓派服务器。

2.2.3 内网穿透

本项目主要选择方向是想使用的ngrok来进行树莓派的内网穿透,主要使用过内网穿透有:国内之前比较好用的ngrok.ttun\ frp \ ngrok.ciqiuwl \ ngrok等,该项目的最后选择的是ngrok

2.3 性能需求

2.3.1 处理能力

根据项目的预期负载和网站的性质,应该选择适当的树莓派型号。不同型号的树莓派具有不同的处理器和内存规格,较高规格的型号可以处理更多的并发请求和复杂的任务。

2.3.2 内存

树莓派的内存(RAM)对于同时处理多个请求和运行内存密集型应用程序非常重要。较大的内存容量可以提高服务器的响应速度和性能。

2.3.3 存储空间

存储空间:考虑您需要存储的网站内容和相关文件的大小。选择合适的存储介质,如SD卡或外部硬盘驱动器,以满足您的存储需求。


3. 系统设计

3.1 系统设计模块流程图

在这里插入图片描述

Image8 系统设计模块流程图

3.2 简易网站pi-website搭建

原本是想将chatgpt和midjourney部署到树莓派服务器的,但是由于后端开发的经验较少,并且树莓派的硬件承受不起这两个模块的并发运行,故只能将本地部署chatgpt的vue项目打包成一个rar放到服务器上了。

3.2.1 pi-website项目层次结构

  • dist:build生成的文件
  • src:源代码目录
    • assets:静态资源目录
    • components:组件目录
      • ChatingModule.vue:聊天模块
      • DrawingModule.vue:绘画模块
      • FileModule.vue:文件模块
      • ImageModule.vue:图片模块
    • views:视图目录
      • Home
    • App.vue:根组件
    • main.js:入口文件
  • babel.config.js:Babel配置文件
  • package.json:项目配置文件
  • vue.config.js:Vue配置文件

3.3.2 pi-website项目功能

Pi-website主要功能有四个图片文件聊天绘画

  1. 在图片模块中可以查看服务器上的存放的图片名称、图片大小等,并且还可以点击download进行下载。
  2. 在文件模块中功能与图片类似用户也可以下载存放在服务器的相关文件,包括但不限于.doc.ppt.md.txt。
  3. 在聊天模块中用户可以通过调用chatgpt的接口来跟chatgpt进行互动聊天。
  4. 在绘画模块中用户可以通过输入特定的prompt给midjourney提示,让其生成四张符合要求的图片。

3.3.3 pi-website 截图

在这里插入图片描述

Image9 图片模块截图

在这里插入图片描述

Image10 文件模块截图

在这里插入图片描述

Image11 聊天模块截图

在这里插入图片描述

Image12 绘画模块截图

3.3 web服务器搭建

3.3.1 使用apache2使网站局域网化

  1. 首先需要执行sudo apt-get install apache2命令
    执行该命令后会在树莓派的/var/www/html生成一个apache的初始页面index.html文件。放置在这里面的html文件都会被部署到树莓派服务器上。(前提是你的apach在运行中),下面这张图是我部署了打包后的vue项目,并非初始的index.html,一开始只有一个index.html文件。
    在这里插入图片描述
Image13安装apache2后index.html文件存放位置示意图
  1. 在浏览器上输入你的树莓派ip地址,这里我的树莓派ip地址是10.141.42.21,后会看到下面这个页面。
    在这里插入图片描述
Image 14输入树莓派ip地址后的页面

3.3.2 使用ngrok使用网站达到内网穿透

  1. 进入ngrok官网https://ngrok.com/
  2. 登录或者注册一个账号,这里我用Github注册了一个账号
    在这里插入图片描述
Image15 ngrok官网
  1. 为树莓派下载 Linux(ARM) 版本的ngrok
    在这里插入图片描述
Image16 ngrok下载
  1. 下载完毕后通过 FileZilla 将压缩包传到树莓派上
    在这里插入图片描述
Image17 传输ngrok压缩包
  1. 使用unzip /path/to/ngrok.zip为ngrok-v3-stable-linux-arm .tgz解压
  2. 在命令行中使用ngrok config add-authtoken <your authoken>为ngrok配置账号token
  3. 使用./ngrok http 80来启动ngrok,默认端口是80端口
    在这里插入图片描述
Image18 启动ngrok成功页面
启动后可以访问Forwarding后面的网址`https://f4916595f05a.ngrok.app`来访问树莓派上部署的web,不需要在跟树莓派同一局域网中就可以访问到该web了。

3.3.3 优化ngrok

单独只是这样还不够优雅,ngrok除了支持最基本的内网穿透还提供很多增值服务,其中选定服务器地区Region和二级域名subdomain功能都可以应用

  1. 登录ngrok官网进入仪表盘中的Cloud Edge选项卡中的Domains里,在这里你可以提前预定一个或者多个专属二级域名
    在这里插入图片描述
Image19 设置二级域名
  1. 点击右边的New Domain选项并输入你喜欢的二级域名
    在这里插入图片描述
Image20 选择二级域名
  1. 设置完成后,你可以使用./ngrok http --region=ap --domain=hiddensharppi.ap.ngrok.io 9000来部署你的网址
    这条指令有些参数是可选的,比如--region --domain以及后面的9000这个端口,具体的参数列表可参考官方中文文档http://ngrok.cn/docs.html#subdomain
    在这里插入图片描述
Image21 设置二级域名并内网穿透成功

4. 硬件组装

4.1 总体组装示意图

在这里插入图片描述

Image22 整体连接的实物图

4.2 各部分连接情况

在这里插入图片描述

Image23 各部分连接情况1

在这里插入图片描述

Image24 各部分连接情况2

在这里插入图片描述

Image25 各部分连接情况3

5. 项目总结

5.1 成功概述

本项目旨在搭建一个基于树莓派的轻量级服务器,为用户提供一个功能简洁但性能稳定的服务器环境。通过利用树莓派的低成本、低功耗和可扩展性,我们实现了一个可靠的服务器解决方案。该服务器具有较低的能耗和占用空间,并提供基本的网站托管、文件存储与共享等功能,下面是这个项目的成果分述。

  1. 本项目以树莓派为基础,利用其性能和资源优势,构建了一个稳定而高效的服务器环境。树莓派的低功耗特性使其成为可持续运行的选择,并且其较小的尺寸使其适用于空间有限的场所。
  2. 我们采用了ngrok实现了内网穿透功能,使得服务器可以通过公网访问,解决了内网环境下无法直接访问的问题。这为用户提供了便捷的远程访问和管理服务器的方式,增加了灵活性和便利性。
  3. 我们选择了Apache2作为服务器软件,其稳定性、灵活性和安全性得到了广泛认可。Apache2的模块化架构和丰富的功能使其能够满足不同用户的需求,并提供了可靠的网站托管和应用程序支持。
  4. 本项目以低成本和可扩展性为优势,适用于个人用户和小型应用场景。用户可以在较低的预算下搭建一个稳定的服务器环境,满足其基本需求,并随着需求的增长进行灵活扩展。

5.2 特色和创新点

5.2.1 低成本和可扩展性

项目利用树莓派这款低成本、小型化的单板计算机作为服务器的核心,使得服务器搭建的成本大大降低。同时,树莓派具有良好的可扩展性,可以根据需求灵活添加更多硬件组件或扩展功能。
内网穿透技术:通过应用ngrok实现内网穿透功能,将内部网络的服务器暴露到公网上。这一创新点解决了传统内网环境下无法直接访问服务器的问题,用户可以方便地通过公网访问和管理服务器,提高了远程操作的便捷性。

5.2.2 基于Apache2的稳定性和灵活性

选择Apache2作为服务器软件的核心,借助其稳定性和灵活性,为用户提供可靠的网站托管和应用程序支持。Apache2的模块化架构和丰富的功能使得服务器能够满足不同用户的需求,并且具备良好的安全性。

5.2.3 功能简洁但实用

项目的目标是提供一个轻量级服务器环境,专注于基本的网站托管和文件存储与共享功能。通过简化功能的同时确保性能稳定,使得服务器使用更加便捷和高效。

5.2.4 适用于个人用户和小型应用

由于低成本和可扩展性的特点,本项目适用于个人用户和小型应用场景。用户可以在有限的预算下快速搭建一个稳定的服务器环境,满足其基本需求,并且可以随着需求的增长进行灵活扩展。

5.3 后续拓展和延申想法

主要目标就是完善一下聊天模块和绘画模块,由于对后端技术掌握不够熟练很多东西不知道怎部署到树莓派上面,只能做一个简易的框架,虽然说已经自己搭建了一个chatgpt的网站但是并不能作为一个chating模块嵌入到原来的网站中。


6. 附录

6.1 pi-website代码

6.1.1 DrawingModule.vue

<!--
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-28 14:59:08
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-29 16:02:21
 * @FilePath: \pi-website\src\components\FileModule.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="main_page">
    <div class="content_section floating_element">
      <div class="section_header section_header_red">
        <div id="about"></div>
        README FIRST
      </div>
      <div class="content_section_text">
        <p>
          由于树莓派的硬件设施问题,暂不支持绘画模块,后期会可能会进行添加,本地draw的网站正在紧张的研发中,敬请期待。
        </p>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "DrawingModule",
  data() {
    return {
    };
  },
};
</script>

<style scoped>
* {
  margin: 10px 0px 0px 0px;
  padding: 0px 0px 0px 0px;
}
body,
html {
  background-color: #d8dbe2;
  font-family: Verdana, sans-serif;
  font-size: 11pt;
  text-align: center;
}
div.main_page {
  position: relative;
  display: table;

  width: 800px;

  margin-bottom: 3px;
  margin-left: auto;
  margin-right: auto;
  padding: 0px 0px 0px 0px;

  border-width: 2px;
  border-color: #212738;
  border-style: solid;

  background-color: #ffffff;

  text-align: center;
}

div.table_of_contents {
  clear: left;

  min-width: 200px;

  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.table_of_contents_item {
  clear: left;

  width: 100%;

  margin: 4px 0px 0px 0px;

  background-color: #ffffff;

  color: #000000;
  text-align: left;
}

div.table_of_contents_item a {
  margin: 6px 0px 0px 6px;
}

div.content_section {
  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.content_section_text {
  padding: 4px 8px 4px 8px;

  color: #000000;
  font-size: 100%;
}

div.content_section_text pre {
  margin: 8px 0px 8px 0px;
  padding: 8px 8px 8px 8px;

  border-width: 1px;
  border-style: dotted;
  border-color: #000000;

  background-color: #f5f6f7;

  font-style: italic;
}

div.content_section_text p {
  margin-bottom: 6px;
}

div.content_section_text ul,
div.content_section_text li {
  padding: 4px 8px 4px 16px;
}

div.section_header {
  padding: 3px 6px 3px 6px;

  background-color: #8e9cb2;

  color: #ffffff;
  font-weight: bold;
  font-size: 112%;
  text-align: center;
}

div.section_header_red {
  background-color: #cd214f;
}

div.section_header_grey {
  background-color: #9f9386;
}

.floating_element {
  position: relative;
  float: left;
}

div.table_of_contents_item a,
div.content_section_text a {
  text-decoration: none;
  font-weight: bold;
}

div.table_of_contents_item a:link,
div.table_of_contents_item a:visited,
div.table_of_contents_item a:active {
  color: #000000;
}

div.table_of_contents_item a:hover {
  background-color: #000000;

  color: #ffffff;
}

div.content_section_text a:link,
div.content_section_text a:visited,
div.content_section_text a:active {
  background-color: #dcdfe6;

  color: #000000;
}

div.content_section_text a:hover {
  background-color: #000000;

  color: #dcdfe6;
}

div.validator {
}
</style>


6.1.2 ChatingModule.vue

<!--
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-28 14:59:08
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-29 16:07:08
 * @FilePath: \pi-website\src\components\FileModule.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="main_page">
    <div class="content_section floating_element">
      <div class="section_header section_header_red">
        <div id="about"></div>
        README FIRST
      </div>
      <div class="content_section_text">
        <p>
          由于树莓派的硬件设施问题,暂不支持聊天模块,后期会可能会进行添加,下面是一个部署好了本地chatgpt的网站,详情请下载下面这个压缩包。
        </p>
        <p>简易教程</p>
        <p>1.安装node和npm</p>
        <p>2.安装pnmp: <code>npm install pnpm -g</code></p>
        <p>3.在终端打开chatgpt-web,输入命令<code>pnpm bootstrap</code></p>
        <p>4.添加一个新的终端CD进入services文件夹,输入<code>pnpm install</code></p>
        <p>5.OPENAI_API_KEY后面填写密钥 若没有可以使用我的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</p>
        <p>6.启动魔法,尽量使用chatgpt支持的地区</p>
        <p>7.SOCKS_PROXY_HOST填写服务器的ip地址,可以使用本地主机</p>
        <p>8.SOCKS_PROXY_PORT填写魔法的端口号</p>
        <p>9.配置完后在services的终端输入<code>pnpm start</code>启动后端</p>
        <p>10.运行起来后若不确定是否启动成功可以访问ip:3002,若显示Cannot GET则说明成功</p>
        <p>11.不要关闭后端的命令行,重新打开前端目录chatgpt-web,输入命令<code>pnpm dev</code>即可运行  </p>
      </div>

      <div class="section_header">
        <div id="changes"></div>
        Source code
      </div>
      <div class="content_section_text">
        <div class="file-list" style="display: flex; flex-direction: column">
          <div v-for="file in files" :key="file.name" class="file-item">
            <p style="display: flex; flex-direction: column-reverse">
              {{ file.name }}
              {{ file.size }}
              <a :href="file.downloadUrl" download>Download</a>
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "ChatingModule",
  data() {
    return {
      files: [
        {
          name: "chatgpt-web.rar",
          size: "593957 KB",
          downloadUrl: "/file/chatgpt-web.rar",
        },
      ],
    };
  },
};
</script>

<style scoped>
* {
  margin: 10px 0px 0px 0px;
  padding: 0px 0px 0px 0px;
}
body,
html {
  background-color: #d8dbe2;
  font-family: Verdana, sans-serif;
  font-size: 11pt;
  text-align: center;
}
div.main_page {
  position: relative;
  display: table;

  width: 800px;

  margin-bottom: 3px;
  margin-left: auto;
  margin-right: auto;
  padding: 0px 0px 0px 0px;

  border-width: 2px;
  border-color: #212738;
  border-style: solid;

  background-color: #ffffff;

  text-align: center;
}

div.table_of_contents {
  clear: left;

  min-width: 200px;

  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.table_of_contents_item {
  clear: left;

  width: 100%;

  margin: 4px 0px 0px 0px;

  background-color: #ffffff;

  color: #000000;
  text-align: left;
}

div.table_of_contents_item a {
  margin: 6px 0px 0px 6px;
}

div.content_section {
  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.content_section_text {
  padding: 4px 8px 4px 8px;

  color: #000000;
  font-size: 100%;
}

div.content_section_text pre {
  margin: 8px 0px 8px 0px;
  padding: 8px 8px 8px 8px;

  border-width: 1px;
  border-style: dotted;
  border-color: #000000;

  background-color: #f5f6f7;

  font-style: italic;
}

div.content_section_text p {
  margin-bottom: 6px;
}

div.content_section_text ul,
div.content_section_text li {
  padding: 4px 8px 4px 16px;
}

div.section_header {
  padding: 3px 6px 3px 6px;

  background-color: #8e9cb2;

  color: #ffffff;
  font-weight: bold;
  font-size: 112%;
  text-align: center;
}

div.section_header_red {
  background-color: #cd214f;
}

div.section_header_grey {
  background-color: #9f9386;
}

.floating_element {
  position: relative;
  float: left;
}

div.table_of_contents_item a,
div.content_section_text a {
  text-decoration: none;
  font-weight: bold;
}

div.table_of_contents_item a:link,
div.table_of_contents_item a:visited,
div.table_of_contents_item a:active {
  color: #000000;
}

div.table_of_contents_item a:hover {
  background-color: #000000;

  color: #ffffff;
}

div.content_section_text a:link,
div.content_section_text a:visited,
div.content_section_text a:active {
  background-color: #dcdfe6;

  color: #000000;
}

div.content_section_text a:hover {
  background-color: #000000;

  color: #dcdfe6;
}

div.validator {
}
</style>


6.1.3 FileModule.vue

<!--
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-28 14:59:08
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-29 15:27:03
 * @FilePath: \pi-website\src\components\FileModule.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="main_page">
    <div class="content_section floating_element">
      <div class="section_header section_header_red">
        <div id="about"></div>
        README FIRST
      </div>
      <div class="content_section_text">
        <p>
          <tt>PHOTO LIST</tt>里面是一些文件,可以点击<tt>download</tt>进行下载。也可以右击选择<tt>在新标签页中打开链接</tt>来查看文件。现在一共有六个样例文件,后期可进行添加或者删除。
        </p>
        <p></p>
      </div>
      <div class="section_header">
        <div id="changes"></div>
        File LIST
      </div>
      <div class="content_section_text">
        <div class="file-list" style="display: flex; flex-direction: column">
          <div v-for="file in files" :key="file.name" class="file-item">
            <p style="display: flex; flex-direction: column-reverse">
              {{ file.name }}
              {{ file.size }}
              <a :href="file.downloadUrl" download>Download</a>
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "fileModule",
  data() {
    return {
      files: [
        {
          name: "file1.doc",
          size: "0 KB",
          downloadUrl: "/file/file1.doc",
        },
        {
          name: "file2.txt",
          size: "0 KB",
          downloadUrl: "/file/file2.txt",
        },
        {
          name: "file3.zip",
          size: "0 KB",
          downloadUrl: "/file/file3.zip",
        },
        {
          name: "file4.ppt",
          size: "0 KB",
          downloadUrl: "/file/file4.ppt",
        },
        {
          name: "file5.md",
          size: "0 KB",
          downloadUrl: "/file/file5.md",
        },
      ],
    };
  },
};
</script>

<style scoped>
* {
  margin: 10px 0px 0px 0px;
  padding: 0px 0px 0px 0px;
}
body,
html {
  background-color: #d8dbe2;
  font-family: Verdana, sans-serif;
  font-size: 11pt;
  text-align: center;
}
div.main_page {
  position: relative;
  display: table;

  width: 800px;

  margin-bottom: 3px;
  margin-left: auto;
  margin-right: auto;
  padding: 0px 0px 0px 0px;

  border-width: 2px;
  border-color: #212738;
  border-style: solid;

  background-color: #ffffff;

  text-align: center;
}

div.table_of_contents {
  clear: left;

  min-width: 200px;

  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.table_of_contents_item {
  clear: left;

  width: 100%;

  margin: 4px 0px 0px 0px;

  background-color: #ffffff;

  color: #000000;
  text-align: left;
}

div.table_of_contents_item a {
  margin: 6px 0px 0px 6px;
}

div.content_section {
  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.content_section_text {
  padding: 4px 8px 4px 8px;

  color: #000000;
  font-size: 100%;
}

div.content_section_text pre {
  margin: 8px 0px 8px 0px;
  padding: 8px 8px 8px 8px;

  border-width: 1px;
  border-style: dotted;
  border-color: #000000;

  background-color: #f5f6f7;

  font-style: italic;
}

div.content_section_text p {
  margin-bottom: 6px;
}

div.content_section_text ul,
div.content_section_text li {
  padding: 4px 8px 4px 16px;
}

div.section_header {
  padding: 3px 6px 3px 6px;

  background-color: #8e9cb2;

  color: #ffffff;
  font-weight: bold;
  font-size: 112%;
  text-align: center;
}

div.section_header_red {
  background-color: #cd214f;
}

div.section_header_grey {
  background-color: #9f9386;
}

.floating_element {
  position: relative;
  float: left;
}

div.table_of_contents_item a,
div.content_section_text a {
  text-decoration: none;
  font-weight: bold;
}

div.table_of_contents_item a:link,
div.table_of_contents_item a:visited,
div.table_of_contents_item a:active {
  color: #000000;
}

div.table_of_contents_item a:hover {
  background-color: #000000;

  color: #ffffff;
}

div.content_section_text a:link,
div.content_section_text a:visited,
div.content_section_text a:active {
  background-color: #dcdfe6;

  color: #000000;
}

div.content_section_text a:hover {
  background-color: #000000;

  color: #dcdfe6;
}

div.validator {
}
</style>


6.1.4 ImageModule.vue

<!--
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-28 14:58:44
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-28 22:21:58
 * @FilePath: \pi-website\src\components\imageModule.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <div class="main_page">
    <div class="content_section floating_element">
      <div class="section_header section_header_red">
        <div id="about"></div>
        README FIRST
      </div>
      <div class="content_section_text">
        <p>
          <tt>PHOTO LIST</tt>里面是一些图片,可以点击<tt>download</tt>进行下载。也可以右击选择<tt>在新标签页中打开链接</tt>来查看图片。现在一共有六个样例图片,后期可进行添加或者删除。
        </p>
        <p></p>
      </div>
      <div class="section_header">
        <div id="changes"></div>
        PHOTO LIST
      </div>
      <div class="content_section_text">
        <div class="image-list" style="display: flex; flex-direction: column">
          <div v-for="image in images" :key="image.name" class="image-item">
            <p style="display: flex; flex-direction: column-reverse">
              {{ image.name }}
              {{ image.size }}
              <a :href="image.downloadUrl" download>Download</a>
            </p>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "ImageModule",
  data() {
    return {
      images: [
        {
          name: "image1.png",
          size: "350 KB",
          downloadUrl: require("../assets/img/image1.png"),
        },
        {
          name: "image2.png",
          size: "46 KB",
          downloadUrl: require("../assets/img/image2.png"),
        },
        {
          name: "image3.png",
          size: "78 KB",
          downloadUrl: require("../assets/img/image3.png"),
        },
        {
          name: "image4.png",
          size: "419 KB",
          downloadUrl: require("../assets/img/image4.png"),
        },
        {
          name: "image5.png",
          size: "351 KB",
          downloadUrl: require("../assets/img/image5.png"),
        },
        {
          name: "image6.png",
          size: "449 KB",
          downloadUrl: require("../assets/img/image6.png"),
        },
      ],
    };
  },
};
</script>

<style scoped>
* {
  margin: 10px 0px 0px 0px;
  padding: 0px 0px 0px 0px;
}
body,
html {
  background-color: #d8dbe2;
  font-family: Verdana, sans-serif;
  font-size: 11pt;
  text-align: center;
}
div.main_page {
  position: relative;
  display: table;

  width: 800px;

  margin-bottom: 3px;
  margin-left: auto;
  margin-right: auto;
  padding: 0px 0px 0px 0px;

  border-width: 2px;
  border-color: #212738;
  border-style: solid;

  background-color: #ffffff;

  text-align: center;
}

div.table_of_contents {
  clear: left;

  min-width: 200px;

  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.table_of_contents_item {
  clear: left;

  width: 100%;

  margin: 4px 0px 0px 0px;

  background-color: #ffffff;

  color: #000000;
  text-align: left;
}

div.table_of_contents_item a {
  margin: 6px 0px 0px 6px;
}

div.content_section {
  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.content_section_text {
  padding: 4px 8px 4px 8px;

  color: #000000;
  font-size: 100%;
}

div.content_section_text pre {
  margin: 8px 0px 8px 0px;
  padding: 8px 8px 8px 8px;

  border-width: 1px;
  border-style: dotted;
  border-color: #000000;

  background-color: #f5f6f7;

  font-style: italic;
}

div.content_section_text p {
  margin-bottom: 6px;
}

div.content_section_text ul,
div.content_section_text li {
  padding: 4px 8px 4px 16px;
}

div.section_header {
  padding: 3px 6px 3px 6px;

  background-color: #8e9cb2;

  color: #ffffff;
  font-weight: bold;
  font-size: 112%;
  text-align: center;
}

div.section_header_red {
  background-color: #cd214f;
}

div.section_header_grey {
  background-color: #9f9386;
}

.floating_element {
  position: relative;
  float: left;
}

div.table_of_contents_item a,
div.content_section_text a {
  text-decoration: none;
  font-weight: bold;
}

div.table_of_contents_item a:link,
div.table_of_contents_item a:visited,
div.table_of_contents_item a:active {
  color: #000000;
}

div.table_of_contents_item a:hover {
  background-color: #000000;

  color: #ffffff;
}

div.content_section_text a:link,
div.content_section_text a:visited,
div.content_section_text a:active {
  background-color: #dcdfe6;

  color: #000000;
}

div.content_section_text a:hover {
  background-color: #000000;

  color: #dcdfe6;
}

div.validator {
}
</style>


6.1.5 main.js

/*
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-28 14:56:45
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-28 18:52:19
 * @FilePath: \pi-website\src\main.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router'
import ImageModule from './components/ImageModule.vue'
import FileModule from './components/FileModule.vue'
import ChatModule from './components/ChatingModule.vue'
import DrawingModule from './components/DrawingModule.vue'

Vue.config.productionTip = false
Vue.use(VueRouter)

const routes = [
  { path: '/image', component: ImageModule },
  { path: '/file', component: FileModule },
  { path: '/chat', component: ChatModule },
  { path: '/drawing', component: DrawingModule }
]
const router = new VueRouter({
  routes
})

new Vue({
  router,
  render: h => h(App)
}).$mount('#app')


6.1.6 App.vue

<!--
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-28 14:56:45
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-28 18:10:54
 * @FilePath: \pi-website\src\App.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <body>
    <div class="main_page">
      <div
        class="page_header floating_element"
        style="display: flex; flex-direction: column; align-items: center"
      >
        <img
          src="./assets/img/bg.png"
          alt="Debian Logo"
          class="floating_element"
          style="
            width: 100px;
            height: 50px;
            position: absolute;
            top: 0;
            left: 0;
          "
        />
        <span class="floating_element" style="margin-left: 0px">
          PI website
        </span>
        <div
          class="module-container"
          style="
            width: auto;
            display: flex;
            flex-direction: row;
            margin-top: 10px;
          "
        >
          <router-link to="/image" class="module-link">
            <div class="module">
              <span>图片</span>
            </div>
          </router-link>
          <router-link to="/file" class="module-link">
            <div class="module">
              <span>文件</span>
            </div>
          </router-link>
          <router-link to="/chat" class="module-link">
            <div class="module">
              <span>聊天</span>
            </div>
          </router-link>
          <router-link to="/drawing" class="module-link">
            <div class="module">
              <span>绘画</span>
            </div>
          </router-link>
        </div>
        <router-view></router-view>
      </div>
    </div>
    <div class="validator"></div>
    <div class="tip" v-if="flag">
      <div class="first">welcome to my pi website</div>
      <div class="first">@author:hiddensharp</div>
      <div class="first">欢迎来到我的树莓派web服务器</div>
      <div class="close" @click="flag = false">×</div>
    </div>
  </body>
</template>

<script>
export default {
  name: "App",
  created() {
    setTimeout(() => {
      this.flag = false;
    }, 5000);
  },
  data() {
    return {
      flag: true,
    };
  },
};
</script>

<style scoped>
* {
  margin: 0px 0px 0px 0px;
  padding: 0px 0px 0px 0px;
}
body,
html {
  padding: 3px 3px 3px 3px;

  background-color: #d8dbe2;

  font-family: Verdana, sans-serif;
  font-size: 11pt;
  text-align: center;
}

div.main_page {
  position: relative;
  display: table;

  width: 800px;

  margin-bottom: 3px;
  margin-left: auto;
  margin-right: auto;
  padding: 0px 0px 0px 0px;

  border-width: 2px;
  border-color: #212738;
  border-style: solid;

  background-color: #ffffff;

  text-align: center;
}

div.page_header {
  height: 99px;
  width: 100%;

  background-color: #f5f6f7;
}

div.page_header span {
  margin: 15px 0px 0px 50px;

  font-size: 180%;
  font-weight: bold;
}

div.page_header img {
  margin: 3px 0px 0px 40px;

  border: 0px 0px 0px;
}

div.table_of_contents {
  clear: left;

  min-width: 200px;

  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.table_of_contents_item {
  clear: left;

  width: 100%;

  margin: 4px 0px 0px 0px;

  background-color: #ffffff;

  color: #000000;
  text-align: left;
}

div.table_of_contents_item a {
  margin: 6px 0px 0px 6px;
}

div.content_section {
  margin: 3px 3px 3px 3px;

  background-color: #ffffff;

  text-align: left;
}

div.content_section_text {
  padding: 4px 8px 4px 8px;

  color: #000000;
  font-size: 100%;
}

div.content_section_text pre {
  margin: 8px 0px 8px 0px;
  padding: 8px 8px 8px 8px;

  border-width: 1px;
  border-style: dotted;
  border-color: #000000;

  background-color: #f5f6f7;

  font-style: italic;
}

div.content_section_text p {
  margin-bottom: 6px;
}

div.content_section_text ul,
div.content_section_text li {
  padding: 4px 8px 4px 16px;
}

div.section_header {
  padding: 3px 6px 3px 6px;

  background-color: #8e9cb2;

  color: #ffffff;
  font-weight: bold;
  font-size: 112%;
  text-align: center;
}

div.section_header_red {
  background-color: #cd214f;
}

div.section_header_grey {
  background-color: #9f9386;
}

.floating_element {
  position: relative;
  float: left;
}

div.table_of_contents_item a,
div.content_section_text a {
  text-decoration: none;
  font-weight: bold;
}

div.table_of_contents_item a:link,
div.table_of_contents_item a:visited,
div.table_of_contents_item a:active {
  color: #000000;
}

div.table_of_contents_item a:hover {
  background-color: #000000;

  color: #ffffff;
}

div.content_section_text a:link,
div.content_section_text a:visited,
div.content_section_text a:active {
  background-color: #dcdfe6;

  color: #000000;
}

div.content_section_text a:hover {
  background-color: #000000;

  color: #dcdfe6;
}

div.validator {
}

.tip {
  z-index: 10;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translateY(-50%) translateX(-50%);
  width: 800px;
  height: auto;
  background-color: rgba(126, 126, 126, 0.6);
  border-radius: 20px;
  color: #fff;
  text-align: center;
  font-size: 40px;

  .first {
    margin-top: 40px;
  }

  .close {
    font-size: 60px;
    position: absolute;
    top: 0;
    right: 20px;
    cursor: pointer;
  }
}
.module-link {
  text-decoration: none;
  color: #9f9386;
}
</style>


6.2 涉及的指令

sudo apt-get update //更新Ubuntu系统软件包列表
sudo apt upgrade //升级 Ubuntu 系统中已安装软件包

sudo apt install nodejs //安装nodejs
sudo apt install npm //安装npm
sudo apt-get install <packageName> //用于在 Ubuntu 系统中安装软件包
sudo apt-get install raspi2png //安装raspi2png

sudo raspi-config//打开Raspberry Pi 配置工具

sudo raspi2png -p screenshot.png //使用raspi2png进行页面截图

ifconfig //显示ip地址 
ip addr show //显示ip地址
whoami //显示当前登录用户的用户名
sudo passwd <username> //更改用户的密码
sudo nft list ruleset //查看防火墙规则
sudo service ssh status //查看ssh服务是否在运行
sudo service ssh start //开启ssh服务

ls //当前文件夹中的所有文件和子文件夹的列表
ls -l //长格式列出文件和文件夹,并包括它们的权限、所有者、大小、修改日期
ls -a //括以点开头的隐藏文件和文件夹。

sudo tar xvzf /ngrok-v3-stable-linux-amd64.tgz -C /user/local/bin //n解压grok文件到/user/local/bin目录中
sudo nautilus //以管理员身份运行文件管理器


sudo unzip /path/to/ngrok.zip //解压某个文件
sudo ngrok config add-authtoken <your authoken> //为ngrok配置token
sudo ./ngrok http 80 //使用ngrok启动树莓派服务器的80端口

cd /etc/apache2/ //跳转到指定的文件目录下
sudo vim ports.conf //用管理员的身份进入ports.conf文件进行修改

sudo service apache2 restart //重启apache2服务

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hiddenSharp429

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值