去中心化社交平台Mastodon(v2.7.3)的部署

准备

  • 域名一枚
  • Let’s Encrypt 证书(或其他SSL证书,Mastodon在2.0版本后强制使用https)可以参考 通过certbot获取Let‘s Encrypt证书
  • 1GB内存的VPS(未在更小内存的机器上测试,运行了docker和Mastodon后的内存占用为 816M/985M)

环境

  • Ubuntu 18.04(未在14.04/16.04测试)
  • 安装curl, git 和 nginx

参考

步骤

有两种部署方法——Docker和传统方式,在使用Docker部署时会出现一些问题导致最后访问页面时提示错误,故先介绍传统方式。

19.03.06更新:

关于Docker部署,详见下篇 Mastodon Docker 部署

即使是传统方式也存在不少坑点,以下步骤默认的用户为root

  1. 在开始前可以先将域名的DNS解析到VPS。
  2. 添加并更新源
    1. 添加multiverse, universe 和 restricted 源并更新包
      add-apt-repository multiverse
      add-apt-repository restricted
      apt update
    2. 添加Node.js源
      apt -y install curl
      curl -sL https://deb.nodesource.com/setup_8.x | bash -
    3. 添加Yarn源
      curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
      echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
      apt update
    4. 安装Yarn以及其他软件,每个软件的具体用途可参照官方安装指南
      apt -y install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev file git-core g++ libprotobuf-dev protobuf-compiler pkg-config nodejs gcc autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm5 libgdbm-dev nginx redis-server redis-tools postgresql postgresql-contrib certbot yarn libidn11-dev libicu-dev
  3. 安装必须以非root用户安装的依赖
    1. 新建mastodon用户(或者其他名字)
      adduser mastodon
    2. 登录mastodon用户
      su - mastodon
    3. 安装并设置rbenv和ruby-build
      git clone https://github.com/rbenv/rbenv.git ~/.rbenv
      cd ~/.rbenv && src/configure && make -C src
      echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
      echo 'eval "$(rbenv init -)"' >> ~/.bashrc
      # 重启shell
      exec bash
      # 检查rbenv是否正确安装
      type rbenv
      # 以rbenv插件形式安装ruby-build
      git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
    4. 安装Mastodon使用的Ruby版本。需要注意ruby的版本号,官方文档里使用2.5.1,但最新版本的Mastodon(v2.7.3)使用的为2.6.0版本。
      安装Ruby耗时较长。

      rbenv install 2.6.0
      rbenv global 2.6.0
    5. 安装Node.js和Ruby依赖(依然在非root用户下操作)
      # 返回非root用户的home目录
      cd ~
      # clone mastodon的项目到live文件夹
      git clone https://github.com/tootsuite/mastodon.git live
      # 进入live目录
      cd ~/live
      # 校验最新的稳定分支
      git checkout $(git tag -l | grep -v 'rc[0-9]*$' | sort -V | tail -n 1)
      # 安装bundler
      gem install bundler
      # 使用bundler安装其他ruby依赖
      bundle install -j$(getconf _NPROCESSORS_ONLN) --deployment --without development test
      # 使用yarn安装Node.js依赖
      yarn install --pure-lockfile

      这一步完成后即可切换为root用户。

  4. PostgreSQL数据库创建
    1. 创建数据库用户
      # 以postgres用户启动psql
      sudo -u postgres psql
      
      # 在提示符内输入以下指令
      CREATE USER mastodon CREATEDB;
      \q

      注意这里不需要设置密码,以便本地用户可以无需密码即可访问数据库。

  5. 设置Nginx代理
    1. 删除链接,关闭默认配置文件
      rm /etc/nginx/sites-enabled/default
      nginx -s reload
    2. /etc/nginx/sites-available/ 下新建配置文件 [你的域名].conf ,写入以下内容
      map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
      }
      
      server {
        listen 80;
        listen [::]:80;
        server_name example.com;
        root /home/mastodon/live/public;
        # Useful for Let's Encrypt
        location /.well-known/acme-challenge/ { allow all; }
        location / { return 301 https://$host$request_uri; }
      }
      
      server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name example.com;
      
        ssl_protocols TLSv1.2;
        ssl_ciphers HIGH:!MEDIUM:!LOW:!aNULL:!NULL:!SHA;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
      
        ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
      
        keepalive_timeout    70;
        sendfile             on;
        client_max_body_size 80m;
      
        root /home/mastodon/live/public;
      
        gzip on;
        gzip_disable "msie6";
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_buffers 16 8k;
        gzip_http_version 1.1;
        gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
      
        add_header Strict-Transport-Security "max-age=31536000";
      
        location / {
          try_files $uri @proxy;
        }
      
        location ~ ^/(emoji|packs|system/accounts/avatars|system/media_attachments/files) {
          add_header Cache-Control "public, max-age=31536000, immutable";
          try_files $uri @proxy;
        }
        
        location /sw.js {
          add_header Cache-Control "public, max-age=0";
          try_files $uri @proxy;
        }
      
        location @proxy {
          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 https;
          proxy_set_header Proxy "";
          proxy_pass_header Server;
      
          proxy_pass http://127.0.0.1:3000;
          proxy_buffering off;
          proxy_redirect off;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection $connection_upgrade;
      
          tcp_nodelay on;
        }
      
        location /api/v1/streaming {
          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 https;
          proxy_set_header Proxy "";
      
          proxy_pass http://127.0.0.1:4000;
          proxy_buffering off;
          proxy_redirect off;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection $connection_upgrade;
      
          tcp_nodelay on;
        }
      
        error_page 500 501 502 503 504 /500.html;
      }

      注意替换“example.com”为你的域名地址。
      配置文件中默认使用了Let’s Encrypt的SSL证书,如果使用了其他证书替换 ssl_certificate_keyssl_certificate 的路径即可。
      关于Let’s Encrypt证书的获取,可以参考 通过certbot获取Let‘s Encrypt证书
      原文介绍了如何自动更新证书,这里因为不打算长期使用,所以跳过。

    3. 添加链接激活配置文件,重新启动nginx
      cd /etc/nginx/sites-enabled
      ln -s ../sites-available/[your domain].conf
      
      nginx -t # 测试
      nginx -s reload
  6. 添加swap分区(已有1G以上分区可以跳过),详情可参照 Increase Ubuntu Swap partition,这里可以直接运行
    fallocate -l 1G /swap
    chmod 600 /swap
    mkswap /swap
    swapon /swap
    # 查看交换空间
    free -m

    之后的assets编译需要用到交换分区

  7.  设置Mastodon
    1. 切换到非root用户
      su - mastodon
    2. 进入Mastodon项目目录,运行Mastodon设置向导
      cd ~/live
      RAILS_ENV=production bundle exec rake mastodon:setup

      按照提示填写信息,在填写PostgreSQL和Redis密码时留空(未测试从外部访问,可能有安全隐患)
      如果不使用邮件发送功能可以不写。
      新建管理员账号后会输出初始登录密码。

  8. 将Mastodon的服务注册为系统服务,在 /etc/systemd/system/ 下新建三个服务文件
    1. mastodon-web.service,写入
      [Unit]
      Description=mastodon-web
      After=network.target
      
      [Service]
      Type=simple
      User=mastodon
      WorkingDirectory=/home/mastodon/live
      Environment="RAILS_ENV=production"
      Environment="PORT=3000"
      ExecStart=/home/mastodon/.rbenv/shims/bundle exec puma -C config/puma.rb
      ExecReload=/bin/kill -SIGUSR1 $MAINPID
      TimeoutSec=15
      Restart=always
      
      [Install]
      WantedBy=multi-user.target
    2. mastodon-sidekiq.service,写入
      [Unit]
      Description=mastodon-sidekiq
      After=network.target
      
      [Service]
      Type=simple
      User=mastodon
      WorkingDirectory=/home/mastodon/live
      Environment="RAILS_ENV=production"
      Environment="DB_POOL=5"
      ExecStart=/home/mastodon/.rbenv/shims/bundle exec sidekiq -c 5 -q default -q push -q mailers -q pull
      TimeoutSec=15
      Restart=always
      
      [Install]
      WantedBy=multi-user.target
    3. mastodon-streaming.service,写入
      [Unit]
      Description=mastodon-streaming
      After=network.target
      
      [Service]
      Type=simple
      User=mastodon
      WorkingDirectory=/home/mastodon/live
      Environment="NODE_ENV=production"
      Environment="PORT=4000"
      ExecStart=/usr/bin/npm run start
      TimeoutSec=15
      Restart=always
      
      [Install]
      WantedBy=multi-user.target
  9. 设置开机启动并启动服务
    # 开机启动
    systemctl enable /etc/systemd/system/mastodon-web.service
    systemctl enable /etc/systemd/system/mastodon-sidekiq.service
    systemctl enable /etc/systemd/system/mastodon-streaming.service
    
    # 启动服务
    systemctl start /etc/systemd/system/mastodon-web.service
    systemctl start  /etc/systemd/system/mastodon-sidekiq.service
    systemctl start /etc/systemd/system/mastodon-streaming.service
    
    #查看状态
    systemctl status /etc/systemd/system/mastodon-web.service
    systemctl status  /etc/systemd/system/mastodon-sidekiq.service
    systemctl status /etc/systemd/system/mastodon-streaming.service
  10. 访问域名,可以看到管理员页面,使用管理员邮箱和初始密码登录。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据