1. 背景

作为一名移动开发人员,缺少对于整个网站开发技术栈的系统认知。因此想通过在阿里云搭建个人网站,从而熟悉从前端到后端一整套技术栈。同时也希望可以在自己的服务器上搭建一个用于系统梳理技术、生活、爱好等方方面面的个人知识库,既是记录也是分享,如果可以在服务器上做些好玩的东西更好了:)

2. 服务器

服务器的选择上面没有做太多调研,首选了国内云服务器领域的老大阿里云,27年3月31日前可以99元/年的价格租用一台2C2G的ECS云服务器,续费同价(具体规则详见官方99套餐活动)。

2.1 购买说明

ecs_buy

选项说明:

  • 地域:页面中已注明“不同地域的实例之间内网互不相通;选择靠近您客户的地域,可降低网络时延、提高您客户的访问速度。”,因此我直接选择了所在城市杭州。
  • 可用区:可用区是指在同一地域内,电力和网络相互独立的物理数据中心,一个地域通常包含多个可用区。可以简单理解为不同的物理机房,对于多机高可用部署需要考虑选择不同的可用区,但是我的个人网站场景只是单机部署,所以默认随机分配即可(购买后可以看到分配的可用区是什么)。
  • 实例规格:99元固定不可调整
  • 镜像:99元只能选择“操作系统”类型(“云市场镜像”是阿里云在服务器上预先安装了一些环境,并且价格会有所增加),作为以个人网站搭建为目的,直接选择默认的Alibaba Cloud Linux 3了(购买后可以更换系统盘)
  • 其他:99元固定不可调整

2.2 基础配置

2.2.1 密码/密钥对

创建实例时不会自动创建密码/密钥对,因此如果使用本地SSH工具连接,需要先手动创建密码或密钥对。(备注:使用管控台Workbench连接无需创建)

创建密码

  1. 实例管理页面“重置密码”入口

reset_pw

  1. 输入密码后选择“在线重置密码”无需重启实例即可生效

reset_pw

创建密钥对

  1. 密钥对登录方式更加安全,可从管控台左侧“全部菜单”入口找到密钥对设置入口:

reset_secret_1

  1. 选择“创建密钥对”,输入密钥对名称即可,资源组和标签可留空:

reset_secret_1

  1. 完成上一步创建后浏览器会自动下载私钥文件(妥善保存,丢失后无法再次下载),下载到本地的私钥文件可添加到本地SSH工具中用于登录使用,Termius添加私钥示例:
    1. 进入“Keychain”列表
    2. 点击“Key”按钮创建新的密钥
    3. 从本地私钥文件导入

reset_secret_1

  1. 上一步是在本地SSH工具中添加私钥,这里需手动将密钥对和实例进行绑定(将公钥添加到实例中):

reset_secret_1

备注:完成密钥对全部配置流程后,可登录实例使用如下命令查看实例中的公钥:

# 输出 authorized_keys 文件内容
cat /root/.ssh/authorized_keys
  1. 左侧勾选需要绑定密钥对的实例并点击向右移动按钮,下一步完成绑定:

reset_secret_1

  1. 确认绑定操作后重启实例即可通过密钥对方式进行登录:

reset_secret_1

安全建议

建议使用密钥对登录而非密码登录,可通过修改sshd_config配置文件中PasswordAuthentication配置为no来禁用密码登录:

# 使用 vi 编辑 sshd_config 文件
vi /etc/ssh/sshd_config

2.2.2 安全组

  1. 实例创建完成后默认配置了三个安全组,RDP 远程连接(3389端口)、SSH 远程连接(22端口)和ICMP报文(例如 ping 命令)

safe_address_1

  1. 三个安全组均允许任何位置的来源访问实例,为了保障实例安全,需要将 RDP 远程连接(3389端口)和 SSH 远程连接(22端口)的访问来源限制为自己本地 IP(支持添加多个入方向规则实现添加多个本地 IP ):

safe_address_1

2.3 Nginx

2.3.1 安装

# Alibaba Cloud Linux 系统需要使用 yum 命令安装
yum install -y nginx

# 查看 Nginx 版本
nginx -v

2.3.2 启动

# 设置开机自启
systemctl enable nginx

# 启动 Nginx
systemctl start nginx

# 查看 Nginx 状态
systemctl status nginx

# 检查 Nginx 是否正常运行,应该看到 Nginx 默认欢迎页面
curl http://localhost

2.3.3 部署

  1. 本地打包
# 进入构建输出目录
cd ./docs/.vitepress/dist 

# 打包所有文件
# -c :核心参数,全称 --create,创建一个新的压缩包 / 打包文件
# -z :核心参数,全称 --gzip,使用 gzip 压缩算法进行压缩
# -f :核心参数,全称 --file,指定要创建的压缩包文件名
tar -czf vitepress-dist.tar.gz *
  1. 服务器创建目标文件夹,通常建议静态资源存放在/var/www/xxx目录下
# 递归创建目录
mkdir -p /var/www/wiki
  1. 上传vitepress-dist.tar.gz到服务器,可使用SCP/SFTP/图形化工具,以Termius为例:

vitepress_dist_1

  1. 解压构建文件到目标目录
# 进入部署目录
cd /var/www/wiki

# 解压文件
# -x :核心解压参数,全称 --extract 或 --get,执行解压操作
# -z :核心格式参数,全称 --gzip,解析 gzip 格式的压缩包
# -f :核心指定参数,全称 --file,指定要操作的压缩包完整路径
tar -xzf /var/www/vitepress-dist.tar.gz

# 查看解压后的文件
ls -la

# 删除压缩包(可选)
rm /var/www/vitepress-dist.tar.gz

2.3.4 配置

  1. 创建站点配置文件
# 创建配置文件
vim /etc/nginx/conf.d/wiki.conf

配置文件示例:

server {
    listen 80;
    server_name _;  # 使用 IP 访问,如果有域名则改为你的域名
    
    # 网站根目录
    root /var/www/wiki;
    index index.html;
    
    # 字符集
    charset utf-8;
    
    # 访问日志
    access_log /var/log/nginx/wiki-access.log;
    error_log /var/log/nginx/wiki-error.log;
    
    # 主要路由配置
    location / {
        try_files $uri $uri/ /index.html;
    }
    
    # 静态资源缓存配置
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    location ~* \.(css|js|woff|woff2|ttf|eot)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    
    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript 
               application/json application/javascript application/xml+rss 
               application/rss+xml font/truetype font/opentype 
               application/vnd.ms-fontobject image/svg+xml;
    
    # 禁止访问隐藏文件
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

注意:/etc/nginx/nginx.conf配置文件默认的server配置块监听了80端口且配置了server_name _;,因此在没有域名的情况下wiki.conf里面也监听80端口且配置了server_name _;会与默认配置冲突,需要删除或注释掉/etc/nginx/nginx.conf配置文件默认的server配置块。

  1. 测试并重启Nginx
# 测试配置文件语法
nginx -t

# 如果测试通过,重新加载配置
systemctl reload nginx

# 或者重启 Nginx
systemctl restart nginx

# 查看 Nginx 状态
systemctl status nginx
  1. 完成以上操作后使用 vitepress 构建的静态页面就部署到 Nginx 上了,可以通过云服务器实例的公网 IP 进行访问

ip_wiki

3. 域名

域名我是直接在阿里云上面购买的,想着服务器和域名都在阿里云购买省事点,不需要在多个平台管理这些东西。

注意:只有列入域名后缀列表中的域名才可以进行ICP备案

3.1 购买说明

  1. 注册域名需要使用信息模板,信息模板需经过阿里云和注册局的审核,创建信息模板示例:

domain_1

  1. 信息模板创建完成后阿里云审核就会通过,需要等待注册局的审核结果(我是周日下午5点提交,5点5分就审核通过了,速度还是很快的):

domain_2

  1. 支付订单完成购买

domain_3

3.2 DNS解析

域名注册完成后需要添加解析才能让域名执行服务器:

  1. 添加A类型记录指向服务器公网IP,对于我只有一台服务器(一个公网IP)的情况下,所有记录都指向这台服务器公网IP即可:
    1. 记录类型:A
    2. 主机记录:添加一条“@”和一条“*”即可,满足主域名和所有二级域名解析
    3. 解析请求来源:默认
    4. 记录值:服务器公网IP

domain_4

  1. 添加完成后可通过如下命令验证DNS解析结果,如果可以在输出结果中看到服务器IP说明解析成功(此时还无法通过域名访问服务器,需要先完成ICP备案):
nslookup your-domain.com

4. 备案

国内服务器需要ICP备案通过后才可以通过域名访问,因此下一步需要准备相关材料提交ICP备案申请。

4.1 基础信息校验

基础信息主要包括需要备案的网站/App信息和个人信息,如实填写即可:

beian_0

4.2 填写主办者信息

主办者信息主要包括身份证件、地址等信息:

beian_1

4.3 填写互联网信息服务

  • 网站名称:备案对网站有些要求,很多人建站可能是为了搭建博客,但是“博客”字样是不能出现在网站名称中的。等等还有一些其他要求,可以把要求贴给AI,让AI生成一个名称。或者自己想一个名称,然后让AI根据要求判断是否符合规范。
  • 其他信息:如实填写即可

beian_2

4.4 上传图片资料

主要是身份证正反面照片和人脸识别信息:

beian_3

4.5 提交订单

确认信息无误后提交备案订单即可

beian_4

4.6 等待备案结果

  1. 首先是阿里云初审,整体还是比较快的。我是中午提交的审核,下午初审就通过了。中间有个小插曲,提交审核后阿里云多次发送短信通知备案审查员电话联系不上我,后面莫名其妙的又接到的审查电话。

beian_5

  1. 阿里云初审通过后就是等待管局审核了,各地审核速度不一样,浙江审核速度参考:

beian_6

5. DNS解析

完成ICP备案后就可以做DNS解析了,把域名解析到服务器IP。注意:ICP备案后还有一个公安联网备案,公安联网备案是网站开通后的法定义务,而非 DNS 解析或网站访问的前置条件,所以网站搭建全部工作做完后再去做公安联网备案就可以了。

  1. 云解析DNS管控台,进入“解析设置”

dns_1

  1. 选择“添加记录”(解析记录)

dns_2

  1. 记录类型选择A记录,对于只有一台服务器的情况,主机记录选择“@”和“*”即可满足所有一级二级域名解析到服务器

dns_3

  1. 记录值输入服务器的公网IP

dns_4

  1. 完成“@”和“*”两条记录添加即可

dns_5

  1. 验证解析结果,通过域名访问(还没有配置SSL证书,所以只能通过http协议访问,无法通过https协议访问)

dns_6

6. SSL证书

6.1 证书申请

阿里云提供免费版SSL证书(个人测试证书)申请,证书有效期3个月

  1. 进入“数字证书管理服务”控制台,左侧进入“SSL证书管理”菜单,选择“个人测试证书”,点击“立即购买”按钮

ssl_1

  1. 确认证书信息(只能购买20个免费证书,因此只能用于20个域名),立即购买即可

ssl_2

  1. 购买完成后需要创建证书,域名名称添加二级域名即可,会自动赠送三级域名“www.xxx.xxx”证书。勾选“快捷签发”,添加联系人和所在地提交审核即可

ssl_3

  1. 状态进入“申请审核中”,等待CA中心审核证书

ssl_4

6.2 证书部署

CA中心审核大概1个小时内就会完成,审核通过后阿里云会自动为域名添加TXT记录

ssl_5

TXT记录添加完成后还需要下载证书部署到服务器上,从而才能通过https协议访问服务器

  1. 从管控台下载证书,根据服务器类型下载对应格式的证书

ssl_6

  1. 服务器上为Nginx创建证书目录
# 逐层创建文件夹,已存在则忽略
mkdir -p /etc/nginx/cert
  1. 上传证书到服务器证书目录下

ssl_7

  1. 修改Nginx配置文件,参考示例如下:
# 1. HTTP 自动跳转 HTTPS
server {
    listen 80;
    server_name wiki.xxx.xxx;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name wiki.xxx.xxx;

    # ======================= 证书配置 =======================
    ssl_certificate /etc/nginx/cert/wiki.xxx.xxx.pem;
    ssl_certificate_key /etc/nginx/cert/wiki.xxx.xxx.key;
    ssl_session_cache shared:SSL:1m;
    ssl_session_timeout 5m;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    # ======================= 基础配置 =======================
    root /var/www/wiki;
    index index.html;
    charset utf-8;
    access_log /var/log/nginx/wiki-access.log;
    error_log /var/log/nginx/wiki-error.log;

    # ======================= 安全响应头(可选) =======================
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;

    # ======================= 静态资源缓存(可选优化) =======================
    location ~* \.(jpg|jpeg|png|gif|ico|svg|webp)$ {
        expires 1y;
        etag off;
        add_header Cache-Control "public, immutable";
    }

    location ~* \.(css|js|woff|woff2|ttf|eot)$ {
        expires 1y;
        etag off;
        add_header Cache-Control "public, immutable";
    }

    # ======================= index.html 禁止缓存(可选) =======================
    location = /index.html {
        expires -1;
        add_header Cache-Control "no-cache, no-store, must-revalidate";
        add_header Pragma "no-cache";
        add_header Expires "0";
    }

    # ======================= 路由兜底 =======================
    location / {
        try_files $uri $uri/ /index.html;
    }

    # ======================= Gzip 压缩(建议移到nginx.conf的http块) =======================
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css text/xml text/javascript
               application/json application/javascript application/xml+rss
               application/rss+xml font/truetype font/opentype
               application/vnd.ms-fontobject image/svg+xml;

    # ======================= 禁止访问隐藏文件 =======================
    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}
  1. 重启Nginx
# 测试配置文件语法
nginx -t

# 如果测试通过,重新加载配置
systemctl reload nginx

# 或者重启 Nginx
systemctl restart nginx

# 查看 Nginx 状态
systemctl status nginx
  1. 使用https访问服务器,大功告成

ssl_8