部署教程
这一章详细介绍怎样把Vallotton部署到一台服务器上。部署以后,你可以在任何地方(包括手机上),通过自己的域名打开Vallotton;画图也在服务器上进行,不需要你的电脑一直开着。这一章假设你会用命令行登录和操作一台Linux服务器。如果你只想在自己的电脑上用,看快速上手就够了。
你需要准备的东西
- 一台Linux服务器,能从公网访问。下面的命令都以Ubuntu为例。画图是在NovelAI那边进行的,所以服务器不需要显卡。
- 一个域名。在域名服务商那里添加一条A记录,指向服务器的IP。Vallotton只能通过HTTPS域名登录,直接用IP地址打开是登录不了的。
- NovelAI和DeepSeek的密钥,和快速上手里要的一样,获取方法见准备两个账号。
- 在服务器上装好Docker、nginx和certbot。Docker用来运行Vallotton,nginx负责把你的域名接到Vallotton上,certbot用来申请免费的HTTPS证书:
curl -fsSL https://get.docker.com | sh sudo apt install nginx certbot python3-certbot-nginx - 在云服务商的控制台里放行22、80、443三个端口(通常在「安全组」或「防火墙」设置里)。22用来登录服务器,80和443用来访问网页。
部署步骤
部署好以后,Vallotton会在服务器上的Docker里运行,只在服务器本机开一个端口(默认是8300)。从外面访问你的域名时,请求先到服务器上的nginx,由它负责HTTPS,再转给Vallotton。下面按顺序来讲解。
1.下载代码
登录服务器,把代码下载到一个固定的位置,比如/srv/vallotton/app。还要建一个目录专门存放画好的图,比如/srv/vallotton/media。后文中会以这两个地址为例,如果要用其他路径,后文中的指令都需要对应地调整。
sudo mkdir -p /srv/vallotton/media
sudo chown -R $USER /srv/vallotton
git clone https://github.com/FFTYYY/ProjectVallotton.git /srv/vallotton/app
cd /srv/vallotton/app
下文的命令都默认在这个代码目录/srv/vallotton/app里运行。
2.填写.env
Vallotton的所有配置都写在代码目录下的.env文件里,包括各种密钥和密码。先从模板复制一份:
cp .env.example .env
然后用编辑器打开它(比如nano .env),修改下面这些项:
| 项 | 填什么 |
|---|---|
LLM_PROVIDER | 用什么语言模型。目前只支持deepseek或grok。模板里默认是deepseek。 |
DEEPSEEK_API_KEY | DeepSeek的API key。只有LLM_PROVIDER选deepseek时需要填。以sk-开头。 |
GROK_API_KEY | Grok的API key。只有LLM_PROVIDER选grok时需要填。以xai-开头。 |
NOVELAI_API_KEY | NovelAI的密钥。以pst-开头。 |
APP_USERNAMEAPP_PASSWORD | 登录Vallotton网页用的用户名和密码。 |
ADMIN_PASSWORD | 管理后台的密码。通常不会用到,随便设一个长一点的随机密码就行。 |
DJANGO_SECRET_KEY | 一串随机字符,用来保护登录状态。 |
POSTGRES_PASSWORD | 数据库的密码。你自己不会用到它,同样填一串随机字符即可。 |
DOMAIN | 你的域名。不要带https://前缀。例如vallotton.example.com。 |
MEDIA_DIR | 存放图片的目录,填上一步建的/srv/vallotton/media。 |
下面几项不是必填的,但比较常用:
OPENROUTER_API_KEY:Openrouter的API key。填了以后,如果语言模型的官方接口连不上,Vallotton会自动暂时切换到OpenRouter备用线路。MCP_TOKEN:MCP的密钥。只有打算开启MCP时需要填。一般填一串随机字符,用到的时候复制即可。- 各家的模型型号和推理强度,比如
DEEPSEEK_MODEL、GROK_REASONING_EFFORT:想换模型或者调快慢时改。详细列表见后文环境变量一览
其余的项通常保持默认就可以。环境变量的详细列表见最后的环境变量一览。
3.启动
在代码目录下运行:
docker compose up -d --build
第一次启动要下载和构建几个Docker镜像,需要等几分钟。完成以后,用下面两条命令检查一下:
docker compose ps
curl -s http://127.0.0.1:8300/api/auth/me
第一条命令应该列出db、backend、web三个容器,状态都是Up。第二条命令应该返回{"authenticated": false},说明Vallotton已经在服务器本机的8300端口上跑起来了。
这时还不能从外网访问,因为8300端口只对服务器本机开放。外网访问要经过下一步配置的nginx。如果8300端口已经被服务器上别的程序占用了,可以在.env里把VALLOTTON_HTTP_PORT改成别的端口,然后再运行一次docker compose up -d,下一步中的nginx配置也要跟着改。
4.配置域名和HTTPS
代码里带了一份nginx的配置模板deploy/host-nginx.conf.example,它会把发到你域名上的访问转给Vallotton。下面的命令会自动配置nginx。这个命令以及后文中,我们以vallotton.example.com这个域名为例。运行之前,记得先把命令里的vallotton.example.com换成你的域名。
sudo sh -c 'sed "s/YOUR_DOMAIN/vallotton.example.com/g" deploy/host-nginx.conf.example > /etc/nginx/sites-available/vallotton'
sudo ln -s /etc/nginx/sites-available/vallotton /etc/nginx/sites-enabled/
sudo nginx -t && sudo systemctl reload nginx
然后用certbot申请HTTPS证书(同样,把示例域名vallotton.example.com换成你的域名)。它会自动修改刚才的配置,加上HTTPS,并且把http的访问自动跳转到https:
sudo certbot --nginx -d vallotton.example.com
证书的有效期是90天,certbot会在到期前自动续期,不需要额外操作。
如果你的域名用了Cloudflare:用certbot申请证书之前,记得先在Cloudflare里把这条记录切成「仅DNS」(灰色的云朵),申请成功以后再切回代理。
也可以选择不用certbot,改用Cloudflare签发的源站证书(Origin Certificate):在Cloudflare的SSL/TLS → Origin Server里生成,有效期15年,不用续期。把证书和私钥放到服务器上,在nginx配置里加一段443端口的server块指向它们就行。这种证书只在经过Cloudflare代理访问时有效。
不管用哪种证书,Cloudflare的SSL/TLS模式都要选「Full (strict)」,不能选「Flexible」,否则网页能打开,但是登录不了。
5.打开网页
一切顺利的话,在浏览器里打开https://vallotton.example.com(换成你的域名),用.env里设的APP_USERNAME和APP_PASSWORD即可登录Vallotton。之后的用法和快速上手、进阶指南里讲的完全一样。也可以在手机上将Vallotton安装为一个app。见进阶指南的在手机上用。
需要注意的是,一定要通过https和域名访问。如果直接用http或者用服务器的IP打开,那么即使页面能显示,也无法登录。这是为了安全而故意设计的。
日常维护
下面的命令都在代码目录/srv/vallotton/app里运行。
- 更新到新版本:拉取最新的代码,再重新构建、启动。
git pull && docker compose up -d --build - 修改配置:改完
.env以后运行docker compose up -d就会生效。网页登录的账号和密码也是这样改,每次启动时会自动更新。 - 查看日志:出了问题想看看发生了什么,可以看后端的日志,按Ctrl+C退出。
docker compose logs -f backend - 停止:运行
docker compose down。对话和图片都会保留,下次docker compose up -d就能继续用。不要加-v,那样会把数据库一起删掉。 - 备份:Vallotton的全部数据就是数据库和图片目录(图片存在单独的文件夹中,而非数据库内,这是为了提高性能和便于管理)。以下命令备份数据库和图片目录:
从备份恢复数据库(将docker compose exec db pg_dump -U vallotton vallotton | gzip > backup-$(date +%F).sql.gz tar czf media-$(date +%F).tar.gz -C /srv/vallotton media日期换成对应的日期后缀):gunzip -c backup-日期.sql.gz | docker compose exec -T db psql -U vallotton vallotton
Vallotton还带有一个管理后台,能看到所有对话、消息和图片,以及每天的API花费。为了安全,它默认不对外开放,平时也用不到。确实需要的话,只需要在代码目录里新建一个docker-compose.override.yml,给backend加上ports: ["127.0.0.1:8000:8000"],并在.env里临时设置COOKIE_SECURE=0,重新启动服务。然后用SSH隧道连到服务器,打开http://127.0.0.1:8000/admin/,用ADMIN_USERNAME和ADMIN_PASSWORD登录。用完记得把这两处改回去。
MCP
MCP是Vallotton提供的一套通过url访问内部服务的接口。别的程序可以通过它发一句话并拿回画好的图,也可以直接用提示词画图、查询额度等。通过MCP发起的对话在网页的左边栏里同样能看到。
注意Vallotton这个接口用的是自己的一套魔改版的简易协议,不是标准的MCP协议,所以无法直接在Claude Desktop、Cursor这类客户端中连接(现在MCP也不那么常用就是了...)。
启用方法:
- 在
.env里设置MCP_TOKEN,填一串任意的字符串。这是你的Vallotton的MCP服务的密钥。 - 运行
docker compose --profile mcp up -d --build。可以用curl -s http://127.0.0.1:8301/health检查,返回里有"ok": true就说明启动了。 - 默认情况下,MCP只在服务器本机的8301端口上。如果想从外网访问,需要在
.env里设置MCP_BIND=0.0.0.0,并重新运行上一条命令。记得在云服务商的控制台放行8301端口。
使用MCP时,只需要把如下信息告诉你的coding agent,然后它自会figure out如何与Vallotton的MCP服务交互。
{
"name": "vallotton",
"url": "http://服务器IP:8301",
"bearer_token": "你的.env里的 MCP_TOKEN"
}
有两点需要注意。第一,打开了外网访问的话,从外网直接访问MCP走的是明文HTTP协议。第二,画一张图可能要好几分钟,客户端的超时要设到600秒以上。
关于安全
如果你按照本教程部署,那么Vallotton默认已经做了这些保护:
- 对外只开放nginx的80和443端口。Vallotton自己的端口和数据库都只在服务器内部,外面访问不到。MCP只有在你设置了
MCP_BIND=0.0.0.0时才对外。 - 网页登录连续输错8次密码,会锁定15分钟。网页登录和管理后台是两个独立的账号。
- 画好的图也要登录以后才能看到,别人拿到图片的地址也打不开。
- 上传的图片会经过检查,只接受图片格式,每张不超过15 MB。
你需要自己注意的是:.env里的密码尽量都用随机的长字符串;.env文件不要外传,也不要提交到git;云服务商的控制台里只放行22、80、443,以及你确实要对外开放的MCP端口。
附录:出了问题怎么办
以下是一个简易的问题自查表。
| 看到的现象 | 原因和处理办法 |
|---|---|
| 网页能打开,但是登录不了 | 检查是不是用https://你的域名 打开的,用IP地址或者http打开都登录不了。用了Cloudflare的话,检查SSL/TLS模式是不是「Full (strict)」。服务器的系统时间偏差太大也会导致这个问题。 |
| 登录时提示被锁定 | 连续输错8次密码会锁定15分钟,等一会儿再试。 |
| 启动时提示端口被占用 | 在.env里把VALLOTTON_HTTP_PORT(或者MCP的MCP_PUBLIC_PORT)改成别的端口,运行docker compose up -d,再把nginx配置里proxy_pass的端口改成一样的,重新加载nginx。 |
| 画到一半显示「任务中断」 | 画图的过程中重启了Vallotton,比如正好更新了版本。重新发送那句话即可。 |
| 一直停在「正在构思」 | 大模型的官方接口连不上。可以在.env里配置备用线路OPENROUTER_API_KEY,官方接口不通时Vallotton会自动改走备用线路。设置页的「线路」里能看到当前用的是哪一条。 |
| 出图失败,错误里有「402」 | NovelAI账号里的点数(Anlas)用完了,通常是因为用了「高」画质。在生成设置里改回「中」。 |
| NovelAI显示「状态未知」 | 偶尔查不到NovelAI的账号状态,不影响画图,几分钟后会自己恢复。 |
| MCP客户端超时 | 把客户端的超时调到600秒以上。画图要等它画完才返回。 |
附录:环境变量一览
下面是.env里可以设置的项,按用途分组。「默认」是不填对应项时的默认值;标了「必填」的项目没有默认值,必须指定一个值,不填的话Vallotton会无法启动,或者无法使用对应的功能。
.env.example里给的示例值可能和默认值不同,以.env中实际填的为准。部署时一般只需要改第2步里列出的那几项。
| 变量 | 默认 | 说明 |
|---|---|---|
| 语言模型相关 | ||
LLM_PROVIDER | deepseek | 用哪家的大模型:deepseek或grok。 |
DEEPSEEK_API_KEY | — | DeepSeek的密钥。用DeepSeek时必填。 |
DEEPSEEK_MODEL | deepseek-flash | 用DeepSeek的哪个模型型号。 |
DEEPSEEK_REASONING_EFFORT | high | DeepSeek在理解对话、规划画面时的推理强度,可填low、high、max。max每张图要多等一倍以上的时间,图并不更好。 |
DEEPSEEK_DRAW_REASONING_EFFORT | high | DeepSeek写绘图提示词时的推理强度,可填的值同上。 |
DEEPSEEK_MAX_TOKENS | 128000 | 一次回答最多输出多少token。如果设得太小,回答会容易被截断。 |
DEEPSEEK_RETRIES | 2 | DeepSeek回答为空或者格式不对时,自动重试次数(DeepSeek偶尔会有格式问题)。 |
DEEPSEEK_CONTEXT_LIMIT | 1000000 | DeepSeek上下文的上限。 |
DEEPSEEK_LONG_CONTEXT_THRESHOLD | 400000 | DeepSeek对话上下文长度到多少时提醒你一次。 |
OPENROUTER_API_KEY | 空 | Openrouter的密钥。由于DeepSeek官方的服务有些时候不太稳定,如果填了Openrouter的密钥,那么官方接口超时时会自动转到OpenRouter上的同一个模型。 |
OPENROUTER_BASE | https://openrouter.ai/api/v1 | Openrouter备用线路的地址。 |
OPENROUTER_MODEL | deepseek/deepseek-v4.1-flash | Openrouter备用线路上用的模型。 |
LLM_ROAD_BLOCKED_SECONDS | 1800 | 官方接口出错以后,最长绕开它多少秒。 |
LLM_ROAD_PROBE_SECONDS | 60 | 绕开官方接口期间,每隔多少秒重试一次。 |
GROK_API_KEY | — | xAI的密钥。用Grok时必填。 |
GROK_MODEL | grok-4.6 | 用Grok的哪个模型。 |
GROK_REASONING_EFFORT | high | Grok在理解对话、规划画面时的推理强度。high相当于xAI所说的expert档。 |
GROK_DRAW_REASONING_EFFORT | medium | Grok写绘图提示词时的推理强度。 |
GROK_TITLE_MODEL | grok-4.20-non-reasoning | Grok给对话自动起标题用的模型。留空就用GROK_MODEL。(顺带一提,用DeepSeek时起标题直接用 DEEPSEEK_MODEL,没有单独的设置,因为DeepSeek本来就很便宜。) |
GROK_CONTEXT_LIMIT | 500000 | Grok上下文的上限。 |
GROK_LONG_CONTEXT_THRESHOLD | 200000 | Grok对话上下文长度到多少时提醒你一次。 |
GROK_MAX_TOKENS | 20000 | Grok一次回答最多输出多少token。 |
GROK_CONTEXT_WARN_RATIO | 0.8 | 上下文用到几成时开始提醒。这一项不管用哪家都生效。 |
LLM_TIMEOUT_SECONDS | 420 | 模型多少秒没有任何输出,就算超时。 |
LLM_ANSWER_SECONDS | 600 | 一次回答最多等多少秒,超过就重新问一次。 |
LEAD_TOOL_ROUNDS | 2 | 理解对话、规划画面时,最多查几次tag表。0表示不查。 |
DRAW_TOOL_ROUNDS | 4 | 把画面写成提示词时,最多查几次tag表。0表示不查。 |
LEAD_USAGE_SCENARIODRAW_USAGE_SCENARIO | 空 | 系统提示词开头的「使用场景」一段。 |
DRAW_TEMPERATURE | 0 | 把画面写成提示词时的随机程度。这一步只是翻译,不需要发挥,所以默认设为0。 |
| 画图相关 | ||
NOVELAI_API_KEY | — | NovelAI的密钥,pst-开头。 |
NAI_MODEL | nai-diffusion-5-full | 中、高画质下用的NovelAI模型型号(低画质则固定用上一代的V4.5)。 |
| 反思和连续生成 | ||
MAX_REFLECTION_ROUNDS | 10 | 「反思轮数」最多能调到多少。 |
MAX_CONTINUOUS_ROUNDS | 20 | 「连续生成」最多能调到多少。 |
FREE_RETRIES_IN_RUN | 2 | 反思或连续生成中途失败时的重试次数。 |
JOB_STALE_SECONDS | 180 | 一个任务多少秒没有进展,就当作已经中断。 |
JOB_SWEEP_SECONDS | 60 | 每隔多少秒检查一次中断的任务,并发出连续生成的下一句。如果填0则表示不检查(此时连续生成也就不会继续)。 |
| 账号 | ||
APP_USERNAME | user | 网页登录的用户名。 |
APP_PASSWORD | — | 网页登录的密码。 |
ADMIN_USERNAME | admin | 管理后台的用户名。 |
ADMIN_PASSWORD | — | 管理后台的密码。 |
| 网站 | ||
DJANGO_SECRET_KEY | 一个不安全的占位值 | 用来保护登录状态的密钥。部署时建议改成一串随机字符。不改也能启动,但是不安全。 |
DOMAIN | 空 | 你的域名。只有通过这个域名访问才能登录。 |
DJANGO_DEBUG | 0 | 调试开关,1表示开启,0表示关闭。部署时保持0。如果按本教程部署,那么compose已经把它固定成0,技术改了也不生效。 |
COOKIE_SECURE | 1 | 设置为1时,登录状态只通过https传输。只有临时开启管理后台时才需要设成0,用完改回。 |
TRUSTED_PROXY_HOPS | 1 | 服务器上有几层反向代理。按本教程部署的话是1,一般不用改。数错了会让登录次数限制失效。 |
| 数据库和图片 | ||
POSTGRES_PASSWORD | — | 数据库的密码,填一串随机字符即可。 |
POSTGRES_DBPOSTGRES_USER | vallotton | 数据库名和用户名,一般不用改。 |
POSTGRES_HOSTPOSTGRES_PORT | 127.0.0.15432 | 数据库的地址和端口。按本教程部署的话,compose会固定连到自己的数据库容器,不用改。只在docker外运行后端时才会用到。 |
MEDIA_DIR | ./tmp/media | 服务器上存放图片的目录,部署时建议改成绝对路径。 |
| 端口和MCP | ||
VALLOTTON_HTTP_PORT | 8300 | Vallotton在服务器本机上开的端口,nginx会把访问转到这里。一般不需要改,除非和和别的应用端口冲突。 |
MCP_PUBLIC_PORT | 8301 | MCP在服务器上的端口。只在启用MCP时用到。 |
MCP_BIND | 127.0.0.1 | MCP的端口对谁开放。127.0.0.1表示只有服务器本机能访问,0.0.0.0表示外面可以直接访问。 |
MCP_TOKEN | — | 访问MCP时要带上的密钥。启用MCP时必填。 |
MCP_HOSTMCP_PORT | 127.0.0.18766 | 在docker外单独运行mcp/server.py时的监听地址和端口。使用compose时不用改。 |
VALLOTTON_BACKEND_URL | http://127.0.0.1:8000 | MCP把请求转到哪个后端。使用compose时会自动指向后端容器,不用改。 |
只在开发和测试时用到的几个变量(比如把数据库换成sqlite、不调用NovelAI而是画占位图)这里没有列出。
