{"_id":"@aifabrix/server-setup","_rev":"18-d3e5699dd267cffe4ac12f932e668b89","name":"@aifabrix/server-setup","dist-tags":{"latest":"2.0.5"},"versions":{"0.1.0":{"name":"@aifabrix/server-setup","version":"0.1.0","_id":"@aifabrix/server-setup@0.1.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"1acc949c105b7da44c55dcbb96a534810be86364","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-0.1.0.tgz","fileCount":43,"integrity":"sha512-y1MmZMNtkXl8H7ZMggB8/JSe5Tlj341ALWlGwiDXyZnTV/2t1aIrqOB1zzU23tkICL9UR2ybLg3K7dNKb6ELfQ==","signatures":[{"sig":"MEUCIQDghyt/iwoMq9o/OTD0INXEF7DVkjUzqc6N0jnxB5/BjwIgf9ndq/YbB6IpwxEh5S+o52jVAgJpv+sTpFypL7/8cHY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110779},"main":"dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"2f2b145aa57c1dadefcf9803b2fc5b2703c17786","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^11.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_0.1.0_1771335806433_0.7886821836289366","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@aifabrix/server-setup","version":"1.1.0","_id":"@aifabrix/server-setup@1.1.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"ee4ee5b3dc3a0809587a23a73c7e4ef3fbd14c76","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.1.0.tgz","fileCount":43,"integrity":"sha512-vu2YTLCCO+5WiHis9WDJexvmDdBxdP+FqVlTIjAIUMz1bV5hD3K+Aju/ar4P/qNur8UuxYo6NgW9UsdpbIMLLA==","signatures":[{"sig":"MEQCIEgf+fjUZtV/WKiGW58R8gUpYelx901pyWTAKoCev3zWAiBlBaq9/bFt5TQYLmkjxfv62+00d0zeKI9p9KNiPQgu2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":110803},"main":"dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"37a8828892c143665229248249095609c8850478","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^11.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.1.0_1771341144735_0.07012101538356763","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@aifabrix/server-setup","version":"1.2.0","_id":"@aifabrix/server-setup@1.2.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"58b5bc367e96a3eb40ea028d4b97dc334669b0cc","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.2.0.tgz","fileCount":43,"integrity":"sha512-Q4IRfFHizs6ZUxYPCPqGOuZDvOPSPzWb2UxaC4BKcakECQTkb4MQNhzczjc6mQj7FhF9A2/0TPWeWYARIxYjyQ==","signatures":[{"sig":"MEYCIQDYUDNVEcoMPuLra/GBfZ1m7TN1WwrScKqf8Vc9gjKwDAIhAJGB956yHaopzksBm+vafneo/TzDaJlFDYsLDP957b1v","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":123425},"main":"dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"122b12b0f1c71b1785f8ab922ddcd28c628324c6","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^11.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.2.0_1771406237224_0.15385194217001819","host":"s3://npm-registry-packages-npm-production"}},"1.3.0":{"name":"@aifabrix/server-setup","version":"1.3.0","_id":"@aifabrix/server-setup@1.3.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"17e0726f2f23610f6cef049f7001b1d599e78136","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.3.0.tgz","fileCount":43,"integrity":"sha512-tTj7eBD6CdZ7QsHXO3703h/naSmXzIgCCKuXJqxMiOMWsOLD4sS/oILecGmy9OZSJ8qoYPXV6IurEVrzmLSK4A==","signatures":[{"sig":"MEYCIQCtWr4RNneKA+Xlu74d7LKP8XC7dGShoAm4pp1tjrcsQwIhAN7r3RBKeOtjY4C+AiIQbyR4jjvc1JCC1y/hzvXhSlK9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":125810},"main":"dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"640ffbf08c675c7c930b94d8b8bd0f8d51891a24","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^11.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.3.0_1771440177128_0.9919332334340045","host":"s3://npm-registry-packages-npm-production"}},"1.4.0":{"name":"@aifabrix/server-setup","version":"1.4.0","_id":"@aifabrix/server-setup@1.4.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"5694a8354fed652c1bda7f6dcd7e6b9d0b425f50","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.4.0.tgz","fileCount":48,"integrity":"sha512-2QaOo3auBBcZpR3a8YzETRnUZBzIHYBjW2WaLKH/zZ4ij+UCUxGFS6/oOB/qa3FzK3+mfIuQQLGYshIPcCl5dg==","signatures":[{"sig":"MEUCIAuAHznKH5pri4XHo3Bl0OqyU8ePhenrLpBsXLAgoD05AiEAt2Xmp2rb7aVTRSMWBCQCdp7XGEBGI7t+YABF9GgXcUQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":149846},"main":"dist/cli.js","type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"e589094ebd93258c70714ebdbb06761f111a05ae","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^11.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.4.0_1771614694684_0.13228872810900683","host":"s3://npm-registry-packages-npm-production"}},"1.5.2":{"name":"@aifabrix/server-setup","version":"1.5.2","_id":"@aifabrix/server-setup@1.5.2","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"c38d08bdd2d58791c6029a7b6396d92ba47992d8","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.5.2.tgz","fileCount":55,"integrity":"sha512-2leEwMT0Vxrd0x5APLc5rtV7l8zciJbakC9bik4SA7ASTYWQ5z99hH2pGBVdTQFZhLqQxR+xJiTzjhC0iV7lNg==","signatures":[{"sig":"MEUCIQCAZCYwPwO9+KJJkp5PwZv67iKhg7QfjLuYpGJskAufPQIgC5WJ2mcu29bq+5lcmoFQKC6WVTf7LqudCNX4uCxnYto=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162641},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"ca26d3d15145ee7362ec16b2597dc7bca4575498","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^11.6.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.5.2_1771776448343_0.49644316710495384","host":"s3://npm-registry-packages-npm-production"}},"1.5.3":{"name":"@aifabrix/server-setup","version":"1.5.3","_id":"@aifabrix/server-setup@1.5.3","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"fe31e9fdfcb94b7408585bd26ab609daa3afe1a1","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.5.3.tgz","fileCount":55,"integrity":"sha512-lURNDTL41f9C4CDJ4jpQRwbFPxEkgH55myEHnbgsBN8AeV9OU+eNjpsYKuK6LdhdS8F9ALRpObHDRWZp/20pwQ==","signatures":[{"sig":"MEQCIFFXrpzOVrfAqMM6waQ+9opx69FkmrEIGM9nq0Bdu3m/AiAg20Qj4eSTnCgN63biSTKIbyY3Oke545i2uMFTRD0TSw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":167380},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"4876c015fed4713eb95c1422f68eb02d43f9cbc6","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.5.3_1771787413693_0.7772784510349817","host":"s3://npm-registry-packages-npm-production"}},"1.5.5":{"name":"@aifabrix/server-setup","version":"1.5.5","_id":"@aifabrix/server-setup@1.5.5","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"8e8f4d839d96d42f8c47e6249984be1896f98318","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.5.5.tgz","fileCount":59,"integrity":"sha512-i9+Wq0i134HejZOXniKzbramjcEc7crJRkvfbunOpkXqD9mg+/46luCqTd1OU2dManTx9zapKBwaSfgxxEFeEw==","signatures":[{"sig":"MEYCIQD4FMmqGOCb0CTF+7ZKd0SiZNPg4bU/JTtTaCMZNGhpaAIhAJiFm0e3+TZuqVM0Ywmw/9WmevmtFu6h+jRQbPNr/lH3","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":177859},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"321b37e2e0ccb817c559722aaaba52f630f260bc","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.5.5_1771863786382_0.407323184585624","host":"s3://npm-registry-packages-npm-production"}},"1.5.6":{"name":"@aifabrix/server-setup","version":"1.5.6","_id":"@aifabrix/server-setup@1.5.6","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"e82d05cf4e4faa9e58ec6e630460a211a3b5671a","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.5.6.tgz","fileCount":59,"integrity":"sha512-mMTdl7QVUVMlrf/jxShUYILFyNjqQ/K7QSOBONYk1lmXWJXzptQl5kwfcCLwlZVb8l5U2EAmGZQFrLpGflzzYw==","signatures":[{"sig":"MEQCIE5ZOafplt5crDZO23/P41SHvcZDASvPXuQACQcXFJe0AiAYjh11e2YKVsJffIfkYaDJM433a3OWiM0KcmUgtaD6/g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":178549},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"c60f9f27871203e4d2faba252314759b7be3bd07","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"18.20.8","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.5.6_1771866722987_0.9655868495406019","host":"s3://npm-registry-packages-npm-production"}},"1.7.1":{"name":"@aifabrix/server-setup","version":"1.7.1","_id":"@aifabrix/server-setup@1.7.1","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"78c65df9521277abcc54fb6be195dbd378890164","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.7.1.tgz","fileCount":95,"integrity":"sha512-6Hp3fEDrc33Qf9Mkz4a2FRSXgjYmvraFNrIW3ufP8EUhQfe0PjRIy48pvHZMZ7utZvWlAocUj5ZFIOvvvpRkSA==","signatures":[{"sig":"MEYCIQCnO4QiTrKLdsL4eeKsZAPzsUZrrM8YPmYSTI0peME9ogIhAKFy9asQCSY5AudLWoSLnN29edb03sLKTIwnDAT8lGaL","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":329910},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"e883ebb70882045fe4153a0cc7b34fe88d83d649","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"11.12.1","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.7.1_1782230810614_0.8643835647302713","host":"s3://npm-registry-packages-npm-production"}},"1.7.2":{"name":"@aifabrix/server-setup","version":"1.7.2","_id":"@aifabrix/server-setup@1.7.2","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"5379f9e9d2e3b0c3d98952e2848d6af16eb291d0","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.7.2.tgz","fileCount":103,"integrity":"sha512-35SIjA32J7Nl33ZgDPSp3q4EaQfpgWEbu/H27czNiHV0PztrYSADHQoxWjEy4Jxmrv01njufmcZ7XAZ3M6cMWw==","signatures":[{"sig":"MEYCIQDwSn3yQYk0Tx27gc3Efmj4pBIPGsQVK8Qu9sMH1ASuCAIhAL6iq7fpIHds2SO4KmltgCGxqEY4MgCNB5AW8FrBMPxv","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":371042},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"2b13681cb1de2d19cc1e1d12a89c6d86146b7175","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.7.2_1782279520657_0.4064504946220928","host":"s3://npm-registry-packages-npm-production"}},"1.9.0":{"name":"@aifabrix/server-setup","version":"1.9.0","_id":"@aifabrix/server-setup@1.9.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"47ad741d358e1a668dbda115fe26180e72f982f9","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-1.9.0.tgz","fileCount":179,"integrity":"sha512-SW4QWi8YTQVHKeg4RbNsSs21P6rR0ujDXAIsdbMd6Ln/exV5d+NaV4DRGZV7lmetGGo70CoE3X3OzxvUhqTz8Q==","signatures":[{"sig":"MEQCIB8onMwUVEm1Q4xVbtLCBWe8EWwsxVl/lXmf+o5kh77nAiB/bH+sFimLWwfQuEv2+r69Y7mazob8ijLsMZE+QLZGiA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":600880},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"c9f22e18efd2594333e3a52ccb494b9331156a58","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_1.9.0_1782480413839_0.3315100926362551","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@aifabrix/server-setup","version":"2.0.0","_id":"@aifabrix/server-setup@2.0.0","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"30f1e7072cc481db6b0413334cda5a7c17fc5ffd","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-2.0.0.tgz","fileCount":192,"integrity":"sha512-cMaVYJUBqv6HZHAwUIVljslTyRfNuyQIWW70O7wDUO9O7sRRDGEvnhaUkm1atPU4sbOseiIzHc8SZacM2pfd2g==","signatures":[{"sig":"MEUCIQCv6COSueK9QdAjP4TLPGGCKCNfn/+lAr1LV7iC8Bd7swIgW3NWpzd38tEU2XrEd8H6ktAlO3yV/LJ60r6XaHrOYc0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":628490},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"7ae5346429732ce345c230f16c1c72ec45862b0c","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_2.0.0_1782489386180_0.3084776315230482","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"@aifabrix/server-setup","version":"2.0.1","_id":"@aifabrix/server-setup@2.0.1","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"64355a18b8a8a423293a12d0a3d786bd156dd1d0","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-2.0.1.tgz","fileCount":196,"integrity":"sha512-R80OQ8i98To2mq7yu10Pi5wFeoilDNwoRVzeG/AqTzgNsfny4dZJCjcX/v966UevDMI0MwGb5hHEW1G3JKw7WQ==","signatures":[{"sig":"MEQCICPlL16SEbeYj+DHXR8JZsxgh6XkqANJ62J5XZUlJyAyAiBsC0ePkP98FbAt1O8sG62fxsR+mI3fitRnwL886JK+PQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":640702},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"780230f1e2357fe26700469b52da753206d41f52","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_2.0.1_1782910811704_0.7996052408379632","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"@aifabrix/server-setup","version":"2.0.2","_id":"@aifabrix/server-setup@2.0.2","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"d03878e15eed8257af580f5fb156a186edf8c680","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-2.0.2.tgz","fileCount":196,"integrity":"sha512-+4TVPitNEX0XMUj9XXuuc/tQLa3YmRuiJEfUDQvUMk9ILCtqdpAunl6Id7OESlMLKUin4DkGBUYO/KJuQuaz5A==","signatures":[{"sig":"MEYCIQCuB3E4Iu3HU/Elfewxap3Hp1DpMaHIhtyS+2YP34FkaQIhAKI+XrOSHY21Q7DaAJhGtJpDpfwkBsUBqfb9ZrnxxGgF","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":643604},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"ab3eae602102e3f53a8c232b5e3efa6de98dcdd2","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_2.0.2_1785156182982_0.5471544826911112","host":"s3://npm-registry-packages-npm-production"}},"2.0.3":{"name":"@aifabrix/server-setup","version":"2.0.3","_id":"@aifabrix/server-setup@2.0.3","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"12cba2a7bfda047d679ce9458153dd0217029993","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-2.0.3.tgz","fileCount":198,"integrity":"sha512-k0g7g8t22g3BKvVklYCbt7VE6kse+pig61MCZ2g5ukPaVr/YBhWrhr+LsUAjpqpZKE5A4nl+uR/9kiwkTYIz+w==","signatures":[{"sig":"MEUCIQD7B7ZGAy/AtB3kUGp+BNk+m0OQsJklaj0nOboFhmfPFwIgGs5eCMx9HRBdxOsg6OI5uLe+r8W8FpmUKCIRSkUxPuo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":649869},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"198a960a16a7eea9eee78ff9795647497e429c14","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_2.0.3_1785160670502_0.8710470446573173","host":"s3://npm-registry-packages-npm-production"}},"2.0.4":{"name":"@aifabrix/server-setup","version":"2.0.4","_id":"@aifabrix/server-setup@2.0.4","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"bin":{"af-server":"dist/cli.js"},"dist":{"shasum":"d424c572fc6ed85d37bf198529663e20fe163f56","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-2.0.4.tgz","fileCount":198,"integrity":"sha512-IvW5U1ngvUZdd034iT+UuLrFD7CN8fMs7rOxuRDoSfIef6W3ByOtotlCEYESV7Uc17CQdtx9QW3ym9eY6zQIkg==","signatures":[{"sig":"MEUCIQDrD6c52dnvc9w2pooATD6kU40gvjCKzBAMWpyD1J6SqAIgdK2jl5TL0B9CTPLF5b+ylCRJ1tmjRYPgIvlbjtY4Eqs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":651123},"main":"dist/cli.js","pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"type":"module","types":"./dist/cli.d.ts","engines":{"node":">=18"},"gitHead":"1b28605dbfb501b4447a8c31ce027a102bb876c9","scripts":{"lint":"eslint src","test":"jest","build":"tsc","build:ci":"npm run lint && npm run test && npm run build","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"overrides":{"glob":"^13.0.0"},"_npmVersion":"10.8.2","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","directories":{},"_nodeVersion":"20.20.2","dependencies":{"read":"^1.0.7","ssh2":"^1.15.0","archiver":"^7.0.1","commander":"^12.1.0","extract-zip":"^2.0.1","better-sqlite3":"^12.0.0"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.17.0","globals":"^15.15.0","ts-jest":"^29.4.6","@eslint/js":"^9.17.0","typescript":"^5.7.2","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@typescript-eslint/parser":"^8.17.0","@typescript-eslint/eslint-plugin":"^8.17.0"},"_npmOperationalInternal":{"tmp":"tmp/server-setup_2.0.4_1787042946297_0.3287069491754755","host":"s3://npm-registry-packages-npm-production"}},"2.0.5":{"name":"@aifabrix/server-setup","version":"2.0.5","description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","type":"module","main":"dist/cli.js","bin":{"af-server":"dist/cli.js"},"scripts":{"build":"tsc","build:ci":"npm run lint && npm run test && npm run build","lint":"eslint src","test":"jest","test:cov":"jest --coverage","test:watch":"jest --watch","prepublishOnly":"npm run build"},"engines":{"node":">=18"},"dependencies":{"archiver":"^7.0.1","better-sqlite3":"^12.0.0","commander":"^12.1.0","extract-zip":"^2.0.1","read":"^1.0.7","ssh2":"^1.15.0"},"overrides":{"glob":"^13.0.0"},"devDependencies":{"@eslint/js":"^9.17.0","@types/archiver":"^6.0.2","@types/better-sqlite3":"^7.6.11","@types/jest":"^29.5.14","@types/node":"^22.10.2","@types/read":"^0.0.32","@types/ssh2":"^1.15.5","@typescript-eslint/eslint-plugin":"^8.17.0","@typescript-eslint/parser":"^8.17.0","eslint":"^9.17.0","globals":"^15.15.0","jest":"^29.7.0","ts-jest":"^29.4.6","typescript":"^5.7.2"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org"},"pnpm":{"onlyBuiltDependencies":["better-sqlite3"]},"_id":"@aifabrix/server-setup@2.0.5","gitHead":"45a5f9417fb0e48c63f9962ca52e07f80049ad41","types":"./dist/cli.d.ts","_nodeVersion":"20.20.2","_npmVersion":"10.8.2","dist":{"integrity":"sha512-KeX4lejkGz+zlJkSHVs5ysclczpOxHQz2xtUq7YcfjAszJyneiM036oKMdXgROBSTCwlvRUrTOFcZiIrPPlhmQ==","shasum":"597e2b6e9ab16ef4027578b550afdb396b90b9e8","tarball":"https://registry.npmjs.org/@aifabrix/server-setup/-/server-setup-2.0.5.tgz","fileCount":198,"unpackedSize":652170,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFyo3Zy+bgrXzhHBgXO9HlsNumKUcuschdY6gdiCxKByAiEA//x3qzmDz6uJWi6+OnyEfvtxL1rCKvya5bNXYtiamO4="}]},"_npmUser":{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"},"directories":{},"maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/server-setup_2.0.5_1787584466277_0.9011031959937859"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-17T13:43:26.363Z","modified":"2026-08-24T15:14:28.077Z","0.1.0":"2026-02-17T13:43:26.607Z","1.1.0":"2026-02-17T15:12:24.911Z","1.2.0":"2026-02-18T09:17:17.378Z","1.3.0":"2026-02-18T18:42:57.265Z","1.4.0":"2026-02-20T19:11:34.829Z","1.5.2":"2026-02-22T16:07:28.485Z","1.5.3":"2026-02-22T19:10:13.860Z","1.5.5":"2026-02-23T16:23:06.543Z","1.5.6":"2026-02-23T17:12:03.145Z","1.7.1":"2026-06-23T16:06:50.768Z","1.7.2":"2026-06-24T05:38:40.818Z","1.9.0":"2026-06-26T13:26:54.012Z","2.0.0":"2026-06-26T15:56:26.363Z","2.0.1":"2026-07-01T13:00:11.846Z","2.0.2":"2026-07-27T12:43:03.162Z","2.0.3":"2026-07-27T13:57:50.652Z","2.0.4":"2026-08-18T08:49:06.442Z","2.0.5":"2026-08-24T15:14:26.453Z"},"description":"CLI to install, backup, and restore AI Fabrix builder-server (config + DB) over SSH","maintainers":[{"name":"mika.roivainen","email":"mika.roivainen@esystems.fi"}],"readme":"# AI Fabrix Builder Server Setup (af-server)\n\nThis is the **one document** you need to get your builder-server **from zero to up and running** in your own Docker. How to use the server (users, secrets, onboarding, etc.) is in the **[AI Fabrix documentation](https://docs.aifabrix.ai)** — start with the [Builder CLI reference](https://docs.aifabrix.ai/docs/reference-cli-reference) and [developer workstation setup](https://docs.aifabrix.ai/docs/build-ai-ready-systems-get-started-developer-workstation-setup).\n\n---\n\n## Why AI Fabrix Builder server?\n\n- **Full AI Fabrix platform, one server, multi-developer:** You run the full AI Fabrix platform and a **separate builder-server** where multiple developers each get their **own dedicated, isolated environment** (users, certificates, secrets, workspaces). One installer (af-server) sets up Docker (including the **Compose v2** CLI plugin), nginx, SSL proxy, sync user, and backup on that server.\n- **One tool for install and management:** The same **AI Fabrix Builder** CLI gets you the platform and manages users, secrets, and onboarding. See [AI Fabrix docs](https://docs.aifabrix.ai/docs/build-ai-ready-systems).\n- **Security and standards:** TLS, client certificates, no secrets in version control. Backups are explicit (config + DB + keys); store them encrypted.\n\n---\n\n## Getting the builder-server Docker image\n\n**The builder-server Docker image is not on a public registry.** You get it with the **AI Fabrix platform**.\n\n1. Install the **AI Fabrix Builder** CLI: `npm install -g @aifabrix/builder`\n2. Install the **AI Fabrix server-setup** CLI (af-server): `npm install -g @aifabrix/server-setup`  \n   - If you get **EACCES** (permission denied), use either:  \n     `sudo npm install -g @aifabrix/server-setup`\n3. Use the Builder CLI to run or deploy the platform (including builder-server). See [Build AI-ready systems](https://docs.aifabrix.ai/docs/build-ai-ready-systems) and [developer workstation setup](https://docs.aifabrix.ai/docs/build-ai-ready-systems-get-started-developer-workstation-setup).\n\nOnce you have the platform (and the builder-server image), use **af-server** to install that server on your own host.\n\n---\n\n## Prerequisites\n\n- **Node.js ≥ 18** (where you run af-server)\n- **SSH access** to the server (key-based auth). af-server uses `~/.ssh/id_ed25519.pub` or `~/.ssh/id_rsa.pub` by default; use `-i path/to/key` if your key is elsewhere.\n- **Server:** Ubuntu. For remote install the script can install Docker and Docker Compose v2. For **local default** you need hostname (e.g. builder01.local) and no pre-existing certs; for **custom domain** you provide domain, SSL directory, and certificates (see below).\n\n---\n\n## Local default (recommended)\n\nThe **default** setup is **local**: service name **builder01.local**, automatic Root CA and wildcard server certificate.\n\n- Set the server hostname to **builder01.local**: `sudo hostnamectl set-hostname builder01.local`\n- Run install (bootstrap runs in the server phase and creates Root CA + wildcard cert in `/opt/aifabrix/certs`; certs are copied to the SSL directory)\n- **DNS:** Add **\\*.builder01.local** to your DNS pointing to this server's IP. The server IP is shown at the end of installation.\n- Then use **<https://builder01.local/install-ca>** to download the Root CA for your PC; **`aifabrix dev init`** with server URL `https://builder01.local` uses that URL to fetch and install the CA. See [Builder CLI reference](https://docs.aifabrix.ai/docs/reference-cli-reference).\n\n---\n\n## Manual prerequisites (before install)\n\nDo the steps in [What you must do before running af-server](#what-you-must-do-before-running-af-server) (below). For **local default**: Ubuntu, root/sudo, SSH, hostname (e.g. builder01.local); after install, add **\\*.builder01.local** in DNS to the printed server IP. For **custom domain**: DNS (CNAME or A), SSL directory, and certificate + key; the install script does not create certificates and configures nginx to use the files you provide.\n\n---\n\n## Install: from zero to running\n\nComplete the [manual prerequisites](#what-you-must-do-before-running-af-server) first. For **local default** you do not copy SSL (step 3); bootstrap creates certs during the server phase.\n\n**Flow summary:** Only **step 1** runs over SSH from your PC. Steps **5** and **7** run **on the server** after you log in. **Install output** prints the DNS instruction with the server IP when using local default.\n\n| Step | Where         | Action |\n| ---- | --------------| ------ |\n| 1    | From PC       | `af-server install-init $SSH` — only command over SSH; installs on server: SSH (if needed), Node 20+, npm, and `af-server` CLI. |\n| 2    | One-time      | Log in to the server once (e.g. with password) to approve passwordless SSH; then from PC: `af-server ssh-cert install $SSH`. |\n| 3    | From PC       | **Custom domain only:** Copy SSL certificate and key to the server (see **SSL directory and certificates**). For **local default** (builder01.local), skip—bootstrap creates certs in server phase. |\n| 4    | From PC       | Log in to the server via SSH (passwordless). |\n| 5    | **On server** | `sudo af-server install` — install all services (Docker, Docker Compose v2, nginx package, Mutagen, cron, data dir); no builder-server container yet. |\n| 6    | On server     | Get the builder-server image (e.g. `az login` / `docker pull`). |\n| 7    | **On server** | `sudo af-server install-server --dev-domain $DOMAIN` — nginx vhost, builder-server container (with `REMOTE_SERVER=https://$DOMAIN` and `DOCKER_ENDPOINT=tcp://$DOMAIN:2376`), Docker TLS. For local default (`$DOMAIN=builder01.local`), bootstrap runs and creates Root CA + wildcard cert; nginx gets `/install-ca` for the Root CA. |\n| 8    | —             | Done. At end of install (local default), the script prints: *Add \\*.builder01.local to your DNS pointing to &lt;IP&gt;* and *Then open <https://builder01.local/install-ca> to get the Root CA for your PC.* |\n\n### Step 1: Bootstrap the server (from PC)\n\nSet your target and run the only command that uses SSH from your PC. For **local default** use the server IP or hostname (e.g. builder01.local once DNS is set):\n\n```bash\nexport SSH=serveradmin@builder01.local\n# Or use the server IP until DNS is set: export SSH=serveradmin@192.168.1.30\naf-server install-init $SSH\n```\n\nThis installs on the server: openssh-server (if needed), Node 20+, npm, and `@aifabrix/builder` + `@aifabrix/server-setup` so `af-server` is available there. You’ll see progress messages and live output from the bootstrap (package lists, SSH, Node, npm install). No Docker, nginx, or builder-server yet.\n\n### Step 2: Passwordless SSH (from PC)\n\nLog in to the server once (e.g. with password) to accept the host key and/or approve auth. Then from your PC:\n\n```bash\naf-server ssh-cert install $SSH\n```\n\n### Step 3: Copy SSL (from PC) — custom domain only\n\nFor **custom domain** (e.g. builder01.aifabrix.dev), put `wildcard.crt` and `wildcard.key` in `/opt/aifabrix/ssl` on the server. For **local default** (builder01.local), skip this step—bootstrap creates certs during install-server.\n\nExample (replace `$HDD` with the folder on your PC that has the cert and key):\n\n```bash\nexport HDD=/path/on/your/pc/to/certs\nssh $SSH \"sudo mkdir -p /opt/aifabrix/ssl\"\nscp $HDD/wildcard.crt $SSH:/tmp/wildcard.crt\nscp $HDD/wildcard.key $SSH:/tmp/wildcard.key\nssh $SSH \"sudo mv /tmp/wildcard.crt /tmp/wildcard.key /opt/aifabrix/ssl/ && sudo chmod 600 /opt/aifabrix/ssl/wildcard.key\"\n```\n\n### Step 4: Log in to the server\n\n```bash\nssh $SSH\n```\n\n### Step 5: Install services (on server)\n\n```bash\nsudo af-server install\n```\n\nThis installs Docker, the **Docker Compose v2** plugin (`docker compose`), nginx (package only), Mutagen, data dir, apply-dev-users script and cron. It does **not** write the builder nginx vhost or start the builder-server container.\n\n### Step 6: Get the builder-server image (on server)\n\nThe image is not on a public registry. Use your platform’s method (e.g. Azure CLI or Docker login), then pull. Example:\n\n```bash\naz login\naz acr login --name youracr\ndocker pull youracr.azurecr.io/aifabrix/builder-server:latest\n```\n\nOr with Docker login (username/password from your registry):\n\n```bash\ndocker login <registry> -u <user> -p <password>\ndocker pull <registry>/aifabrix/builder-server:latest\n```\n\n### Step 7: Install server (nginx vhost + container) (on server)\n\n**Local default:**\n\n```bash\nsudo hostnamectl set-hostname builder01.local\nsudo af-server install-server --dev-domain builder01.local\n```\n\nBootstrap runs and creates Root CA + wildcard cert; nginx is configured with `/install-ca` serving the Root CA. At the end you'll see: *Add \\*.builder01.local to your DNS pointing to &lt;IP&gt;* — add that DNS record, then use <https://builder01.local/install-ca> to get the Root CA for your PC.\n\n**Custom domain:**\n\n```bash\nexport DOMAIN=builder01.aifabrix.dev\nsudo af-server install-server --dev-domain $DOMAIN\n```\n\nUse the same domain as your DNS and SSL. Optional: `--ssl-dir /opt/aifabrix/ssl`, `--data-dir /opt/aifabrix/builder-server/data`, `--builder-port 3000`.\n\n**Production layout (flat app hostnames + legacy workspaces):** When the Builder API stays at one host (e.g. `builder01.aifabrix.dev`) but per-developer apps use `devNN.<root>` and workspaces live under `/home/devNN` (not `$DATA_DIR/workspace`), pass both flags on **`install`** and **`install-server`** (same values):\n\n```bash\nsudo af-server install \\\n  --dev-domain builder01.aifabrix.dev \\\n  --developer-root-domain aifabrix.dev \\\n  --workspace-root /home\n\nsudo af-server install-server \\\n  --dev-domain builder01.aifabrix.dev \\\n  --developer-root-domain aifabrix.dev \\\n  --workspace-root /home\n```\n\n- **`--developer-root-domain`** — app URL root (e.g. `dev06.aifabrix.dev` via Traefik/nginx sync).\n- **`--workspace-root`** — canonical developer data at `/home/devNN`; SSH sessions bind **`/workspace`** → that path (PAM mount script). Default without this flag: `$DATA_DIR/workspace/devNN`.\n\nIf the builder-server image is not on the host yet, the first run writes an nginx vhost without client-cert verification (so `nginx -t` passes). After you pull the image and re-run install-server, the container will start, create `ca.crt`, and a subsequent run will enable client-cert verification and reload nginx.\n\n### Step 8: Done\n\nYour builder-server is up. Use the **AI Fabrix Builder CLI** for users, secrets, certs, etc.—see [Platform developer access](https://docs.aifabrix.ai/docs/build-ai-ready-systems-govern-protect-platform-developer-access).\n\n### Onboarding the first user\n\nUse the **AI Fabrix Builder** CLI to onboard the first developer. The first user comes with a single-use PIN `123456` valid for 30 days. Run (from your PC, after installing the Root CA from <https://builder01.local/install-ca>):\n\n```bash\naifabrix dev init --developer-id 01 --server https://builder01.local --pin 123456\n```\n\nFor a custom domain, use your server URL instead (e.g. `https://builder01.aifabrix.dev`). See [Builder CLI reference](https://docs.aifabrix.ai/docs/reference-cli-reference).\n\n### Migrating from a legacy dev-box (per developer)\n\nWhen moving existing **`devNN`** OS users without replacing their SSH keys immediately:\n\n1. **`aifabrix dev add <id>`** (Builder CLI, from an enrolled admin PC) — register the user in builder-server (`developer`, `docker` groups as needed).\n2. **`sudo af-server import-legacy-ssh-keys <id>`** — copy existing `~devNN/.ssh/authorized_keys` into `builder.db` and `$DATA_DIR/ssh-keys` **before** `dev init` on the PC (otherwise onboarding replaces keys). Omit `<id>` to scan all `dev*` accounts.\n3. **`aifabrix dev pin <id>`** — optional PIN for PC **`dev init`** (mTLS + remote Docker).\n4. On the PC: point SSH/Mutagen at the new builder host; run **`aifabrix dev init`** when ready for certificates.\n\nAfter apply-dev-users runs, migrated users get **`/bin/bash`** login (not legacy dev-box shell), **`/workspace`** bind-mount on SSH when **`--workspace-root`** is set, and docker group membership from builder-server state.\n\n**Per-user Builder CLI on the host:** Legacy dev-box setups often left a stale global **`/usr/local/bin/aifabrix`** or broken pnpm shims under **`~/.local/bin`**. After migration, install the current **`@aifabrix/builder`** for each **`devNN`** account in one command — see [Builder CLI on the server (install / clean)](#builder-cli-on-the-server-install--clean).\n\nIf the onboarding PIN was already used or expired, prefer **`POST /api/dev/users/:id/pin`** with a valid TLS client certificate (admin or self) to create a new PIN. Full request and response shapes are in the builder-server **OpenAPI** UI at **`https://<your-builder-host>/api-docs`** (use the same host you use for the Builder CLI; client-certificate auth applies). If you are locked out but have **shell access on the builder host**, you can mint a new single-use PIN with **`sudo af-server reset pin <developer-id>`** (see [Commands](#commands) and [Troubleshooting](#troubleshooting)). Then use the printed **`aifabrix dev init … --pin …`** line (server URL from the running builder-server container when available).\n\n---\n\n## Builder-server logs\n\nUse these when you need to confirm what the API did or why a request failed. PINs, private keys, decrypted secrets, and certificate request bodies are **not** written to logs.\n\n**Container stdout / stderr**  \nThe builder-server process logs through Docker. Inspect with `docker logs` on your builder-server container (name depends on how it was created). Normal HTTP error responses (4xx) are logged at **warn** with method, URL path, status code, and a short message—the same kind of message the client sees (for example “invalid or expired PIN”), not the PIN value. Unexpected failures are logged at **error** with a stack trace.\n\n**Audit file: `audit.log` in the data directory**  \nOn the host, this file lives next to other builder data (for example **`/opt/aifabrix/builder-server/data/audit.log`** when you use the default data dir from `af-server install-server`). Each line is one JSON record for security-relevant events: certificate issuance outcomes, onboarding PIN creation, user create/update/delete, SSH key add/remove, secret key create/delete (key **names** only), and similar actions. Server errors (**5xx**) and uncaught exceptions also add lines when file auditing is on.\n\n- **Turn off the audit file** (stdout logging unchanged): set **`AUDIT_LOG_ENABLED=false`** or **`0`** in the builder-server container environment (alongside `DATA_DIR` and other variables), then restart the container.\n- **Rotation:** Treat `audit.log` like any growing log on the host—logrotate, truncation, or shipping to your log stack. The data directory must stay writable by the container.\n\n**Nginx** on the host has separate access and error logs for TLS and reverse proxy behaviour; they complement but do not replace application logs above.\n\n---\n\n## Commands\n\n| Command | Description |\n| -------- | ----------- |\n| `af-server install-init <user@host> [ -i SSH_KEY ]` | **From PC only.** One-time bootstrap over SSH: install on server SSH (if needed), Node 20+, npm, and af-server CLI. Shows progress and streams server output. |\n| `af-server install [ user@host ] [ -d DATA_DIR ] [ --dev-domain DOMAIN ] [ --developer-root-domain DOMAIN ] [ --workspace-root PATH ] [ --ssl-dir PATH ] [ -i SSH_KEY ]` | **Run on server** (omit target): `sudo af-server install`. Infra: Docker, Docker Compose v2, nginx pkg, Mutagen, data dir, cron, helper scripts. **No builder vhost or container.** For **`DEV_DOMAIN` ending in `.local`**, also runs **bootstrap** (Root CA + wildcard under **`/opt/aifabrix/certs`**, copies to **`SSL_DIR`**) and **installs the dev root CA into the Debian/Ubuntu OS trust store** (same PEM as **`/install-ca`**). With target: same over SSH. |\n| `af-server install-server --dev-domain DOMAIN [ -d DATA_DIR ] [ --developer-root-domain DOMAIN ] [ --workspace-root PATH ] [ --ssl-dir PATH ] [ --builder-port PORT ]` | **On server only.** Nginx vhost, builder-server container, Docker TLS. Run after `sudo af-server install`. For **`.local`**, runs bootstrap again if needed and **re-applies** OS trust for the dev root CA (idempotent; first install already did this during **`install`**). |\n| `af-server install-trust-dev-ca [ -s, --source PATH ]` | **On server only (root).** Re-install bootstrap dev root CA into OS trust (default source **`/opt/aifabrix/certs/root-ca.crt`**). Use after **CA rotation** or if **`install-server`** ran before the PEM existed. |\n| `af-server backup [ user@host ] [ -d DATA_DIR ] [ -o output.zip ] [ -i SSH_KEY ]` | On-demand backup (config + DB + keys). |\n| `af-server backup [ user@host ] --schedule [ --backup-dir PATH ] [ --keep-days N ] [ -i SSH_KEY ]` | Cron backup (daily 02:00, keep last N, default 7). |\n| `af-server restore backup.zip [ user@host ] [ -d DATA_DIR ] [ --force ] [ -i SSH_KEY ]` | Restore backup to DATA_DIR. |\n| `af-server ssh-cert install [ user@host ] [ -i SSH_KEY ]` | Add your SSH public key to server (passwordless auth). |\n| `af-server install-ssh [ user@host ] [ -i SSH_KEY ]` | Activate SSH server (install openssh-server, enable and start ssh) without login. Omit target for local. |\n| `af-server reset pin <developer-id> [ -d DATA_DIR ] [ --no-restart ] [ --no-apply-dev-users ]` | **On server only (break-glass).** Writes `builder.db`: removes existing PIN tokens for that user and inserts a new random 6-digit PIN (24h TTL, same rules as API `createPin`). Prints the PIN, expiry (UTC), and a copy-paste **`aifabrix dev init … --pin …`** line (server URL from builder container `REMOTE_SERVER` when the container is running). When run as **root** and `/usr/local/bin/aifabrix-apply-dev-users.sh` exists, runs that script with `DATA_DIR` set (same as cron) so dev SSH users get immediate host sync (workspace, **`git safe.directory`** for clones, etc.); skip with **`--no-apply-dev-users`**. Then restarts containers (unless **`--no-restart`**). Docker output is suppressed so the terminal stays readable. Run with **`sudo`** if `DATA_DIR` is not writable. **Anyone who can run this effectively has host-level access to mint PINs**—use only when mTLS admin PIN creation is not available. |\n| `af-server import-legacy-ssh-keys [ developer-id ] [ -d DATA_DIR ] [ --no-apply ]` | **On server only (root).** Migration: copy existing `dev<id>` **`~/.ssh/authorized_keys`** into `builder.db` and **`$DATA_DIR/ssh-keys/<id>/authorized_keys`**. Omit **`developer-id`** to import for all `dev*` OS users. Runs apply-dev-users afterward unless **`--no-apply`**. Run **after** **`aifabrix dev add`** and **before** PC **`dev init`** so legacy keys are preserved. |\n| `af-server fix-workspace-access [ linux-user ] [ -d DATA_DIR ]` | **On server only (root).** Runs **`chown -R linux-user:linux-user`** on **`$DATA_DIR/workspace/<linux-user>`** (creates the directory if missing). Omit **`linux-user`** when using **`sudo`** so **`SUDO_USER`** is used. **Does not** chown **`WORKSPACE_ROOT/dev<id>`** when **`--workspace-root`** is set—use **`sudo chown -R devNN:devNN /home/devNN`** for that layout. |\n| `af-server install-builder-cli [ developer-id ] [ --builder-version VERSION ] [ --include IDS ] [ --exclude IDS ]` | **On server only (root).** Installs **`@aifabrix/builder`** into each selected **`dev*`** user's **`~/.local`** (`~/.local/bin/aifabrix` and **`af`**). See [Builder CLI on the server](#builder-cli-on-the-server-install--clean). |\n| `af-server clean-builder-cli [ developer-id ] [ --include IDS ] [ --exclude IDS ] [ --dry-run ]` | **On server only (root).** Removes **`~/.local`** Builder CLI binaries and package tree (broken pnpm wrappers, partial installs). **`--dry-run`** previews only. See [Builder CLI on the server](#builder-cli-on-the-server-install--clean). |\n| `af-server install-dev-platform [ developer-id ] …` | **On server only (root).** Run **`aifabrix setup --mode fresh`** as each **`devNN`** (first-time platform). See [Per-developer platform install and update](#per-developer-platform-install-and-update). |\n| `af-server update-dev-platform [ developer-id ] …` | **On server only (root).** Run **`aifabrix setup --mode update-images`** as each **`devNN`** (refresh images, keep data). See [Per-developer platform install and update](#per-developer-platform-install-and-update). |\n| `af-server provision-dev-user [ developer-id ] …` | **On server only (root).** One-call server readiness after **`aifabrix dev add`**. See [Per-developer platform install and update](#per-developer-platform-install-and-update). |\n| `af-server remove-dev-platform [ developer-id ] …` | **On server only (root).** Tear down **`devNN`** platform only (`aifabrix teardown --yes`). Keeps OS user and **`builder.db`**. See [Per-developer platform install and update](#per-developer-platform-install-and-update). |\n| `af-server remove-dev-user [ developer-id ] …` | **On server only (root).** Full developer removal: platform + **`builder.db`** + workspace + OS user. See [Per-developer platform install and update](#per-developer-platform-install-and-update). |\n\nBackups contain secrets; store encrypted. Cron backup needs SQLite (`builder.db`) and `zip` on the server; default backup dir: `/opt/aifabrix/backups`.\n\n## Command examples (quick reference)\n\nCopy-paste patterns; replace `user@host`, paths, and domains. Defaults match `af-server <command> --help`. On-demand backup without `-o` writes `./aifabrix-backup-YYYYMMDD-HHMM.zip` in the current working directory.\n\n### install-init (from your PC)\n\n```bash\naf-server install-init serveradmin@192.168.1.10\naf-server install-init serveradmin@builder01.local -i ~/.ssh/id_ed25519\n```\n\n### install\n\nOn the server (infra only; no builder-server container yet):\n\n```bash\nsudo af-server install\n```\n\nFrom your PC over SSH:\n\n```bash\naf-server install serveradmin@builder01.local -i ~/.ssh/id_ed25519\naf-server install serveradmin@host \\\n  --dev-domain builder01.aifabrix.dev \\\n  --developer-root-domain aifabrix.dev \\\n  --workspace-root /home \\\n  --ssl-dir /opt/aifabrix/ssl \\\n  --data-dir /opt/aifabrix/builder-server/data \\\n  --builder-port 3000 \\\n  -i ~/.ssh/id_ed25519\n```\n\n### install-server (on server only, after `sudo af-server install`)\n\n```bash\nsudo af-server install-server --dev-domain builder01.local\nexport DOMAIN=builder01.aifabrix.dev\nsudo af-server install-server --dev-domain \"$DOMAIN\" \\\n  --developer-root-domain aifabrix.dev \\\n  --workspace-root /home \\\n  --ssl-dir /opt/aifabrix/ssl \\\n  --data-dir /opt/aifabrix/builder-server/data\n```\n\nRe-run after pulling a new builder-server image or when nginx must pick up new **`devNN`** routes. See [Host install and update](#host-install-and-update-af-server-install--install-server).\n\n### install-dev-platform / update-dev-platform / provision-dev-user\n\nSee [Per-developer platform install and update](#per-developer-platform-install-and-update).\n\n```bash\nsudo af-server install-dev-platform --include 03,04,05 --check\nsudo af-server update-dev-platform --include 03,04,05 --check\nsudo af-server provision-dev-user 09 --check\n```\n\n### install-trust-dev-ca (on server only; after bootstrap PEM exists)\n\n```bash\nsudo af-server install-trust-dev-ca\nsudo af-server install-trust-dev-ca --source /opt/aifabrix/certs/root-ca.crt\n```\n\n### backup\n\n```bash\naf-server backup\naf-server backup -o ~/backups/builder-snapshot.zip\naf-server backup serveradmin@host -i ~/.ssh/id_ed25519 -o ./snapshot.zip\nsudo af-server backup --schedule\nsudo af-server backup --schedule --backup-dir /opt/aifabrix/backups --keep-days 14\n```\n\n### restore\n\n```bash\naf-server restore /path/to/aifabrix-backup-20250402-1200.zip\naf-server restore ./backup.zip serveradmin@host -i ~/.ssh/id_ed25519\naf-server restore ./backup.zip -d /opt/aifabrix/builder-server/data --force\n```\n\n### install-ssh\n\n```bash\nsudo af-server install-ssh\naf-server install-ssh serveradmin@host -i ~/.ssh/id_ed25519\n```\n\n### reset pin (on builder host; usually sudo)\n\n```bash\nsudo af-server reset pin 01\nsudo af-server reset pin 01 -d /var/lib/docker/volumes/aifabrix_builder-server_data/_data\nsudo af-server reset pin 01 --no-restart\nsudo af-server reset pin 01 --no-apply-dev-users\n```\n\n### import-legacy-ssh-keys (on builder host; sudo)\n\nUse when migrating legacy **`devNN`** users so existing SSH keys are kept in builder-server before PC **`dev init`**:\n\n```bash\nsudo af-server import-legacy-ssh-keys 06\nsudo af-server import-legacy-ssh-keys\nsudo af-server import-legacy-ssh-keys 06 --no-apply\nsudo af-server import-legacy-ssh-keys -d /opt/aifabrix/builder-server/data\n```\n\n### install-builder-cli (on builder host; sudo)\n\nInstall or upgrade the **AI Fabrix Builder** CLI for **`dev*`** OS users. See the full section [Builder CLI on the server (install / clean)](#builder-cli-on-the-server-install--clean) for behaviour, user selection, and troubleshooting.\n\n```bash\nsudo af-server install-builder-cli\nsudo af-server install-builder-cli --builder-version 2.49.2\nsudo af-server install-builder-cli 03\nsudo af-server install-builder-cli --include 01,03,05 --exclude 02\nsudo af-server install-builder-cli 03 --builder-version 2.49.2\n```\n\n### clean-builder-cli (on builder host; sudo)\n\nRemove broken or unwanted **`~/.local`** Builder CLI installs before reinstalling. Use **`--dry-run`** first to preview.\n\n```bash\nsudo af-server clean-builder-cli --dry-run\nsudo af-server clean-builder-cli\nsudo af-server clean-builder-cli 03\nsudo af-server clean-builder-cli --include 01,03,05 --exclude 02\n```\n\n### fix-workspace-access (on builder host; sudo)\n\nUse when **`cp`**, sync, or similar fails with **permission denied** under your **`DATA_DIR/workspace/<user>`** tree (files owned by root or the container user).\n\n```bash\nsudo af-server fix-workspace-access\nsudo af-server fix-workspace-access dev02\nsudo af-server fix-workspace-access dev02 -d /opt/aifabrix/builder-server/data\n```\n\n### ssh-cert install\n\n```bash\nexport SSH=serveradmin@builder01.local\naf-server ssh-cert install \"$SSH\"\naf-server ssh-cert install serveradmin@host -i ~/.ssh/id_ed25519\n```\n\n### ssh-cert request\n\nNot implemented yet; reserved for a future SSH CA flow. Use `ssh-cert install` for passwordless key-based SSH.\n\n---\n\n## Builder CLI on the server (install / clean)\n\nOn a multi-developer builder host, each **`devNN`** Linux account needs its **own** copy of **`@aifabrix/builder`** on **`PATH`** so commands like **`aifabrix dev init`**, **`make dev-install`**, and **`af`** work inside SSH sessions. The global **`npm install -g`** on the host (used by **`serveradmin`**) does **not** apply to **`dev01`…`dev16`**.\n\n**`af-server install-builder-cli`** and **`af-server clean-builder-cli`** manage per-user installs under **`~/.local`**. Run both **on the builder host as root** (`sudo`).\n\n**Cron (`aifabrix-apply-dev-users.sh`) does not upgrade or downgrade Builder CLI.** It only installs **`@aifabrix/builder@${BUILDER_CLI_VERSION}`** when **`~/.local/bin/aifabrix`** is missing or broken. Any version already working there is left alone so developers can pin a local version. Use **`install-builder-cli`** for deliberate batch upgrades.\n\n### When to use\n\n| Situation | Command |\n| --------- | ------- |\n| Batch-upgrade all developers to a known Builder CLI version | `sudo af-server install-builder-cli --builder-version 2.49.2` |\n| Install latest from npm for everyone | `sudo af-server install-builder-cli` |\n| One developer after onboarding | `sudo af-server install-builder-cli 03` |\n| Legacy host still has **`/usr/local/bin/aifabrix`** (wrong version) or broken pnpm **`af`** shims | `sudo af-server clean-builder-cli` then `install-builder-cli` |\n| Preview what would be removed | `sudo af-server clean-builder-cli --dry-run` |\n| Migration from dev-box (with **`import-legacy-ssh-keys`**) | Run **`install-builder-cli`** after SSH keys and workspace are set |\n\n### What install-builder-cli does (per user)\n\n1. Skips users who already have the target version at **`~/.local/bin/aifabrix`** and **`~/.local/bin/af`** (login-shell **`PATH`**).\n2. Ensures **`export PATH=\"$HOME/.local/bin:$PATH\"`** is present in **`~/.bashrc`** / **`~/.profile`** when missing.\n3. Removes stale **`~/.local/bin/aifabrix`**, **`~/.local/bin/af`**, and **`~/.local/lib/node_modules/@aifabrix/builder`** (same as **`clean-builder-cli`**).\n4. Runs **`npm install -g @aifabrix/builder@<version> --prefix \"$HOME/.local\"`** as that user.\n5. Verifies **`aifabrix --version`**, **`af --version`**, and **`command -v`** point at **`~/.local/bin`**.\n\n**Version flag:** use **`--builder-version`** (not **`--version`** — that prints the **`af-server`** package version). Omit **`--builder-version`** to resolve the latest **`@aifabrix/builder`** from npm (`npm view` on the host).\n\n**npm registry:** **`@aifabrix/builder`** must be reachable for each **`devNN`** user (GitHub Packages or your configured registry). If install fails with **404** or **permission**, fix **`~devNN/.npmrc`** / registry auth on the host before retrying.\n\n### What clean-builder-cli does (per user)\n\nRemoves these paths when present (working symlinks included — this is a full local uninstall, not only “broken” files):\n\n- **`~/.local/bin/aifabrix`**\n- **`~/.local/bin/af`**\n- **`~/.local/lib/node_modules/@aifabrix/builder`**\n\nThen **`chown -R devNN:devNN ~/.local`**. Does **not** remove **`/usr/local/bin/aifabrix`** (host-wide); after clean + install, login shells should prefer **`~/.local/bin`** via **`PATH`**.\n\nUse **`--dry-run`** to list what would be removed without changing disk. Always run **`install-builder-cli`** afterward if users still need the CLI.\n\n### Selecting users\n\nAll three forms can be combined; **`developer-id`** positional arg targets one user (**`03`** → **`dev03`**).\n\n| Pattern | Example | Users affected |\n| ------- | ------- | -------------- |\n| All **`dev*`** OS accounts on the host | `sudo af-server install-builder-cli` | Every **`dev01`**, **`dev02`**, … from **`getent passwd`** |\n| Single id | `sudo af-server install-builder-cli 06` | **`dev06`** only |\n| Explicit list | `sudo af-server install-builder-cli --include 01,03,16` | **`dev01`**, **`dev03`**, **`dev16`** |\n| All except some | `sudo af-server install-builder-cli --exclude 02,06` | All **`dev*`** minus **`dev02`** and **`dev06`** |\n| List minus exclusions | `sudo af-server install-builder-cli --include 01,02,03,04,05 --exclude 02` | **`dev01`**, **`dev03`**, **`dev04`**, **`dev05`** |\n\nIds accept **`3`** or **`03`**; **`--include`** / **`--exclude`** use comma-separated lists without spaces required.\n\n### Examples\n\n```bash\n# Upgrade everyone to a pinned release\nsudo af-server install-builder-cli --builder-version 2.49.2\n\n# Latest from npm, all dev* users\nsudo af-server install-builder-cli\n\n# Subset during migration\nsudo af-server install-builder-cli --include 01,03,04,05,07,08,09,10,11,12,13,14,15,16\n\n# Clean broken shims, then reinstall\nsudo af-server clean-builder-cli --dry-run\nsudo af-server clean-builder-cli --include 01,03\nsudo af-server install-builder-cli --include 01,03 --builder-version 2.49.2\n\n# Verify as the developer (SSH login shell)\nsudo -u dev03 bash -lc 'aifabrix --version && command -v aifabrix'\n```\n\n### Output\n\nBoth commands print a per-user summary (`ok` / `failed` / `skipped` for install; `cleaned` / `unchanged` / `skipped` for clean). Install exits non-zero if any user **`failed`**; clean does not fail on **`unchanged`** users.\n\nHelp: **`af-server install-builder-cli --help`**, **`af-server clean-builder-cli --help`**.\n\n---\n\n## Documentation\n\nThis README covers **`@aifabrix/server-setup`** (`af-server`) only — install, backup, restore, and host maintenance for builder-server.\n\n**AI Fabrix Builder CLI** (users, secrets, onboarding, remote Docker, developer isolation):\n\n- [Documentation index](https://docs.aifabrix.ai/llms.txt) — full page list for AI Fabrix docs  \n- [Build AI-ready systems](https://docs.aifabrix.ai/docs/build-ai-ready-systems) — integrator and platform overview  \n- [Builder CLI reference](https://docs.aifabrix.ai/docs/reference-cli-reference) — command index  \n- [Developer workstation setup](https://docs.aifabrix.ai/docs/build-ai-ready-systems-get-started-developer-workstation-setup) — install Builder CLI and connect to your environment  \n- [Platform developer access](https://docs.aifabrix.ai/docs/build-ai-ready-systems-govern-protect-platform-developer-access) — developer personas and access model  \n\n**Server operations on the host:** use `af-server <command> --help` for flags and examples. Per-developer **Builder CLI** install/clean: [Builder CLI on the server (install / clean)](#builder-cli-on-the-server-install--clean). **Re-run / upgrade** host infra: [Host install and update](#host-install-and-update-af-server-install--install-server). **Per-developer platform** (install / update / provision): [Per-developer platform install and update](#per-developer-platform-install-and-update). Advanced topics covered here include Docker TLS on `:2376`, nginx mTLS, and env vars (`DEV_DOMAIN`, `WORKSPACE_ROOT`, `DEVELOPER_ROOT_DOMAIN`) — see [High level: what install vs install-server does](#high-level-what-install-vs-install-server-does) and [Troubleshooting](#troubleshooting).\n\nThis README is: **zero to up and running your builder server**.\n\n---\n\n## What you must do before running af-server\n\nComplete these **manually** before `af-server install`. The install script does not create DNS, certificates, or the admin account; it expects them to exist.\n\n**Server and access**\n\n- **Ubuntu** — 22.04 LTS or later (recommended). Other Debian-based systems may work but are not guaranteed.\n- **Root or sudo** — The install script must run with root (or sudo). From your PC you SSH as a user that can `sudo` to root; on the server you run `sudo af-server install` (or as root).\n- **SSH access** — You need key-based or password SSH to the server so you can run `af-server install user@host`, or you run install locally on the server.\n\n**DNS (CNAME or A record)**\n\n- **Local default (builder01.local):** Set hostname to builder01.local; after install, add **\\*.builder01.local** to your DNS pointing to this server's IP (the IP is printed at the end of installation).\n- **Custom domain:** Create a **DNS A record** or **CNAME** so your chosen domain points to the server's IP. Set `--dev-domain` or env `DEV_DOMAIN` (e.g. builder01.aifabrix.dev). Ensure DNS has propagated before install.\n\n**SSL directory and certificates**\n\n- **Local default:** No manual certs. The install runs a bootstrap that creates a Root CA and wildcard server cert; they are placed in `/opt/aifabrix/certs` and copied to the SSL directory. The Root CA is served at `https://<domain>/install-ca`.\n- **Custom domain:** Create the SSL directory (default `/opt/aifabrix/ssl`):  \n  `sudo mkdir -p /opt/aifabrix/ssl`  \n  To use another path, set `--ssl-dir` or env `SSL_DIR`.\n- **Obtain** a TLS certificate and private key (e.g. Let’s Encrypt, internal CA, or purchased). Full chain if applicable.\n- **Place** in the SSL directory:\n  - `wildcard.crt` — certificate (full chain if applicable)\n  - `wildcard.key` — private key  \n  Set permissions: `chmod 600 /opt/aifabrix/ssl/wildcard.key`  \n  The install script does not create certificates for custom domain; it only configures nginx to use these files.\n\n**Admin user (optional but typical)**  \nIf you SSH as a non-root user, that user must be able to sudo. The script will add an admin user (default `serveradmin`) to the `docker` group and grant it passwordless sudo. Ensure that user exists on the server if you rely on it, or set `SETUP_ADMIN_USER` to your SSH user.\n\n---\n\n## High level: what install vs install-server does\n\n**`af-server install`** (step 5 — run on the server) does **infra only**:\n\n- **System** — `apt update` and `apt upgrade`; optional hostname if `SETUP_HOSTNAME` is set.\n- **Docker** — Installs Docker if missing; enables and starts it.\n- **Admin user** — Adds the admin user (default `serveradmin`) to the `docker` group and grants passwordless sudo.\n- **Nginx** — Installs the nginx **package** only; enables and starts it. Does **not** write the builder vhost yet.\n- **Data dir** — Creates the data directory (default `/opt/aifabrix/builder-server/data`), workspace and ssh-keys subdirs, ownership for the container.\n- **Apply-dev-users** — Installs the script and cron job (every 2 minutes) that sync per-developer OS users from builder-server state. Creates **`dev<id>`** Linux accounts, merges managed SSH keys, sets login shell to **`/bin/bash`**, adds **`docker`** group membership from **`$DATA_DIR/aifabrix-os-docker-user-ids.json`**, and writes per-user **`~/.aifabrix/config.yaml`** stubs (remote-server, docker-endpoint). When **`WORKSPACE_ROOT`** is set (via **`--workspace-root`** at install), workspaces live at **`$WORKSPACE_ROOT/dev<id>`** and PAM mounts **`/workspace`** on SSH login. The script configures a user-writable npm/pnpm prefix (`~/.local`) for dev users and the aifabrix user so they can run `npm install -g` and `pnpm add -g` without sudo. **Builder CLI:** bootstraps **`@aifabrix/builder`** only when **`~/.local/bin/aifabrix`** is missing or broken — it does **not** change an existing version (use **`af-server install-builder-cli`** or **`aifabrix dev platform-install-cli`** for upgrades). When run as root, it can also grant passwordless sudo to the aifabrix user (override with `SUDO_NOPASSWD_USER` in apply-dev-users-defaults). **Without sudo:** run the script as the current user (e.g. `SUDO_NOPASSWD_USER=aifabrix`); it will only set up that user's `~/.local` and `~/.npmrc`/`~/.pnpmrc` so npm and pnpm global installs work without sudo.\n- **Host-ops processor** — Installs **`/usr/local/bin/aifabrix-host-ops.sh`** and cron **`/etc/cron.d/aifabrix-host-ops`** (every minute). Processes one pending job from **`$DATA_DIR/host-ops/pending/`** at a time (`flock` single-flight), runs **`af-server host-ops process`**, moves jobs to **`running/`** / **`completed/`** and writes logs under **`host-ops/logs/`**. Used when admins queue work via **`aifabrix dev platform-*`**, **`dev add`** (provision), or **`dev delete`** from their PC. Passwords in job files are redacted in API responses.\n- **Mutagen** — Downloads and installs Mutagen; systemd service and daemon.\n- **Optional** — If `INSTALL_PORTAINER=1`, installs the Portainer container.\n\n**`af-server install-server`** (step 7 — run on the server) does the **server phase**:\n\n- **Nginx vhost** — Writes the builder site config from template (domain, SSL dir, proxy to builder-server), reloads nginx.\n- **Builder-server container** — Creates data dir (if needed), starts the builder-server container (if the image is present).\n- **Docker TLS** — Copies certs and configures `/etc/docker/daemon.json` for TLS on **`tcp://0.0.0.0:2376`**. **Server certificate:** same wildcard as nginx (`wildcard.crt` / public CA or bootstrap). **Client auth:** builder-server internal CA (`$DATA_DIR/ca.crt` → `/etc/docker/ca.pem`). Developers use client certs from **`aifabrix dev init`**; the Builder CLI merges the daemon’s public trust chain into **`~/.aifabrix/certs/<id>/ca.pem`** when the server cert is not signed by the issue-cert CA.\n\nResult: after both steps, the server has Docker, nginx (HTTPS for your domain), the builder-server container (if image present), and Mutagen—ready for the Builder CLI to use.\n\n---\n\n## Host install and update (`af-server install` / `install-server`)\n\nUse this section when the builder host is **already running** and you need to refresh infra scripts, nginx, or the builder-server container — not for first-time setup (see [Install: from zero to running](#install-from-zero-to-running)).\n\n### When to re-run `sudo af-server install`\n\n| Situation | Action |\n| --------- | ------ |\n| Upgraded **`@aifabrix/server-setup`** on the host and need new helper scripts | `sudo af-server install` with the **same flags** as the original install (`--dev-domain`, `--developer-root-domain`, `--workspace-root`, `-d`, `--ssl-dir`) |\n| **`aifabrix-apply-dev-users.sh`** on disk is stale (cron behaviour changed) | Re-run **`install`** — each run copies the bundled script to **`/usr/local/bin/aifabrix-apply-dev-users.sh`** |\n| **`aifabrix-host-ops.sh`** missing or stale (host-ops jobs never run) | Re-run **`install`** — copies script to **`/usr/local/bin/aifabrix-host-ops.sh`** and refreshes **`/etc/cron.d/aifabrix-host-ops`** |\n| Added **`--developer-root-domain`** or **`--workspace-root`** after first install | Re-run **`install`** with both flags so **`apply-dev-users-defaults`** and PAM workspace mounts match production layout |\n| **`.local`** dev domain: OS should trust the bootstrap Root CA | **`install`** re-applies **`install-trust-dev-ca`** logic when bootstrap PEM exists (idempotent) |\n\n**Safe to re-run:** apt upgrade, Docker enablement, Mutagen, cron, data-dir layout, apply-dev-users script install, nginx **package** only. **Does not** recreate the builder-server container or rewrite the builder nginx vhost (that is **`install-server`**).\n\n**From your PC over SSH** (same as first install):\n\n```bash\naf-server install serveradmin@builder01.aifabrix.dev \\\n  --dev-domain builder01.aifabrix.dev \\\n  --developer-root-domain aifabrix.dev \\\n  --workspace-root /home \\\n  -i ~/.ssh/id_ed25519\n```\n\n### When to re-run `sudo af-server install-server`\n\n| Situation | Action |\n| --------- | ------ |\n| Pulled a **new builder-server image** | `sudo af-server install-server --dev-domain …` — recreates container when config/image changed |\n| First run had **no image** (nginx without client-cert verify) | After **`docker pull`**, re-run **`install-server`** so **`ca.crt`** exists and nginx enables mTLS |\n| Changed **`--dev-domain`**, **`--ssl-dir`**, **`--builder-port`**, or Traefik nginx templates | Re-run with updated flags; nginx vhost and **`aifabrix-sync-dev-traefik-nginx.sh`** refresh |\n| New **`devNN`** developers added in builder-server | Re-run **`install-server`** (or wait for **`systemd.path`**) so **`/etc/hosts`** and **`devNN.<developer-root-domain>`** nginx map update |\n\n**Pass the same `--dev-domain`, `--developer-root-domain`, and `--workspace-root` values** you used on **`install`**.\n\n```bash\nsudo af-server install-server \\\n  --dev-domain builder01.aifabrix.dev \\\n  --developer-root-domain aifabrix.dev \\\n  --workspace-root /home\n```\n\n### Upgrade the `af-server` CLI itself\n\nOn the builder host (or your PC):\n\n```bash\nsudo npm install -g @aifabrix/server-setup@latest\naf-server --version\n```\n\nThen re-run **`sudo af-server install`** on the server so bundled assets under **`/usr/local/bin`** match the new package.\n\n---\n\n## Per-developer platform install and update\n\nAfter **`aifabrix dev add`** on an admin PC, use **`provision-dev-user`** for one-call server readiness, or run **`install-dev-platform`** / **`update-dev-platform`** separately.\n\n> **Builder CLI prerequisite:** automation calls **`aifabrix setup --mode fresh`** or **`--mode update-images`**. The installed **`@aifabrix/builder`** must expose **`--mode`** on `aifabrix setup` (upgrade with **`install-builder-cli`** when a release ships it). Until then, **`--check`** still runs host preflight; apply will exit with an upgrade hint.\n\n| Command | Purpose | Builder equivalent (as `devNN`) |\n| ------- | ------- | -------------------------------- |\n| **`install-dev-platform`** | First-time AI Fabrix platform for selected developers | `aifabrix setup --mode fresh` |\n| **`update-dev-platform`** | Refresh platform container images; keep volumes/data | `aifabrix setup --mode update-images` |\n| **`provision-dev-user`** | Full server provision (includes platform + cert steps) | Combines host steps + **`install-dev-platform`** |\n\nAll three will:\n\n- Run **on the server only** as **root** (`sudo af-server …`).\n- Execute **`aifabrix` as each `devNN` user** (never as root).\n- Support **`[developer-id]`**, **`--include`**, **`--exclude`** (same as **`install-builder-cli`**).\n- Print a per-user report (**PASS** / **SKIP** / **FAIL** / **BLOCKED**) and exit non-zero if any user **FAIL**s.\n\n### `install-dev-platform`\n\n**When:** Developer has Builder CLI and secrets file on the host, but **no** running platform (Keycloak + miso-controller + dataplane) yet.\n\n**Default platform mode on shared hosts:** **`single-traefik`** (Traefik + TLS, public URLs like `https://devNN.<developer-root-domain>/…`), not `single` (localhost ports only).\n\n**Admin credentials:** Batch runs read **`$DATA_DIR/apply-dev-platform-defaults`** (`ADMIN_EMAIL`, `ADMIN_PASSWORD`, optional `DEFAULT_PLATFORM_MODE`, `BUILDER_SERVER_URL`). Create that file on the host before the first batch install (mode `600`; not in git). There is **no** silent `admin123` default in automation.\n\n**Skip when:** Platform already healthy for that user (infra + three apps up).\n\n```bash\n# One developer\nsudo af-server install-dev-platform 09\n\n# Batch\nsudo af-server install-dev-platform --include 03,04,05\n\n# Preflight only\nsudo af-server install-dev-platform 09 --check\n```\n\n**Planned flags:** `--platform`, `--installation`, `--admin-email`, `--admin-password`, `--builder-version`, `--timeout-minutes`, `--check`, `--fail-on-blocked` — see **`af-server install-dev-platform --help`**.\n\n### `update-dev-platform`\n\n**When:** Platform is already installed; you need newer images after ACR/build bump **without** wiping Postgres/Redis volumes.\n\n**Skip when:** Platform not installed or not healthy for that user.\n\n```bash\nsudo af-server update-dev-platform\nsudo af-server update-dev-platform --include 01,05\nsudo af-server update-dev-platform --check\n```\n\n**Update ignores** install-only flags (`--admin-password`, `--platform` fresh wipe, etc.).\n\n### `remove-dev-platform`\n\n**When:** Platform install failed or you need a clean **`aifabrix setup --mode fresh`** retry. Removes Docker stack and local platform state only.\n\n**Keeps:** OS user, **`builder.db`**, SSH keys, **`~/.local`** Builder CLI, **`config.yaml`**, client certs.\n\n```bash\nsudo af-server remove-dev-platform 03\nsudo af-server remove-dev-platform 03 --check\nsudo af-server remove-dev-platform --include 03,04\n```\n\nThen re-install: **`sudo af-server install-dev-platform 03`**.\n\n### `remove-dev-user`\n\n**When:** Remove the developer completely from the host (inverse of **`provision-dev-user`**).\n\n**Removes:** Platform (unless **`--skip-teardown`**), **`builder.db`** entry, workspace data, SSH keys, OS user (**`userdel -r`** via apply-dev-users).\n\n```bash\nsudo af-server remove-dev-user 03\nsudo af-server remove-dev-user 03 --check\nsudo af-server remove-dev-user 03 --skip-teardown   # platform already stopped\n```\n\nRe-add with **`aifabrix dev add`** then **`provision-dev-user`**.\n\n### Relationship to other commands\n\n| Step | Command |\n| ---- | ------- |\n| Register user in builder-server | **`aifabrix dev add`** (admin PC) |\n| Host SSH, `config.yaml`, Builder CLI | **`install-builder-cli`**, **`import-legacy-ssh-keys`**, migration prep script |\n| Platform Docker stack per `devNN` | **`install-dev-platform`** |\n| Image refresh | **`update-dev-platform`** |\n| Platform teardown only (retry install) | **`remove-dev-platform`** |\n| Full developer removal | **`remove-dev-user`** |\n| One-call after `dev add` | **`provision-dev-user`** |\n| PC mTLS / remote Docker | **`aifabrix dev pin`** + **`aifabrix dev init`** on laptop |\n\n**Integrator groups at `dev add`:** **`developer,secret-reader`** (read-only central secrets) or **`developer,secret-manager`** (read/write). SSH-first developers: **`developer,docker`**.\n\n---\n\n## Troubleshooting\n\n### `error: unknown command 'reset'`\n\nThe **`af-server reset pin`** command needs **@aifabrix/server-setup 1.6.0** or newer (current release **1.7.x**). If `af-server --help` does not list **`reset`**, install a current release from npm:\n\n```bash\nsudo npm install -g @aifabrix/server-setup@latest\n```\n\nCheck `af-server --version`, then `af-server reset pin --help`.\n\n### Onboarding PIN used up or expired (`reset pin`)\n\n- With a **client certificate**, create a new PIN via **`POST /api/dev/users/<developer-id>/pin`** (documented under **`/api-docs`** on your builder host).\n- **On the server**, with write access to the data directory (usually **`sudo`**):\n\n  ```bash\n  sudo af-server reset pin 01\n  ```\n\n  That default **`DATA_DIR`** is **`/opt/aifabrix/builder-server/data`** (af-server install layout). If you run builder-server with the **AI Fabrix Builder** CLI (**`aifabrix run builder-server`**), data often lives in a **Docker named volume** instead, e.g. mount destination **`/mnt/data`** with host path like **`/var/lib/docker/volumes/aifabrix_builder-server_data/_data`**. In that case you **must** point reset at the same place the container uses, or the API will still see the old PINs:\n\n  ```bash\n  sudo af-server reset pin 01 -d /var/lib/docker/volumes/aifabrix_builder-server_data/_data\n  ```\n\n  Your volume name may differ; confirm with **`docker inspect <container> --format '{{json .Mounts}}'`** and use the **`Source`** directory that maps to **`/mnt/data`** (or whatever **`DATA_DIR`** is inside the container).\n\n  Copy the printed PIN (do not log or commit it) and run the printed **`aifabrix dev init … --pin …`** line (or complete onboarding per [Builder CLI reference](https://docs.aifabrix.ai/docs/reference-cli-reference)).\n\n- If **`reset pin`** fails with **Could not resolve builder server URL**, start the builder-server container first (or pass the correct **`--server`** URL manually in the printed command pattern).\n\n- If SQLite reports **database is locked**, stop the builder-server container, run `reset pin` with **`--no-restart`**, then start the container again—or retry after the default restart finishes.\n\n### Workspace `Permission denied` when copying or syncing (e.g. under `DATA_DIR/workspace/<user>`)\n\nIf **`cp`**, **`make sync`**, or similar fails because files under your builder workspace were created as **root** or the **container user**, reclaim ownership on the **builder host**:\n\n```bash\nsudo af-server fix-workspace-access\n```\n\nThat uses your login name (**`SUDO_USER`**) and the default **`DATA_DIR`**. To fix another account (e.g. as an admin):\n\n```bash\nsudo af-server fix-workspace-access dev02\n```\n\nUse **`-d`** if **`DATA_DIR`** is not the default **`/opt/aifabrix/builder-server/data`**.\n\nWhen **`--workspace-root /home`** is in use, workspaces are under **`/home/devNN`**—this command does not fix those paths; run **`sudo chown -R devNN:devNN /home/devNN`** instead.\n\n### Builder CLI wrong version or `command not found` for `devNN` (SSH)\n\nSymptoms: **`aifabrix --version`** shows an old number (e.g. from **`/usr/local/bin/aifabrix`**), **`af`** is missing, or pnpm left a non-working shim under **`~/.local/bin`**.\n\n1. **Install per-user CLI on the host** (see [Builder CLI on the server](#builder-cli-on-the-server-install--clean)):\n\n   ```bash\n   sudo af-server install-builder-cli --builder-version 2.49.2\n   ```\n\n   Or for one user: **`sudo af-server install-builder-cli 03 --builder-version 2.49.2`**.\n\n2. **If install keeps picking up stale files**, clean first:\n\n   ```bash\n   sudo af-server clean-builder-cli --dry-run\n   sudo af-server clean-builder-cli 03\n   sudo af-server install-builder-cli 03 --builder-version 2.49.2\n   ```\n\n3. **Verify in a login shell** (matches SSH and **`make dev-install`**):\n\n   ```bash\n   sudo -u dev03 bash -lc 'aifabrix --version; command -v aifabrix; command -v af'\n   ```\n\n   Expected: version matches **`--builder-version`**, paths are **`/home/dev03/.local/bin/aifabrix`** and **`.../af`**.\n\n4. **npm 404 / permission errors** during install: each **`devNN`** user needs registry access to **`@aifabrix/builder`** (check **`~devNN/.npmrc`** and GitHub Packages token scope). Fix auth on the host, then re-run **`install-builder-cli`**.\n\n5. **`af-server install-builder-cli` unknown command**: install **`@aifabrix/server-setup`** **1.7.2** or newer on the host (`sudo npm install -g @aifabrix/server-setup@latest`).\n\n6. **Version changed back after `install-builder-cli` (older hosts):** **`aifabrix-apply-dev-users.sh`** used to reinstall **`BUILDER_CLI_VERSION`** every 2 minutes. Current script **only bootstraps when CLI is missing** — refresh with **`sudo af-server install`** (copies the script to **`/usr/local/bin`**) or redeploy **`@aifabrix/server-setup`**. Deliberate upgrades are **`install-builder-cli` only**; cron will not override a working **`~/.local`** install.\n\n### AI Fabrix banner missing in some terminals\n\nThe welcome line comes from the **`# aifabrix dev shell`** block in **`~/.bashrc`** (written by apply-dev-users). It runs only for **interactive** shells (`$-` contains **`i`**). Non-interactive sessions and some IDE reconnects show a plain prompt without the banner — that is normal. **`af`** / **`aifabrix`** still resolve via **`~/.local/bin`** when **`.bashrc`** or **`.profile`** sets **`PATH`**.\n\n### `af-server --version` shows an old version after installing a newer one\n\nIf you installed a newer `@aifabrix/server-setup` from npm but `af-server --version` still shows an older number:\n\n1. **Check which binary is used**  \n   Run `which af-server` and `sudo which af-server`. If they differ, your shell may be using a user-level install while the new one was installed for root.\n\n2. **Uninstall, clear cache, then reinstall**\n\n   ```bash\n   sudo npm uninstall -g @aifabrix/server-setup\n   npm cache clean --force\n   sudo npm install -g @aifabrix/server-setup@latest\n   hash -r   # clear shell’s command cache\n   af-server --version\n   ```\n","readmeFilename":"README.md"}