文章

服务器折腾记

之前我一直有一台阿里云的学生机。忘记了是因为什么原因以几乎免费的价格白嫖了三年。主要用来跑一跑小网页,和爬虫什么的。大学中期变懒了,后面更是考研究生去了,基本上就搁置了。就是毕设的时候拿出来展示了一下成果。

工作以后又一直插了flag,说要等自己的mio blog框架写出来了再统一部署各种服务和博客。本来预期是打算在21年的十一竣工的。但是后来又突发奇想,想要把各种爬虫集成进去。又集成了一堆工具链和持续集成的一些功能。甚至手写了半个mdhtml。可以说是非常sb了。

最后最后一直到22年春节被隔离了才完全写完。调bug又调了几天。最后发现写出了一个性能、拓展性都很差的玩具。前端还贼丑。。。和一些通用的博客、爬虫主控、持续集成平台比起来更是没得比。最后就放弃幻想,采用了一些主流的技术栈。。。

技术选型

云服务器:在阿里云和腾讯云之间纠结了很久。最后选择了之前买的2c4g的腾讯云。主要是部署的应用比较简单,没必要使用全套阿里云的方案。

部署方式:最开始因为自己的玩具主控容器化非常麻烦而选择裸部署,后面考虑到安全性和一些易用性方面的考虑,还是选择了docker。同时也能好好学习docker

对外端口:本来出于懒的考虑,打算直接暴露docker的端口到外网。后来考虑到看上去太过于野鸡了,加上暴露外部端口也不是件好事。

反代:有朋友推荐了caddy,看了一眼确实挺方便的,和lets encrypt的集成性也挺好的。但是最后考虑到了nginx用的更加普遍些,配置也更自由点,选择了nginx

ssl:因为早年ssl证书比较麻烦,同时比较贵,形成了某种刻板影响。所以前期完全没有考虑这个,后期部署了博客以后觉得左上角不安全三个字太扭曲了打算部署的时候别的东西都部署的差不多了,只能选择阿里云的免费单域名证书,加上手动配置nginx。其实应该选择集成了lets encryptnginx插件的,因为只是需要一个https的加密功能,并不需要证书和对应的解析记录证明我不野鸡。因为证明一只野鸡不野鸡这件事本身就挺搞笑的。。。同时避免了每年更新证书。

博客:考虑到技术洁癖,首先排除了world press,这玩意商业化程度太高,不喜欢。在hexohugohalosolo纠结了一会。排除了静态界面生成器,这个的自动化程度不够,也没什么好的后台生态。halosolo选了会,还是选择了生态还行的halo(其实也不太行,主题太少)。

影音服务器:开源的只能选jellyfin

btaria2 pro + ariang,通用方案不说了。

私人云+简易文件管理:file browser,之前用的比较习惯。

docker运维:本来觉得逼格不够,但是鼠标点点点实在是太方便了。推荐portainer

此外推荐一波zshvscode ssh插件。福音,真的是福音。有gui坚决不用命令行,用也得用zsh,比bash好太多了

域名解析

首先选择使用我的intmian域名。为了和之前的阿里云系列做区分,使用tencent.intmian.com解析到我的腾讯云服务器。主要用来解析和ping和远控时不用输ip。耦合性小一点。

同时分配各个服务使用对应的三级域名*.ten.intmian.com,使用一个cname解析到tencent.intmian.com。最后给我的博客地址www.intmian.comCNAME解析到它实际的地址blog.ten.intmian.com。个人觉得还挺井然有序的。试了一下套娃对解析速度没有啥影响。

image.png

服务的部署

本来打算用一个docker compose起所有的云服务的。但是因为需要写一些docker命令所以还是写了一个比较繁琐的shell

端口的划分

防火墙只开放80、443、20001-20010这几个端口。

http请求统一通过80、443反代到内部的10001-10010,20001-20010主要负责一些tcp连接,例如bt的DHT之类的。

反代

最先需要解决的就是多主机头的反代。因为一些设计上的问题,所以采用了一些不特别优秀的方法。

申请www.intmian.com的对应证书,注意一下下载下来的时候前面带一串hash,改成服务对应的名字例如 blog.key blog.pem 就好了。新建一个/data/nginx/ssl目录存放,同时准备好对应的nginx配置conf.d,存放在/data/nginx下面。conf.d可以参考我写的。

client_max_body_size 10m

server {
        listen       80;
        server_name  media.ten.intmian.com;

        location / {
            proxy_pass http://127.0.0.1:10001;
        }
    }

server {
        listen       80;
        server_name  docker.ten.intmian.com;

        location / {
            proxy_pass http://127.0.0.1:10002;
        }
    }

server {
        listen       80;
        server_name  cloud.ten.intmian.com;

        location / {
            proxy_pass http://127.0.0.1:10003;
        }
    }

server {
        listen       80;
        server_name  download.ten.intmian.com;

        location / {
            proxy_pass http://127.0.0.1:10004;
        }
    }

server {
        listen       80;
        server_name  blog.ten.intmian.com;

        location / {
            proxy_pass http://127.0.0.1:10005;
        }
    }

server {
        listen       80;
        server_name  www.intmian.com;

        location / {
            proxy_pass http://127.0.0.1:10006;
        }
    }

server {
        listen       443 ssl;
        server_name  blog.ten.intmian.com www.intmian.com;
        root         /usr/share/nginx/html;
        ssl_certificate      /ssl/7211651_www.intmian.com.pem;
        ssl_certificate_key  /ssl/7211651_www.intmian.com.key;
        ssl_session_timeout  5m;
        ssl_session_cache    shared:SSL:1m;
        ssl_ciphers          ECDHE-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 / {
                proxy_pass http://127.0.0.1:10006;
            }
    }

注意一下这里有个坑爹的问题,nginx的默认请求头最大为1M,这个就很坑了,如果有什么服务需要上传大文件的话要和我第一行那样进行对应的配置。如果不需要全域配置可以配到server块里面去。

之后就是启动nginxdocker,这里需要注意的是。docker网络有四种种方式可以选择。

第一种是nginx 配上 -net = host,这样的话可以直接当物理的nginx

第二种是先自定义一个网络,需要反代的dockernginx全部通过-net挂在这个网络上,nginx映射443、80进来,别的服务就映射非http的。

第三种是使用链接,这个块废弃了不使用。

第四种是使用docker的虚拟网卡通信,docker里面可以使用别的docker的名字作为主机名来解析出虚拟ip。有过局域网nginx反代经验的老哥一定很熟悉。但是这个方法我尝试一直失败,遂罢。

建议第二种,各方面最优秀了。

启动nginx docker,配好网络并映射ssl证书和配置进去,一般就没问题了。

最后要注意nginx启动的时候,你映射进去的配置不一定会生效,保险起见配完执行一下。不然到时候有问题,一通定位还得依附进docker来各种调试。。。

sudo docker exec -it mynginx service nginx reload

文件夹划分

我的存储结构基本如下

  • /data 主目录
    • nginx nginx配置
      • ssl ssl证书放在这
    • jellyfin 配置放着,方面迁移之后不用配环境了
    • download 下载数据
    • media 影视库
    • halo 博客配置,方面迁移之后不用配环境了

私人云映射整个/data文件夹,方便进行运维操作,真的比输命令行使用vim方便太多了。。。

media映射进jellyfin,电影电视剧就放这了。

download映射进aria2

halo映射博客的主文件夹。

别的通通不映射出来,因为没啥交互。

服务

放一下docker语句,说起来多亏了runlike这个工具,反推出docker语句太难了。这个是最早版本的shell,后面有改动的。

此处有个坑,docker映射文件夹挺多不支持的,建议多看看提示。

同时注意下,如果映射的外部端口不一致的话,建议看看对应镜像的部署指南,将外部实际开放端口配进去,不然容器可能发送给别人错误的可连接端口。。。

有些自己的服务,配置里面我就删掉了,aria2我后来加了密码,就不提了。ariang的配置存在浏览器的,记得对应配下。

如果配置一般的话,建议使用docker调度的一些参数,分配cpu、内存。

# 1xxxx 内部端口 2xxxx外部端口
sudo docker run \
        --name=media \
        --volume= /data/jellyfin/config:/config \
        --volume= /data/media:/media \
        --volume=/cache \
        --volume=/config \
        --volume=/media \
        -p 10001:8096 \
        --detach=true \
        jellyfin/jellyfin


sudo docker run \
        --name=aria2-pro \
        --volume=/data/aria2-config:/config \
        --volume=/data:/downloads \
        --volume=/config \
        --volume=/downloads \
        --workdir=/ \
        -p 20001:6800 \
        -p 6888:6888 \
        -p 6888:6888/udp \
        --detach=true \
        p3terx/aria2-pro

sudo docker run \
        --name=filebrowser \
        --volume=/data:/srv \
        --volume=/srv \
        -p 10002:80 \
        --detach=true \
        filebrowser/filebrowser

sudo docker run \
        --name=ariang \
        --workdir=/ \
        -p 10003:6880 \
        --detach=true \
        p3terx/ariang \

sudo docker run \
        --name=prtainer \
        --workdir=/ \
        -p 10004:9000 \
        --restart=always \
        --detach=true \
        portainer/portainer

docker run \
        --name=mynginx \
        --hostname=mianserver \
        --volume=/data/nginx:/etc/nginx \
        --network=host \
        -p 80:80 \
        --detach=true \
        nginx \

docker run -it --name teamcity-server-instance  \
    -v /data/teamcity:/data/teamcity_server/datadir \
    -v <path to logs directory>:/opt/teamcity/logs  \
    -p 10005:8111 \
    jetbrains/teamcity-server

本地服务器

部署完云服务器,我就发现他的硬盘太小了。加上各种原因。我就给我的笔记本装上linux,插上网线,装成服务器了。主要是有几个坑点。

一就是我虽然有公网IP但是会变,因此本地部署了一个自己写的ddns,映射了local.intmian.com到本地。同时建议各位放弃反代然后通过三级域名区分服务,因为屏蔽80、443的,输端口号的话,就没必要费心思配了。

二就是无线网卡。ubantu使用无线的话,内网速度只有20Mb,甚至没有我外网速度的十分之一快。这个是驱动问题,挺难解决的。

三就是端口映射。首先确认你是电信,你有公网ip,之后需要完整映射到外网。例如我的外网时local.intmian.com。光猫ip192.168.1.1.1局域网里路由器ip192.168.1.2,.2局域网网关为192.186.2.1就是192.168.1.2,服务器开放端口为10086。此时配置192.186.2.1的外部端口10086转发到192.168.1.210086.配完这一步确认下192.168.1.2``:10086是否通的了。此时注意192.186.2.1:10086是不通的,不懂得看下原理就好了。如果你使用小米路由器,千万别忘了保存并生效。。。。之后将光猫配端口映射到192.168.1.210086,此时记得配完保存完重启光猫。某些版本的光猫它虽然没写但是就是这么坑。。。此处又引发两个坑点:1. 某些光猫的端口映射是假的,这里建议电话电信客服改桥接,然后里面接个路由器。光猫的性能太垃圾了,总是死机,任何时候都建议这么做。2. 此时注意理论上你的local.intmian.com是能一路穿透进来的,但是你在内网是完全不能用local.intmian.com:10086访问的,使用telnet或者tcping完全不通的,这个不要慌。。。这个很神奇而且太坑了,但是不知道为什么。同时手机移动4g网络访问的速度极为拉跨,同时不能跑满宽带的理论上行。外网的宽带可以跑满,但是延时比较高。但是无论如何都比各种frp好得多。

最后屏蔽显卡时,待机大概20w,一天0.6度电,完全可以接受,偶尔还能用向日葵满足出差需求,蛮好的。

后记

建议家里还是群晖完整一套好了,什么都不用折腾。

如果不想开启telnet或者安装telnet污染环境,建议使用我开发的tcping工具,我的github主页就有。打个小广告哈哈哈。

这篇博客是下班回家有点无聊写的。写到一半就想打游戏了,所以写的比较潦草、急躁。还望见谅哈,有空的话会好好校对一遍的。

License:  CC BY 4.0