林荫
林荫
发布于 2025-05-18 / 97 阅读
0
0

从零架设自己的公网服务

前言

这一套流程集合了从服务器搭建到公网挂载的全流程配置,经过最近几天的踩坑,总算让体验达到了勉强可用的程度,特此记录一下希望有同样需求的读者在配置时能够轻松一些。笔者基于的系统环境是fnOS,其实就是一个特殊发行版本的Debian,不过理论上这一套应该是无所谓什么平台,只要能够运行docker,就都能完成配置,而且全程几乎无代码。

主要资费成本有:服务器硬件费用(弹性)+宽带(弹性)+域名(购自腾讯云的顶级域名一年83)。

实现的效果:可根据域名+统一端口号,以带宽上限速度访问自己的服务器提供的不同服务,本文以Gitea代码托管服务为例。

笔者在记录时尽量用简单朴实的语言来描述,希望读者可以在跟着一步一步配置的同时,还能真正理解每一步的意义,从而可以自己尝试更高阶的扩展技巧。

局域网内环境搭建

这一步主要是在局域网环境内把我们的服务跑起来,让它可以在局域网环境内稳定运行。

服务器系统搭建

既然是从零开始,第一步当然是给我们的服务器硬件装系统啦,笔者自己是用的家庭Nas兼顾服务器,并且没有开虚拟机,因为fnOS本身就是基于Debian的嘛,而且这系统本身也挺自由的,所以我感觉没什么太大开虚拟机的必要,就直接用了飞牛系统作为环境。

大家自己在装的时候也可以任意选择系统,只要能支持Docker就可以,不过为了运行效率和足够丰富的应用支持,我一般会推荐常用的Linux发行版本,此处主要点名Debian和Ubuntu,因为它们的教程会比较多,遇到问题解决起来会比较方便。为了给本文截图,笔者就是在fnOS上装了Ubuntu的虚拟机,跑了全流程。

操作系统的安装流程此处就不展开叙述了,各个系统各不相同,教程也很多,读者们各凭本领。

读者此处是去Ubuntu官网下载最新的server版本的种子文件,上传到飞牛使用qBitorrent磁力下载iso文件完成虚拟机搭建~

系统安装完成后重启登录会打印出系统相关信息,就算安装完成了。

注意一定要记住root用户的密码,后面很多操作都要基于root权限。

系统安装好之后,建议使用ssh的方式远程连接服务器,这样可以保证我们服务器在局域网内的可见性,也可以提前习惯ssh的远程管理方式(毕竟一般不会一直给服务器插个显示屏吧……)

根据系统使用自身命令获取本机的局域网ip地址后就可以尝试连接ssh了。

笔者此处是使用ifconfig,如果没有命令会提示先用sudo apt install net-tools安装,另外可以先用sudo -i切换到root用户,以免每次都要加sudo命令。

此处大家选择自己喜欢的ssh工具即可,笔者选择的是FinalShell,撰写本文时因为使用的是fnOS的虚拟机所以直接使用了自带的VNC访问工具。

docker管理器安装

Docker是一组平台即服务(PaaS)的产品。它基于操作系统层级的虚拟化技术,将软件与其依赖项打包为容器。托管容器的软件称为Docker引擎。Docker能够帮助开发者在轻量级容器中自动部署应用程序,并使得不同容器中的应用程序彼此隔离,高效工作。该服务有免费和高级版本。它于2013年首次发布,由Docker, Inc. 开发。

简单来讲,你可以把docker容器想象成一个个极简的虚拟机,有多极简呢,你不需要考虑虚拟机的cpu、内存甚至系统和用户管理,你只需要知道你需要的环境变量以及你想要安装的软件的版本以及一些初始化配置,通过几行配置,就可以原地启动一个安装好了你需要软件的极简虚拟机,这大大简化了我们部署、更新、卸载服务的流程。

不过对于笔者这种懒逼,这寥寥几行配置我也懒得配,所以选择安装docker的图形化管理界面~

我这里安装的是1panel,这是国人开发的一款all in one的服务器运维控制面板,它的优势在于功能多而且都很易于使用,比如本文后面openresty的管理也会基于它来配置,就可以避免代码式的配置过程。

并且它更新很快,最近刚推出了v2的beta版本,我这里就装一下试试看。

注意基于不同系统的安装命令是不同的,大家选择自己系统对应的安装命令即可。

INSTALL_MODE=beta bash -c "$(curl -sSL https://resource.fit2cloud.com/1panel/package/v2/quick_start.sh)"

下载完成后进入安装初始化步骤,首先会让你选择语言,当然是选择中文啦~输入2并按回车即可~

啊不过因为笔者此处的虚拟机未安装中文字符集所以看不到中文,就暂且选择英文了~

接下来是安装目录,我们保持默认直接回车即可

docker安装完成后它会询问你是否开启镜像加速,这个主要是为了解决国内直连docker hub困难的问题,会自动帮你选择比较快的国内镜像,所以国内的用户无脑输入y并且回车即可~

然后它会问你部署1panel的端口号,后面我们会使用这个端口号来访问1panel的图形化界面,看个人爱好选择即可,因为后面还可以通过反向代理来隐藏掉它,所以平时也很少用到,笔者这里就直接维持默认了。

下一步它会询问我们安全入口设置为多少,安全入口就是为了防止别人通过端口可以直接访问到控制台的多一层保护,这边建议不要使用默认的,以防后面忘记,不过忘记也可以用指令打印啦,所以也还好,笔者这里选择改为avenue~

接下来设置你的用户名密码之后,就会自动启动服务了,看到打印了下面这一大坨,就说明服务启动成功了。

可以看到安装成功的打印里面已经包含了访问的连接,由“ip:端口号/安全入口”组合而成,我们使用这个url就可以访问控制台界面啦!

笔者这里用的是ipv6地址打开的,一般用ipv4就可以,笔者这里是闲的蛋疼,给大家演示一下奇怪的操作。

然后用刚才设置的账号密码登录后,就可以开始代码托管服务的搭建过程了。

gitea平台搭建

接下来就是代码托管平台的搭建,这里我们选择的是gitea,选择gitea的原因主要是因为它开源、免费、轻量而且功能齐全,笔者使用下来,整体体验个人感觉跟github真的非常类似,真的是少见的极其优秀的开源项目。

gitea在我们的服务器上作为一个服务存在,其实我们刚才已经搭建了一个了,就是1panel,gitea也类似,需要监听一个端口来提供服务,不过gitea要复杂一些,因为它还需要基于数据库服务,并且本身包裹在docker容器中。

所以我们首先要安装一个数据库,此处我们选择mysql,mysql就不用多说了吧,大家应该都熟悉。

为了方便笔者使用1panel安装,大家也可以使用自己钟爱的docker工具安装,或者直接使用指令。

使用1panel安装的话,非常简单,因为1panel为大家把一些常用的docker镜像直接包装成了应用,预先设置好了参数,我们安装时就不需要去头疼每个服务各不相同而且项目繁杂的配置,只需要点击左边菜单的“应用商店”然后找到mysql选择安装即可。

点击安装弹出配置界面,建议大家只设置一下root用户密码这一项,其他维持默认即可。

点击确定会弹出二次弹窗询问你未勾选“端口外部访问”的话没办法在外部访问此端口,此处外部指当前设备以外的设备,并非公网,所以局域网内其他设备也不行,但是我们目前确实没有外部访问的需求,所以我们点击确定即可。

打印[TASK-END]表示安装并启用服务成功结束,此时我们在设备内就可以访问这个数据库服务了。

安装完成后我们需要为gitea预创建一个专属数据库以及一个对应的用户,1panel也有操作数据库的功能,没使用1panel的读者可以连接docker容器后直接使用SQL命令。

使用1panel的直接在左侧菜单栏选择“数据库”菜单,然后点击“创建数据库”按钮。

我们需要创建一个名为gitea的数据库,一个名为gitea的用户,ip为%,即任何ip来源都可以操作,并为此用户设置密码

创建成功后我们的数据库界面应该多出了如下图的一项:

到此我们为gitea做的准备工作就算完成了,之后我们继续安装gitea的镜像并启动容器。

使用1panel的读者同样可以在应用商店安装,不同的是安装前的配置记得把数据库相关配置修改为我们刚才创建的数据库和用户,并且打开“端口外部访问”,其实这里也可以不打开外部访问,但为了后面直接用ip+端口测试服务是否成功启动,建议此处还是打开。

同样在几秒钟的等待之后,我们的服务就启动成功了。

安装好之后,我们就可以通过端口访问该服务了,注意首次访问该服务会进入基础配置界面,该界面的大部分配置后续也可以通过更改配置文件并重建容器实现更改,所以不用太紧张。

按照如下图示配置即可:

配置完成后,点击“立即安装”会进入一个初始化过程,这个时候重复访问端口会返回500错误,不要一直尝试,免得服务出问题,耐心等待几分钟就好了。

初始化完成后,我们就可以像使用github一样来在局域网内使用我们自己搭建的gitea了,所以如果你对自己的代码安全有比较强的焦虑,不想分享你的平台,同时也没有远程合作的需求,到这里就可以停止了。

可以试着创建一个仓库,或者组织。

而如果你有上述需求,接下来的内容可以帮助你尽量低成本高反馈的去实现远程访问。

网络设置

看完这部分之后,你可以学会如何把局域网内的服务挂载到公网分享给你的小伙伴们,但需要注意的是,此部分只包含挂载服务的学习,不包含安全维护内容,在不了解基础的防火墙等安全系统的情况下,请不要随便把自己的机器挂载到公网

另外因为笔者写这段代码的时候处于远端,不方便连接路由器开放新的端口映射,所以后面的截图和测试会有一部分使用笔者已经在fnOS挂在好的服务进行,此部分会遮挡部分隐私信息。

基础挂载

基础挂载主要是基于ip实现局域网外,即公网上的远程服务访问,ip就像是门牌号,每一台设备在公网上都需要有一个门牌号才可以让别人寻找到你的地址。

ip目前主要分为ipv4和ipv6两种,目前由于ipv4地址紧缺,国内运营商一般默认不提供ipv4的公网ip,而是通过Nat的方式使用临时的ipv4地址来实现公网访问,但是ipv6地址相对比较宽松,所以一般都会提供公网的ipv6地址。(注意是一般,不是一定,也存在连公网ipv6也默认不给的运营商)所以我们最简单,成本最低的远程访问方式就是通过ipv6直接访问

这一步首先要保证你的网络支持ipv6,可以使用此网站查询你的网络环境是否支持ipv6,需要用户方和服务方双方都支持ipv6才行,如果当前网络环境不支持ipv6,就联系宽带运营商帮你打开。

确定服务端支持ipv6后,就可以获取公网ipv6地址,依然是大家各凭本领,笔者这里使用ip -6 addr show获取Ubuntu的ipv6地址。

需要注意的是,ipv6地址会有很多个,每个网口都有,标注global的才是公网的,有时候一个网口甚至会有两个global的ipv6地址,这两个地址有效期不同,一般来说无脑选第二个就行。

我们此处只有一个,就是[2408:8210:4810:55e0:8a39:b1ff:fe1b:8c0]。

拿到服务端的ipv6地址后,需要创造一个远程环境的客户端,我们可以找一台笔记本,连接手机的热点,热点一般都是支持ipv6的。

接下来可以用大名顶顶的ping指令从客户端ping一下服务端的ipv6测试连接性,笔者这里直接使用windows cmd,试试能不能ping通,不能的话就检查光猫和路由器的防火墙配置,理论上不可能不能。

可以看到笔者这里很顺利地ping通了。

接下来使用curl指令测试“地址:端口号”看能否通,地址就使用刚才的ipv6地址,端口号使用gitea提供服务的端口号即可,如果没通就使用curl -v 地址:端口号看停在哪一步。

可以看到笔者这边也curl通了,直接打印出了html代码,如果curl不通的话会显示超时之类的。

读者们此时不通可以再回局域网或者服务器内,测试在局域网环境下通否,如果也不通的话,可以在服务器命令行检查端口是否在listen,理论上之前局域网可以成功打开gitea网页的话应该不会没listen。

可以使用netstat -aon | grep 端口号来查看端口监听情况。

可以看到笔者这里有一条进程在listen[:::3000],这表示任意ipv6来的访问3000端口的指令会发到此进程,相应的”0.0.0.0:3000“则表示ipv4的访问,这个后面会用到。

如果局域网能curl通,远程不通的话一样检查防火墙配置。

curl能通就可以直接用浏览器访问ipv6:端口号了。

到这一步就可以实现最简单的远程访问服务了。

接下来是ipv4,因为有些用户的网络比较老旧,光猫默认没有开启ipv6支持,所以如果我们仅仅实现ipv6的远程访问是很难满足大部分需求的,但笔者提前提个醒,想要开通ipv4的远程访问需要社交,有社恐的朋友可以退下了

首先需要拿到你的宽带账号和密码,备用,方式根据运营商各不相同,教程很多,大家依然各凭本事,实在看不到密码也可以后面直接问对接的运营商工程师。

接着联系你的宽带运营商客服,说要申请公网ip,注意动态的就可以,不需要固定的ip地址,一般是免费的,问你用途你就说智能家居需要远程访问,然后会安排工程师给你远程开通,此时不知道宽带密码的记得问清楚,最好让工程师远程把你的光猫设置成桥接模式,你自己就不需要设置光猫了。

否则的话就要想办法拿到你光猫的管理员密码(这个也是各凭本事,而且工程师不一定愿意告诉你,实在不行就去海鲜市场买),然后自己直连光猫的wifi或者lan口来修改成桥接。

注意申请开通之后你本地会连不上公网,有什么需要准备的最好提前准备一下。

然后连接你的路由器或者ac控制台,开启pppoe拨号上网,输入刚才的宽带账号和密码,保存,应该就恢复公网连接了。

笔者这里没有现成的图,用之前手机拍的老图支撑一下,读者们见谅。

此时如果公网没有恢复,首先尝试断电重启光猫和路由器,还不行的话首先看路由器是否插在光猫lan1口,有些桥接设置会强制lan口,一般是lan1口。

还不行的话就找台笔记本,用网线直连lan1口,打开“网络和共享中心”->“设置新的网络”尝试用笔记本直接pppoe拨号,如果可以成功接入,就检查路由器配置,如果不行的话,就看笔记本这边的错误提示,笔记本这边pppoe拨号失败会有错误提示的,比如密码错误之类的。

局域网内恢复公网连接之后,你的设备应该就已经分配到公网ipv4地址了。

使用curl ipinfo.io/ip获取一下ipv4的地址试试看。

可以看到我已经拿到我当前的公网ip地址了。

因为是公网地址,所以现在远端也可以ping到此地址了,切换到远端ping一下试试。

很好ping成功了。

读者们ping不通一样检查防火墙。

不同的是,一般由于路由器配置,ipv4不能直接访问部分端口,所以现在直接curl是curl不通的,需要在路由器做一下端口转发。

端口映射相当于是快递邮寄,距离比较远的时候不可能从商家下单后直接一路送到你家,都需要经过一些快递集散点,比如从浙江某县城买东西买到河北某县城,可能就要先到杭州某集散点,再到北京某集散点,再发往县里。端口映射也类似,公网上的协议,要发到你的服务器,都要先到你家的路由器,协议到你家路由之后,就可以做一些操作,比如公网协议本身使用的是12345端口,路由内提前设置了端口映射,默认当ip是你的服务器ip时,把所有到12345的协议转发到23456端口,你的服务器就会接收到来自23456端口的访问。

此处需要配置这个端口映射并不是为了改变端口,而是因为我的路由的ipv4访问因为防火墙的原因所有端口都不通,只能通过端口映射绕过,我不确定是不是路由都是这样的。

配置好端口映射之后,使用外部端口号访问,就可以curl通了。

笔者此处curl通的打印和读者应该不同,因为笔者现在已经配置好了反向代理,所以直接用域名访问不到想要的服务了,故会打印出404,但只要打印出html代码,就说明ping通了。

curl不通的话一样是用-v查看一下停在哪了,然后自己想办法,经历了这么多我相信你有这个能力了。

curl通之后应该就可以浏览器用ip地址+端口号访问了。

需要额外注意的是,80、443和8080端口从公网是没办法直接访问到内网的,因为政策要求,运营商屏蔽了国内机器的这三个端口,所以在配置端口映射时,不要把外部端口配置成这三个端口,因为发给这三个端口的协议在默认情况下是没法从公网到你家路由的。

域名解析+反向代理

到此为止我们已经可以用ip+端口的方式使用我们架设的服务了,但是我们在访问自己的服务时,都需要通过ip和端口这些数字,几个服务还好,服务多了端口真的很难记忆,所以最好通过类似端口映射的机制,让我们能用容易记忆的字符串来替代ip,端口最好能够统一甚至省略。

首先解决域名,总算到了买买买环节,读者直接去各大域名服务商购买即可,笔者这里使用的是腾讯云平台,因为比较习惯(虽然很奸商),com顶级域名大概是83块钱一年。

需要注意的是购买域名后需要实名认证之类的环节,需要一定的时间,当域名状态显示为正常可使用时才能继续。

至于如何实现域名到ip地址的映射,主要是通过dns服务器的解析,一般域名服务平台都提供免费的解析服务。

不过入口可能看起来比较隐蔽,因为高级动态解析之类的服务是收钱的,就会比较显眼。

点击解析界面的添加记录按钮,增加两条记录分别用来指向我们的ipv4地址和ipv6地址

注意ipv4的记录类型是A,ipv6的是AAAA,TTL是指修改后多久生效,保持默认就可以。

解析大概需要10分钟左右的时间,解析完成后,就可以用域名+服务端口号的方式直接访问服务了。

那么如何把端口号也统一一下呢?

这就到反向代理的领域了,反向代理有点类似在你的设备网口和你的服务之间,又加了一层软件路由,它可以实现把对“不同域名+相同端口”的访问,转发给当前设备下的不同端口,即使这不同的域名指向的是相同的ip地址。

Nginx就是常见的用于实现反向代理的web服务器实现之一,而OpenResty则是基于Nginx进一步封装和扩展的web服务器实现,此处我们就选择使用最新潮最酷炫的OpenResty。

依然是在docker中构造OpenResty的容器,此处注意OpenResty的开放端口,应该是路由器通过端口映射中配置的“内部端口”,从而实现“公网->路由器->OpenResty->服务”的协议转发顺序,我这里依然使用1panel安装,端口就保持默认的80/443端口。

OpenResty启动完成之后,就可以开始配置反向代理了,很巧啊,1Panel也有方便的配置工具,非1Panel用户没关系,也可以直接连接到docker容器去配置,也不复杂。

点击网站->网站->创建网站,打开配置界面。

如下图配置后点击确定,反向代理就配置完成了。

反向代理配置完成后,就可以使用域名+反向代理中配置的端口号来访问服务了,从而实现不同的服务能够统一端口,只通过区别三级域名的方式来访问服务了。

赶紧把你的服务分享给小伙伴们一起玩耍吧。

增值效果

接下来介绍一些可以进一步提升体验的操作~

ddns

因为我们使用的是免费的公网ip服务,ip是会动态变化的,但手动解析的配置方式不会自动更改解析的ip地址,所以当ip发生变化时域名解析就会失效,为了解决这个问题我们可以在服务器上跑一个ddns服务,它可以在ip发生变化时自动更新dns服务器的解析地址。

不过当然每次ip发生变化的时候域名还是会失效十几分钟这就是免费的代价

此处推荐使用的是DDNS-GO服务。

隐藏端口号

使用默认端口号可以实现隐藏端口访问的效果,http是80,https是443。

但由于政策要求,接入国内运营商的服务器默认封锁了80、443和8080三个端口,所以我们没法简单的完全省略端口实现纯域名访问,只能通过绕过端口封锁的方式,比如通过开放端口的云服务器转发消息,或者内网穿透等方式,但是这些方式都对流量和带宽有限制,很难无上限的跑满服务器的带宽上限,体验效果都不如直接解封端口。

关于这个我咨询了联通的客服,个人家庭服务器想要开通这三个端口,需要有固定的公网ip,走企业资费的宽带,并且要去公安局申请备案,才能解封,有条件的可以自己探索下。笔者钱袋空空,就不尝试了。哭

防火墙

为了防止公网用户访问到我们不希望暴露到公网的服务,可以通过防火墙来限制端口访问,只把想要暴露到公网的端口放开访问,比如openresty的对外端口。

大家根据自己的系统选择防火墙即可。

Gitea开启电子邮件功能

开启Gitea的电子邮件功能可以增强平台的安全性,并且能够提供一些及时的通知。

开通这个功能并不需要自建服务器,因为实际上gitea只使用电子邮件的发送功能,而不接收邮件,所以可以直接使用现在市面上很多服务商邮箱的SMTP功能,以下拿腾讯邮箱举例。

首先需要在QQ邮箱里开启smtp功能,点击QQ邮箱设置里的“账号与安全”

在弹出来的界面点击安全设置,并开启SMTP服务,同时生成一个授权码备用。

接下来就可以往gitea的设置里填配置了。

主机地址:smtp.qq.com

端口:465或者587

电子邮件发件人:你自己的QQ邮箱

用户名:你的QQ号

密码:刚才生成的授权码

最后根据需要勾选你需要的邮件功能即可~

结语

作为一个菜鸡,第一次这么大规模的部署网络服务,真的是一路踩了各种坑,进一步感受到了自己有多菜,不过能成文一篇帮助读者们也算是倍感欣慰,希望大家可以一起努力,继续学习!


评论