TOTP Vault DocsDeployment & Recovery
TOTP VAULT · OPERATIONS GUIDE · v1.2.0

项目安装与上线

第四章 项目安装与上线

说明

上传最终源码、执行安装脚本、修复权限、配置 Nginx/SSL 并完成后台首次登录。

#19. 上传最终源码

服务器 SSH / 终端

🖥️ 执行位置:服务器 SSH / 终端

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

最终 ZIP:

TOTP-Vault-v1.2.0-Baota-Final-20260824.zip

上传到:

/www/wwwroot

终端:

cd /www/wwwroot
unzip TOTP-Vault-v1.2.0-Baota-Final-20260824.zip

如果 ZIP 解压得到:

/www/wwwroot/totp-vault

移动为你的站点目录:

rm -rf /www/wwwroot/2fa.example.com/*
cp -a /www/wwwroot/totp-vault/. /www/wwwroot/2fa.example.com/
rm -rf /www/wwwroot/totp-vault

注意:如果网站目录里已有重要文件,不要先执行 rm -rf。首次空站才使用上面的清理命令。

检查:

cd /www/wwwroot/2fa.example.com
ls -la

必须能看到:

.env.example
artisan
bootstrap.php
app
public
routes
scripts
storage
vendor
tools

#20. 执行最终安装脚本

服务器 SSH / 终端

🖥️ 执行位置:服务器 SSH / 终端

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

cd /www/wwwroot/2fa.example.com
export PATH=/www/server/php/82/bin:$PATH
php -v
bash scripts/install.sh

填写:

#20.1 正式网站地址

https://2fa.example.com

#20.2 SQLite

SQLite 路径 [/www/server/totp-vault/data/database.sqlite]:

直接 Enter。

#20.3 vault.key

vault.key 路径 [/www/server/totp-vault/secrets/vault.key]:

直接 Enter。

#20.4 secure-store.enc

加密配置路径 [/www/server/totp-vault/secrets/secure-store.enc]:

直接 Enter。

#20.5 PHP-FPM 用户

PHP-FPM 用户 [www]:

直接 Enter。

#20.6 管理员

设置唯一管理员用户名与强密码。

如果安装中断后重新执行:

bash scripts/install.sh

最终脚本会检测已有管理员并自动跳过,不会重复创建。


#21. 安装后权限检查

服务器 SSH / 终端

🖥️ 执行位置:服务器 SSH / 终端

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

namei -l /www/server/totp-vault/data/database.sqlite
ls -ld /www/server/totp-vault
ls -ld /www/server/totp-vault/data
ls -ld /www/server/totp-vault/secrets
ls -ld /www/server/totp-vault/tmp
ls -l /www/server/totp-vault/data/database.sqlite
ls -l /www/server/totp-vault/secrets/vault.key

推荐:

/www/server/totp-vault       root:www 750
data                           www:www 700
secrets                        www:www 700
tmp                            www:www 700
database.sqlite                www:www 600
vault.key                      www:www 600

用网页运行用户检查:

sudo -u www test -r /www/server/totp-vault/data/database.sqlite && echo 'DB READ OK' || echo 'DB READ FAIL'
sudo -u www test -w /www/server/totp-vault/data/database.sqlite && echo 'DB WRITE OK' || echo 'DB WRITE FAIL'
sudo -u www test -w /www/server/totp-vault/data && echo 'DB DIR WRITE OK' || echo 'DB DIR WRITE FAIL'

必须:

DB READ OK
DB WRITE OK
DB DIR WRITE OK

#22. 宝塔运行目录

宝塔面板

🧰 执行位置:宝塔面板(部分步骤配合 SSH)

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

宝塔 → 网站 → 站点 → 网站目录

设置:

网站目录:/www/wwwroot/2fa.example.com
运行目录:/public

最终 Nginx root 必须:

/www/wwwroot/2fa.example.com/public

#23. Nginx 最终配置

宝塔面板

🧰 执行位置:宝塔面板(部分步骤配合 SSH)

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

项目自带:

docs/nginx-baota-location.conf

先生成适合当前域名的临时版本:

cd /www/wwwroot/2fa.example.com
DOMAIN='2fa.example.com'
PHP_VER='82'
sed "s#SITE_PATH#$DOMAIN#g; s#php-cgi-82#php-cgi-$PHP_VER#g" docs/nginx-baota-location.conf > /root/totp-nginx-location.conf
cat /root/totp-nginx-location.conf

把输出的 location、安全响应头等规则整合到宝塔当前 HTTPS server {} 中。

必须:

root /www/wwwroot/2fa.example.com/public;
index index.php;

location / {
    try_files $uri $uri/ /index.php?$query_string;
}

# Direct TOTP:Secret 位于 URL 中,因此该路径不写访问日志。
location ^~ /2fa/ {
    access_log off;
    log_not_found off;
    error_log /dev/null crit;

    try_files /index.php =404;
    include fastcgi_params;
    fastcgi_pass unix:/tmp/php-cgi-82.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    fastcgi_param SCRIPT_NAME /index.php;
    fastcgi_param HTTP_PROXY "";
    fastcgi_read_timeout 60s;
    fastcgi_hide_header X-Powered-By;
}

location = /index.php {
    try_files $uri =404;
    include fastcgi_params;
    fastcgi_pass unix:/tmp/php-cgi-82.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTP_PROXY "";
    fastcgi_hide_header X-Powered-By;
}

location ~ \.php(?:/|$) {
    return 404;
}

CSP 必须包含:

form-action 'self' https://login.microsoftonline.com

否则点击“连接 Microsoft OneDrive”后浏览器可能不跳 Microsoft 登录页。

不要同时保留宝塔默认:

include enable-php-82.conf;

如果它会再创建任意 PHP 执行规则,就删除该 include,使用上面的精确 /index.php 规则。

检查:

/www/server/nginx/sbin/nginx -t

必须:

syntax is ok
test is successful

然后:

/etc/init.d/nginx reload

#24. SSL

宝塔面板

🧰 执行位置:宝塔面板(部分步骤配合 SSH)

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

宝塔 → 网站 → SSL → Let's Encrypt

申请后开启:

强制 HTTPS

检查:

ss -lntp | grep -E ':80|:443'

#25. 本机 HTTPS 测试

服务器 SSH / 终端

🖥️ 执行位置:服务器 SSH / 终端

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

不要只用旧版程序的 HEAD 结果判断。 最终版已经兼容 HEAD,但建议测试真实 GET:

curl -k --resolve 2fa.example.com:443:127.0.0.1 \
  https://2fa.example.com/ \
  -o /dev/null \
  -w 'HTTP_CODE=%{http_code}\n'

正常:

HTTP_CODE=200

后台:

curl -k --resolve 2fa.example.com:443:127.0.0.1 \
  https://2fa.example.com/admin \
  -o /dev/null \
  -w 'HTTP_CODE=%{http_code}\nREDIRECT=%{redirect_url}\n'

未登录通常:

302
/admin/login

#26. 基础健康检查

服务器 SSH / 终端

🖥️ 执行位置:服务器 SSH / 终端

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

cd /www/wwwroot/2fa.example.com
sudo -u www /www/server/php/82/bin/php artisan totp:migrate
sudo -u www /www/server/php/82/bin/php artisan totp:test
sudo -u www /www/server/php/82/bin/php artisan totp:health

重点必须 PASS:

PHP version
pdo_sqlite
sodium
curl
json
mbstring
SQLite connection
Database outside web root
Vault key
Vault key outside web root
Vault key permissions
storage writable
Backup temp writable
HTTPS URL
APP_DEBUG
proc_open
age binary
tar binary

OneDrive/备份/计划任务尚未配置时 WARN 正常。


#27. 管理员后台

浏览器 / Microsoft Entra

🌐 执行位置:浏览器 / Microsoft Entra / 网站后台

下方命令块可以直接复制;带“检查/预期”的内容用于核对结果,不要当作命令输入。

打开:

https://2fa.example.com/admin

登录后立即:

安全设置 → 开启管理员 MFA

管理员 MFA 不要只保存在这个 Vault 自己内部。