CS 教程 · 第 16 章

搭建个人网站

域名 / 服务器 / Nginx / HTTPS

学习目标: 从零到一搭建一个可以通过公网访问、带HTTPS的个人网站,掌握域名、服务器、Nginx、证书配置的全流程。

16.1 整体架构概览

在动手之前,先理解一个网站是如何工作的:

用户浏览器
    │
    ▼ ① 输入 yourdomain.com
DNS服务器 ──▶ 返回服务器IP地址
    │
    ▼ ② HTTPS请求
云服务器(ECS)
    │
    ▼ ③ Nginx接收请求
    ├── 静态文件 → 直接返回HTML/CSS/JS
    │   (yourdomain.com)
    │
    └── API请求 → 转发给后端
        (yourdomain.com/api/* → Flask:5000)

本章我们分步骤实现上面这个架构。


16.2 域名注册与DNS配置

选购域名

推荐域名注册商:

平台 优点 价格参考
Namesilo 海外最便宜,送免费WHOIS隐私保护 .com约$10/年
Cloudflare 成本价(不加价),自带CDN和DDoS防护 .com约$10/年
阿里云(万网) 国内最方便,备案流程完善 .com约¥55/年
腾讯云(DNSPod) 国内性价比高 .com约¥55/年

选域名建议:

🔒 国内特殊要求: 使用国内服务器需要备案,而备案的前提是域名已经实名认证。实名认证通常需要1-3个工作日。

DNS配置

DNS(域名系统)就是电话簿——把域名翻译成IP地址。

常见DNS记录类型:

A记录     域名 → IPv4地址       yourdomain.com → 123.123.123.123
AAAA记录  域名 → IPv6地址       yourdomain.com → 2001:db8::1
CNAME     域名 → 另一个域名      www.yourdomain.com → yourdomain.com
MX        邮件服务器记录         → 用于配置邮箱
TXT       文本记录              → SPF/DKIM(邮箱验证)、域名验证

配置流程(以阿里云为例):

1. 进入域名控制台 → 解析设置

2. 添加两条记录:

`

记录类型: A

主机记录: @ (表示根域名 yourdomain.com)

记录值: 你服务器的公网IP

记录类型: A

主机记录: www

记录值: 你服务器的公网IP (或CNAME到@)

`

3. 等待DNS生效(几分钟到几小时,可通过nslookup yourdomain.com验证)

💡 DNS修改后不会立刻全球生效,因为有TTL(缓存时间)。可以用 `dig yourdomain.com` 或 [DNSChecker.org](https://dnschecker.org) 查看全球传播状态。

16.3 云服务器选购

选哪家?

平台 适合人群 新用户优惠
阿里云 ECS 国内用户首选 经常有百元/年活动
腾讯云 CVM 国内性价比 学生优惠不错
AWS Lightsail 海外用户/学AWS $3.5/月起步
Vultr / DigitalOcean 海外便宜VPS $6/月起

入门配置建议: 1核CPU + 1-2GB内存 + 40GB SSD,足够支撑个人博客/小项目(月费约¥30-70)。

服务器初始配置

SSH登录后首先做安全加固:

# 1. 更新系统
apt update && apt upgrade -y

# 2. 创建普通用户(不要一直用root)
adduser deploy
usermod -aG sudo deploy

# 3. 配置SSH密钥登录(禁用密码登录更安全)
# 在本地生成密钥:
ssh-keygen -t ed25519 -C "my-server"
# 上传公钥到服务器:
ssh-copy-id deploy@your-server-ip

# 编辑SSH配置 /etc/ssh/sshd_config:
#   PasswordAuthentication no
#   PermitRootLogin no
#   Port 2222              (改端口减少扫描)
systemctl restart sshd

# 4. 配置防火墙
ufw allow 2222/tcp     # SSH
ufw allow 80/tcp       # HTTP
ufw allow 443/tcp      # HTTPS
ufw enable

16.4 Nginx安装与配置

Nginx是世界上最流行的Web服务器之一,以高性能、低资源消耗著称。

安装与基本命令

sudo apt install nginx -y

# 常用命令
sudo systemctl start nginx      # 启动
sudo systemctl enable nginx     # 开机自启
sudo systemctl status nginx     # 查看状态
sudo nginx -t                    # 测试配置文件语法
sudo nginx -s reload             # 热重载配置(不中断服务)

安装后浏览器访问 http://your-server-ip,看到Nginx欢迎页就说明成功了。

配置静态网站

Nginx配置文件在 /etc/nginx/sites-available/,启用时创建符号链接到 sites-enabled/

# /etc/nginx/sites-available/myblog
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;

    root /var/www/myblog;           # 网站文件根目录
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # 静态资源缓存(提升性能)
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }
}
# 启用配置
sudo ln -s /etc/nginx/sites-available/myblog /etc/nginx/sites-enabled/
sudo rm /etc/nginx/sites-enabled/default  # 删除默认配置
sudo nginx -t && sudo nginx -s reload

# 创建网站目录并放入文件
sudo mkdir -p /var/www/myblog
echo "

Hello World!

" | sudo tee /var/www/myblog/index.html

反向代理到后端API

当你有后端应用(如Flask运行在5000端口),Nginx作为反向代理:

server {
    listen 80;
    server_name yourdomain.com;

    # 前端静态文件
    root /var/www/myblog;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;  # SPA fallback
    }

    # API请求转发到Flask
    location /api/ {
        proxy_pass http://127.0.0.1:5000/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

16.5 HTTPS证书配置(Let's Encrypt)

🔒 没有HTTPS的网站,浏览器会标记为"不安全"。任何人(WiFi管理员、运营商)都可以看到甚至篡改你和网站之间的通信。

为什么选Let's Encrypt?

配置步骤

# 安装certbot
sudo apt install certbot python3-certbot-nginx -y

# 一键获取并配置证书(certbot自动修改nginx配置)
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

# 按提示操作:
# 1. 输入邮箱(用于证书到期提醒)
# 2. 同意服务条款
# 3. 选择是否强制HTTP→HTTPS跳转(建议选2:自动重定向)

完成后certbot自动修改Nginx配置,listen 443 ssl和证书路径都配好了。

验证自动续期:

sudo certbot renew --dry-run   # 模拟续期,确认一切正常
# certbot默认添加了cron/systemd timer,证书到期前30天自动续期

手动配置HTTPS + HTTP重定向(理解内部机制):

# HTTP → 强制跳转到HTTPS
server {
    listen 80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$host$request_uri;
}

# HTTPS实际服务
server {
    listen 443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate      /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/yourdomain.com/privkey.pem;

    # 现代SSL配置(安全评分A+)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HSTS:告诉浏览器"以后只走HTTPS"
    add_header Strict-Transport-Security "max-age=63072000" always;

    root /var/www/myblog;
    index index.html;
    location / { try_files $uri $uri/ =404; }
}

你可以用 [SSL Labs](https://www.ssllabs.com/ssltest/) 给网站评分,目标A+。


16.6 静态网站部署

方案对比

方案 适合场景 优点 缺点
Nginx直接托管 简单静态站 简单直接 无自动部署
GitHub Pages 开源项目/个人主页 免费+自动部署 仅静态,国内访问慢
Vercel / Netlify 现代前端项目 自动HTTPS+CDN+CI 国内访问速度一般
对象存储+CDN 纯静态+AWS/阿里云生态 按量付费,流量大便宜 配置稍复杂

使用GitHub Actions自动部署到服务器

# .github/workflows/deploy.yml
name: Deploy to Server
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: |
          npm install
          npm run build

      - name: Deploy to server
        uses: easingthemes/ssh-deploy@v4
        with:
          SSH_PRIVATE_KEY: ${{ secrets.SSH_KEY }}
          REMOTE_HOST: ${{ secrets.HOST }}
          REMOTE_USER: deploy
          SOURCE: "dist/"
          TARGET: "/var/www/myblog/"

每次git push到main分支,GitHub Actions自动构建并部署到服务器。真正的"push就上线"。


16.7 简易后端API(Python Flask)

前端有了,还需要一个能处理数据的后端。

# app.py — 一个带数据库的简易API
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_cors import CORS

app = Flask(__name__)
CORS(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///blog.db'
db = SQLAlchemy(app)

# 数据模型
class Article(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)

    def to_dict(self):
        return {'id': self.id, 'title': self.title, 'content': self.content}

with app.app_context():
    db.create_all()  # 创建数据库表

# API路由
@app.route('/api/articles', methods=['GET'])
def list_articles():
    articles = Article.query.order_by(Article.id.desc()).all()
    return jsonify([a.to_dict() for a in articles])

@app.route('/api/articles', methods=['POST'])
def create_article():
    data = request.json
    article = Article(title=data['title'], content=data['content'])
    db.session.add(article)
    db.session.commit()
    return jsonify(article.to_dict()), 201

@app.route('/api/articles/', methods=['GET'])
def get_article(article_id):
    article = Article.query.get_or_404(article_id)
    return jsonify(article.to_dict())

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000)

部署方式(使用systemd管理Flask进程):

# /etc/systemd/system/myblog.service
[Unit]
Description=My Blog Flask App
After=network.target

[Service]
User=deploy
WorkingDirectory=/home/deploy/myblog
ExecStart=/home/deploy/myblog/venv/bin/gunicorn -w 2 -b 127.0.0.1:5000 app:app
Restart=always
Environment=FLASK_ENV=production

[Install]
WantedBy=multi-user.target
# 生产环境用Gunicorn运行Flask
cd /home/deploy/myblog
python3 -m venv venv
source venv/bin/activate
pip install flask flask-sqlalchemy flask-cors gunicorn

# 启动服务
sudo systemctl enable --now myblog
sudo systemctl status myblog
⚠️ 生产环境请用PostgreSQL/MySQL替代SQLite,并把SECRET_KEY等配置放到环境变量而非代码中。

16.8 备案流程(中国大陆)

如果你的服务器在国内,域名必须备案。这不是可选的,是法律要求。

备案前准备

1. ✅ 域名已完成实名认证(注册商处操作)

2. ✅ 服务器已购买(需要有至少3个月有效期)

3. ✅ 准备身份证件(个人)或营业执照(企业)

备案流程

第1步:登录云厂商备案系统
  → 阿里云:aliyun.com → 备案
  → 腾讯云:cloud.tencent.com → 备案

第2步:填写备案信息
  → 主体信息(你是谁)
  → 网站信息(网站名称、域名、服务内容)
  → 网站负责人信息

第3步:云厂商初审(1-2个工作日)
  → 检查填写是否正确
  → 网站名称不能含"中国""国家""官方"等敏感词

第4步:人脸核验 + 上传资料

第5步:工信部短信验证

第6步:管局审核(3-20个工作日,各省不同)
  → 审核通过后会收到工信部短信
  → 获得备案号(如 京ICP备2025XXXXXX号)

第7步:备案号必须放在网站底部
  京ICP备2025XXXXXX号

常见踩坑:


本章小结

整个流程走下来,你有了:

yourdomain.com ──DNS──▶ 云服务器IP ──Nginx──▶ 静态网站 + Flask API
                         🔒 HTTPS (Let's Encrypt自动续期)
                         🔄 GitHub Actions 自动部署

核心技能清单:


⬅️ [上一章:15-人工智能入门](15-人工智能入门.html)   |   ➡️ [下一章:17-职业发展路径](17-职业发展路径.html)
Collaplex · 克拉普莱克斯 collaplex.me · 2026 浙ICP备2026080865号