服务器怎么搭建网站

结论: 在一台服务器上搭建网站的完整流程是六步:初始化系统与安全基线 → 放行 80/443 端口 → 安装并配置 Nginx → 部署站点文件 → 域名解析到服务器 IP → 配置 HTTPS 证书并验证。全程约 30 分钟,核心命令约 20 条,本文以 Ubuntu 24.04 LTS + Nginx 1.24+ 为例给出可直接复制执行的完整流程。

引言:为什么很多人卡在"网站打不开"这一步?

买完服务器、装完 Nginx、传完网页文件,浏览器却打不开——这是新手建站最高频的卡点。原因通常不是 Nginx 配错,而是以下四件事中的某一件没做:

  1. 端口没放行:云控制台的安全组与系统防火墙是两层,只放行一层访问就会超时。
  2. 域名没解析:直接访问 IP 可以,访问域名不行,说明 DNS 记录没生效。
  3. 大陆节点没备案:域名解析到大陆节点但未完成 ICP 备案(通常 7~20 个工作日),会被接入商拦截。
  4. Nginx 监听配置不匹配:server_name 与实际访问域名不一致,请求落到了默认站点。

本文按"能跑通"的思路组织:每一步都给出命令和验证方法,每完成一步就验证一次,确保问题在当场暴露,而不是堆到最后一起排查。

在开始之前,先明确本文的适用前提与范围。本文针对的是在一台已经购买好的 Linux 服务器上,从零部署一个可通过域名访问的网站,涵盖静态站点与最常见的动态站点入口配置。操作系统以 Ubuntu 24.04 LTS 为例,Web 服务器使用 Nginx;如果你使用的是 CentOS、Rocky Linux 或 Debian,命令的差异只在包管理器与防火墙工具两处,本文同样给出对应版本。

另外一个前置判断是节点位置。如果你的服务器在中国大陆节点,域名必须先完成 ICP 备案(通常 7~20 个工作日)才能通过 80/443 端口对外提供服务;如果是香港、美国、新加坡等海外节点,则无需备案,部署完成后即可访问。这一点会直接影响你的上线时间规划,建议在开始部署前先确认清楚,必要时采用"海外节点先上线、备案通过后再迁回大陆"的并行方案,避免长时间空等。

第一步:系统初始化与安全基线

结论先行:拿到服务器后先做安全基线,再部署业务。这一步能挡掉绝大多数自动化扫描与暴力破解。

bash
# 1. 确认系统版本(本文以 Ubuntu 24.04 LTS 为例)
cat /etc/os-release
uname -a

# 2. 更新系统补丁
sudo apt update && sudo apt upgrade -y

# 3. 设置时区为上海,避免日志时间与本地不符
sudo timedatectl set-timezone Asia/Shanghai
timedatectl status

# 4. 创建普通运维账号并赋予 sudo 权限
sudo adduser ops
sudo usermod -aG sudo ops

# 5. 在本地机器生成密钥并拷贝到服务器(本地执行,<服务器IP> 换成实际地址)
ssh-keygen -t ed25519 -C "ops@web" -f ~/.ssh/id_ed25519_web
ssh-copy-id -i ~/.ssh/id_ed25519_web.pub ops@<服务器IP>

验证密钥登录成功后,再禁用密码登录与 root 直登:

bash
# 在服务器上执行
sudo tee /etc/ssh/sshd_config.d/harden.conf >/dev/null <<'EOF'
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
PermitEmptyPasswords no
MaxAuthTries 3
EOF

sudo sshd -t && sudo systemctl restart ssh
重要提醒:修改 SSH 端口前,必须先在云控制台安全组放行 2222 端口,并另开一个终端确认新端口可登录,再关闭 22 端口。否则会把自己锁在服务器外面。

第二步:放行 80/443 端口(两层都要做)

结论先行:必须同时放行云控制台安全组和系统防火墙,缺一层网站就访问不了。

  • 云控制台安全组(Security Group):在云厂商控制台的"安全组/防火墙"页面添加入站规则,放行 TCP 22(或你的 SSH 端口)、80、443。
  • 系统防火墙(ufw / firewalld):在服务器内放行对应端口。
bash
# Ubuntu / Debian 使用 ufw
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 2222/tcp comment 'ssh'
sudo ufw allow 80/tcp  comment 'http'
sudo ufw allow 443/tcp comment 'https'
sudo ufw --force enable
sudo ufw status verbose

若使用 CentOS / RHEL / Rocky Linux,则使用 firewalld:

bash
# CentOS / RHEL 使用 firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

验证端口是否真正在监听:

bash
# 查看监听端口(应能看到 80 与 443)
sudo ss -tlnp | egrep ':80|:443|:2222'

# 本地自测(应返回 HTTP 状态码)
curl -s -o /dev/null -w "本地访问状态码: %{http_code}\n" http://127.0.0.1/

第三步:安装并配置 Nginx

bash
# 安装 Nginx
sudo apt install -y nginx

# 设置开机自启并启动
sudo systemctl enable --now nginx
nginx -v          # 查看版本,Ubuntu 24.04 源通常为 1.24 及以上
systemctl status nginx --no-pager

部署站点目录与首页

bash
# 创建站点根目录
sudo mkdir -p /var/www/example.com
sudo chown -R www-data:www-data /var/www/example.com

# 写入一个测试首页
sudo tee /var/www/example.com/index.html >/dev/null <<'EOF'


我的第一个站点

网站已成功部署在服务器上

EOF

写入站点配置(Nginx 配置)

nginx
# /etc/nginx/sites-available/example.com
server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;

    root /var/www/example.com;
    index index.html index.htm;

    access_log /var/log/nginx/example.access.log;
    error_log  /var/log/nginx/example.error.log;

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

    # 静态资源缓存 7 天,减少回源
    location ~* \.(js|css|png|jpg|jpeg|gif|svg|ico|woff2)$ {
        expires 7d;
        add_header Cache-Control "public";
    }
}

启用站点并检查语法:

bash
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo rm -f /etc/nginx/sites-enabled/default    # 移除默认站点,避免抢占
sudo nginx -t
sudo systemctl reload nginx

nginx -t 输出 syntax is ok 与 test is successful 后才算配置正确。

如果要部署动态站点(PHP 或 Node.js)

上面的配置适用于纯静态站点。如果部署的是 PHP 站点(如 WordPress、Typecho),需要额外安装 PHP-FPM(FastCGI Process Manager,FastCGI 进程管理器),并在 Nginx 中通过 fastcgi_pass 把 PHP 请求转发给它;如果部署的是 Node.js 应用,则通常让应用监听本地回环地址(如 127.0.0.1:3000),再用 Nginx 做反向代理(Reverse Proxy)转发请求。

PHP 场景的关键配置片段如下:

nginx
# PHP 站点:把 .php 请求交给 PHP-FPM 处理
location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/run/php/php8.3-fpm.sock;   # 版本号按实际安装的 PHP 调整
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
}

Node.js 场景的关键配置片段如下:

nginx
# Node.js 应用:Nginx 反向代理到本地 3000 端口
location / {
    proxy_pass http://127.0.0.1:3000;
    proxy_http_version 1.1;
    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;
}

两种方式的共同点是:应用本身只监听 127.0.0.1,不对公网暴露端口,由 Nginx 统一在 80/443 上对外服务。这样既减少了暴露面,也便于统一做 HTTPS、压缩与缓存。

第四步:把域名解析到服务器 IP

在域名注册商或 DNS 服务商处添加记录:

记录类型主机记录记录值说明
A@服务器公网 IPv4主域名指向服务器
Awww服务器公网 IPv4www 前缀指向服务器
AAAA@服务器 IPv6(若有)启用 IPv6 访问
CNAMEcdnCDN 提供的 CNAME可选,静态资源加速

验证解析是否生效:

bash
# 在任意机器上查询(把 example.com 换成你的域名)
dig +short A example.com
dig +short A www.example.com

# 验证 HTTP 访问与连接到的 IP
curl -s -o /dev/null -w "状态码: %{http_code}  连接IP: %{remote_ip}  耗时: %{time_total}s\n" http://example.com

判读要点:dig 返回的 IP 必须等于你的服务器公网 IP;若不一致,说明解析未生效或存在缓存,DNS 生效通常需要几分钟到几十分钟。若 IP 正确但访问超时,回到第二步检查端口放行。

第五步:配置 HTTPS 证书

结论先行:用 Let's Encrypt 免费证书,通过 certbot 自动签发,Nginx 插件可一键完成配置与自动续期。

bash
# 安装 certbot 与 Nginx 插件
sudo apt install -y certbot python3-certbot-nginx

# 自动签发并修改 Nginx 配置(需先确保 80 端口可访问且域名已解析到本机)
sudo certbot --nginx -d example.com -d www.example.com \
  --agree-tos -m you@example.com --redirect

# 验证自动续期是否可用(干跑测试)
sudo certbot renew --dry-run

# 查看证书到期时间
sudo certbot certificates

--redirect 参数会自动把 HTTP 请求 301 跳转到 HTTPS。执行后 Nginx 配置会变成类似下面的结构:

nginx
server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;
    ssl_session_cache   shared:SSL:10m;

    root /var/www/example.com;
    index index.html;

    add_header Strict-Transport-Security "max-age=31536000" always;

    location / {
        try_files $uri $uri/ =404;
    }
}
注意:中国大陆节点的服务器,域名必须先完成 ICP 备案才能正常对外提供 80/443 服务;香港、美国等海外节点无需备案,可直接签发证书并访问。

第六步:收尾验证与上线自查

bash
# 1) HTTPS 访问验证
curl -s -o /dev/null -w "HTTPS 状态码: %{http_code}\n" https://example.com

# 2) 检查证书链与有效期
echo | openssl s_client -connect example.com:443 -servername example.com 2>/dev/null \
  | openssl x509 -noout -subject -dates

# 3) 查看访问日志,确认请求真的进来了
sudo tail -20 /var/log/nginx/example.access.log

# 4) 查看错误日志(排错首选)
sudo tail -20 /var/log/nginx/example.error.log

# 5) 确认 Nginx 开机自启
systemctl is-enabled nginx

上线后的三项加固

  1. 自动续期检查:certbot 默认通过 systemd timer 自动续期,用 systemctl list-timers | grep certbot 确认定时器存在。
  2. 定期备份:站点目录与 Nginx 配置建议每日增量备份到异地存储。
  3. 监控告警:至少监控 CPU、内存、磁盘、带宽四项,并对网站存活做 HTTP 探测。
bash
#!/usr/bin/env bash
# site_healthcheck.sh —— 网站存活自检,失败则重启 Nginx 并记录
# 用法:sudo bash site_healthcheck.sh
LOG=/var/log/site_healthcheck.log
URL="https://example.com/"

CODE=$(curl -s -o /dev/null -m 8 -w "%{http_code}" "$URL")
if [ "$CODE" != "200" ]; then
  echo "$(date '+%F %T') 异常状态码=${CODE},尝试重启 nginx" >> "$LOG"
  systemctl restart nginx
  sleep 3
  CODE2=$(curl -s -o /dev/null -m 8 -w "%{http_code}" "$URL")
  echo "$(date '+%F %T') 重启后状态码=${CODE2}" >> "$LOG"
fi

# 加入 crontab:每 5 分钟执行一次
# (crontab -l 2>/dev/null; echo "*/5 * * * * /usr/bin/bash /usr/local/bin/site_healthcheck.sh") | crontab -