Bookmark

Tự host Mastodon bằng Docker: PostgreSQL, Redis, SSL và Nginx

Mastodon là mạng xã hội liên hợp, vì vậy tutorial này dài hơn một container Docker đơn lẻ: cần domain ổn định, PostgreSQL, Redis, secrets, VAPID, streaming, Sidekiq và reverse proxy HTTPS. LOCAL_DOMAIN là giá trị không nên đổi tùy tiện sau khi instance hoạt động.1

Youtube video player

Video i12bretro đã được xác thực title/author. Tôi giữ player gốc và không rehost video.2

1. Điều kiện domain và Docker

Host Certbot phải truy cập được từ Internet qua port 80 hoặc 443 để Let's Encrypt xác minh. Với HomeLab, tôi forward port 80 tới host trong thời gian handshake, kiểm tra DNS trỏ đúng và dừng web server đang chiếm port 80.

Cài Docker bằng block source:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
# install prerequisites
sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg-agent -y
# add docker gpg key
curl -fsSL https://download.docker.com/linux/$(awk -F'=' '/^ID=/{ print $NF }' /etc/os-release)/gpg | sudo apt-key add -
# add docker software repository
sudo add-apt-repository "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/$(awk -F'=' '/^ID=/{ print $NF }' /etc/os-release) $(lsb_release -cs) stable"
# install docker
sudo apt install docker-ce docker-compose containerd.io -y
# enable and start docker service
sudo systemctl enable docker && sudo systemctl start docker
# add the current user to the docker group
sudo usermod -aG docker $USER
# reauthenticate for the new group membership to take effect
su - $USER

2. Lấy SSL certificate

Loại Certbot apt, cài snapd/core/certbot, tạo symlink, rồi chạy standalone với domain thật:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
# remove apt version of certbot if installed
sudo apt remove certbot -y
# install snapd
sudo apt install snapd -y
# install snap core and update
sudo snap install core; sudo snap refresh core
# install certbot snap
sudo snap install --classic certbot
# create certbot symbolic link
sudo ln -s /snap/bin/certbot /usr/bin/certbot
# if a web server process is currently using port 80, stop it before proceeding
# generate a certificate
sudo certbot certonly --standalone --preferred-challenges http -d <%DNS NAME%>

Khi được hỏi, nhập email, đồng ý terms và chọn có/không nhận email từ Certbot. Ghi lại vị trí file certificate mà Certbot in ra.

Tạo group để Nginx đọc certificate theo hướng dẫn source:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# create ssl-certs group
sudo groupadd ssl-certs
# add $USER and root users to group
sudo usermod -aG ssl-certs $USER
sudo usermod -aG ssl-certs root
# verify the members of ssl-cert
getent group ssl-certs
# set owner group of /etc/letsencrypt
sudo chgrp -R ssl-certs /etc/letsencrypt
# set permissions on /etc/letsencrypt
sudo chmod -R g=rX /etc/letsencrypt

3. Chuẩn bị Mastodon và .env

Tạo thư mục PostgreSQL, Redis, public system và Nginx; pull image, chạy rake secret hai lần, chạy lệnh tạo VAPID key rồi mở .env:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
# create working directories
mkdir ~/docker/postgres -p && mkdir ~/docker/redis -p && mkdir ~/docker/mastodon/public/system -p && mkdir ~/docker/nginx/conf -p
# pull the mastodon web container
docker pull tootsuite/mastodon
# generate secrets, run this 2 times
docker run --rm -it tootsuite/mastodon bundle exec rake secret
# generate VAPID keys
docker run --rm -it tootsuite/mastodon bundle exec rake mastodon:webpush:generate_vapid_key
# create a mastodon .env file
# copy the generated secrets and keys into the .env file
# make sure to set the LOCAL_DOMAIN as this cannot be changed later
nano ~/docker/mastodon/.env

Dán mẫu .env và sửa LOCAL_DOMAIN, WEB_DOMAIN, PostgreSQL, secret, Web Push và SMTP. Tôi giữ tên biến nhưng không đưa password nguồn vào repo; giá trị DB_PASS, password database và SMTP nếu có phải là secret riêng:1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# This is a sample configuration file. You can generate your configuration
# with the `rake mastodon:setup` interactive setup wizard, but to customize
# your setup even further, you'll need to edit it manually. This sample does
# not demonstrate all available configuration options. Please look at
# https://docs.joinmastodon.org/admin/config/ for the full documentation.
# Note that this file accepts slightly different syntax depending on whether
# you are using `docker-compose` or not. In particular, if you use
# `docker-compose`, the value of each declared variable will be taken verbatim,
# including surrounding quotes.
# See: https://github.com/mastodon/mastodon/issues/16895
# Federation
# ----------
# This identifies your server and cannot be changed safely later
# ----------
LOCAL_DOMAIN=i12bretro.local
# ----------
# Optional, if different than LOCAL_DOMAIN
# ----------
#WEB_DOMAIN=toots.webredirect.org
# Redis
# -----
REDIS_HOST=redis
REDIS_PORT=6379
# PostgreSQL
# ----------
DB_HOST=postgres
DB_USER=mastodon_rw
DB_NAME=mastodon
DB_PASS=[REDACTED]
DB_PORT=5432
# Secrets
# -------
# Make sure to use `rake secret` to generate secrets
# -------
SECRET_KEY_BASE=
OTP_SECRET=
# Web Push
# --------
# Generate with `rake mastodon:webpush:generate_vapid_key`
# --------
VAPID_PRIVATE_KEY=
VAPID_PUBLIC_KEY=
# Sending mail
# ------------
SMTP_SERVER=smtp.example.com
SMTP_PORT=25
SMTP_LOGIN=
SMTP_PASSWORD=
SMTP_FROM_ADDRESS=mastodon@example.com
# IP and session retention
# -----------------------
# Make sure to modify the scheduling of ip_cleanup_scheduler in config/sidekiq.yml
# to be less than daily if you lower IP_RETENTION_PERIOD below two days (172800).
# -----------------------
IP_RETENTION_PERIOD=31556952
SESSION_RETENTION_PERIOD=31556952

Nhấn CTRL+O, Enter, CTRL+X để lưu .env. Tài liệu cấu hình đầy đủ của Mastodon là nguồn bổ sung được i12bretro liên kết; tôi không coi sample rút gọn là đầy đủ cho production.

4. Chạy PostgreSQL, Redis và Mastodon

Chạy network, database, migration, frontend, tạo owner/admin, rồi khởi động streaming và Sidekiq. Ở lệnh tạo account, thay placeholder username/email và lưu password output an toàn; không ghi password vào Markdown:1

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# set owner of docker directory
sudo chown "$USER":"$USER" ~/docker -R
# create containers
docker network create containers
# run the postgesql container
# Replace the source password value with your own local secret before running.
docker run -d --name postgres -e POSTGRES_USER=mastodon_rw -e POSTGRES_PASSWORD=[REDACTED] -e POSTGRES_DB=mastodon -v ~/docker/postgres:/var/lib/postgresql/data --network containers --restart=unless-stopped postgres:latest
# run the redis container
docker run -d --name redis -v ~/docker/redis:/data --network containers --restart=unless-stopped redis
# initialize the mastodon database
docker run --rm -it --network containers --env-file ~/docker/mastodon/.env tootsuite/mastodon rails db:migrate
# run the mastodon frontend container
docker run -d --name mastodon --env-file ~/docker/mastodon/.env -p 3000:3000 -v ~/docker/mastodon/public/system:/mastodon/public/system --network containers --restart=unless-stopped tootsuite/mastodon bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p 3000"
# connect to shell inside mastodon container
docker exec -it mastodon /bin/bash
# set the RAILS_ENV variable
RAILS_ENV=production
# create an owner/admin account
# copy the password output for later
bin/tootctl accounts create <%username%> --email <%email address%> --confirmed --role Owner
# exit the container
exit
# run the mastodon streaming container
docker run -d --name mastodon-stream --env-file ~/docker/mastodon/.env -p 4000:4000 --network containers --restart=unless-stopped tootsuite/mastodon node ./streaming
# run the mastodon sidekiq container
docker run -d --name mastodon-sidekiq --env-file ~/docker/mastodon/.env --network containers -v ~/docker/mastodon/public/system:/mastodon/public/system --restart=unless-stopped tootsuite/mastodon bundle exec sidekiq

5. Nginx reverse proxy

Tải nginx config chính thức của Mastodon, sửa upstream để chạy qua Docker network, thay domain và đường dẫn certificate, rồi tạo container proxy:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
# download the default mastodon nginx configuration
wget -O ~/docker/nginx/conf/mastodon.conf https://raw.githubusercontent.com/mastodon/mastodon/main/dist/nginx.conf
# replace some options to work running in docker containers
sed -i "s/try_files \$uri =404;/try_files \$uri @proxy;/" ~/docker/nginx/conf/mastodon.conf
# update the server_name with the URL being used to reach mastodon
# make sure to replace WEB_DOMAIN
sed -i "s/server_name example.com;/\server_name <%WEB_DOMAIN%>;/" ~/docker/nginx/conf/mastodon.conf
# update mastodon frontend server
sed -i 's/server 127.0.0.1:3000/server mastodon:3000/' ~/docker/nginx/conf/mastodon.conf
# update mastodon stream server
sed -i 's/server 127.0.0.1:4000/server mastodon-stream:4000/' ~/docker/nginx/conf/mastodon.conf
# update the ssl certificate path
# make sure to replace DNS NAME
sed -i 's/# ssl_certificate\s*\/etc\/letsencrypt\/live\/example.com\/fullchain.pem;/ssl_certificate\t\/etc\/letsencrypt\/live\/<%DNS NAME%>\/fullchain.pem;/' ~/docker/nginx/conf/mastodon.conf
# update the ssl key path
# make sure to replace DNS NAME
sed -i 's/# ssl_certificate_key\s*\/etc\/letsencrypt\/live\/example.com\/privkey.pem;/ssl_certificate_key\t\/etc\/letsencrypt\/live\/<%DNS NAME%>\/privkey.pem;/' ~/docker/nginx/conf/mastodon.conf
# create nginx proxy container
docker run --name nginx -p 80:80 -p 443:443 --network containers -v ~/docker/nginx/conf:/etc/nginx/conf.d:ro -v /etc/letsencrypt:/etc/letsencrypt:ro -d nginx

Đọc lại mastodon.conf sau mỗi sed; các placeholder <%WEB_DOMAIN%><%DNS NAME%> phải được thay bằng domain thật trước khi chạy. Kiểm tra port 80/443 chỉ có proxy cần thiết đang listen.

6. Đăng nhập và đổi password

Mở https://<%WEB_DOMAIN%>, bấm Sign in và dùng owner email/password đã tạo. Vào PreferencesAccount, nhập password hiện tại, đặt và xác nhận password mới, bấm Save Changes, Logout rồi login lại để xác nhận.

Kiểm tra sau triển khai

Kiểm tra docker ps, log từng container, certificate chain, HTTPS redirect, PostgreSQL/Redis health, streaming và Sidekiq. Backup ~/docker/mastodon, .env ngoài repo với quyền chặt; không public trực tiếp cổng 3000/4000 và không đưa .env vào Git.

Nguồn


  1. https://i12bretro.github.io/tutorials/0853.html — i12bretro tutorial 0853. Tutorial được biên tập độc lập từ numbered HTML page; credential trong source đã được thay bằng placeholder an toàn. ↩︎ ↩︎ ↩︎

  2. https://www.youtube.com/watch?v=_K5la-WchuY — Run Mastodon - A Federated Twitter Alternative - in Docker — i12bretro ↩︎


0 Bình luận

Góp Ý / Bình Luận / Đánh giá