openvibers/openvibe.host Commits
Tests follow Live's release layout (C-76): the example inventory's live entry reads /opt/openvibe.live/current as root with runAs ubuntu, and the live drill test's simulated host has the release unit and files under current/
Changes
@@@ -23,7 +23,10 @@ runTests([assert.strictEqual(inv.services.live.protected.url, 'http://127.0.0.1:3000/api/streams');assert.match(inv.services.media.protected.sql, /is_recording = 1/);assert.strictEqual(inv.services.games.managed, false);-- for (const s of Object.values(inv.services)) assert.strictEqual(s.owner, 'ubuntu', `${s.id} checkout owner`);++ // Live's release layout (C-76) is root-owned worktrees; its service and drills still run as ubuntu.++ for (const s of Object.values(inv.services)) assert.strictEqual(s.owner, s.id === 'live' ? 'root' : 'ubuntu', `${s.id} checkout owner`);++ assert.strictEqual(inv.services.live.runAs, 'ubuntu');++ assert.strictEqual(inv.services.live.repo, '/opt/openvibe.live/current');const text = JSON.stringify(raw);assert.ok(!/(sk_|ghp_|BEGIN [A-Z ]*PRIVATE KEY|password\s*[:=]\s*\S)/i.test(text), 'no secret values in the example');}),@@@ -47,13 +47,13 @@ async function liveHost({ switchInCheckout = true, drillBodies = null } = {}) {doc.services.live = JSON.parse(JSON.stringify(EXAMPLE.services.live));host.put('/etc/openvibe/host.json', JSON.stringify(doc, null, 2), { mode: 0o640, owner: 'root' });if (switchInCheckout) {-- host.put('/opt/openvibe.live/server/drill.js', "const enabled = parse(process.env.LIVE_DRILL);\n", { owner: 'ubuntu' });-- host.put('/opt/openvibe.live/server/paths.js', "return path.resolve(process.env.DATA_DIR || './data');\n", { owner: 'ubuntu' });++ host.put('/opt/openvibe.live/current/server/drill.js', "const enabled = parse(process.env.LIVE_DRILL);\n", { owner: 'root' });++ host.put('/opt/openvibe.live/current/server/paths.js', "return path.resolve(process.env.DATA_DIR || './data');\n", { owner: 'root' });}host.put('/etc/systemd/system/openvibe-live.service', [-- '[Service]', 'Type=simple', 'User=ubuntu', 'WorkingDirectory=/opt/openvibe.live', 'EnvironmentFile=/etc/openvibe/live.env',++ '[Service]', 'Type=simple', 'User=ubuntu', 'WorkingDirectory=/opt/openvibe.live/current', 'EnvironmentFile=/etc/openvibe/live.env','Environment=NODE_ENV=production', 'Environment=PATH=/usr/local/bin:/usr/bin:/bin',-- 'ExecStart=/usr/bin/env node /opt/openvibe.live/server/index.js', 'ReadWritePaths=/opt/openvibe.live/data', '',++ 'ExecStart=/usr/bin/env node /opt/openvibe.live/current/server/index.js', 'ReadWritePaths=/opt/openvibe.live/shared/data', '',].join('\n'));host.put('/etc/systemd/system/openvibe-live.service.d/socket.conf', '[Unit]\nRequires=openvibe-live.socket\nAfter=openvibe-live.socket\n');const unit = host.units.get('openvibe-live.service');@@@ -173,8 +173,8 @@ runTests([assert.strictEqual(host.systemdRuns.length, 1);const run = host.systemdRuns[0];-- assert.deepStrictEqual(run.argv, ['/usr/bin/env', 'node', '/opt/openvibe.live/server/index.js']);-- assert.strictEqual(run.cwd, '/opt/openvibe.live');++ assert.deepStrictEqual(run.argv, ['/usr/bin/env', 'node', '/opt/openvibe.live/current/server/index.js']);++ assert.strictEqual(run.cwd, '/opt/openvibe.live/current');assert.deepStrictEqual(run.envFiles, ['/etc/openvibe/live.env', `${rec.dir}/drill.env`]);for (const p of ['SocketBindAllow=tcp:13000', 'SocketBindDeny=any', 'IPAddressDeny=any', 'IPAddressAllow=localhost', 'ProtectSystem=strict', `ReadWritePaths=${rec.dir}`, 'Environment=NODE_ENV=production']) assert.ok(run.props.includes(p), p);assert.ok(!run.props.some((p) => /BindPaths=|ReadWritePaths=\/opt/.test(p)), 'no bind mounts; production\'s data directory is not writable');
@@ -23,7 +23,10 @@ runTests([
@@ -23,7 +23,10 @@ runTests([
assert.strictEqual(inv.services.live.protected.url, 'http://127.0.0.1:3000/api/streams');
assert.strictEqual(inv.services.live.protected.url, 'http://127.0.0.1:3000/api/streams');
assert.match(inv.services.media.protected.sql, /is_recording = 1/);
assert.match(inv.services.media.protected.sql, /is_recording = 1/);
assert.strictEqual(inv.services.games.managed, false);
assert.strictEqual(inv.services.games.managed, false);
- for (const s of Object.values(inv.services)) assert.strictEqual(s.owner, 'ubuntu', `${s.id} checkout owner`);
+ // Live's release layout (C-76) is root-owned worktrees; its service and drills still run as ubuntu.
+ for (const s of Object.values(inv.services)) assert.strictEqual(s.owner, s.id === 'live' ? 'root' : 'ubuntu', `${s.id} checkout owner`);
+ assert.strictEqual(inv.services.live.runAs, 'ubuntu');
+ assert.strictEqual(inv.services.live.repo, '/opt/openvibe.live/current');
const text = JSON.stringify(raw);
const text = JSON.stringify(raw);
assert.ok(!/(sk_|ghp_|BEGIN [A-Z ]*PRIVATE KEY|password\s*[:=]\s*\S)/i.test(text), 'no secret values in the example');
assert.ok(!/(sk_|ghp_|BEGIN [A-Z ]*PRIVATE KEY|password\s*[:=]\s*\S)/i.test(text), 'no secret values in the example');
}),
}),
@@ -47,13 +47,13 @@ async function liveHost({ switchInCheckout = true, drillBodies = null } = {}) {
@@ -47,13 +47,13 @@ async function liveHost({ switchInCheckout = true, drillBodies = null } = {}) {
doc.services.live = JSON.parse(JSON.stringify(EXAMPLE.services.live));
doc.services.live = JSON.parse(JSON.stringify(EXAMPLE.services.live));
host.put('/etc/openvibe/host.json', JSON.stringify(doc, null, 2), { mode: 0o640, owner: 'root' });
host.put('/etc/openvibe/host.json', JSON.stringify(doc, null, 2), { mode: 0o640, owner: 'root' });
if (switchInCheckout) {
if (switchInCheckout) {
- host.put('/opt/openvibe.live/server/drill.js', "const enabled = parse(process.env.LIVE_DRILL);\n", { owner: 'ubuntu' });
- host.put('/opt/openvibe.live/server/paths.js', "return path.resolve(process.env.DATA_DIR || './data');\n", { owner: 'ubuntu' });
+ host.put('/opt/openvibe.live/current/server/drill.js', "const enabled = parse(process.env.LIVE_DRILL);\n", { owner: 'root' });
+ host.put('/opt/openvibe.live/current/server/paths.js', "return path.resolve(process.env.DATA_DIR || './data');\n", { owner: 'root' });
}
}
host.put('/etc/systemd/system/openvibe-live.service', [
host.put('/etc/systemd/system/openvibe-live.service', [
- '[Service]', 'Type=simple', 'User=ubuntu', 'WorkingDirectory=/opt/openvibe.live', 'EnvironmentFile=/etc/openvibe/live.env',
+ '[Service]', 'Type=simple', 'User=ubuntu', 'WorkingDirectory=/opt/openvibe.live/current', 'EnvironmentFile=/etc/openvibe/live.env',
'Environment=NODE_ENV=production', 'Environment=PATH=/usr/local/bin:/usr/bin:/bin',
'Environment=NODE_ENV=production', 'Environment=PATH=/usr/local/bin:/usr/bin:/bin',
- 'ExecStart=/usr/bin/env node /opt/openvibe.live/server/index.js', 'ReadWritePaths=/opt/openvibe.live/data', '',
+ 'ExecStart=/usr/bin/env node /opt/openvibe.live/current/server/index.js', 'ReadWritePaths=/opt/openvibe.live/shared/data', '',
].join('\n'));
].join('\n'));
host.put('/etc/systemd/system/openvibe-live.service.d/socket.conf', '[Unit]\nRequires=openvibe-live.socket\nAfter=openvibe-live.socket\n');
host.put('/etc/systemd/system/openvibe-live.service.d/socket.conf', '[Unit]\nRequires=openvibe-live.socket\nAfter=openvibe-live.socket\n');
const unit = host.units.get('openvibe-live.service');
const unit = host.units.get('openvibe-live.service');
@@ -173,8 +173,8 @@ runTests([
@@ -173,8 +173,8 @@ runTests([
assert.strictEqual(host.systemdRuns.length, 1);
assert.strictEqual(host.systemdRuns.length, 1);
const run = host.systemdRuns[0];
const run = host.systemdRuns[0];
- assert.deepStrictEqual(run.argv, ['/usr/bin/env', 'node', '/opt/openvibe.live/server/index.js']);
- assert.strictEqual(run.cwd, '/opt/openvibe.live');
+ assert.deepStrictEqual(run.argv, ['/usr/bin/env', 'node', '/opt/openvibe.live/current/server/index.js']);
+ assert.strictEqual(run.cwd, '/opt/openvibe.live/current');
assert.deepStrictEqual(run.envFiles, ['/etc/openvibe/live.env', `${rec.dir}/drill.env`]);
assert.deepStrictEqual(run.envFiles, ['/etc/openvibe/live.env', `${rec.dir}/drill.env`]);
for (const p of ['SocketBindAllow=tcp:13000', 'SocketBindDeny=any', 'IPAddressDeny=any', 'IPAddressAllow=localhost', 'ProtectSystem=strict', `ReadWritePaths=${rec.dir}`, 'Environment=NODE_ENV=production']) assert.ok(run.props.includes(p), p);
for (const p of ['SocketBindAllow=tcp:13000', 'SocketBindDeny=any', 'IPAddressDeny=any', 'IPAddressAllow=localhost', 'ProtectSystem=strict', `ReadWritePaths=${rec.dir}`, 'Environment=NODE_ENV=production']) assert.ok(run.props.includes(p), p);
assert.ok(!run.props.some((p) => /BindPaths=|ReadWritePaths=\/opt/.test(p)), 'no bind mounts; production\'s data directory is not writable');
assert.ok(!run.props.some((p) => /BindPaths=|ReadWritePaths=\/opt/.test(p)), 'no bind mounts; production\'s data directory is not writable');