Node 版
适合您自己维护的服务器:一台机器、一个常驻服务、前面加一层反向代理。
Node 22、一个 C 编译器、一块本地磁盘。几十人规模,单核机器足矣。有 MySQL 服务器就用它;没有的话,SQLite 一无所求。
同一产品的两个版本:一个作为服务常驻在您的服务器上,另一个直接放到虚拟主机里。不强制要求数据库,无需第三方服务——但您若有 MySQL 服务器,它也照样驱动。预留一小时。
托管在欧洲,什么都不用装:五名员工以内免费,而且第一天就是完整的产品。
免费方案并不止于 SaaS:五名员工以内,你同样可以把产品装在自己那里——自己的文件、自己的数据库、自己的备份——分文不付。决定方案的是人数,而不是实例跑在哪里。超过五名员工就需要订阅,无论实例跑在我们这边还是你那边。
取决于您的主机环境,而非业务需求:两个版本做的事完全一样。
适合您自己维护的服务器:一台机器、一个常驻服务、前面加一层反向代理。
Node 22、一个 C 编译器、一块本地磁盘。几十人规模,单核机器足矣。有 MySQL 服务器就用它;没有的话,SQLite 一无所求。
适合虚拟主机:上传一个目录、填一个文件、设一个定时任务。不需要命令行。
PHP 8.1 与 SQLite 扩展。无需安装任何依赖:不用 Composer,也不用包管理器。若你更想用数据库服务器,再加上 PDO MySQL 扩展。
两个版本共用同一套数据库结构和同一种密码格式。从一个换到另一个,就是复制一个数据库文件和五个目录:没有转换步骤,也没有人需要改密码。
第二个选择,也是唯一难以更改的那个。它与版本无关:两个版本都支持两种引擎,四种组合通过同一套测试。
服务器磁盘上的一个文件。没有东西要装、要管、要盯——搬迁实例只需复制一个目录。
这是默认值,也是大多数情况下正确的答案:一台应用服务器,加上一块能跨部署留存的本地磁盘。
一台数据库服务器,可以在本机,也可以在网络的别处。数据就住在贵司信息部门已经在备份、复制和监控的地方。
出于三个理由选它:多台应用服务器共用一个库;有内部规定要求如此;或者应用磁盘是临时的——每次部署都重建的容器。
这是流传最广的看法,而它是错的:SQLite 活在进程内部,MySQL 活在套接字之后。我们在两千次操作上实测,SQLite 视操作而定要快上两倍半到一百五十倍——即便八个进程同时写入,它也扛得住比较。选 MySQL,是为了数据住在哪里、由谁来管,而不是为了响应时间。
刚好够把向导打开。详细步骤紧随其后,一步一步说明每条命令做什么、为什么这样做。
在你自己管理的服务器上执行三条命令。最后一条生成安装令牌并启动实例。
git clone <votre-dépôt> toutadmin
cd toutadmin && npm ci --omit=dev
INSTALL_TOKEN=$(openssl rand -hex 16) \
NODE_ENV=production node src/server.js
完全不需要命令行:上传一个目录,复制一个文件,打开一项写权限。
# 1. déposer le dossier (racine web → public/)
# 2. cp config.sample.php config.php
# 3. chmod 770 data/
# 4. ouvrir https://votre-domaine/install
实例以空白状态启动,并把自己关起来:未安装之前,任何地址都通向向导;安装完成后,向导就彻底消失。
https://votre-domaine/install
从第一次启动到你自己走进向导之间,谁先到谁就能创建管理员账号。INSTALL_TOKEN 把这扇窗关上:没有它,向导拒绝打开。
用 npm ci 而不是 npm install:它严格按锁定文件安装。在服务器上,一个悄悄漂移的版本就是一次谁也说不清的故障。
git clone <votre-dépôt> /var/www/toutadmin
cd /var/www/toutadmin
npm ci --omit=dev
一切都通过环境变量设置,且没有一项是必填的。开放端口前先设好 INSTALL_TOKEN:从首次启动到您进入安装向导之间,先到者就能创建管理员账户。
cp .env.example .env
# PORT, NODE_ENV=production, INSTALL_TOKEN…
手工启动的话,关掉终端产品就停了。服务会自行重启,并且只被允许写入自己的数据目录。
sudo systemctl enable --now toutadmin
journalctl -u toutadmin -f
切勿把应用端口直接暴露到公网。在代理之后,实例会自行设置安全响应头——包括 HSTS,且仅在已加密的连接上。
sudo certbot --nginx -d intranet.exemple.fr
这一步最容易出错。如果服务器把整个目录都对外提供,数据库就人人可下载:账户、密码摘要和保险柜全在内。
# déposer le dossier ; la racine web pointe sur public/, pas sur le dossier
配置由向导写入,而且放在最后写:只要文件还不存在,中断的安装就什么也没留下。它会在其中放一把本实例专属的密钥,用来封缄签章、加密库中的机密——请连同其他一起备份。
cp config.sample.php config.php
php -r "echo bin2hex(random_bytes(32));" # session_secret
SQLite 会在数据库旁边写入伴随文件:需要可写的是目录,而不只是那个文件。产品的其余部分可以保持只读。
chmod 770 data/ # le dossier, pas seulement la base
PHP 站点只在请求期间存活。定时任务负责关闭到期合同、开具周期性发票、发送 Webhook 并创建备份。
* * * * * /usr/bin/php /var/www/toutadmin/tools/cron.php
趁数据库还小,立刻做一份,并配置好异地目标。留在它所保护的那台服务器上的归档,什么也保护不了。
用它登录并四处走走。这是唯一能以同事视角看产品的办法——也是最常被跳过的一项检查。
若您启用了双重验证,又同时弄丢手机和恢复码,只有另一名管理员能让您重新进入。系统没有后门。