手动部署 Tandoor 食谱服务
Tandoor 是一个使用 Python 开发的食谱管理程序,使用 Web 访问。
如果环境允许,使用 Docker 部署是最方便的,这里就不介绍了。
我因为一些原因选择手动部署,踩了些坑,在此记录下。
基础信息
- 官网: tandoor.dev
- 内存: 运行时 ~300M,构建前端代码需要 ~2G 内存。
- 参考: 参考了官网的手动部署教程。
- 注意: 无官方中文语言包,但是这不会阻止你使用中文撰写食谱。
开始部署
范例环境为 Debian 12。大部分步骤一致,RHEL 系列系统需要注意替换部分指令。
建议:部署前将系统更新至最新,如 apt update && sudo apt dist-upgrade
如未特别说明,本文提及的指令均需要使用 root
账号执行。
数据库访问
数据库可以安装到同一个机器或单独一个机器。
执行下述 SQL 语句初始化一个用户名为 tandoor
密码为 tand00r
的数据库:
CREATE USER tandoor WITH PASSWORD 'tand00r';
CREATE DATABASE tandoor OWNER tandoor;
GRANT CONNECT ON DATABASE tandoor TO tandoor;
GRANT ALL PRIVILEGES ON DATABASE tandoor TO tandoor;
ALTER ROLE tandoor SET client_encoding TO 'utf8';
ALTER ROLE tandoor SET default_transaction_isolation TO 'read committed';
ALTER ROLE tandoor SET timezone TO 'UTC';
应用用户
单独分配一个用户给 Tandoor 储存数据。使用 root
执行下述指令:
adduser --system --shell "$(command -v nologin)" --home /var/lib/tandoor tandoor --no-create-home
mkdir -p /var/lib/tandoor/{app,logs,nodejs}
安装依赖
注意 Python 要求 3.9 或以上版本。
apt install -y curl nginx git python3 python3-dev python3-pip python3-venv \
libpq-dev libsasl2-dev libldap2-dev libssl-dev
部署代码
下载源码并部署到指定目录:
curl -Ls https://github.com/TandoorRecipes/recipes/archive/refs/tags/1.5.4.tar.gz \
| tar -zxf - -C /var/lib/tandoor/app --strip-components=1
然后初始化专属的虚拟环境:
python3 -m venv --prompt tandoor /var/lib/tandoor/venv
/var/lib/tandoor/venv/bin/pip install -r /var/lib/tandoor/app/requirements.txt
构建前端代码
首先需要简易部署一下比较新版本的 nodejs
:
curl -Ls https://nodejs.org/dist/v18.17.1/node-v18.17.1-linux-x64.tar.xz \
| tar -Jxf - -C /var/lib/tandoor/nodejs --strip-components=1
因为是免安装,所以一会需要把指令包围在 PATH
环境变量配置内执行:
cd /var/lib/tandoor/app/vue
PATH="/var/lib/tandoor/nodejs/bin:$PATH" bash <<'EOF'
# 启用 yarn
corepack enable
# 安装依赖并构建
yarn install --frozen-lockfile && yarn build
EOF
最后,将构建后的文件部署到对应的位置:
# 部署构建后的文件
/var/lib/tandoor/venv/bin/python3 manage.py collectstatic --no-input
/var/lib/tandoor/venv/bin/python3 manage.py collectstatic_js_reverse
提示:如果机器的内存不够,你可以提前在其他设备构建好并打包,然后重复【部署代码】步骤:
# 使用 docker 容器构建:
# node:18.17.1-bookworm
TANDOOR_VERSION="1.5.4"
# 部署源码
mkdir -p "tandoor-${TANDOOR_VERSION}"
curl -LfSs https://github.com/TandoorRecipes/recipes/archive/refs/tags/${TANDOOR_VERSION}.tar.gz \
| tar -zx -C "tandoor-${TANDOOR_VERSION}" --strip-components 1
# 构建
pushd "tandoor-${TANDOOR_VERSION}"/vue
yarn install --frozen-lockfile
yarn build
# 这个目录太大了,运行时不需要
rm -rf node_modules
popd
# 打包
tar zcf tandoor-${TANDOOR_VERSION}.tar.gz "tandoor-${TANDOOR_VERSION}"
配置服务器
服务器设定需要在服务器端更改。
cd /var/lib/tandoor/app
cp -n .env.template .env
nano .env # 或其他你喜欢的编辑器
最基础的情况下需要修改下述内容:
SECRET_KEY
: 随机生成,每个网站独一无二的密钥。- 例如
base64 /dev/urandom | head -c50
- 例如
POSTGRES_*
: PostgreSQL 服务器连接信息配置
最后,将该程序的目录所有权修改为 tandoor
系统用户:
chown -R tandoor /var/lib/tandoor
数据库迁移
第一次执行或升级应用程序后,需要更新数据库结构。这项操作在业内称之为数据库迁移。
cd /var/lib/tandoor/app/
env $(cat .env |grep "^[^#]" | xargs) \
/var/lib/tandoor/venv/bin/python3 manage.py migrate
建立系统服务
首先安装一个名为 gunicorn_tandoor
,然后设定为自动启动,并立即启动。
cat > /etc/systemd/system/gunicorn_tandoor.service <<EOF
[Unit]
Description=tandoor recipes
After=network.target
[Service]
Type=simple
Restart=always
RestartSec=3
User=tandoor
Group=www-data
WorkingDirectory=/var/lib/tandoor/app
EnvironmentFile=/var/lib/tandoor/app/.env
ExecStart=/var/lib/tandoor/venv/bin/gunicorn --bind unix:/var/lib/tandoor/tandoor.sock recipes.wsgi:application
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable gunicorn_tandoor
systemctl restart gunicorn_tandoor
配置 nginx 服务器
cat > /etc/nginx/conf.d/tandoor.conf <<'EOF'
server {
listen 8002;
access_log /var/log/nginx/access_tandoor.log;
error_log /var/log/nginx/error_tandoor.log;
# serve media files
location /static/ {
alias /var/lib/tandoor/app/cookbook/static/;
}
location /media/ {
alias /var/lib/tandoor/mediafiles/;
}
location / {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://unix:/var/lib/tandoor/tandoor.sock;
}
}
EOF
nginx -t && nginx -s reload
注意这个配置文件没有 HTTPS,推荐使用 acme.sh
+ DNS 验证方式获取免费证书,并配置自动续签。
结束
部署完成后,你应当可以通过 ip:8082
来访问该服务器了。
此时应该还会有一些基础的配置(如默认管理员账号),本文就此略过。