Docker搭建Misskey实例记录

yaya
最后编辑于 November 21 Misskey

本次搭建使用 Ubuntu 22.10 系统

超级啰嗦预警

购买 VPS

⚠️不要买机房在大陆的服务商 VPS ⚠️

在备案通过之前 80 和 443 端口是封禁的 -> 无法申请 SSL 证书 -> Misskey 需要 SSL 才能访问,GG

(即使没有这个问题,买大陆节点的服务建站也是一种自杀行为)

注册

注册Vultr 账号,充值

image-20221120012614543

创建 VPS

image-20221120012203832

  • 选 Cloud Computer

  • CPU 选 AMD 和 Intel 都行

  • 机房位置选择日本、新加坡、美西都行,一般不推荐欧洲(对于中国国内)

  • 选择操作系统:Ubuntu 22.10 x64

  • 选择 Size:$5 的 1C1G1TB 套餐(记得勾选 No Thanks)

  • 关闭自动备份,省 $1

  • Additional Features:勾选 Enable IPv6

  • 添加 SSH Keys

image-20221120135314470

打开命令行,输入

ssh-keygen -t rsa -b 4096 -C "Example comment"

在这行提示后面输入你想要保存密钥的路径

Generating public/private rsa key pair.
Enter file in which to save the key (/home/example_user/.ssh/id_rsa):

我输入(uu是我的电脑用户名)

/home/uu/.ssh/id_rsa_vultr

所以在 /.ssh 目录下可以找到 id_rsa_vultrid_rsa_vultr.pub 文件,它们分别是私钥和公钥

接下来要把公钥内容添加到 vultr 去

# 进入.ssh 目录
cd .ssh
# 打印文件内容
cat id_rsa_vultr.pub

image-20221120140350349

  • 这时底部付款栏应该显示 $5.00/month ,点击 Deploy Now 确认创建服务器,等待一会,等 Status 变成 Running 就好了

image-20221120012909994

点击刚刚创建的 VPS,看到如下界面。

左下角的 IP Address、Username、Password 是待会连接服务器的时候,要用到的 SSH 连接信息

image-20221120013010174

  1. 登录 VNC:查看控制台
  2. 关机:就和关电脑一样(关机的时候仍然在计费哦!)
  3. 重启:就和重启电脑一样
  4. 重装系统:把服务器重置成刚创建时的状态
  5. 销毁/删除:销毁了服务器就不计费了,数据丢失,无法找回

Snapshots:快照,指将当前 VPS 的状态保存下来,对 VPS 进行完整备份

服务器创建完成

检查 IP

Ping 一下 IP

image-20221120013147886

用检查工具比如 https://ip112.cn/ 检查 IP,此 IP 可用

image-20221120013305544

其它测试工具

域名

在域名商 Dynadot 注册账号,买一个域名

解析域名

依次点击

image-20221120013439245

暂停⏸️

CloudFlare 注册登录账号,依次操作:

添加新站点

image-20221120013614146

输入你的域名

image-20221120013635155

选择免费方案

添加 DNS 解析记录

image-20221120013747246

  • * 是通配符,意思是我的二级域名,xxx.ponderduck.cc 的 DNS 解析也一起被接管了。不用我一个一个设置

  • 第二行是域名本体

  • www 让输入 www.ponderduck.cc 也能访问

复制 CloudFlare 提供的两个名称服务器,填进 Dynadot 的 DNS 设置,保存

image-20221120013847175

回到 CloudFlare 点击 Done, check nameservers,等一会

image-20221120013935205

测试,ping 你的域名,返回服务器 IP 说明解析生效

image-20221120014006868

开启完全 SSL,否则访问站点会报「重定向次数过多」的错误

image-20221121185003309

✅域名解析完成

服务器基础配置

对哪一步不自信,可以在开始做之前先去服务器管理面板创建一个快照(snapshots),快照就是存档点

远程连接

ssh [email protected] # 换成你的ip地址,回车

然后把密码从 vultr 复制过来回车,会看到类似这样的提示就表示连接服务器成功

Welcome to Ubuntu 22.10 (GNU/Linux 5.19.0-23-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage
 ...省略一部分内容...
[email protected]:~# 

安全设置

因为 root 权限太太太强大,为了避免婴儿(我)拿核武器发射按钮的情况出现,创建一个普通用户日常使用

新建普通用户并设定密码

adduser vpsadmin # vpsadmin是用户名

然后输入密码 - 确认密码(太简单会被拒绝==)

image-20221120014438453

赋予 「vpsadmin」 使用 sudo 指令的权限

什么是 su 和 sudo 请看:Linux 的 su 與 sudo 指令教學與範例

sudo adduser vpsadmin sudo

另外开一个终端窗口,登录 vpsadmin 账号

ssh [email protected] # 换成你的IP,回车,然后输入密码

验证是否获得 sudo 权限

sudo ls -al /root

返回类似内容(展示 /root 目录下的资料)就表示成功了

image-20221120014519093

[可选]SSH免密登录

每次登录 vpsadmin 都要手动输密码很麻烦,设置一下免密登录

在 Tabby 设置 - Profiles & connections - + New profile - SSH connection

image-20221120144436295

禁止 root 登录

(禁用核按钮)

登录 root 账户,输入

nano /etc/ssh/sshd_config

使用 control + W 进入搜索模式,输入 PerimitRootLogin 并回车,找到所在行,改成(记得要取掉注释 #!!)

PermitRootLogin: no

*prohibit-password/without-password 意为禁止密码登录

使用 control + O,保存更改,control + X 退出

重新启动 SSH 服务

sudo /etc/init.d/ssh restart

打开一个新窗口,尝试用 root 登录,返回 Permission denied...

image-20221120150026614

✅成功禁止 root 登录

从现在开始,用「vpsadmin」这个账户远程连接 VPS 吧

搭建环境

修改服务器时间

查看时间

timedatectl

image-20221120014657166

列出所有时区

timedatectl list-timezones

image-20221120014727816

改成香港🇭🇰

sudo timedatectl set-timezone Asia/Hong_Kong

安装常用命令

sudo apt-get install curl wget screen tree -y

*curl用于请求 Web 服务器

*wget用来下载软件包

*screen用于命令行终端的窗口切换

*tree用于显示当前文件夹的目录结构

(如果你有其它要用的也一起加进来,或者要用了再用这个命令单独安装也可以)

添加 SWAP

swap 是 Linux 中的虚拟内存,用于在物理内存不足的情况下储存临时数据,可以提升小内存 VPS 的运行效率

确认是否已存在 SWAP

free -m

image-20221120014807159

有 Swap 项而且 total 列不为零,说明 Swap 已存在,可以自行修改分区容量,参考:为 Linux 添加 swap 分区或修改 swap 分区容量

配置防火墙

sudo ufw allow OpenSSH
sudo ufw enable

打开防火墙

sudo ufw allow http
sudo ufw allow https

打开 80、443 的端口

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

(其它服务需要的端口也用 sudo ufw allow xx/tcp 开启)

验证防火墙是否打开,端口是否开启

sudo ufw status

image-20221120014838387

和其它服务商不同,Vultr 没有默认防火墙设置,所以要自己开启

在 Vultr 添加防火墙规则

image-20221120014901103

image-20221120014938210

image-20221120015008060

安装 Docker 和 Docker Compose

*Compose 是 Docker 的一个命令行工具,通过 yml 文件定义、创建、管理多容器的 Docker 应用

跟着 如何在 Ubuntu 22.04 LTS 中安装 Docker 和 Docker Compose 丝滑完成安装

推荐:Docker Commands Tutorial | Getting Started With Docker In Linux

修改 Docker 配置

Docker 的配置文件路径是 /etc/docker/daemon.json,需要手动创建:

进入 /etc/docker 目录

cd /etc/docker

用 vim 编辑 daemon.json 文件

sudo vim daemon.json

进入 vim 后输入如下内容,这段代码会增加一段自定义内网 IPv6 地址,开启容器的 IPv6 功能,限制日志文件的大小(20M),限制日志文件数量,防止 Docker 日志过多占用硬盘

(代码来自烧饼博客

{
    "log-driver": "json-file",
    "log-opts": {
        "max-size": "20m",
        "max-file": "3"
    },
    "ipv6": true,
    "fixed-cidr-v6": "fd00:dead:beef:c0::/80",
    "experimental":true,
    "ip6tables":true
}

⚠️ vim 和普通键入略有不用

  • 首先 I 进入编辑模式,输入内容(注意格式:大括号 {} 里的内容除了最后一行,都必须用英文逗号 , 结尾)
  • 完成输入后,按 esc 回到一般模式
  • 输入 :wq ,回车(意为保存-离开)

  • 不放心可以再次进入 daemon.json 检查是否成功写入,效果类似:

image-20221120015046625

了解:Linux vi/vim 是什么,怎么使用

重启 Docker 服务

sudo systemctl daemon-reload
sudo systemctl restart docker
检查 Docker 是否正在运行
sudo systemctl status docker

image-20221120015133790

换个方式,再测试一下

sudo docker run hello-world

image-20221120015200357

终于成功了 😭

评论

  • yaya
    最后编辑于 November 21

    Misskey

    创建安装目录

    之前给 Docker 的数据和配置文件新建一个目录 docker_data,这个文件夹就是包住整个 Misskey 的盒子

    sudo mkdir -p data/docker_data
    

    进入目录

    cd data/docker_data
    

    创建 misskey 文件夹

    sudo mkdir misskey
    

    配置安装文件

    进入 misskey 文件夹

    cd misskey
    

    创建并编辑 yml 文件,让它去部署

    sudo vim docker-compose.yml
    

    I,切换到编辑模式,把以下内容粘贴进去

    # Misskey minimal deploy config
    version: "3"
    
    services:
      web:
        restart: unless-stopped # always意味着自动重启,请注意如果您对您的配置没有信心,请不要开启这个选项,以避免进程崩溃反复重启耗费大量资源!
        image: misskey/misskey:latest # 这里使用了官方镜像,以避免本地构建时资源不足的问题
        container_name: misskey_web # 容器名,方便管理,您可以自行修改为您觉得合适的内容
        links:
          - db
          - redis
        ports:
          - "3001:3001"
        networks:
          - internal_network
          - external_network
        volumes:
          - ./config:/misskey/.config:ro # 用于映射配置文件,请根据您的实际配置来决定文件夹名称,设定为只读即可;
          - ./files:/misskey/files # 用户上传到本地的文件,如果您一开始就接入外部存储(如wasabi或是AWS S3)您可以忽略这块配置
    
      redis:
        restart: unless-stopped
        image: redis:latest
        container_name: misskey_redis
        networks:
          - internal_network
        volumes:
          - ./redis:/data # redis数据库的数据文件夹映射,创建后默认在 ./redis 文件夹中
    
      db:
        restart: unless-stopped
        image: postgres:12.2-alpine
        container_name: misskey_db
        networks:
          - internal_network
        env_file:
          - ./config/docker.env # 需要使用配置文件中设置的 Docker 环境变量
        volumes:
          - ./db:/var/lib/postgresql/data # 主数据库的数据文件夹映射,创建后默认在 ./db 文件夹中
    
    networks:
      internal_network: # 内部网络
        internal: true
      external_network: # 外部网
    

    esc ,按 :wq ,回车(保存-退出)

    创建 config/default.yml 目录并进入 yml 文件中

    sudo mkdir config
    cd config
    sudo vim default.yml
    

    I,切换到编辑模式,填入以下内容

    #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    # Misskey configuration
    #━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
    
    #   ┌─────┐
    #───┘ URL └─────────────────────────────────────────────────────
    
    # Final accessible URL seen by a user.
    url: https://ponderduck.cc/       # 注意改成自己最后反向代理想要的网址
    
    # ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
    # URL SETTINGS AFTER THAT!
    
    #   ┌───────────────────────┐
    #───┘ Port and TLS settings └───────────────────────────────────
    
    #
    # Misskey requires a reverse proxy to support HTTPS connections.
    #
    #                 +----- https://example.tld/ ------------+
    #   +------+      |+-------------+      +----------------+|
    #   | User | ---> || Proxy (443) | ---> | Misskey (3000) ||
    #   +------+      |+-------------+      +----------------+|
    #                 +---------------------------------------+
    #
    #   You need to set up a reverse proxy. (e.g. nginx)
    #   An encrypted connection with HTTPS is highly recommended
    #   because tokens may be transferred in GET requests.
    
    # The port that your Misskey server should listen on.
    port: 3001
    
    #   ┌──────────────────────────┐
    #───┘ PostgreSQL configuration └────────────────────────────────
    
    db:
      host: db
      port: 5432
    
      # Database name
      db: misskey
    
      # Auth
      user: example-misskey-user
      pass: example-misskey-pass
    
      # Whether disable Caching queries
      #disableCache: true
    
      # Extra Connection options
      #extra:
      #  ssl: true
    
    #   ┌─────────────────────┐
    #───┘ Redis configuration └─────────────────────────────────────
    
    redis:
      host: redis
      port: 6379
      #family: 0  # 0=Both, 4=IPv4, 6=IPv6
      #pass: example-pass
      #prefix: example-prefix
      #db: 1
    
    #   ┌─────────────────────────────┐
    #───┘ Elasticsearch configuration └─────────────────────────────
    
    #elasticsearch:
    #  host: localhost
    #  port: 9200
    #  ssl: false
    #  user: 
    #  pass: 
    
    #   ┌───────────────┐
    #───┘ ID generation └───────────────────────────────────────────
    
    # You can select the ID generation method.
    # You don't usually need to change this setting, but you can
    # change it according to your preferences.
    
    # Available methods:
    # aid ... Short, Millisecond accuracy
    # meid ... Similar to ObjectID, Millisecond accuracy
    # ulid ... Millisecond accuracy
    # objectid ... This is left for backward compatibility
    
    # ONCE YOU HAVE STARTED THE INSTANCE, DO NOT CHANGE THE
    # ID SETTINGS AFTER THAT!
    
    id: 'aid'
    
    #   ┌─────────────────────┐
    #───┘ Other configuration └─────────────────────────────────────
    
    # Whether disable HSTS
    #disableHsts: true
    
    # Number of worker processes
    #clusterLimit: 1
    
    # Job concurrency per worker
    # deliverJobConcurrency: 128
    # inboxJobConcurrency: 16
    
    # Job rate limiter
    # deliverJobPerSec: 128
    # inboxJobPerSec: 16
    
    # Job attempts
    # deliverJobMaxAttempts: 12
    # inboxJobMaxAttempts: 8
    
    # IP address family used for outgoing request (ipv4, ipv6 or dual)
    #outgoingAddressFamily: ipv4
    
    # Syslog option
    #syslog:
    #  host: localhost
    #  port: 514
    
    # Proxy for HTTP/HTTPS
    #proxy: http://127.0.0.1:3128
    
    #proxyBypassHosts: [
    #  'example.com',
    #  '192.0.2.8'
    #]
    
    # Proxy for SMTP/SMTPS
    #proxySmtp: http://127.0.0.1:3128   # use HTTP/1.1 CONNECT
    #proxySmtp: socks4://127.0.0.1:1080 # use SOCKS4
    #proxySmtp: socks5://127.0.0.1:1080 # use SOCKS5
    
    # Media Proxy
    #mediaProxy: https://example.com/proxy
    
    # Proxy remote files (default: false)
    #proxyRemoteFiles: true
    
    # Sign to ActivityPub GET request (default: false)
    #signToActivityPubGet: true
    
    #allowedPrivateNetworks: [
    #  '127.0.0.1/32'
    #]
    
    # Upload or download file size limits (bytes)
    #maxFileSize: 262144000
    

    esc ,按 :wq ,回车(保存-退出)

    进入 env 文件

    sudo vim docker.env
    

    I,切换到编辑模式,填写如下内容

    # db settings
    POSTGRES_PASSWORD=example-misskey-pass
    POSTGRES_USER=example-misskey-user
    POSTGRES_DB=misskey
    
    

    部署

    还记得我说「创建并编辑 yml 文件,让它去部署」吗?

    现在文件已经配置完毕了,是时候让它跑起来了!

    双手合十🙏

    切换到上一级目录

    cd ..
    

    初始化数据库

    sudo docker-compose run --rm web yarn run init 
    

    后台启动项目容器

    sudo docker-compose up -d 
    

    访问站点

    查看端口状态

    sudo lsof -i:<port>
    

    假如这个端口不能用,那就换一个。

    新端口要在服务商防火墙、ufw 命令、default.ymldocker-compose.yml 里都开启、改过来

    然后重启 Docker

    sudo docker-compose restart [指定服务的容器]
    

    完成这一步之后,尝试用 IP 访问站点吧

    在浏览器输入 http://<ip>:<port>(IP 可以用 curl ip.sb 返回)

    image-20221120015412689

    (;

    还有两个任务

    • SSL 证书
    • 反向代理
  • Nginx

    安装 Nginx

    sudo apt update
    sudo apt install nginx
    

    调整防火墙,允许 Nginx 服务通过

    sudo ufw allow 'Nginx HTTP'
    sudo ufw allow 'Nginx HTTPS'
    sudo ufw allow 'Nginx FULL'
    

    查看更改结果

    sudo ufw status
    

    查看 Nginx 状态(是 active 就行)

    systemctl status nginx
    

    在浏览器输入 http://your_vps_ip,返回 Nginx 默认页面

    image-20221121023144221

    让 Nginx 在系统启动时自动启动

    sudo systemctl enable nginx
    

    设置服务器块

    创建站点对应目录

    sudo mkdir -p /var/www/ponderduck.cc/html
    

    使用$USER环境变量分配目录的所有权

    sudo chown -R $USER:$USER /var/www/ponderduck.cc/html
    

    如果我们没有修改自己的umask值,那么 Web 根目录的权限应该正确,我们可以通过输入以下命令来确认:

    sudo chmod -R 755 /var/www/ponderduck.cc
    

    编辑index.html

    sudo vim /var/www/ponderduck.cc/html/index.html
    

    添加以下示例HTML

    <html>
        <head>
            <title>Welcome to ponderduck.cc!</title>
        </head>
        <body>
            <h1>Success!  The ponderduck.cc server block is working!</h1>
        </body>
    

    为 Nginx 创建一个服务器块

    创建一个新文件

    sudo vim /etc/nginx/sites-available/ponderduck.conf
    

    添加以下内容

    server {
            listen 80;
            listen [::]:80;
            root /var/www/ponderduck.cc/html;
            index index.html index.htm index.nginx-debian.html;
            server_name ponderduck.cc www.ponderduck.cc;
            location / {
                    try_files $uri $uri/ =404;
            }
    }
    

    通过 ls 命令在sites-enabled目录新建一个链接,好让 Nginx 在启动过程中会读取这个目录:

    sudo ln -s /etc/nginx/sites-available/ponderduck.conf /etc/nginx/sites-enabled/
    

    打开文件:

    sudo vim /etc/nginx/nginx.conf
    

    找到server_names_hash_bucket_size指令并删除#符号:

    ...
    http {
        ...
        server_names_hash_bucket_size 64;
        ...
    }
    ...
    

    接下来,测试以确保我们在 Nginx 文件中的改动,没有任何问题:

    sudo nginx -t
    

    如果没有任何问题,请重新启动 Nginx:

    sudo systemctl restart nginx
    

    现在通过 http://ponderduck.cc 访问服务器的时候,Nginx 会指向我们刚刚添加的那个 HTML 页面

    SSL

    安装 Certbot

    我们需要获得被信任的证书授权中心( CA )签发的安全证书。Let’s Encrypt 是 ISRG ( Internet Security Research Group ,互联网安全研究小组)的组织推出的免费安全证书计划。

    ISRG 的发起者 EFF (电子前哨基金会)为 Let’s Encrypt 项目发布了一个官方的客户端 Certbot ,利用它可以完全自动化的获取、部署和更新安全证书

    安装 Certbot

    官网 选择我正在使用的 Web 服务器(Nginx)和操作系统(Ubuntu 20),操作对应的安装步骤

    Ubuntu 自带 Snap,用 Snap 安装 Certbot

    sudo snap install --classic certbot
    

    用 ln 命令创建符号连接,将 Certbot 加入 PATH 环境变量中

    sudo ln -s /snap/bin/certbot /usr/bin/certbot
    
    生成 SSL 证书
    sudo certbot --nginx -d www.ponderduck.cc
    

    输入邮箱地址,用于接收邮件

    输入 Y,同意协议;询问是否接收前哨基金会的邮件,接不接收都行

    返回(注意证书储存位置)

    Successfully received certificate.
    Certificate is saved at: /etc/letsencrypt/live/www.ponderduck.cc/fullchain.pem
    Key is saved at:         /etc/letsencrypt/live/www.ponderduck.cc/privkey.pem
    This certificate expires on 2023-02-18.
    These files will be updated when the certificate renews.
    Certbot has set up a scheduled task to automatically renew this certificate in the background.
    

    Let's Encrypt 的 SSL 证书会在 90 天后过期,但是 Certbot 会自动续订

    测试证书自动续订是否生效

    sudo certbot renew --dry-run
    

    返回⬇️说明已生效

    Simulating renewal of an existing certificate for www.ponderduck.cc
    

    找到存放站点证书的目录

    sudo ls /etc/letsencrypt/live
    

    我的是www.ponderduck.cc

    查询证书

    sudo ls /etc/letsencrypt/live/www.ponderduck.cc
    

    返回文件名

    cert.pem  chain.pem  fullchain.pem  privkey.pem  
    

    后两个要添加到 Nginx 配置文件 .conf

    反向代理

    修改网站配置文件

    参考 官网文档,以下是我的完整文件内容

    # For WebSocket
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    proxy_cache_path /tmp/nginx_cache levels=1:2 keys_zone=cache1:16m max_size=1g inactive=720m use_temp_path=off;
    
    server {
           listen 80;
           listen [::]:80;
           server_name www.ponderduck.cc ponderduck.cc;
    
           # For SSL domain validation
           root /var/www/html;
           location /.well-known/acme-challenge/ { allow all; }
           location /.well-known/pki-validation/ { allow all; }
           location / { return 301 https://$server_name$request_uri; }
    }
    
    server {
            listen [::]:443 ssl http2;
            listen 443 ssl http2; 
            server_name ponderduck.cc www.ponderduck.cc;
    
            ssl_session_cache shared:ssl_session_cache:10m;
    
            # ssl
            ssl_certificate /etc/letsencrypt/live/www.ponderduck.cc/fullchain.pem;
            ssl_certificate_key /etc/letsencrypt/live/www.ponderduck.cc/privkey.pem; 
    
            include /etc/letsencrypt/options-ssl-nginx.conf;
            ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; 
            ssl_stapling on;
            ssl_stapling_verify on;
    
            # Change to your upload limit
            client_max_body_size 80m;
    
            # 对"/"启用反向代理
            location / {
                    # 指定转发地址
                    proxy_pass http://127.0.0.1:3001;
                    proxy_set_header Host $host;
                    proxy_http_version 1.1;
                    proxy_redirect off;
    
                    proxy_set_header   Upgrade             $http_upgrade;
                    proxy_set_header   Connection          $connection_upgrade;
    
                    proxy_cache cache1;
                    proxy_cache_lock on;
                    proxy_cache_use_stale updating;
                    add_header X-Cache $upstream_cache_status;
            }
    
    }
    

    接下来,测试以确保我们在 Nginx 文件中的改动,没有任何问题:

    sudo nginx -t
    

    有问题的话按照提示修改,做完之后,重新启动 Nginx:

    sudo systemctl restart nginx
    

    现在 SSL 证书和反向代理都生效了,尝试用域名访问站点

    image-20221121190615731

    完成🎉

    其它参考

    mjj版的linux入门教程

    [User] Linux 新增使用者並賦予其使用 sudo 的權限

    保护好你的小鸡!保姆级服务器安全教程!

    【好玩儿的Docker项目】10分钟搭建一个去中心化微博平台——Misskey |二次元风格、联邦宇宙

    如何在 Ubuntu 20.04 中安装和配置 Nginx

    Nginx 教程:如何在 Ubuntu 20.04 下安装并配置 Nginx

    如何在Ubuntu 20.04 Nginx配置Let's Encrypt SSL证书

登录注册后才能评论。