Socialhome 0.24.0 Docker Compose 部署指南

Socialhome 0.24.0 容器化部署实录:按官方四层路线组装后端制品+PostgreSQL+Redis+nginx,前端 SPA 路由衔接、webfinger/nodeinfo/建号全链路实测,沉淀 7 条 2026-11-02 排障记录。

SocialhomeSocialhomeFediverseDjangoPythonDocker自托管2026/11/02

Socialhome 0.24.0 Docker Compose 部署指南

目标:在一台 Ubuntu 服务器上,用 Docker Compose 把 Socialhome 0.24.0 官方文档 Docker 安装页给出的路线(后端制品 + PostgreSQL + Redis + 负载均衡四层)完整落地,并逐条实测验证 Web、管理后台、API、webfinger、nodeinfo 与管理员建号流程。本文全部配置与回显均为 2026-11-02 真实部署记录;官方从未提供 compose 编排文件,本文的 compose 文件是按官方指南组装后的真实形态。产品背景与选型见 《Socialhome 0.24.0 介绍与选型指南》。

一、环境信息

项目值
操作系统Ubuntu(内核 7.0.0-38-generic)
DockerDocker version 29.9.2, build a82e528
ComposeDocker Compose version v5.6.1
硬件6 vCPU / 15Gi 内存(官方按 4 vCPU 估算约需 3GB,见架构章)
组件版本后端 v0.24.0(Codeberg tag,2026-08-01);前端 socialhome-ui 0.12.2(Codeberg generic 制品)
依赖服务PostgreSQL 17、Redis 7、nginx 1.27
对外端口8135(HTTP,TLS 由外部反代终结后本层仅示例)
私有网络10.89.70.0/24(显式指定,避开已占用槽位)
编排项目名socialhome-v0.24.0-stack(compose 顶层 name: 显式声明)
部署目录/opt/data/quzuo/tmp/socialhome/
示例账号admin / q1w2e3r4

二、部署架构总览

官方文档 Docker 安装页(https://socialhome.readthedocs.io/en/latest/installation.html)给出的容器化路线由四个角色组成,本文的编排一一对应:

角色本文实现官方依据
后端应用制品 codeberg.org/socialhome/socialhome:v0.24.0官方容器制品库,可匿名拉取
PostgreSQLpostgres:17官方建议最新版,数据路径需持久化
Redisredis:7同上
负载均衡(LB)nginx:1.27官方要求 LB 承担 TLS 终结与 /media 服务

后端进程内部由 Circus 统一守护四类进程(官方文档与制品内 config/circus_docker.ini):Daphne(HTTP+WebSocket,端口 23564)、RQ worker(highest/high/default/low/lowest 五级队列)、Dramatiq(进程数默认等于 vCPU 数)、APScheduler(runscheduler)。

官方文档给出的内存规划依据:基础约 650MB,Daphne 每 worker 约 320MB,Dramatiq 每 vCPU 约 500MB;4 vCPU 默认配置约 3GB。

后端有两个路径必须持久化(官方原文):

  • /app/socialhome/media(读写,上传的媒体文件)
  • /app/var(读写,搜索索引等运行期数据)

关键认知:v0.23 起后端不再内置任何用户界面(官方原文「does not serve media and does not include any frontend」),前端是独立的 socialhome-ui 单页应用,由 LB 按路由规则分流——只起后端四件套你会看到首页 405,这是本部署最容易踩的结构性坑(见第十二章排障 2)。

三、获取前端制品

官方文档明确「Currently there are no Docker images for the frontend application. You will need to serve the extracted frontend files via your chosen web server」,前端制品在 Codeberg generic 包仓库。取 0.12.2 版并解压:

mkdir -p /opt/data/quzuo/tmp/socialhome/ui-dist
curl -sL -o socialhome-ui-0.12.2.tar.gz \
  "https://codeberg.org/api/packages/socialhome/generic/socialhome-ui/0.12.2/socialhome-ui-0.12.2.tar.gz"
tar -xzf socialhome-ui-0.12.2.tar.gz -C ui-dist

解压后目录核对(实测):

$ ls ui-dist/dist
assets
favicon.ico
index.html

index.html、favicon.ico、/assets 正是官方文档「Routing to the frontend」一节要求由 LB 直接托管的内容。

四、Compose 编排文件

官方从未在现行仓库提供 compose 文件(2016 年 cookiecutter 脚手架遗留即删),以下是按官方指南组装、当天实际跑通的完整 docker-compose.yml:

name: socialhome-v0.24.0-stack
services:
  backend:
    image: codeberg.org/socialhome/socialhome:v0.24.0
    restart: unless-stopped
    env_file: .env
    volumes:
      - media:/app/socialhome/media
      - var:/app/var
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - shnet

  db:
    image: postgres:17
    restart: unless-stopped
    environment:
      POSTGRES_USER: socialhome
      POSTGRES_PASSWORD: ${PG_PASSWORD}
      POSTGRES_DB: socialhome
    volumes:
      - dbdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U socialhome -d socialhome"]
      interval: 5s
      timeout: 3s
      retries: 10
    networks:
      - shnet

  redis:
    image: redis:7
    restart: unless-stopped
    command: ["redis-server", "--appendonly", "yes"]
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s
      retries: 10
    networks:
      - shnet

  web:
    image: nginx:1.27
    restart: unless-stopped
    ports:
      - "8135:80"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - media:/srv/media:ro
      - ./ui-dist:/srv/ui:ro
    depends_on:
      - backend
    networks:
      - shnet

networks:
  shnet:
    ipam:
      config:
        - subnet: 10.89.70.0/24

volumes:
  dbdata:
  redisdata:
  media:
  var:

要点对照官方要求:

  • 后端不映射任何端口,只暴露给私有网络内的 LB——官方要求「TLS should be terminated by a load balancer before sending traffic to the application container」;
  • media/var 两个卷对应官方「Backend container volumes」一节必须持久化的两个路径;web 服务以只读方式共享 media 卷来履行「LB 负责 /media 服务」的职责;
  • db/redis 设健康检查,后端 depends_on 健康条件,避免迁移抢跑;
  • 顶层 name: 显式声明项目名,防止多栈环境互删。

五、负载均衡路由配置

官方文档给出路由规则:12 个路径前缀 + 两类 Accept 头正则必须转后端 23564,其余落前端文件,LB 回写 X-Forwarded-Proto。实测跑通的 nginx.conf 全文:

map $http_accept$http_content_type $ap_request {
    default 0;
    "~*application/(activity|ld)\+json.*" 1;
    "~*application/(xrd\+|magic-envelope\+)xml.*" 1;
}

upstream socialhome_backend {
    server backend:23564;
}

server {
    listen 80;
    server_name _;

    client_max_body_size 20m;

    location /media {
        alias /srv/media;
        add_header X-Robots-Tag "noindex, nofollow";
    }

    location ~* /(admin|api|api-token-auth|django-rq|fetch|hcard|jsi18n|nodeinfo|receive|static|webfinger|\.well-known|ch) {
        proxy_pass http://socialhome_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 3600s;
    }

    location / {
        if ($ap_request = 1) {
            proxy_pass http://socialhome_backend;
            break;
        }
        root /srv/ui/dist;
        try_files $uri $uri/ $uri.html /index.html;
    }
}

三个易错点:

  1. Accept 头分流是联邦识别的命门:对端实例用 application/activity+json 抓取你的 profile,若这条 map 缺失,AP 对端会拿到 SPA 的 index.html 而非活动流 JSON;
  2. /media 必须加 X-Robots-Tag "noindex, nofollow":官方原文要求 LB「deny indexing of the files」;
  3. WebSocket 升级头:Daphne 同时承载 /ch 实时通道,缺 Upgrade/Connection 头则前端时间线不实时。

生产环境请再套一层 TLS 终结并把 X-Forwarded-Proto 固定为 https(官方要求),本示例以 8135 端口 HTTP 直连演示。

六、准备 .env

后端配置全部走环境变量,官方「Backend configuration」一节列出最小集。实测 .env 全文:

PG_PASSWORD=ShPg2026q1w2
DATABASE_URL=postgres://socialhome:ShPg2026q1w2@db:5432/socialhome
DJANGO_SECRET_KEY=0e371812caa290902b5e54501dad71a426116e35bf48c456e23ec8ac16fa7c0e80ceb6f42fa63f2bcb9a05b20ba20b202234
DJANGO_ALLOWED_HOSTS=127.0.0.1,localhost
SOCIALHOME_DOMAIN=127.0.0.1:8135
SOCIALHOME_HTTPS=False
DJANGO_SECURE_SSL_REDIRECT=False
DJANGO_ACCOUNT_ALLOW_REGISTRATION=True
REDIS_HOST=redis
RQWORKER_NUM=1
DAPHNE_WORKER_NUM=1
SOCIALHOME_LOG_TARGET=console
  • DJANGO_SECRET_KEY 用官方 django-extensions 的 generate_secret_key 命令生成(见 CLI 篇);官方强调「do NOT change this after setup」;
  • SOCIALHOME_DOMAIN 与 DJANGO_ALLOWED_HOSTS 都写成 域名[:端口],联邦身份(handle)即 用户名@SOCIALHOME_DOMAIN;
  • SOCIALHOME_LOG_TARGET=console 是官方 Docker 页的推荐值(裸机默认 file);
  • 其余全部可选变量与默认值,见 《Socialhome 0.24.0 配置参数详解》。

七、启动与数据迁移

cd /opt/data/quzuo/tmp/socialhome
docker compose up -d

后端启动脚本会自动执行 python manage.py migrate,无需手工初始化。启动日志(实测节选):

Operations to perform:
  Apply all migrations: account, activities, admin, auth, authtoken, content, contenttypes, django_dramatiq, django_rq, dynamic_preferences, dynamic_preferences_users, federate, redisboard, reversion, robots, sessions, sites, socialaccount, socialhome, users
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0001_initial... OK
  ...

服务状态核对(实测):

$ docker compose ps
NAME                               IMAGE                                        COMMAND                  SERVICE   CREATED         STATUS                   PORTS
socialhome-v0240-stack-backend-1   codeberg.org/socialhome/socialhome:v0.24.0   "/bin/sh -c /start_s…"   backend   7 minutes ago   Up 7 minutes
socialhome-v0240-stack-db-1        postgres:17                                  "docker-entrypoint.s…"   db        7 minutes ago   Up 7 minutes (healthy)   5432/tcp
socialhome-v0240-stack-redis-1     redis:7                                      "docker-entrypoint.s…"   redis     7 minutes ago   Up 7 minutes (healthy)   6379/tcp
socialhome-v0240-stack-web-1       nginx:1.27                                   "/docker-entrypoint.…"   web       3 minutes ago   Up 3 minutes             0.0.0.0:8135->80/tcp, [::]:8135->80/tcp

八、Web 与联邦端点验证

页面与 API(实测):

$ curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}B\n" http://127.0.0.1:8135/
200 text/html 655B
$ curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}B\n" http://127.0.0.1:8135/admin/login/
200 text/html; charset=utf-8 4256B
$ curl -s -o /dev/null -w "%{http_code} %{content_type} %{size_download}B\n" http://127.0.0.1:8135/api/
200 text/html; charset=utf-8 1029B

首页 655B 即前端 ui-dist/dist/index.html(SPA 壳,<title>Socialhome</title>),管理后台与 API 由后端响应——前后端分流生效。

webfinger(实测完整回显):

$ curl -s "http://127.0.0.1:8135/.well-known/webfinger?resource=acct:admin@127.0.0.1:8135"
{"subject": "acct:admin@127.0.0.1:8135", "aliases": ["http://127.0.0.1:8135/u/admin/", "http://127.0.0.1:8135/u/admin/"], "links": [{"rel": "http://microformats.org/profile/hcard", "type": "text/html", "href": "http://127.0.0.1:8135/hcard/users/0598121f-4e4d-4a8f-921c-aca8707ffccb"}, {"rel": "http://joindiaspora.com/seed_location", "type": "text/html", "href": "http://127.0.0.1:8135"}, {"rel": "http://webfinger.net/rel/profile-page", "type": "text/html", "href": "http://127.0.0.1:8135/u/admin/"}, {"rel": "salmon", "href": "http://127.0.0.1:8135/receive/users/0598121f-4e4d-4a8f-921c-aca8707ffccb"}, {"rel": "self", "href": "http://127.0.0.1:8135/u/admin/", "type": "application/activity+json"}, {"rel": "http://ostatus.org/schema/1.0/subscribe", "template": "http://127.0.0.1:8135/search/?q={uri}"}]}

注意 links 里同时出现 Diaspora 系(joindiaspora.com/seed_location、salmon、hcard)与 AP 系(rel: self 指向 application/activity+json)两套发现链接——双协议联邦的直观证据。

nodeinfo(实测):

$ curl -s "http://127.0.0.1:8135/nodeinfo/1.0/"
{"version": "1.0", "software": {"name": "socialhome", "version": "0.24.0"}, "protocols": {"inbound": ["diaspora"], "outbound": ["diaspora"]}, "services": {"inbound": [], "outbound": []}, "openRegistrations": true, "usage": {"users": {}}, "metadata": {"nodeName": "Socialhome"}}

$ curl -s -o /dev/null -w "%{http_code}\n" "http://127.0.0.1:8135/nodeinfo/2.0/"
404

nodeinfo/1.0 如实报出软件版本 0.24.0;nodeinfo/2.0 不存在(404 为 Django 版「Page Not found」页)——对外可见性登记时注意 2.0 探测会失败。

九、创建管理员账号

官方 running 文档给出的 shell 流程(邮件确认 + 超管授权)。本示例用 createsuperuser 直接建号(注册流程需要可用邮件服务,官方原文「email is required for signing up」,初始实例建议走命令行):

docker compose exec backend python manage.py createsuperuser
# 交互输入:Username: admin / Email: admin@quzuo.net / Password: q1w2e3r4(两次)

建号后按官方「Confirming user emails via the shell」一节跳过邮件确认:

docker compose exec backend python manage.py shell -c "
from allauth.account.models import EmailAddress
EmailAddress.objects.filter(email='admin@quzuo.net').update(verified=True)
"

核验结果(实测):

$ docker compose exec backend python manage.py shell -c "
from socialhome.users.models import User
u = User.objects.get(username='admin')
print('user id:', u.id, '| is_superuser:', u.is_superuser)
print('profile handle:', u.profile.handle)
print('profile uuid:', u.profile.uuid)
"
user id: 1 | is_superuser: True
profile handle: admin@127.0.0.1:8135
profile uuid: 0598121f-4e4d-4a8f-921c-aca8707ffccb

profile handle 即联邦身份 admin@127.0.0.1:8135。此时再查 webfinger 才会返回上面第八节的 200 JSON——建用户之前 webfinger 查任何账号都是 404(见排障 5)。

十、运行时核对

后端进程模型(制品内无 ps,借 /proc 核对,实测节选):

/proc/1:  /usr/local/bin/python3.12 /usr/local/bin/circusd /app/config/circus.ini
/proc/29: /usr/local/bin/python manage.py rqworker highest high default low lowest
/proc/30: /usr/local/bin/python manage.py runscheduler
/proc/31: /usr/local/bin/python3.12 /usr/local/bin/dramatiq --path . --processes 6 --threads 8 ...
/proc/32: /usr/local/bin/python3.12 /usr/local/bin/daphne --fd 6 config.asgi:application -v1 --proxy-headers
/proc/50..55: dramatiq 子进程 ×6

与官方文档一致:Circus 守护 Daphne、RQ worker、Dramatiq、APScheduler 四类;Dramatiq 进程数 --processes 6 正等于本机 vCPU 数(默认行为,可用 DRAMATIQ_NPROCS 压低)。

任务队列水位(实测):

$ docker compose exec backend python manage.py rqstats
Django RQ CLI Dashboard

------------------------------------------------------------------------------------------
| Name           |    Queued |    Active |  Deferred |  Finished |    Failed |   Workers |
------------------------------------------------------------------------------------------
| default        |         0 |         0 |         0 |         0 |         0 |         1 |
| high           |         0 |         0 |         0 |         0 |         0 |         1 |
| highest        |         0 |         0 |         0 |         0 |         0 |         1 |
| low            |         0 |         0 |         0 |         0 |         0 |         1 |
| lowest         |         0 |         0 |         0 |         0 |         0 |         1 |
------------------------------------------------------------------------------------------

搜索索引落盘核对(/app/var 卷,rebuild_index 后实测):

$ docker compose exec backend ls -la /app/var
total 24
drwxrwxr-x 4 root root 4096 Nov  2 09:36 .
drwxr-xr-x 1 root root 4096 Nov  2 09:25 ..
-rw-rw-r-- 1 root root   14 Jan 10  2019 .gitignore
drwxrwxr-x 2 root root 4096 Nov  2 09:25 whoosh
drwxr-xr-x 2 root root 4096 Nov  2 09:36 xapian-index

十一、更新流程

  1. 到 Codeberg tags 页确认新版本(如 v0.25.0),不要追 latest 标签制品(它落后于 tag,本次实查 latest 内是 0.23.0);
  2. 修改 compose 中后端制品 tag,docker compose pull backend;
  3. docker compose up -d backend——启动脚本自动跑增量迁移;
  4. 前端独立升级:下载新版 generic 包解压替换 ui-dist/,docker compose exec web nginx -s reload;
  5. 备份四件套(官方 running 章节口径):数据库、.env、media 路径、Redis 数据。

十二、排障实录汇总

以下 7 条全部为 2026-11-02 部署过程实际遇到并定位的问题:

  1. GitLab 旧 registry 制品陈旧:registry.gitlab.com/jaywink/socialhome:latest 内是 0.20.0(Python 3.10、还带 bower/Gruntfile 的旧构建)。核对版本的方法:进后端执行 cat /app/socialhome/__init__.py。制品一律用 Codeberg 容器库 + 明确 tag。
  2. 只起后端时 GET / 返回 405:回显 Allow: OPTIONS——v0.23+ 后端首页视图是空实现(HomeView(View): pass),不再提供任何界面;必须配前端 SPA + 第五节 nginx 路由才有 200 首页。
  3. 每个进程日志刷 UserWarning: !!! No .env file found!:制品期望 /app/.env 存在,用 compose env_file 注入时该告警必然出现,无害,可忽略。
  4. 启动即报 ERROR ... get_user_private_key - no profile for http://127.0.0.1:8135/u/None/:FEDERATION_USER 未设置导致联邦签名找不到 profile;建好用户并设置该变量后消失(见配置篇)。
  5. 建用户前 webfinger 全 404:属正常时序——acct:<用户>@域名 必须存在对应 profile 才能被解析,先完成第九节建号。
  6. drf-haystack 每次执行命令都打印大段 sunset 公告:上游弃用警告(2026-01-01 后归档),不影响功能,Socialhome 搜索栈仍可用。
  7. 设置了 REDIS_URL 会直接 ImproperlyConfigured 起不来:该环境变量已废弃,官方只认 REDIS_HOST/REDIS_PORT/REDIS_DB/REDIS_PASSWORD(制品 settings 源码 80-84 行实查)。

十三、小结与关联

四层架构(后端制品 + PostgreSQL + Redis + nginx 双职责 LB)是官方 Docker 路线的全部要件;本指南的 compose、nginx、.env 三份文件均为当天跑通的原文。部署完成后:

Socialhome 0.24.0 Docker Compose 部署指南 - Quzuo