2023 年,随着 X 社媒(原 Twitter)的全面塌陷,越来越多的网友逃向了 Fediverse 开源社交平台,其中著名的有 Mastodon、Misskey 和 Pleroma。前阵子,随着 Firefish横空问世 (Misskey 的一个 fork),博主便也想着搭一个玩玩。博主是计算机零基础的小白 (超级白的那种) ,靠着广大热心网友先后搭起了一个 Misskey 实例和一个 Pleroma 实例,这一次,也多亏了大家的帮忙,磕磕绊绊地终于搭好了 Firefish 实例。趁着记忆还鲜明,赶紧记录一下搭建过程。

# 搭建过程

因为是用 Docker-compose 搭建实例,所以默认机器上是有 Docker 容器的。在此基础上,先在任意目录下新建 docker-compose.yml 文件。比如:

mkdir /firefish && cd /firefish
nano docker-compose.yml

然后写入以下

version: "3"
services:
  web:
    image: registry.joinfirefish.org/firefish/firefish
    container_name: firefish_web
    restart: unless-stopped
    depends_on:
      - db
      - redis
### Uncomment one of the following to use a search engine
#     - meilisearch
#     - sonic
    ports:
      - "3000:3000"
    networks:
      - calcnet
#     - web
    environment:
      NODE_ENV: production
    volumes:
      - ./files:/firefish/files
      - ./.config:/firefish/.config:ro
  redis:
    restart: unless-stopped
    image: docker.io/redis:7.0-alpine
    container_name: firefish_redis
    networks:
      - calcnet
    volumes:
      - ./redis:/data
  db:
    restart: unless-stopped
    image: docker.io/postgres:12.2-alpine
    container_name: firefish_db
    networks:
      - calcnet
    env_file:
      - .config/docker.env
    volumes:
      - ./db:/var/lib/postgresql/data
### Only one of the below should be used.
### Meilisearch is better overall, but resource-intensive. Sonic is a very light full text search engine.
#  meilisearch:
#    container_name: meilisearch
#    image: getmeili/meilisearch:v1.1.1
#    environment:
#      - MEILI_ENV=${MEILI_ENV:-development}
#    ports:
#      - "7700:7700"
#    networks:
#      - calcnet
#    volumes:
#      - ./meili_data:/meili_data
#    restart: unless-stopped
#  sonic:
#    restart: unless-stopped
#    image: docker.io/valeriansaliou/sonic:v1.4.0
#    networks:
#      - calcnet
#    volumes:
#      - ./sonic:/var/lib/sonic/store
#      - ./sonic/config.cfg:/etc/sonic.cfg
networks:
  calcnet:
  #  web:
  #    external:
  #      name: web

注意:
如果此前搭建过 Misskey 的话,那么端口号 3000 应当是冲突的,这时候需要把 web 下面的 ports 改成其他端口,比如 4000:4000

写完 docker-compose.yml 文件之后,需要在 firefish 的根目录下新建 .config 文件夹,在里头装入 default.yml docker.env 这两个文件。

注意:

  1. 需要重命名:example.yml -> default.yml && docker_example.env -> docker.env
  2. 修改 default.yml 的内容:url -> 自己的域名 && db localhost -> firefish_db && redis localhost -> redis (备注:localhost 一定要修改,博主就是在这里卡了好久 QAQ)
  3. (可选)修改 default.yml 中的 port,如果端口有冲突的话。修改 db 的 user 和 pass,且两个文件一定要 match。

待文件写入完毕之后,便可使容器上线: docker-compose up -d

# 反向代理:Nginx

这一部分的话,大概有很多种操作方法,我只写了我使用的一种:利用 Certbot 获取证书然后用 Nginx 反向代理。

首先去 DNS 服务商添加一条指向服务器 IP 的 A 记录。 然后回到服务器,先切换 root 用户: sudo -i 。因为要使用 Certbot 和 Nginx,所以默认服务器上有这两个东西。

获取证书,使用指令 sudo certbot --nginx ,然后配置 Nginx。博主刚开始使用的是 firefish 的 Nginx 配置文件,但是没有成功,后来经热心网友建议,使用 Misskey 的配置文件试试,结果就成功了。

我的配置文件如下:

# For WebSocket
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
  
proxy_cache_path /tmp/nginx_cache_firefish levels=1:2 keys_zone=cache2:16m max_size=1g inactive=720m use_temp_path=off;
  
server {
    listen 80;
    listen [::]:80;
    server_name 你的域名;
  
    # 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 你的域名;
  
    ssl_session_timeout 1d;
    ssl_session_cache shared:ssl_session_cache:10m;
    ssl_session_tickets off;
  
    # To use Let's Encrypt certificate
    ssl_certificate /etc/letsencrypt/live/你的域名/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/你的域名/privkey.pem; # managed by Certbot
  
    # To use Debian/Ubuntu's self-signed certificate (For testing or before issuing a certificate)
    #ssl_certificate     /etc/ssl/certs/ssl-cert-snakeoil.pem;
    #ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key;
  
    # SSL protocol settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_stapling on;
    ssl_stapling_verify on;
  
    # Change to your upload limit
    client_max_body_size 80m;
  
    # Proxy to Node
    location / {
        proxy_pass http://127.0.0.1:6110;
        proxy_set_header Host $host;
        proxy_http_version 1.1;
        proxy_redirect off;
  
  
        # For WebSocket
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
  
        # Cache settings
        proxy_cache cache2;
        proxy_cache_lock on;
        proxy_cache_use_stale updating;
        proxy_force_ranges on;
        add_header X-Cache $upstream_cache_status;
  
    }
#1location =/robots.txt {
#2    default_type text/html;
#3    add_header Content-Type "text/plain; charset=UTF-8";
#4    return 200 "User-agent: *\nDisallow: /\n";
#5}
  
}

注意:

  1. 我修改了缓存地址,否则会和原来 Misskey 的缓存地址冲突:proxy_cache_path /tmp/nginx_cache_firefish
  2. 将 cache1 改为了 cache2,共 2 处。
  3. 端口号要和 docker-compose.yml 和 default.yml 的一致。
  4. 需要修改 你的域名 ,共 4 处。

获取完证书和配置好 Nginx 文件之后,试着测试一下: nginx -t , 没有问题的话便是重载和重启 Nginx:

nginx -s reload
systemctl restart nginx

(如果是第一次使用 Nginx 的话,不是 restart 而是 start)

# 痛苦的排错之路

作为一个小白搭建实例免不了一路红灯 (说的就是 error 呜呜) ,总结了一下,出错原因要么是容器里的服务没有跑起来要么就是 Nginx 搞错了。

  1. Docker 容器
  • 首先 restart 一下容器: docker-compose restart ,这是解决 502 error 最好的办法 (大佬说的)
  • 然后看看 docker ps 里面的服务是不是都 up 了。没有的话可能就是配置错了,回去改改配置,最后 docker-compose up -d 来更新容器。
  • 实在不行,就通过 docker compose logs web -f --tail 100 来查看日志。
  1. Nginx 反代
  • 如果是 502 error 的话,如上所说先试试 docker-compose restart
  • 如果不行或是其他错误,先用 nginx -t 看看是否成功,没有成功的话可能就是配置文件写错了,注意端口号等等。
  • test 没有问题的话,再看看 nginx 的 status: sudo systemctl status nginx
  • 清理缓存,再用 service nginx reload 重载,然后 systemctl restart nginx 重启。
  1. 其他
    可以用 curl -v http://localhost:端口号 看能不能拉取到信息。

# 参考资料