Ghost 01 - Nginx / Let's Encrypt / certbot / Docker / Ghost 搭建个人博客

Ghost blog docker 镜像是由 docker 官方维护的。

本文涉及的所有操作均运行于 ubuntu 18.04 server。

准备

安装前先将 ubuntu 软件进行更新。

apt update
apt upgrade

Nginx + Let's Encrypt + cerbot

本章节将利用 Nginx、certbot 完成 http / https 服务器的基础配置。

  1. 安装软件

    apt install nginx certbot
    
  2. 生成 Strong Dh (Diffie-Hellman) Group,此步骤有些耗时

    sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
    
  3. 准备获取 Let's Encrypt 证书所需的目录,(www-data用户需要有写权限)

    mkdir -p /var/lib/letsencrypt/.well-known
    chgrp www-data /var/lib/letsencrypt
    chmod g+s /var/lib/letsencrypt
    
  4. 创建 /etc/nginx/snippets/letsencrypt.conf 内容如下,此文件在配合 certbot 域名 ssl 生成时使用。

    location ^~ /.well-known/acme-challenge/ {
      allow all;
      root /var/lib/letsencrypt/;
      default_type "text/plain";
      try_files $uri =404;
    }
    
  5. 创建 /etc/nginx/snippets/ssl.conf 内容如下,用于 nginx 的全局 ssl 配置

    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
    ssl_prefer_server_ciphers on;
    
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    resolver_timeout 30s;
    
    add_header Strict-Transport-Security "max-age=15768000; includeSubdomains; preload";
    add_header X-Frame-Options SAMEORIGIN;
    add_header X-Content-Type-Options nosniff;
    
  6. 为网站创建配置文件,/etc/nginx/sites-available/example.com 内容如下,请确保域名已经正确解析到相应的 IP。

    server {
      listen 80;
      server_name example.com www.example.com;
    
      include snippets/letsencrypt.conf;
    }
    
  7. 将网站使能,并且重启 Nginx

    sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
    sudo systemctl restart nginx
    
  8. 使用 certbot 获取 SSL 证书,可以同时认证多个子域名。所有子域名的解析必须有效,否则将导致证书获取失败。

    sudo certbot certonly --agree-tos --email admin@example.com --webroot -w /var/lib/letsencrypt/ -d example.com -d www.example.com
    
  9. 如果获取成功将提示如下信息

    IMPORTANT NOTES:
     - Congratulations! Your certificate and chain have been saved at:
       /etc/letsencrypt/live/example.com/fullchain.pem
       Your key file has been saved at:
       /etc/letsencrypt/live/example.com/privkey.pem
       Your cert will expire on 2018-07-28. To obtain a new or tweaked
       version of this certificate in the future, simply run certbot
       again. To non-interactively renew *all* of your certificates, run
       "certbot renew"
     - Your account credentials have been saved in your Certbot
       configuration directory at /etc/letsencrypt. You should make a
       secure backup of this folder now. This configuration directory will
       also contain certificates and private keys obtained by Certbot so
       making regular backups of this folder is ideal.
     - If you like Certbot, please consider supporting our work by:
    
       Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
       Donating to EFF:                    https://eff.org/donate-le
    
  10. 编辑 nginx 网站配置文件,使能 https,并且引用 刚刚获取到的 SSL 证书,同时开启 http2,文件路径/etc/nginx/sites-available/example.com

    server {
        listen 80;
        server_name www.example.com example.com;
    
        include snippets/letsencrypt.conf;
        return 301 https://$host$request_uri;
    }
    
    server {
        listen 443 ssl http2;
        server_name www.example.com;
    
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
        include snippets/ssl.conf;
        include snippets/letsencrypt.conf;
    
        return 301 https://example.com$request_uri;
    }
    
    server {
        listen 443 ssl http2;
        server_name example.com;
    
        ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
        include snippets/ssl.conf;
        include snippets/letsencrypt.conf;
    
        # . . . other code
    }
    
  11. 更新配置后,重载配置使其生效

    sudo systemctl reload nginx
    
  12. 由于 Let‘s Encrypt 证书有效期只有 90 天,所以需要进行定期自动更新。创建文件/etc/cron.d/certbot,并填入如下内容。(使用crontab 定时任务的方法实现)

    0 */12 * * * root test -x /usr/bin/certbot -a \\\\! -d /run/systemd/system && perl -e 'sleep int(rand(3600))' && certbot -q renew --renew-hook "systemctl reload nginx"
    

    使用此方法,certbot 每 12 个小时执行一次检查 SSL 证书有效期,如果距离有效期不足 30 天,自动更新。超过 30 天则跳过。

  13. 此时 nginx 已经同时在服务器上监听了 80 与 443 端口,同时对 80 端口的访问将会重定向为 https。如果任意一步执行有问题,请核查服务器的防火墙配置。

ghost + docker

  1. 安装 docker 软件

    apt install docker.io 
    
  2. 拉取 ghost 镜像

    docker pull ghost
    
  3. 本机创建目录用于存放 ghost 的数据库,配置、主题的内容。(实例使用的 root 用户的 /root 目录)

    mkdir /root/ghost/content
    
  4. 启动 ghost

    docker run --name ghost \\\\
     -p 127.0.0.1:2368:2368 \\\\
     -e url=https://example.com \\\\
     -v /root/ghost/content:/var/lib/ghost/content \\\\
     --restart=always \\\\
      -d ghost
    

    这里创建了一个名为 ghost 的 docker 实例,同时将实例端口 2368 (ghost 服务端口)映射到本机 2368 端口。并且将主机目录/root/ghost/content 挂载到了 docker 实例 /var/lib/ghost/content

  5. 此时 ghost 博客还不能正常访问,因为还需要一步 nginx 代理步骤。

利用 Nginx 代理 Ghost

编辑网站配置文件/etc/nginx/sites-available/example.com,注意替换 example.com 为实际域名。本站域名是 jiapeng.me

server {
    listen 80;
    server_name www.jiapeng.me jiapeng.me;

    include snippets/letsencrypt.conf;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name www.jiapeng.me;

    ssl_certificate /etc/letsencrypt/live/jiapeng.me/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/jiapeng.me/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/jiapeng.me/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    return 301 https://jiapeng.me$request_uri;
}

server {
    listen 443 ssl http2;
    server_name jiapeng.me;

    ssl_certificate /etc/letsencrypt/live/jiapeng.me/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/jiapeng.me/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/jiapeng.me/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    # 以下字段为 nginx 代理 ghost 所需的配置内容
    location / {
        proxy_pass          http://127.0.0.1:2368;
        proxy_set_header    X-Real-IP $remote_addr;
        proxy_set_header    Host      $http_host;
        proxy_set_header    X-Forwarded-Proto https;
        proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

同样,更改 nginx 配置后需要手动刷新一次。

sudo systemctl reload nginx

此时如无意外,ghost 博客已经可以正常访问了。ghost 博客控制台访问地址 http://example.com/ghost,初次访问需要进行账户初始化。现在就可以开始写博客了。

其他

  • 注意:本文并未进行 ghost 邮箱配置,ghost 邮箱功能不可用
  • docker 的便利性并不是没有代价的,我的服务器有 512 MB 内存,跑了个 docker 还有个 v,内存显得有些吃紧了。但是 docker 配置真的很简单。

参考资料

发表于: 作者:JiapengLi
由于某种不存在的原因,评论区正在努力加载中……