omegga 1.15.0 → 1.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/README.md +18 -1
- package/dist/cli/auth.js +18 -0
- package/dist/cli/auth.js.map +1 -1
- package/dist/config/index.js +3 -11
- package/dist/config/index.js.map +1 -1
- package/dist/main.js +35 -19
- package/dist/main.js.map +1 -1
- package/dist/util/env.js +19 -0
- package/dist/util/env.js.map +1 -0
- package/docs/SUMMARY.md +1 -0
- package/docs/containers.md +6 -1
- package/docs/env.md +3 -2
- package/docs/guides/pterodactyl.md +146 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## Latest
|
|
4
4
|
|
|
5
|
+
## 1.16.0 - 2026-09-01
|
|
6
|
+
|
|
7
|
+
A Pterodactyl egg for running Omegga under a game panel.
|
|
8
|
+
|
|
9
|
+
- Add a Pterodactyl egg at [`docker/pterodactyl/egg-omegga.json`](https://github.com/brickadia-community/omegga/blob/master/docker/pterodactyl/egg-omegga.json), documented at https://omegga.brickadia.dev/guides/pterodactyl.html
|
|
10
|
+
- The container entrypoint adopts the `STARTUP` command, `HOME`, and working directory Wings expects an image to supply
|
|
11
|
+
- `VERBOSE` now works; it was documented but never read
|
|
12
|
+
- `BRICKADIA_DEBUG` and `SKIP_STEAMCMD_PROMPT` parse their value, so `BRICKADIA_DEBUG=false` no longer enables debug logging
|
|
13
|
+
- Add `OMEGGA_NONINTERACTIVE` to exit instead of waiting at a prompt nothing can answer, on by default when stdin is not a terminal
|
|
14
|
+
- Fix `omegga auth` exiting 0 when authentication failed
|
|
15
|
+
|
|
5
16
|
## 1.15.0 - 2026-08-31
|
|
6
17
|
|
|
7
18
|
A Prometheus metrics endpoint, dashboards for it in the web UI, and the README split into a documentation site.
|
package/README.md
CHANGED
|
@@ -68,7 +68,7 @@ omegga
|
|
|
68
68
|
|
|
69
69
|
Omegga will prompt for credentials as necessary and only stores the auth tokens brickadia generates on login. **Omegga does not store your password**.
|
|
70
70
|
|
|
71
|
-
To run it in a container instead, see [Containers](docs/containers.md). For the long version, including troubleshooting, see [Installing](docs/install/README.md).
|
|
71
|
+
To run it in a container instead, see [Containers](docs/containers.md), or [Pterodactyl](docs/guides/pterodactyl.md) to run it as an egg under a Pterodactyl panel. For the long version, including troubleshooting, see [Installing](docs/install/README.md).
|
|
72
72
|
|
|
73
73
|
## Documentation
|
|
74
74
|
|
|
@@ -78,6 +78,7 @@ Everything below is also published as a book at
|
|
|
78
78
|
| Setting up | |
|
|
79
79
|
| --- | --- |
|
|
80
80
|
| [Installing](docs/install/README.md) | [linux](docs/install/linux.md), [WSL](docs/install/wsl.md), or a [container](docs/containers.md) |
|
|
81
|
+
| [Pterodactyl](docs/guides/pterodactyl.md) | running omegga as a Pterodactyl egg |
|
|
81
82
|
| [Running](docs/running.md) | starting a server and keeping it updated |
|
|
82
83
|
| [Configuration](docs/config.md) | `omegga-config.yml`, field by field |
|
|
83
84
|
| [Environment variables](docs/env.md) | what omegga reads from the environment |
|
|
@@ -119,3 +120,19 @@ npm run dist # build the web ui, omegga's typescript, and omegga.d.ts
|
|
|
119
120
|
`npm run lint`, `npm run typecheck`, and `npm test` are what CI runs. The API
|
|
120
121
|
pages under `docs/api` are generated from the JSDoc in `src/`; run
|
|
121
122
|
`npm run docs:api` after changing those comments.
|
|
123
|
+
|
|
124
|
+
### Release Process
|
|
125
|
+
|
|
126
|
+
1. **Bump**: Bump `version` in `package.json` and sync the lockfile with
|
|
127
|
+
`npm i --package-lock-only`.
|
|
128
|
+
2. **Changelog**: Move the `## Latest` entries in `CHANGELOG.md` under a
|
|
129
|
+
`## <version> - <date>` heading.
|
|
130
|
+
3. **Pterodactyl**: Point the pinned image in `docker/pterodactyl/egg-omegga.json` at the new
|
|
131
|
+
`<major>.<minor>`. Releases only move `latest`, `<major>`, and
|
|
132
|
+
`<major>.<minor>`, so a pin left on the previous minor is frozen on an
|
|
133
|
+
image that will never be rebuilt, while still being selectable in the
|
|
134
|
+
panel.
|
|
135
|
+
4. **Linters**: `just check`
|
|
136
|
+
5. **Commit**: Ensure everything is pushed
|
|
137
|
+
6. **Deploy Container**: `just tag` to push tag the image to ghcr.
|
|
138
|
+
7. **Deploy NPM**: `just publish` to build `dist/` and publish the package to npm.
|
package/dist/cli/auth.js
CHANGED
|
@@ -2,12 +2,28 @@
|
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
3
|
const softconfig = require("../softconfig.js");
|
|
4
4
|
const auth = require("../omegga/auth.js");
|
|
5
|
+
const env = require("../util/env.js");
|
|
5
6
|
const file = require("../util/file.js");
|
|
6
7
|
require("colors");
|
|
7
8
|
const fs = require("node:fs");
|
|
8
9
|
const path = require("node:path");
|
|
9
10
|
const prompts = require("prompts");
|
|
10
11
|
const AUTH_PATH = path.join(softconfig.default.CONFIG_HOME, softconfig.default.CONFIG_AUTH_DIR);
|
|
12
|
+
function failNonInteractive() {
|
|
13
|
+
console.error(
|
|
14
|
+
"!>".red,
|
|
15
|
+
"No stored auth files and no hosting token, and there is no terminal to prompt on"
|
|
16
|
+
);
|
|
17
|
+
console.error(
|
|
18
|
+
"!>".red,
|
|
19
|
+
"Generate a hosting token at https://brickadia.com/account/tokens, then set",
|
|
20
|
+
"BRICKADIA_TOKEN".yellow,
|
|
21
|
+
"or",
|
|
22
|
+
"credentials.token".yellow,
|
|
23
|
+
"in omegga-config.yml"
|
|
24
|
+
);
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
11
27
|
async function credentialPrompt() {
|
|
12
28
|
console.log(
|
|
13
29
|
">>".green,
|
|
@@ -41,6 +57,7 @@ async function authFromPrompt({
|
|
|
41
57
|
}) {
|
|
42
58
|
let files;
|
|
43
59
|
if (isSteam || !email || !password) {
|
|
60
|
+
if (env.isNonInteractive()) return failNonInteractive();
|
|
44
61
|
const { authType } = await prompts({
|
|
45
62
|
type: "select",
|
|
46
63
|
name: "authType",
|
|
@@ -83,6 +100,7 @@ async function authFromPrompt({
|
|
|
83
100
|
}
|
|
84
101
|
}
|
|
85
102
|
if (!email || !password || !isSteam) {
|
|
103
|
+
if (env.isNonInteractive()) return failNonInteractive();
|
|
86
104
|
try {
|
|
87
105
|
[email, password] = await credentialPrompt();
|
|
88
106
|
} catch (err) {
|
package/dist/cli/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sources":["../../src/cli/auth.ts"],"sourcesContent":["import soft from '@/softconfig';\nimport { genAuthFiles, writeAuthFiles } from '@omegga/auth';\nimport * as file from '@util/file';\nimport 'colors';\nimport fs, { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport prompts from 'prompts';\n\nexport const AUTH_PATH = path.join(soft.CONFIG_HOME, soft.CONFIG_AUTH_DIR);\n\n// async function to prompt for credentials\nasync function credentialPrompt() {\n console.log(\n '>>'.green,\n 'Enter',\n 'Brickadia'.green.underline,\n 'credentials (not stored)',\n );\n\n const response = await prompts([\n {\n type: 'text',\n name: 'email',\n message: 'Email',\n },\n {\n type: 'password',\n name: 'password',\n message: 'Password',\n },\n ]);\n\n return [response.email, response.password];\n}\n\nasync function authFromPrompt({\n email,\n password,\n debug = false,\n isSteam,\n branch,\n authDir,\n savedDir,\n launchArgs,\n}: {\n email?: string | null;\n password?: string | null;\n debug?: boolean;\n isSteam?: boolean;\n branch?: string;\n authDir?: string;\n savedDir?: string;\n launchArgs?: string;\n}) {\n let files: Record<string, Buffer> | null;\n\n if (isSteam || !email || !password) {\n // Prompt user to pick to select username/password or Auth Token\n const { authType } = await prompts({\n type: 'select',\n name: 'authType',\n message: 'Select authentication method',\n choices: [\n { title: 'Hosting Token', value: 'token' },\n { title: 'Username/Password', value: 'credentials' },\n ],\n });\n\n if (!authType) {\n console.error('!>'.red, 'No authentication method selected');\n return false;\n }\n\n if (authType === 'token') {\n // Prompt for hosting token\n const { token } = await prompts({\n type: 'password',\n name: 'token',\n message:\n 'Paste your server hosting token (generate one at https://brickadia.com/account/tokens)',\n validate: value => (value ? true : 'Token is required'),\n });\n\n if (!token) {\n console.error('!>'.red, 'Hosting token is required');\n return false;\n }\n\n // Write to global token file\n try {\n console.log('>>'.green, 'Storing hosting token...');\n fs.writeFileSync(soft.GLOBAL_TOKEN, token.trim());\n } catch (err) {\n console.error('!>'.red, 'Error writing hosting token to config\\n', err);\n return false;\n }\n\n return true;\n }\n\n if (isSteam) {\n console.error(\n '!>'.red,\n 'Launching with steam requires a hosting token right now.',\n );\n return false;\n }\n\n // Non-steam password auth is handled below\n }\n\n if (!email || !password || !isSteam) {\n // prompt for user credentials\n try {\n [email, password] = await credentialPrompt();\n } catch (err) {\n console.error('!>'.red, 'Error prompting credentials\\n', err);\n return false;\n }\n }\n\n if (!email || !password) {\n console.error('!>'.red, 'Email and password are required');\n return false;\n }\n\n // generate auth tokens\n console.log('>>'.green, 'Generating auth tokens...');\n const timeout = setTimeout(() => {\n console.log('>>'.green, 'Probably also installing the game...');\n }, 10000);\n try {\n files = await genAuthFiles(email, password, {\n debug,\n branch,\n authDir,\n savedDir,\n launchArgs,\n });\n clearTimeout(timeout);\n } catch (err) {\n clearTimeout(timeout);\n console.error('!>'.red, 'Error generating tokens:', err);\n return false;\n }\n\n if (!files) {\n console.error('!>'.red, 'Authentication Failed');\n return;\n }\n\n // save the tokens to the config path (will be copied when omegga starts)\n try {\n console.log('>>'.green, 'Storing auth tokens...');\n const authPath = path.join(\n soft.CONFIG_HOME,\n savedDir && savedDir !== soft.CONFIG_SAVED_DIR ? savedDir : '',\n authDir ?? soft.CONFIG_AUTH_DIR,\n );\n file.mkdir(authPath);\n writeAuthFiles(authPath, files);\n } catch (err) {\n console.error('!>'.red, 'Error writing tokens to config\\n', err);\n return false;\n }\n\n console.log('>>'.green, 'Auth tokens successfully generated!');\n return true;\n}\n\n// check if auth files exist\nfunction authExists(dir?: string) {\n return soft.BRICKADIA_AUTH_FILES.every(f =>\n fs.existsSync(path.join(dir ?? AUTH_PATH, f)),\n );\n}\n\n// delete auth files stored in config\n// delete auth files stored in config\nfunction deleteAuthFiles(dir?: string) {\n const isConfigHome = dir && dir.startsWith(soft.CONFIG_HOME);\n // will not delete files outside of the config home\n if (dir && !isConfigHome) return;\n file.rmdir(dir ?? AUTH_PATH);\n\n // Remove the global auth token\n if (existsSync(soft.GLOBAL_TOKEN)) {\n fs.unlinkSync(soft.GLOBAL_TOKEN);\n }\n}\n\nexport function getGlobalToken() {\n if (!fs.existsSync(soft.GLOBAL_TOKEN)) return null;\n return fs.readFileSync(soft.GLOBAL_TOKEN, 'utf-8').trim();\n}\n\nexport const prompt = authFromPrompt;\nexport const exists = authExists;\nexport const clean = deleteAuthFiles;\n\nexport default {\n AUTH_PATH,\n prompt,\n exists,\n clean,\n getGlobalToken,\n};\n"],"names":["soft","genAuthFiles","file.mkdir","writeAuthFiles","file.rmdir","existsSync"],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.js","sources":["../../src/cli/auth.ts"],"sourcesContent":["import soft from '@/softconfig';\nimport { genAuthFiles, writeAuthFiles } from '@omegga/auth';\nimport { isNonInteractive } from '@util/env';\nimport * as file from '@util/file';\nimport 'colors';\nimport fs, { existsSync } from 'node:fs';\nimport path from 'node:path';\nimport prompts from 'prompts';\n\nexport const AUTH_PATH = path.join(soft.CONFIG_HOME, soft.CONFIG_AUTH_DIR);\n\n/**\n * Refuse to authenticate rather than opening a prompt nothing can answer.\n *\n * Reaching a prompt on such a host is worse than failing: omegga blocks\n * before it logs anything a supervisor recognises as a start, so the failure\n * shows up as a startup timeout with no cause in the log.\n */\nfunction failNonInteractive() {\n console.error(\n '!>'.red,\n 'No stored auth files and no hosting token, and there is no terminal to prompt on',\n );\n console.error(\n '!>'.red,\n 'Generate a hosting token at https://brickadia.com/account/tokens, then set',\n 'BRICKADIA_TOKEN'.yellow,\n 'or',\n 'credentials.token'.yellow,\n 'in omegga-config.yml',\n );\n return false;\n}\n\n// async function to prompt for credentials\nasync function credentialPrompt() {\n console.log(\n '>>'.green,\n 'Enter',\n 'Brickadia'.green.underline,\n 'credentials (not stored)',\n );\n\n const response = await prompts([\n {\n type: 'text',\n name: 'email',\n message: 'Email',\n },\n {\n type: 'password',\n name: 'password',\n message: 'Password',\n },\n ]);\n\n return [response.email, response.password];\n}\n\nasync function authFromPrompt({\n email,\n password,\n debug = false,\n isSteam,\n branch,\n authDir,\n savedDir,\n launchArgs,\n}: {\n email?: string | null;\n password?: string | null;\n debug?: boolean;\n isSteam?: boolean;\n branch?: string;\n authDir?: string;\n savedDir?: string;\n launchArgs?: string;\n}) {\n let files: Record<string, Buffer> | null;\n\n if (isSteam || !email || !password) {\n if (isNonInteractive()) return failNonInteractive();\n\n // Prompt user to pick to select username/password or Auth Token\n const { authType } = await prompts({\n type: 'select',\n name: 'authType',\n message: 'Select authentication method',\n choices: [\n { title: 'Hosting Token', value: 'token' },\n { title: 'Username/Password', value: 'credentials' },\n ],\n });\n\n if (!authType) {\n console.error('!>'.red, 'No authentication method selected');\n return false;\n }\n\n if (authType === 'token') {\n // Prompt for hosting token\n const { token } = await prompts({\n type: 'password',\n name: 'token',\n message:\n 'Paste your server hosting token (generate one at https://brickadia.com/account/tokens)',\n validate: value => (value ? true : 'Token is required'),\n });\n\n if (!token) {\n console.error('!>'.red, 'Hosting token is required');\n return false;\n }\n\n // Write to global token file\n try {\n console.log('>>'.green, 'Storing hosting token...');\n fs.writeFileSync(soft.GLOBAL_TOKEN, token.trim());\n } catch (err) {\n console.error('!>'.red, 'Error writing hosting token to config\\n', err);\n return false;\n }\n\n return true;\n }\n\n if (isSteam) {\n console.error(\n '!>'.red,\n 'Launching with steam requires a hosting token right now.',\n );\n return false;\n }\n\n // Non-steam password auth is handled below\n }\n\n if (!email || !password || !isSteam) {\n if (isNonInteractive()) return failNonInteractive();\n\n // prompt for user credentials\n try {\n [email, password] = await credentialPrompt();\n } catch (err) {\n console.error('!>'.red, 'Error prompting credentials\\n', err);\n return false;\n }\n }\n\n if (!email || !password) {\n console.error('!>'.red, 'Email and password are required');\n return false;\n }\n\n // generate auth tokens\n console.log('>>'.green, 'Generating auth tokens...');\n const timeout = setTimeout(() => {\n console.log('>>'.green, 'Probably also installing the game...');\n }, 10000);\n try {\n files = await genAuthFiles(email, password, {\n debug,\n branch,\n authDir,\n savedDir,\n launchArgs,\n });\n clearTimeout(timeout);\n } catch (err) {\n clearTimeout(timeout);\n console.error('!>'.red, 'Error generating tokens:', err);\n return false;\n }\n\n if (!files) {\n console.error('!>'.red, 'Authentication Failed');\n return;\n }\n\n // save the tokens to the config path (will be copied when omegga starts)\n try {\n console.log('>>'.green, 'Storing auth tokens...');\n const authPath = path.join(\n soft.CONFIG_HOME,\n savedDir && savedDir !== soft.CONFIG_SAVED_DIR ? savedDir : '',\n authDir ?? soft.CONFIG_AUTH_DIR,\n );\n file.mkdir(authPath);\n writeAuthFiles(authPath, files);\n } catch (err) {\n console.error('!>'.red, 'Error writing tokens to config\\n', err);\n return false;\n }\n\n console.log('>>'.green, 'Auth tokens successfully generated!');\n return true;\n}\n\n// check if auth files exist\nfunction authExists(dir?: string) {\n return soft.BRICKADIA_AUTH_FILES.every(f =>\n fs.existsSync(path.join(dir ?? AUTH_PATH, f)),\n );\n}\n\n// delete auth files stored in config\n// delete auth files stored in config\nfunction deleteAuthFiles(dir?: string) {\n const isConfigHome = dir && dir.startsWith(soft.CONFIG_HOME);\n // will not delete files outside of the config home\n if (dir && !isConfigHome) return;\n file.rmdir(dir ?? AUTH_PATH);\n\n // Remove the global auth token\n if (existsSync(soft.GLOBAL_TOKEN)) {\n fs.unlinkSync(soft.GLOBAL_TOKEN);\n }\n}\n\nexport function getGlobalToken() {\n if (!fs.existsSync(soft.GLOBAL_TOKEN)) return null;\n return fs.readFileSync(soft.GLOBAL_TOKEN, 'utf-8').trim();\n}\n\nexport const prompt = authFromPrompt;\nexport const exists = authExists;\nexport const clean = deleteAuthFiles;\n\nexport default {\n AUTH_PATH,\n prompt,\n exists,\n clean,\n getGlobalToken,\n};\n"],"names":["soft","isNonInteractive","genAuthFiles","file.mkdir","writeAuthFiles","file.rmdir","existsSync"],"mappings":"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"}
|
package/dist/config/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
3
|
const logger = require("../logger.js");
|
|
4
4
|
const softconfig = require("../softconfig.js");
|
|
5
|
+
const env = require("../util/env.js");
|
|
5
6
|
require("colors");
|
|
6
7
|
const Configstore = require("configstore");
|
|
7
8
|
const fs = require("node:fs");
|
|
@@ -46,15 +47,6 @@ function parseEnvPort(name) {
|
|
|
46
47
|
logger.default.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a port`);
|
|
47
48
|
return void 0;
|
|
48
49
|
}
|
|
49
|
-
function parseEnvBool(name) {
|
|
50
|
-
const raw = process.env[name];
|
|
51
|
-
if (!raw) return void 0;
|
|
52
|
-
const value = raw.trim().toLowerCase();
|
|
53
|
-
if (["true", "1", "yes", "on"].includes(value)) return true;
|
|
54
|
-
if (["false", "0", "no", "off"].includes(value)) return false;
|
|
55
|
-
logger.default.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a boolean`);
|
|
56
|
-
return void 0;
|
|
57
|
-
}
|
|
58
50
|
function parseEnvSeconds(name) {
|
|
59
51
|
const raw = process.env[name];
|
|
60
52
|
if (!raw) return void 0;
|
|
@@ -91,7 +83,7 @@ function applyPortOverrides(conf) {
|
|
|
91
83
|
return conf;
|
|
92
84
|
}
|
|
93
85
|
function applyMetricsOverrides(conf) {
|
|
94
|
-
const enabled = parseEnvBool("METRICS_ENABLED");
|
|
86
|
+
const enabled = env.parseEnvBool("METRICS_ENABLED");
|
|
95
87
|
if (enabled != null) conf.metrics = { ...conf.metrics, enabled };
|
|
96
88
|
const bind = process.env.METRICS_BIND?.trim();
|
|
97
89
|
if (bind) conf.metrics = { ...conf.metrics, bind };
|
|
@@ -104,7 +96,7 @@ function applyMetricsOverrides(conf) {
|
|
|
104
96
|
prometheus[key] = value;
|
|
105
97
|
touched = true;
|
|
106
98
|
};
|
|
107
|
-
set("enabled", parseEnvBool("METRICS_PROMETHEUS_ENABLED"));
|
|
99
|
+
set("enabled", env.parseEnvBool("METRICS_PROMETHEUS_ENABLED"));
|
|
108
100
|
set("url", parseEnvUrl("METRICS_PROMETHEUS_URL"));
|
|
109
101
|
set("instance", parseEnvLabel("METRICS_PROMETHEUS_INSTANCE"));
|
|
110
102
|
set("timeout", parseEnvSeconds("METRICS_PROMETHEUS_TIMEOUT"));
|
package/dist/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/config/index.ts"],"sourcesContent":["import Logger from '@/logger';\nimport soft, { METRICS_DEFAULTS } from '@/softconfig';\nimport 'colors';\nimport Configstore from 'configstore';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport format_js from './formats/format_js';\nimport format_yaml from './formats/format_yml';\nimport reader from './reader';\nimport { type IConfig, type IConfigFormat } from './types';\nimport writer from './writer';\nexport * from './types';\n\nexport const store = new Configstore(\n soft.PROJECT_NAME,\n {\n defaultOmegga: '.',\n legacyBin: '',\n },\n {\n globalConfigPath: true,\n },\n);\n\n// find all format_EXT.js files in the formats path\nconst formats: IConfigFormat[] = [format_js, format_yaml];\n\n// create read/write funcs for the provided formats\nexport const defaultConfig: IConfig = {\n omegga: {\n webui: true,\n port: process.env.OMEGGA_PORT\n ? Number(process.env.OMEGGA_PORT)\n : soft.DEFAULT_PORT,\n https: true,\n },\n server: {\n port: process.env.BRICKADIA_PORT\n ? Number(process.env.BRICKADIA_PORT)\n : 7777,\n map: 'Plate',\n },\n metrics: {\n enabled: false,\n bind: METRICS_DEFAULTS.bind,\n port: METRICS_DEFAULTS.port,\n },\n};\n\n/** parse a port from the environment, warning (and ignoring) when it isn't one */\nfunction parseEnvPort(name: string) {\n const raw = process.env[name];\n if (!raw) return undefined;\n const port = Number(raw);\n if (Number.isInteger(port) && port > 0 && port < 65536) return port;\n Logger.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a port`);\n return undefined;\n}\n\n/** parse a
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/config/index.ts"],"sourcesContent":["import Logger from '@/logger';\nimport soft, { METRICS_DEFAULTS } from '@/softconfig';\nimport { parseEnvBool } from '@util/env';\nimport 'colors';\nimport Configstore from 'configstore';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport format_js from './formats/format_js';\nimport format_yaml from './formats/format_yml';\nimport reader from './reader';\nimport { type IConfig, type IConfigFormat } from './types';\nimport writer from './writer';\nexport * from './types';\n\nexport const store = new Configstore(\n soft.PROJECT_NAME,\n {\n defaultOmegga: '.',\n legacyBin: '',\n },\n {\n globalConfigPath: true,\n },\n);\n\n// find all format_EXT.js files in the formats path\nconst formats: IConfigFormat[] = [format_js, format_yaml];\n\n// create read/write funcs for the provided formats\nexport const defaultConfig: IConfig = {\n omegga: {\n webui: true,\n port: process.env.OMEGGA_PORT\n ? Number(process.env.OMEGGA_PORT)\n : soft.DEFAULT_PORT,\n https: true,\n },\n server: {\n port: process.env.BRICKADIA_PORT\n ? Number(process.env.BRICKADIA_PORT)\n : 7777,\n map: 'Plate',\n },\n metrics: {\n enabled: false,\n bind: METRICS_DEFAULTS.bind,\n port: METRICS_DEFAULTS.port,\n },\n};\n\n/** parse a port from the environment, warning (and ignoring) when it isn't one */\nfunction parseEnvPort(name: string) {\n const raw = process.env[name];\n if (!raw) return undefined;\n const port = Number(raw);\n if (Number.isInteger(port) && port > 0 && port < 65536) return port;\n Logger.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a port`);\n return undefined;\n}\n\n/** parse a positive number of seconds, warning (and ignoring) when it isn't one */\nfunction parseEnvSeconds(name: string) {\n const raw = process.env[name];\n if (!raw) return undefined;\n const seconds = Number(raw);\n if (Number.isFinite(seconds) && seconds > 0) return seconds;\n Logger.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a duration`);\n return undefined;\n}\n\n/** parse an http(s) URL, warning (and ignoring) when it isn't one */\nfunction parseEnvUrl(name: string) {\n const raw = process.env[name]?.trim();\n if (!raw) return undefined;\n try {\n const url = new URL(raw);\n if (url.protocol === 'http:' || url.protocol === 'https:') return raw;\n } catch {\n // fall through to the warning\n }\n Logger.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not an http URL`);\n return undefined;\n}\n\n/**\n * Parse a prometheus label value. The same restriction the config schema\n * applies, repeated here because environment overrides land after the schema\n * has already validated the file.\n */\nfunction parseEnvLabel(name: string) {\n const raw = process.env[name]?.trim();\n if (!raw) return undefined;\n if (/^[A-Za-z0-9_.:-]+$/.test(raw)) return raw;\n Logger.warnp(\n `Ignoring ${name.yellow}: ${raw.yellow} is not a valid label value`,\n );\n return undefined;\n}\n\n/**\n * Apply `OMEGGA_PORT` and `BRICKADIA_PORT` on top of a loaded config. A\n * container's config file lives in a mounted volume that can't be templated,\n * so the environment has to be able to win.\n */\nexport function applyPortOverrides(conf: IConfig): IConfig {\n const omeggaPort = parseEnvPort('OMEGGA_PORT');\n if (omeggaPort) conf.omegga = { ...conf.omegga, port: omeggaPort };\n\n const serverPort = parseEnvPort('BRICKADIA_PORT');\n if (serverPort) conf.server = { ...conf.server, port: serverPort };\n\n return conf;\n}\n\n/**\n * Apply `METRICS_ENABLED`, `METRICS_BIND`, and `METRICS_PORT` on top of a\n * loaded config, for the same reason `applyPortOverrides` exists: a container\n * can't template the config file in its mounted volume.\n */\nexport function applyMetricsOverrides(conf: IConfig): IConfig {\n const enabled = parseEnvBool('METRICS_ENABLED');\n if (enabled != null) conf.metrics = { ...conf.metrics, enabled };\n\n const bind = process.env.METRICS_BIND?.trim();\n if (bind) conf.metrics = { ...conf.metrics, bind };\n\n const port = parseEnvPort('METRICS_PORT');\n if (port) conf.metrics = { ...conf.metrics, port };\n\n const prometheus = { ...conf.metrics?.prometheus };\n let touched = false;\n const set = <K extends keyof typeof prometheus>(\n key: K,\n value: (typeof prometheus)[K] | undefined,\n ) => {\n if (value == null) return;\n prometheus[key] = value;\n touched = true;\n };\n\n set('enabled', parseEnvBool('METRICS_PROMETHEUS_ENABLED'));\n set('url', parseEnvUrl('METRICS_PROMETHEUS_URL'));\n set('instance', parseEnvLabel('METRICS_PROMETHEUS_INSTANCE'));\n set('timeout', parseEnvSeconds('METRICS_PROMETHEUS_TIMEOUT'));\n\n if (touched) conf.metrics = { ...conf.metrics, prometheus };\n\n return conf;\n}\n\n// Writes save data to a file\nexport const write = writer(formats);\n\n// reads save data from a file\nexport const read = reader(formats);\n\n// open config at a specified path\nexport const find = (dir = '.') => {\n // find the first config file matching these config file names\n for (const f of soft.CONFIG_FILENAMES) {\n for (const { extension } of formats) {\n const file = path.join(dir, f + '.' + extension);\n if (fs.existsSync(file)) return file;\n }\n }\n\n return undefined;\n};\n\nexport * from './types';\n\nexport default {\n store,\n write,\n read,\n find,\n defaultConfig,\n formats,\n applyPortOverrides,\n applyMetricsOverrides,\n};\n"],"names":["soft","format_js","format_yaml","METRICS_DEFAULTS","Logger","parseEnvBool","writer","reader"],"mappings":"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"}
|
package/dist/main.js
CHANGED
|
@@ -6,6 +6,7 @@ const version$1 = require("./omegga/matchers/version.js");
|
|
|
6
6
|
const server = require("./omegga/server.js");
|
|
7
7
|
const file = require("./util/file.js");
|
|
8
8
|
const container = require("./util/container.js");
|
|
9
|
+
const env = require("./util/env.js");
|
|
9
10
|
require("colors");
|
|
10
11
|
const commander = require("commander");
|
|
11
12
|
const dotenv = require("dotenv");
|
|
@@ -39,20 +40,25 @@ const createDefaultConfig = () => {
|
|
|
39
40
|
file.mkdir("plugins");
|
|
40
41
|
return index.defaultConfig;
|
|
41
42
|
};
|
|
43
|
+
const isVerbose = (flag) => Boolean(flag) || env.parseEnvBool("VERBOSE") === true;
|
|
44
|
+
const isDebug = (flag) => Boolean(flag) || env.parseEnvBool("BRICKADIA_DEBUG") === true;
|
|
42
45
|
const program = commander.description(version.PKG.description).version(version.VERSION).option(
|
|
43
46
|
"-d, --debug",
|
|
44
47
|
"Print all console logs rather than just chat messages (env: BRICKADIA_DEBUG)"
|
|
45
48
|
).option(
|
|
46
49
|
"-u, --update",
|
|
47
50
|
"Check for brickadia updates (on steam) and install them if available"
|
|
48
|
-
).option(
|
|
51
|
+
).option(
|
|
52
|
+
"-v, --verbose",
|
|
53
|
+
"Print extra messages for debugging purposes (env: VERBOSE)"
|
|
54
|
+
).action(async () => {
|
|
49
55
|
const { verbose, update } = program.opts();
|
|
50
|
-
const debug =
|
|
56
|
+
const debug = isDebug(program.opts().debug);
|
|
51
57
|
if (program.args.length > 0) {
|
|
52
58
|
program.help();
|
|
53
59
|
process.exit(1);
|
|
54
60
|
}
|
|
55
|
-
logger.default.VERBOSE =
|
|
61
|
+
logger.default.VERBOSE = isVerbose(verbose);
|
|
56
62
|
let workDir = index.store.get("defaultOmegga");
|
|
57
63
|
logger.default.verbose("Using working directory", workDir?.yellow);
|
|
58
64
|
if (index.find(".")) workDir = ".";
|
|
@@ -258,10 +264,8 @@ program.command("auth").option("-g, --global", "Remove global auth files").optio
|
|
|
258
264
|
global: globalAuth
|
|
259
265
|
}) => {
|
|
260
266
|
const { verbose } = program.opts();
|
|
261
|
-
const debug =
|
|
262
|
-
|
|
263
|
-
);
|
|
264
|
-
logger.default.VERBOSE = Boolean(verbose);
|
|
267
|
+
const debug = isDebug(program.opts().debug);
|
|
268
|
+
logger.default.VERBOSE = isVerbose(verbose);
|
|
265
269
|
let branch, authDir, savedDir, launchArgs;
|
|
266
270
|
let isSteam;
|
|
267
271
|
if (index.find(".")) workDir = ".";
|
|
@@ -328,7 +332,7 @@ program.command("auth").option("-g, --global", "Remove global auth files").optio
|
|
|
328
332
|
if (!isSteam) {
|
|
329
333
|
logger.default.warnp("Authenticating with", "non-steam launcher".yellow);
|
|
330
334
|
}
|
|
331
|
-
index$1.auth.prompt({
|
|
335
|
+
const success = await index$1.auth.prompt({
|
|
332
336
|
email,
|
|
333
337
|
password,
|
|
334
338
|
debug,
|
|
@@ -337,6 +341,7 @@ program.command("auth").option("-g, --global", "Remove global auth files").optio
|
|
|
337
341
|
savedDir,
|
|
338
342
|
launchArgs
|
|
339
343
|
});
|
|
344
|
+
if (!success) process.exit(1);
|
|
340
345
|
}
|
|
341
346
|
);
|
|
342
347
|
program.command("info").alias("n").description(
|
|
@@ -357,8 +362,9 @@ program.command("install <pluginUrl...>").alias("i").option("-f, --force", "Forc
|
|
|
357
362
|
);
|
|
358
363
|
process.exit(1);
|
|
359
364
|
}
|
|
360
|
-
const {
|
|
361
|
-
|
|
365
|
+
const { force } = program.opts();
|
|
366
|
+
const verbose = isVerbose(program.opts().verbose);
|
|
367
|
+
logger.default.VERBOSE = verbose;
|
|
362
368
|
index$1.pluginUtil.install(plugins, { verbose, force });
|
|
363
369
|
});
|
|
364
370
|
program.command("update [pluginNames...]").alias("u").option("-f, --force", "Forcefully re-upgrade existing plugin").option("-v, --verbose", "Print extra messages for debugging purposes").description("Updates all or selected installed plugins to latest versions").action(async (plugins) => {
|
|
@@ -370,8 +376,9 @@ program.command("update [pluginNames...]").alias("u").option("-f, --force", "For
|
|
|
370
376
|
);
|
|
371
377
|
process.exit(1);
|
|
372
378
|
}
|
|
373
|
-
const {
|
|
374
|
-
|
|
379
|
+
const { force } = program.opts();
|
|
380
|
+
const verbose = isVerbose(program.opts().verbose);
|
|
381
|
+
logger.default.VERBOSE = verbose;
|
|
375
382
|
index$1.pluginUtil.update(plugins, { verbose, force });
|
|
376
383
|
});
|
|
377
384
|
program.command("check [pluginNames...]").option("-v, --verbose", "Print extra messages for debugging purposes").description("Checks plugins for compatibility issues").action(async (plugins) => {
|
|
@@ -383,18 +390,18 @@ program.command("check [pluginNames...]").option("-v, --verbose", "Print extra m
|
|
|
383
390
|
);
|
|
384
391
|
process.exit(1);
|
|
385
392
|
}
|
|
386
|
-
const
|
|
387
|
-
logger.default.VERBOSE =
|
|
393
|
+
const verbose = isVerbose(program.opts().verbose);
|
|
394
|
+
logger.default.VERBOSE = verbose;
|
|
388
395
|
index$1.pluginUtil.check(plugins, { verbose });
|
|
389
396
|
});
|
|
390
397
|
program.command("init-plugin").option("-v, --verbose", "Print extra messages for debugging purposes").description("Initializes a new plugin with the given name and settings").action(async () => {
|
|
391
398
|
const { verbose } = program.opts();
|
|
392
|
-
logger.default.VERBOSE =
|
|
399
|
+
logger.default.VERBOSE = isVerbose(verbose);
|
|
393
400
|
index$1.pluginUtil.init();
|
|
394
401
|
});
|
|
395
402
|
program.command("plugin-init").description("Alias for " + "init-plugin".yellow.underline).option("-v, --verbose", "Print extra messages for debugging purposes").action(async () => {
|
|
396
403
|
const { verbose } = program.opts();
|
|
397
|
-
logger.default.VERBOSE =
|
|
404
|
+
logger.default.VERBOSE = isVerbose(verbose);
|
|
398
405
|
index$1.pluginUtil.init();
|
|
399
406
|
});
|
|
400
407
|
program.command("get-config <pluginName> [configName]").option("-v, --verbose", "Print extra messages for debugging purposes").option("-j, --json", "Print config as json").description(
|
|
@@ -410,7 +417,7 @@ program.command("get-config <pluginName> [configName]").option("-v, --verbose",
|
|
|
410
417
|
}
|
|
411
418
|
const { verbose } = program.opts();
|
|
412
419
|
const json = program.args.includes("-j") || program.args.includes("--json");
|
|
413
|
-
logger.default.VERBOSE =
|
|
420
|
+
logger.default.VERBOSE = isVerbose(verbose);
|
|
414
421
|
if (!configName) {
|
|
415
422
|
index$1.pluginUtil.listConfig(pluginName, json);
|
|
416
423
|
} else {
|
|
@@ -430,7 +437,7 @@ program.command("set-config <pluginName> [configName] [configValue]").option("-y
|
|
|
430
437
|
}
|
|
431
438
|
const { verbose } = program.opts();
|
|
432
439
|
const yes = program.args.includes("-y") || program.args.includes("--yes");
|
|
433
|
-
logger.default.VERBOSE =
|
|
440
|
+
logger.default.VERBOSE = isVerbose(verbose);
|
|
434
441
|
if (!configName) {
|
|
435
442
|
index$1.pluginUtil.resetAllConfigs(pluginName, yes);
|
|
436
443
|
} else if (!configValue) {
|
|
@@ -464,7 +471,16 @@ async function setupSteam(config2, forceUpdate = false) {
|
|
|
464
471
|
if (!fs.existsSync(softconfig.STEAMCMD_PATH)) {
|
|
465
472
|
const hasSteamcmd = hasbin.sync("steamcmd");
|
|
466
473
|
if (!hasSteamcmd) {
|
|
467
|
-
const
|
|
474
|
+
const skipPrompt = env.parseEnvBool("SKIP_STEAMCMD_PROMPT") === true;
|
|
475
|
+
if (!skipPrompt && env.isNonInteractive()) {
|
|
476
|
+
logger.default.errorp(
|
|
477
|
+
"SteamCMD is not installed and there is no terminal to prompt on. Set",
|
|
478
|
+
"SKIP_STEAMCMD_PROMPT=true".yellow,
|
|
479
|
+
"to install it without asking. Exiting..."
|
|
480
|
+
);
|
|
481
|
+
process.exit(1);
|
|
482
|
+
}
|
|
483
|
+
const { install } = skipPrompt ? { install: true } : await prompts({
|
|
468
484
|
type: "confirm",
|
|
469
485
|
name: "install",
|
|
470
486
|
message: "SteamCMD is not installed. OK to download it?",
|
package/dist/main.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.js","sources":["../src/main.ts"],"sourcesContent":["import soft, {\n getOverrideGameBinary,\n getSteamGameDir,\n getSteamInstallDir,\n} from '@/softconfig';\nimport { installLauncher } from '@cli/installer';\nimport * as config from '@config';\nimport { readBinaryVersion } from '@omegga/matchers/version';\nimport Omegga from '@omegga/server';\nimport * as file from '@util/file';\nimport { isContainer } from '@util/container';\nimport 'colors';\nimport commander from 'commander';\nimport dotenv from 'dotenv';\nimport hasbin from 'hasbin';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport prompts from 'prompts';\nimport updateNotifier from 'update-notifier-cjs';\nimport { auth, config as omeggaConfig, pluginUtil, Terminal } from './cli';\nimport { IConfig } from './config/types';\nimport Logger from './logger';\nimport { GAME_BIN_PATH, STEAMCMD_PATH } from './softconfig';\nimport {\n hasSteamUpdate,\n steamcmdDownloadGame,\n steamcmdDownloadSelf,\n steamcmdInteractiveLogin,\n} from './updater';\nimport { PKG, VERSION } from './version';\n\ndotenv.config({ quiet: true });\n\nconst notifier =\n process.env.PACKAGE_NOTIFIER !== 'false'\n ? updateNotifier({\n pkg: PKG,\n updateCheckInterval: 1000 * 60 * 60 * 24,\n })\n : null;\nif (notifier) {\n const { update } = notifier;\n notifier.notify(\n update && isContainer()\n ? {\n message: `Update available ${update.current} → ${update.latest}\\nPull a new container image to update`,\n }\n : undefined,\n );\n}\n\n// TODO: let omegga bundle config (roles, bans, server config) to zip\n// TODO: let omegga unbundle config from zip to current omegga dir\n\n// write a default config file\nconst createDefaultConfig = () => {\n Logger.logp('Created default config file');\n config.write(soft.CONFIG_FILENAMES[0] + '.yml', config.defaultConfig);\n file.mkdir(`data/${soft.CONFIG_SAVED_DIR}/Builds`);\n file.mkdir('plugins');\n return config.defaultConfig;\n};\n\nconst program = commander\n .description(PKG.description)\n .version(VERSION)\n .option(\n '-d, --debug',\n 'Print all console logs rather than just chat messages (env: BRICKADIA_DEBUG)',\n )\n .option(\n '-u, --update',\n 'Check for brickadia updates (on steam) and install them if available',\n )\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .action(async () => {\n const { verbose, update } = program.opts();\n // BRICKADIA_DEBUG is an env-var alias for the --debug flag\n const debug = Boolean(program.opts().debug || process.env.BRICKADIA_DEBUG);\n if (program.args.length > 0) {\n program.help();\n process.exit(1);\n }\n Logger.VERBOSE = Boolean(verbose);\n\n // default working directory is the one specified in config\n let workDir = config.store.get('defaultOmegga');\n Logger.verbose('Using working directory', workDir?.yellow);\n\n // if there's a config in the current directory, use that one instead\n if (config.find('.')) workDir = '.';\n\n // check if configured path exists\n if (!fs.existsSync(workDir)) {\n Logger.errorp('configured omegga default path does not exist');\n process.exit(1);\n }\n if (!fs.statSync(workDir).isDirectory()) {\n Logger.errorp('configured omegga default path is not a directory');\n process.exit(1);\n }\n\n // find the config for the working directory\n const configFile = config.find(workDir);\n Logger.verbose('Target config file:', configFile?.yellow);\n let conf: IConfig;\n\n // create a default config file if it does not already exist, otherwise load in the existing one\n if (!configFile) {\n Logger.verbose('Creating a new config');\n conf = createDefaultConfig();\n } else {\n Logger.verbose('Reading config file');\n try {\n conf = config.read(configFile);\n } catch (error) {\n Logger.errorp('Error reading config file');\n Logger.verbose(error);\n // starting without a working config would only crash later\n process.exit(1);\n }\n }\n\n config.applyPortOverrides(conf);\n config.applyMetricsOverrides(conf);\n\n if (conf?.terminal?.timestamp) {\n Logger.setTimestamp(conf.terminal.timestamp);\n }\n\n const overrideBinary = getOverrideGameBinary();\n const isSteam = !conf?.server?.branch;\n if (overrideBinary) {\n if (!fs.existsSync(overrideBinary)) {\n Logger.error(\n 'Binary',\n overrideBinary.yellow,\n 'in',\n 'BRICKADIA_DIR'.yellow,\n 'does not exist!',\n );\n process.exit(1);\n }\n\n Logger.verbose(\n 'Using override binary',\n overrideBinary.yellow,\n '- skipping download.',\n );\n } else if (isSteam) {\n conf.__STEAM = true;\n await setupSteam(conf, update);\n } else {\n Logger.warnp(\n 'Brickadia will be launched with',\n 'non-steam launcher'.yellow,\n );\n Logger.warnp(\n 'New versions of Brickadia are not published on the old launcher.'\n .yellow,\n );\n\n // Check if the local launcher is installed\n if (fs.existsSync(soft.LOCAL_LAUNCHER)) {\n Logger.verbose(\"Using omegga's brickadia-launcher\");\n conf.server.__LOCAL = true;\n } else {\n Logger.verbose(\"Installing launcher as it's missing\");\n await installLauncher();\n }\n }\n\n const globalToken = auth.getGlobalToken();\n\n const hasHostingToken = Boolean(\n conf?.credentials?.token || process.env.BRICKADIA_TOKEN || globalToken,\n );\n\n // Skip auth when the hosting token is present\n if (hasHostingToken) {\n Logger.verbose(\n 'Skipping auth token generation due to host token presence',\n );\n if (conf?.credentials?.token)\n Logger.verbose('Found token in config file');\n else if (process.env.BRICKADIA_TOKEN)\n Logger.verbose('Found token in', 'BRICKADIA_TOKEN'.yellow);\n else if (globalToken)\n Logger.verbose('Found token in omegga global config');\n else Logger.verbose('unreachable - no token found');\n\n // check if the auth files don't exist\n } else if (\n !auth.exists(\n path.join(\n workDir,\n soft.DATA_PATH,\n conf?.server?.savedDir ?? soft.CONFIG_SAVED_DIR,\n conf?.server?.authDir ?? soft.CONFIG_AUTH_DIR,\n ),\n )\n ) {\n const success = await auth.prompt({\n debug,\n email: conf?.credentials?.['email'] ?? process.env.BRICKADIA_USER,\n password: conf?.credentials?.['password'] ?? process.env.BRICKADIA_PASS,\n isSteam,\n branch: conf?.server?.branch,\n authDir: conf?.server?.authDir,\n savedDir: conf?.server?.savedDir,\n launchArgs: conf?.server?.launchArgs,\n });\n if (!success) {\n Logger.errorp('Start aborted - could not generate auth tokens');\n process.exit(1);\n }\n } else {\n Logger.verbose(\n 'Skipping auth token generation due to existing auth files',\n );\n }\n\n // build options\n const options = {\n // default enable web ui (set to false)\n noweb: typeof conf.omegga?.webui === 'boolean' && !conf.omegga?.webui,\n // default enable https (set to true, will not be https if it can't generate)\n https: typeof conf.omegga?.https !== 'boolean' || conf.omegga?.https,\n port: conf.omegga?.port || soft.DEFAULT_PORT,\n debug,\n };\n\n Logger.verbose('Launching with options', options);\n\n // setup the server\n const server = new Omegga(workDir, conf, options);\n Logger.verbose('Created omegga object');\n\n if (verbose) {\n server.on(\n '*',\n (ev: string) => ev !== 'line' && Logger.verbose('EVENT'.green, ev),\n );\n }\n\n // create a terminal\n Logger.setTerminal(new Terminal(server, options));\n\n if (notifier?.update) {\n Logger.logp(\n `Omegga update is available (${('v' + notifier.update.latest).yellow})!`,\n isContainer()\n ? 'Pull a new container image to update!'\n : `Run ${'npm i -g omegga'.yellow} to update!`,\n );\n }\n\n if (\n conf.__STEAM &&\n !update &&\n !conf.server?.steambetaPassword &&\n process.env.STEAM_NOTIFIER !== 'false'\n ) {\n hasSteamUpdate(conf.server?.steambeta).then(hasUpdate => {\n if (hasUpdate) {\n Logger.logp('A server update is available!'.brightBlue);\n Logger.log(\n ' Restart with',\n 'omegga --update'.yellow,\n 'to update every start.',\n );\n Logger.log(' Run', '/update'.yellow, 'to update', 'now'.green + '!');\n } else {\n Logger.verbose('No server updates available.');\n }\n });\n }\n\n // resolved from the binary, so it's available before the server starts\n const gameVersion = readBinaryVersion(server.getGameBinaryPath());\n\n Logger.logp(\n `Launching Brickadia Server${\n gameVersion ? ' ' + ('CL' + gameVersion).green : ''\n } on port ${('' + (conf.server.port || 7777)).green}...`,\n );\n\n // start the server\n Logger.verbose('Starting Omegga');\n server.start();\n });\n\nprogram\n .command('init')\n .description('Sets up the current directory as a brickadia server')\n .action(async () => {\n const configFile = config.find('.');\n if (configFile) {\n Logger.errorp('Config file already exists:', configFile.yellow.underline);\n process.exit(1);\n }\n createDefaultConfig();\n });\n\nprogram\n .command('steamlogin')\n .description('Interactively log in to Steam (for Steam Guard authentication)')\n .action(async () => {\n if (!process.env.STEAM_USERNAME) {\n Logger.errorp('STEAM_USERNAME environment variable is required.');\n Logger.errorp('Set it in your .env file or environment.');\n process.exit(1);\n }\n\n if (!fs.existsSync(STEAMCMD_PATH)) {\n Logger.errorp(\n 'SteamCMD is not installed. Run',\n 'omegga'.yellow,\n 'first to set it up.',\n );\n process.exit(1);\n }\n\n Logger.logp('Logging in to Steam interactively...');\n const success = await steamcmdInteractiveLogin();\n if (success) {\n Logger.logp('Steam login successful. Credentials are now cached.');\n } else {\n Logger.errorp('Steam login failed.');\n process.exit(1);\n }\n });\n\nprogram\n .command('config [field] [value]')\n .description(\n \"Configure Omegga's default behavior.\\n\" +\n 'Type ' +\n 'omegga config list'.yellow.underline +\n ' for current settings and available fields',\n )\n .action((field, value) => {\n if (!field) field = 'list';\n omeggaConfig(field, value, program.opts());\n });\n\nprogram\n .command('auth')\n .option('-g, --global', 'Remove global auth files')\n .option('-l, --local', 'Remove local auth files')\n .option('-w, --workdir', 'Remove configured location auth files')\n .option('-u, --email <email>', 'User email (must provide password)')\n .option('-p, --pass <password>', 'User password (must provide email)')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description(\n 'Generates server auth tokens from brickadia account email+password',\n )\n .action(\n async ({\n email,\n pass: password,\n local: localAuth,\n workDir,\n global: globalAuth,\n }) => {\n const { verbose } = program.opts();\n // BRICKADIA_DEBUG is an env-var alias for the --debug flag\n const debug = Boolean(\n program.opts().debug || process.env.BRICKADIA_DEBUG,\n );\n Logger.VERBOSE = Boolean(verbose);\n\n let branch: string | undefined,\n authDir: string | undefined,\n savedDir: string | undefined,\n launchArgs: string | undefined;\n let isSteam: boolean | undefined;\n\n // if there's a config in the current directory, use that one instead\n if (config.find('.')) workDir = '.';\n\n // check if configured path exists\n if (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n Logger.verbose('Using working directory', workDir.yellow);\n // find the config for the working directory\n const configFile = config.find(workDir);\n Logger.verbose('Target config file:', configFile?.yellow);\n if (configFile) {\n try {\n // read the config and extract the branch\n const conf = config.read(configFile);\n Logger.verbose(\n 'Auth config:',\n conf?.server ?? 'no server config'.grey,\n );\n branch = conf?.server?.branch;\n authDir = conf?.server?.authDir;\n savedDir = conf?.server?.savedDir;\n launchArgs = conf?.server?.launchArgs;\n isSteam = !conf?.server?.branch;\n\n if (localAuth && conf?.credentials?.token) {\n Logger.logp(\n \"This server's auth is managed by the token in\",\n configFile.yellow,\n );\n return;\n }\n } catch (error) {\n Logger.errorp('Error reading config file');\n Logger.verbose(error);\n }\n }\n } else {\n Logger.verbose('Using default working directory', workDir.yellow);\n }\n\n savedDir ??= soft.CONFIG_SAVED_DIR;\n\n const workdirPath = path.join(\n config.store.get('defaultOmegga'),\n `data/${savedDir}/Auth`,\n );\n\n if (globalAuth || localAuth) {\n if (globalAuth) {\n const globalAuthPath = path.join(\n soft.CONFIG_HOME,\n savedDir !== soft.CONFIG_SAVED_DIR ? savedDir : '',\n authDir ?? soft.CONFIG_AUTH_DIR,\n );\n Logger.logp('Clearing auth files from', globalAuthPath.yellow);\n auth.clean(globalAuthPath);\n }\n if (workDir) {\n Logger.logp('Clearing auth files from', workdirPath.yellow);\n await file.rmdir(workdirPath);\n }\n if (localAuth) {\n const localPath = path.resolve(\n `data/${savedDir}/`,\n authDir ?? soft.CONFIG_AUTH_DIR,\n );\n Logger.logp('Clearing auth files from', localPath.yellow);\n await file.rmdir(localPath);\n }\n return;\n }\n\n if (!isSteam) {\n Logger.warnp('Authenticating with', 'non-steam launcher'.yellow);\n }\n\n auth.prompt({\n email,\n password,\n debug,\n branch,\n authDir,\n savedDir,\n launchArgs,\n });\n },\n );\n\nprogram\n .command('info')\n .alias('n')\n .description(\n 'Shows server name, description, port, install info, and installed plugins',\n )\n .action(async () => {\n Logger.errorp('not implemented yet');\n // TODO: implement config parsing\n });\n\nprogram\n .command('install <pluginUrl...>')\n .alias('i')\n .option('-f, --force', 'Forcefully re-install existing plugin') // TODO: implement install --force\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Installs a plugin to the current brickadia server')\n .action(async plugins => {\n if (!hasbin.sync('git')) {\n Logger.errorp('git'.yellow, 'must be installed to install plugins.');\n process.exit(1);\n }\n\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose, force } = program.opts();\n Logger.VERBOSE = Boolean(verbose);\n pluginUtil.install(plugins, { verbose, force });\n });\n\nprogram\n .command('update [pluginNames...]')\n .alias('u')\n .option('-f, --force', 'Forcefully re-upgrade existing plugin') // TODO: implement update --force\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Updates all or selected installed plugins to latest versions')\n .action(async plugins => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose, force } = program.opts();\n Logger.VERBOSE = Boolean(verbose);\n pluginUtil.update(plugins, { verbose, force });\n });\n\nprogram\n .command('check [pluginNames...]')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Checks plugins for compatibility issues')\n .action(async plugins => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose } = program.opts();\n Logger.VERBOSE = Boolean(verbose);\n pluginUtil.check(plugins, { verbose });\n });\n\nprogram\n .command('init-plugin')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Initializes a new plugin with the given name and settings')\n .action(async () => {\n const { verbose } = program.opts();\n Logger.VERBOSE = Boolean(verbose);\n\n pluginUtil.init();\n });\n\nprogram\n .command('plugin-init')\n .description('Alias for ' + 'init-plugin'.yellow.underline)\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .action(async () => {\n const { verbose } = program.opts();\n Logger.VERBOSE = Boolean(verbose);\n\n pluginUtil.init();\n });\n\nprogram\n .command('get-config <pluginName> [configName]')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .option('-j, --json', 'Print config as json')\n .description(\n 'Gets a config for a plugin. If ' +\n 'configName'.yellow.underline +\n ' is omitted, returns all config values.',\n )\n .action(async (pluginName, configName) => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose } = program.opts();\n const json = program.args.includes('-j') || program.args.includes('--json');\n Logger.VERBOSE = Boolean(verbose);\n if (!configName) {\n pluginUtil.listConfig(pluginName, json);\n } else {\n pluginUtil.getConfig(pluginName, configName, json);\n }\n });\n\nprogram\n .command('set-config <pluginName> [configName] [configValue]')\n .option('-y, --yes', 'Skip confirmation prompt')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description(\n 'Sets a config for a plugin. If ' +\n 'configValue'.yellow.underline +\n ' is omitted, the config will be reset. If ' +\n 'configName'.yellow.underline +\n ' is omitted, the entire plugin config will be reset.',\n )\n .action(async (pluginName, configName, configValue) => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose } = program.opts();\n const yes = program.args.includes('-y') || program.args.includes('--yes');\n Logger.VERBOSE = Boolean(verbose);\n if (!configName) {\n pluginUtil.resetAllConfigs(pluginName, yes);\n } else if (!configValue) {\n pluginUtil.resetConfig(pluginName, configName);\n } else {\n pluginUtil.setConfig(pluginName, configName, configValue);\n }\n });\n\nprogram.parseAsync(process.argv);\n\nasync function setupSteam(config: config.IConfig, forceUpdate = false) {\n const steambeta = config?.server?.steambeta;\n const steambetaPassword = config?.server?.steambetaPassword;\n\n const binaryPath = path.join(\n getSteamInstallDir(), // steam install directory\n steambeta ?? 'main', // steam beta branch (or main)\n getSteamGameDir(), // Brickadia\n GAME_BIN_PATH, // path to binary\n );\n\n if (!forceUpdate && fs.existsSync(binaryPath)) {\n Logger.verbose(\n 'Game binary already exists at',\n binaryPath.yellow,\n '- skipping download.',\n );\n return;\n }\n\n // Check if steamcmd is installed\n if (!fs.existsSync(STEAMCMD_PATH)) {\n // Lookup steamcmd in path\n const hasSteamcmd = hasbin.sync('steamcmd');\n\n if (!hasSteamcmd) {\n // Prompt to install steamcmd\n const { install } =\n process.env.SKIP_STEAMCMD_PROMPT === 'true'\n ? { install: true }\n : await prompts({\n type: 'confirm',\n name: 'install',\n message: 'SteamCMD is not installed. OK to download it?',\n initial: true,\n });\n\n if (!install) {\n Logger.errorp('SteamCMD is required for steam support. Exiting...');\n process.exit(1);\n }\n\n Logger.logp('Downloading SteamCMD...');\n }\n\n try {\n steamcmdDownloadSelf();\n if (!fs.existsSync(STEAMCMD_PATH)) {\n Logger.errorp('Failed to setup SteamCMD. Exiting...');\n process.exit(1);\n }\n } catch (err) {\n Logger.errorp('Error setting up SteamCMD:', err);\n process.exit(1);\n }\n }\n\n Logger.logp('Downloading Brickadia', (steambeta ?? 'main').yellow, '...');\n try {\n await steamcmdDownloadGame({ steambeta, steambetaPassword });\n } catch (err) {\n Logger.errorp('Error downloading Brickadia:', err);\n process.exit(1);\n }\n}\n"],"names":["PKG","isContainer","Logger","config.write","soft","config.defaultConfig","file.mkdir","VERSION","config.store","config.find","config.read","config.applyPortOverrides","config.applyMetricsOverrides","getOverrideGameBinary","installLauncher","auth","server","Omegga","Terminal","hasSteamUpdate","readBinaryVersion","STEAMCMD_PATH","steamcmdInteractiveLogin","omeggaConfig","file.rmdir","pluginUtil","config","getSteamInstallDir","getSteamGameDir","GAME_BIN_PATH","steamcmdDownloadSelf","steamcmdDownloadGame"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"main.js","sources":["../src/main.ts"],"sourcesContent":["import soft, {\n getOverrideGameBinary,\n getSteamGameDir,\n getSteamInstallDir,\n} from '@/softconfig';\nimport { installLauncher } from '@cli/installer';\nimport * as config from '@config';\nimport { readBinaryVersion } from '@omegga/matchers/version';\nimport Omegga from '@omegga/server';\nimport * as file from '@util/file';\nimport { isContainer } from '@util/container';\nimport { isNonInteractive, parseEnvBool } from '@util/env';\nimport 'colors';\nimport commander from 'commander';\nimport dotenv from 'dotenv';\nimport hasbin from 'hasbin';\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport prompts from 'prompts';\nimport updateNotifier from 'update-notifier-cjs';\nimport { auth, config as omeggaConfig, pluginUtil, Terminal } from './cli';\nimport { IConfig } from './config/types';\nimport Logger from './logger';\nimport { GAME_BIN_PATH, STEAMCMD_PATH } from './softconfig';\nimport {\n hasSteamUpdate,\n steamcmdDownloadGame,\n steamcmdDownloadSelf,\n steamcmdInteractiveLogin,\n} from './updater';\nimport { PKG, VERSION } from './version';\n\ndotenv.config({ quiet: true });\n\nconst notifier =\n process.env.PACKAGE_NOTIFIER !== 'false'\n ? updateNotifier({\n pkg: PKG,\n updateCheckInterval: 1000 * 60 * 60 * 24,\n })\n : null;\nif (notifier) {\n const { update } = notifier;\n notifier.notify(\n update && isContainer()\n ? {\n message: `Update available ${update.current} → ${update.latest}\\nPull a new container image to update`,\n }\n : undefined,\n );\n}\n\n// TODO: let omegga bundle config (roles, bans, server config) to zip\n// TODO: let omegga unbundle config from zip to current omegga dir\n\n// write a default config file\nconst createDefaultConfig = () => {\n Logger.logp('Created default config file');\n config.write(soft.CONFIG_FILENAMES[0] + '.yml', config.defaultConfig);\n file.mkdir(`data/${soft.CONFIG_SAVED_DIR}/Builds`);\n file.mkdir('plugins');\n return config.defaultConfig;\n};\n\n/**\n * `--verbose` and `--debug` also have environment aliases. Both parse the\n * value rather than testing for presence: an orchestrator that materialises\n * every declared variable has no way to leave one unset, so `VERBOSE=false`\n * has to mean false.\n */\nconst isVerbose = (flag?: unknown) =>\n Boolean(flag) || parseEnvBool('VERBOSE') === true;\nconst isDebug = (flag?: unknown) =>\n Boolean(flag) || parseEnvBool('BRICKADIA_DEBUG') === true;\n\nconst program = commander\n .description(PKG.description)\n .version(VERSION)\n .option(\n '-d, --debug',\n 'Print all console logs rather than just chat messages (env: BRICKADIA_DEBUG)',\n )\n .option(\n '-u, --update',\n 'Check for brickadia updates (on steam) and install them if available',\n )\n .option(\n '-v, --verbose',\n 'Print extra messages for debugging purposes (env: VERBOSE)',\n )\n .action(async () => {\n const { verbose, update } = program.opts();\n const debug = isDebug(program.opts().debug);\n if (program.args.length > 0) {\n program.help();\n process.exit(1);\n }\n Logger.VERBOSE = isVerbose(verbose);\n\n // default working directory is the one specified in config\n let workDir = config.store.get('defaultOmegga');\n Logger.verbose('Using working directory', workDir?.yellow);\n\n // if there's a config in the current directory, use that one instead\n if (config.find('.')) workDir = '.';\n\n // check if configured path exists\n if (!fs.existsSync(workDir)) {\n Logger.errorp('configured omegga default path does not exist');\n process.exit(1);\n }\n if (!fs.statSync(workDir).isDirectory()) {\n Logger.errorp('configured omegga default path is not a directory');\n process.exit(1);\n }\n\n // find the config for the working directory\n const configFile = config.find(workDir);\n Logger.verbose('Target config file:', configFile?.yellow);\n let conf: IConfig;\n\n // create a default config file if it does not already exist, otherwise load in the existing one\n if (!configFile) {\n Logger.verbose('Creating a new config');\n conf = createDefaultConfig();\n } else {\n Logger.verbose('Reading config file');\n try {\n conf = config.read(configFile);\n } catch (error) {\n Logger.errorp('Error reading config file');\n Logger.verbose(error);\n // starting without a working config would only crash later\n process.exit(1);\n }\n }\n\n config.applyPortOverrides(conf);\n config.applyMetricsOverrides(conf);\n\n if (conf?.terminal?.timestamp) {\n Logger.setTimestamp(conf.terminal.timestamp);\n }\n\n const overrideBinary = getOverrideGameBinary();\n const isSteam = !conf?.server?.branch;\n if (overrideBinary) {\n if (!fs.existsSync(overrideBinary)) {\n Logger.error(\n 'Binary',\n overrideBinary.yellow,\n 'in',\n 'BRICKADIA_DIR'.yellow,\n 'does not exist!',\n );\n process.exit(1);\n }\n\n Logger.verbose(\n 'Using override binary',\n overrideBinary.yellow,\n '- skipping download.',\n );\n } else if (isSteam) {\n conf.__STEAM = true;\n await setupSteam(conf, update);\n } else {\n Logger.warnp(\n 'Brickadia will be launched with',\n 'non-steam launcher'.yellow,\n );\n Logger.warnp(\n 'New versions of Brickadia are not published on the old launcher.'\n .yellow,\n );\n\n // Check if the local launcher is installed\n if (fs.existsSync(soft.LOCAL_LAUNCHER)) {\n Logger.verbose(\"Using omegga's brickadia-launcher\");\n conf.server.__LOCAL = true;\n } else {\n Logger.verbose(\"Installing launcher as it's missing\");\n await installLauncher();\n }\n }\n\n const globalToken = auth.getGlobalToken();\n\n const hasHostingToken = Boolean(\n conf?.credentials?.token || process.env.BRICKADIA_TOKEN || globalToken,\n );\n\n // Skip auth when the hosting token is present\n if (hasHostingToken) {\n Logger.verbose(\n 'Skipping auth token generation due to host token presence',\n );\n if (conf?.credentials?.token)\n Logger.verbose('Found token in config file');\n else if (process.env.BRICKADIA_TOKEN)\n Logger.verbose('Found token in', 'BRICKADIA_TOKEN'.yellow);\n else if (globalToken)\n Logger.verbose('Found token in omegga global config');\n else Logger.verbose('unreachable - no token found');\n\n // check if the auth files don't exist\n } else if (\n !auth.exists(\n path.join(\n workDir,\n soft.DATA_PATH,\n conf?.server?.savedDir ?? soft.CONFIG_SAVED_DIR,\n conf?.server?.authDir ?? soft.CONFIG_AUTH_DIR,\n ),\n )\n ) {\n const success = await auth.prompt({\n debug,\n email: conf?.credentials?.['email'] ?? process.env.BRICKADIA_USER,\n password: conf?.credentials?.['password'] ?? process.env.BRICKADIA_PASS,\n isSteam,\n branch: conf?.server?.branch,\n authDir: conf?.server?.authDir,\n savedDir: conf?.server?.savedDir,\n launchArgs: conf?.server?.launchArgs,\n });\n if (!success) {\n Logger.errorp('Start aborted - could not generate auth tokens');\n process.exit(1);\n }\n } else {\n Logger.verbose(\n 'Skipping auth token generation due to existing auth files',\n );\n }\n\n // build options\n const options = {\n // default enable web ui (set to false)\n noweb: typeof conf.omegga?.webui === 'boolean' && !conf.omegga?.webui,\n // default enable https (set to true, will not be https if it can't generate)\n https: typeof conf.omegga?.https !== 'boolean' || conf.omegga?.https,\n port: conf.omegga?.port || soft.DEFAULT_PORT,\n debug,\n };\n\n Logger.verbose('Launching with options', options);\n\n // setup the server\n const server = new Omegga(workDir, conf, options);\n Logger.verbose('Created omegga object');\n\n if (verbose) {\n server.on(\n '*',\n (ev: string) => ev !== 'line' && Logger.verbose('EVENT'.green, ev),\n );\n }\n\n // create a terminal\n Logger.setTerminal(new Terminal(server, options));\n\n if (notifier?.update) {\n Logger.logp(\n `Omegga update is available (${('v' + notifier.update.latest).yellow})!`,\n isContainer()\n ? 'Pull a new container image to update!'\n : `Run ${'npm i -g omegga'.yellow} to update!`,\n );\n }\n\n if (\n conf.__STEAM &&\n !update &&\n !conf.server?.steambetaPassword &&\n process.env.STEAM_NOTIFIER !== 'false'\n ) {\n hasSteamUpdate(conf.server?.steambeta).then(hasUpdate => {\n if (hasUpdate) {\n Logger.logp('A server update is available!'.brightBlue);\n Logger.log(\n ' Restart with',\n 'omegga --update'.yellow,\n 'to update every start.',\n );\n Logger.log(' Run', '/update'.yellow, 'to update', 'now'.green + '!');\n } else {\n Logger.verbose('No server updates available.');\n }\n });\n }\n\n // resolved from the binary, so it's available before the server starts\n const gameVersion = readBinaryVersion(server.getGameBinaryPath());\n\n Logger.logp(\n `Launching Brickadia Server${\n gameVersion ? ' ' + ('CL' + gameVersion).green : ''\n } on port ${('' + (conf.server.port || 7777)).green}...`,\n );\n\n // start the server\n Logger.verbose('Starting Omegga');\n server.start();\n });\n\nprogram\n .command('init')\n .description('Sets up the current directory as a brickadia server')\n .action(async () => {\n const configFile = config.find('.');\n if (configFile) {\n Logger.errorp('Config file already exists:', configFile.yellow.underline);\n process.exit(1);\n }\n createDefaultConfig();\n });\n\nprogram\n .command('steamlogin')\n .description('Interactively log in to Steam (for Steam Guard authentication)')\n .action(async () => {\n if (!process.env.STEAM_USERNAME) {\n Logger.errorp('STEAM_USERNAME environment variable is required.');\n Logger.errorp('Set it in your .env file or environment.');\n process.exit(1);\n }\n\n if (!fs.existsSync(STEAMCMD_PATH)) {\n Logger.errorp(\n 'SteamCMD is not installed. Run',\n 'omegga'.yellow,\n 'first to set it up.',\n );\n process.exit(1);\n }\n\n Logger.logp('Logging in to Steam interactively...');\n const success = await steamcmdInteractiveLogin();\n if (success) {\n Logger.logp('Steam login successful. Credentials are now cached.');\n } else {\n Logger.errorp('Steam login failed.');\n process.exit(1);\n }\n });\n\nprogram\n .command('config [field] [value]')\n .description(\n \"Configure Omegga's default behavior.\\n\" +\n 'Type ' +\n 'omegga config list'.yellow.underline +\n ' for current settings and available fields',\n )\n .action((field, value) => {\n if (!field) field = 'list';\n omeggaConfig(field, value, program.opts());\n });\n\nprogram\n .command('auth')\n .option('-g, --global', 'Remove global auth files')\n .option('-l, --local', 'Remove local auth files')\n .option('-w, --workdir', 'Remove configured location auth files')\n .option('-u, --email <email>', 'User email (must provide password)')\n .option('-p, --pass <password>', 'User password (must provide email)')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description(\n 'Generates server auth tokens from brickadia account email+password',\n )\n .action(\n async ({\n email,\n pass: password,\n local: localAuth,\n workDir,\n global: globalAuth,\n }) => {\n const { verbose } = program.opts();\n const debug = isDebug(program.opts().debug);\n Logger.VERBOSE = isVerbose(verbose);\n\n let branch: string | undefined,\n authDir: string | undefined,\n savedDir: string | undefined,\n launchArgs: string | undefined;\n let isSteam: boolean | undefined;\n\n // if there's a config in the current directory, use that one instead\n if (config.find('.')) workDir = '.';\n\n // check if configured path exists\n if (fs.existsSync(workDir) && fs.statSync(workDir).isDirectory()) {\n Logger.verbose('Using working directory', workDir.yellow);\n // find the config for the working directory\n const configFile = config.find(workDir);\n Logger.verbose('Target config file:', configFile?.yellow);\n if (configFile) {\n try {\n // read the config and extract the branch\n const conf = config.read(configFile);\n Logger.verbose(\n 'Auth config:',\n conf?.server ?? 'no server config'.grey,\n );\n branch = conf?.server?.branch;\n authDir = conf?.server?.authDir;\n savedDir = conf?.server?.savedDir;\n launchArgs = conf?.server?.launchArgs;\n isSteam = !conf?.server?.branch;\n\n if (localAuth && conf?.credentials?.token) {\n Logger.logp(\n \"This server's auth is managed by the token in\",\n configFile.yellow,\n );\n return;\n }\n } catch (error) {\n Logger.errorp('Error reading config file');\n Logger.verbose(error);\n }\n }\n } else {\n Logger.verbose('Using default working directory', workDir.yellow);\n }\n\n savedDir ??= soft.CONFIG_SAVED_DIR;\n\n const workdirPath = path.join(\n config.store.get('defaultOmegga'),\n `data/${savedDir}/Auth`,\n );\n\n if (globalAuth || localAuth) {\n if (globalAuth) {\n const globalAuthPath = path.join(\n soft.CONFIG_HOME,\n savedDir !== soft.CONFIG_SAVED_DIR ? savedDir : '',\n authDir ?? soft.CONFIG_AUTH_DIR,\n );\n Logger.logp('Clearing auth files from', globalAuthPath.yellow);\n auth.clean(globalAuthPath);\n }\n if (workDir) {\n Logger.logp('Clearing auth files from', workdirPath.yellow);\n await file.rmdir(workdirPath);\n }\n if (localAuth) {\n const localPath = path.resolve(\n `data/${savedDir}/`,\n authDir ?? soft.CONFIG_AUTH_DIR,\n );\n Logger.logp('Clearing auth files from', localPath.yellow);\n await file.rmdir(localPath);\n }\n return;\n }\n\n if (!isSteam) {\n Logger.warnp('Authenticating with', 'non-steam launcher'.yellow);\n }\n\n const success = await auth.prompt({\n email,\n password,\n debug,\n branch,\n authDir,\n savedDir,\n launchArgs,\n });\n if (!success) process.exit(1);\n },\n );\n\nprogram\n .command('info')\n .alias('n')\n .description(\n 'Shows server name, description, port, install info, and installed plugins',\n )\n .action(async () => {\n Logger.errorp('not implemented yet');\n // TODO: implement config parsing\n });\n\nprogram\n .command('install <pluginUrl...>')\n .alias('i')\n .option('-f, --force', 'Forcefully re-install existing plugin') // TODO: implement install --force\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Installs a plugin to the current brickadia server')\n .action(async plugins => {\n if (!hasbin.sync('git')) {\n Logger.errorp('git'.yellow, 'must be installed to install plugins.');\n process.exit(1);\n }\n\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { force } = program.opts();\n const verbose = isVerbose(program.opts().verbose);\n Logger.VERBOSE = verbose;\n pluginUtil.install(plugins, { verbose, force });\n });\n\nprogram\n .command('update [pluginNames...]')\n .alias('u')\n .option('-f, --force', 'Forcefully re-upgrade existing plugin') // TODO: implement update --force\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Updates all or selected installed plugins to latest versions')\n .action(async plugins => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { force } = program.opts();\n const verbose = isVerbose(program.opts().verbose);\n Logger.VERBOSE = verbose;\n pluginUtil.update(plugins, { verbose, force });\n });\n\nprogram\n .command('check [pluginNames...]')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Checks plugins for compatibility issues')\n .action(async plugins => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const verbose = isVerbose(program.opts().verbose);\n Logger.VERBOSE = verbose;\n pluginUtil.check(plugins, { verbose });\n });\n\nprogram\n .command('init-plugin')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description('Initializes a new plugin with the given name and settings')\n .action(async () => {\n const { verbose } = program.opts();\n Logger.VERBOSE = isVerbose(verbose);\n\n pluginUtil.init();\n });\n\nprogram\n .command('plugin-init')\n .description('Alias for ' + 'init-plugin'.yellow.underline)\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .action(async () => {\n const { verbose } = program.opts();\n Logger.VERBOSE = isVerbose(verbose);\n\n pluginUtil.init();\n });\n\nprogram\n .command('get-config <pluginName> [configName]')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .option('-j, --json', 'Print config as json')\n .description(\n 'Gets a config for a plugin. If ' +\n 'configName'.yellow.underline +\n ' is omitted, returns all config values.',\n )\n .action(async (pluginName, configName) => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose } = program.opts();\n const json = program.args.includes('-j') || program.args.includes('--json');\n Logger.VERBOSE = isVerbose(verbose);\n if (!configName) {\n pluginUtil.listConfig(pluginName, json);\n } else {\n pluginUtil.getConfig(pluginName, configName, json);\n }\n });\n\nprogram\n .command('set-config <pluginName> [configName] [configValue]')\n .option('-y, --yes', 'Skip confirmation prompt')\n .option('-v, --verbose', 'Print extra messages for debugging purposes')\n .description(\n 'Sets a config for a plugin. If ' +\n 'configValue'.yellow.underline +\n ' is omitted, the config will be reset. If ' +\n 'configName'.yellow.underline +\n ' is omitted, the entire plugin config will be reset.',\n )\n .action(async (pluginName, configName, configValue) => {\n if (!config.find('.')) {\n Logger.errorp(\n 'Not an omegga directory, run ',\n 'omegga init'.yellow,\n 'to setup one.',\n );\n process.exit(1);\n }\n const { verbose } = program.opts();\n const yes = program.args.includes('-y') || program.args.includes('--yes');\n Logger.VERBOSE = isVerbose(verbose);\n if (!configName) {\n pluginUtil.resetAllConfigs(pluginName, yes);\n } else if (!configValue) {\n pluginUtil.resetConfig(pluginName, configName);\n } else {\n pluginUtil.setConfig(pluginName, configName, configValue);\n }\n });\n\nprogram.parseAsync(process.argv);\n\nasync function setupSteam(config: config.IConfig, forceUpdate = false) {\n const steambeta = config?.server?.steambeta;\n const steambetaPassword = config?.server?.steambetaPassword;\n\n const binaryPath = path.join(\n getSteamInstallDir(), // steam install directory\n steambeta ?? 'main', // steam beta branch (or main)\n getSteamGameDir(), // Brickadia\n GAME_BIN_PATH, // path to binary\n );\n\n if (!forceUpdate && fs.existsSync(binaryPath)) {\n Logger.verbose(\n 'Game binary already exists at',\n binaryPath.yellow,\n '- skipping download.',\n );\n return;\n }\n\n // Check if steamcmd is installed\n if (!fs.existsSync(STEAMCMD_PATH)) {\n // Lookup steamcmd in path\n const hasSteamcmd = hasbin.sync('steamcmd');\n\n if (!hasSteamcmd) {\n const skipPrompt = parseEnvBool('SKIP_STEAMCMD_PROMPT') === true;\n\n if (!skipPrompt && isNonInteractive()) {\n Logger.errorp(\n 'SteamCMD is not installed and there is no terminal to prompt on. Set',\n 'SKIP_STEAMCMD_PROMPT=true'.yellow,\n 'to install it without asking. Exiting...',\n );\n process.exit(1);\n }\n\n // Prompt to install steamcmd\n const { install } = skipPrompt\n ? { install: true }\n : await prompts({\n type: 'confirm',\n name: 'install',\n message: 'SteamCMD is not installed. OK to download it?',\n initial: true,\n });\n\n if (!install) {\n Logger.errorp('SteamCMD is required for steam support. Exiting...');\n process.exit(1);\n }\n\n Logger.logp('Downloading SteamCMD...');\n }\n\n try {\n steamcmdDownloadSelf();\n if (!fs.existsSync(STEAMCMD_PATH)) {\n Logger.errorp('Failed to setup SteamCMD. Exiting...');\n process.exit(1);\n }\n } catch (err) {\n Logger.errorp('Error setting up SteamCMD:', err);\n process.exit(1);\n }\n }\n\n Logger.logp('Downloading Brickadia', (steambeta ?? 'main').yellow, '...');\n try {\n await steamcmdDownloadGame({ steambeta, steambetaPassword });\n } catch (err) {\n Logger.errorp('Error downloading Brickadia:', err);\n process.exit(1);\n }\n}\n"],"names":["PKG","isContainer","Logger","config.write","soft","config.defaultConfig","file.mkdir","parseEnvBool","VERSION","config.store","config.find","config.read","config.applyPortOverrides","config.applyMetricsOverrides","getOverrideGameBinary","installLauncher","auth","server","Omegga","Terminal","hasSteamUpdate","readBinaryVersion","STEAMCMD_PATH","steamcmdInteractiveLogin","omeggaConfig","file.rmdir","pluginUtil","config","getSteamInstallDir","getSteamGameDir","GAME_BIN_PATH","isNonInteractive","steamcmdDownloadSelf","steamcmdDownloadGame"],"mappings":"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"}
|
package/dist/util/env.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const logger = require("../logger.js");
|
|
4
|
+
require("colors");
|
|
5
|
+
function parseEnvBool(name) {
|
|
6
|
+
const raw = process.env[name];
|
|
7
|
+
if (!raw) return void 0;
|
|
8
|
+
const value = raw.trim().toLowerCase();
|
|
9
|
+
if (["true", "1", "yes", "on"].includes(value)) return true;
|
|
10
|
+
if (["false", "0", "no", "off"].includes(value)) return false;
|
|
11
|
+
logger.default.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a boolean`);
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
function isNonInteractive() {
|
|
15
|
+
return parseEnvBool("OMEGGA_NONINTERACTIVE") ?? !process.stdin.isTTY;
|
|
16
|
+
}
|
|
17
|
+
exports.isNonInteractive = isNonInteractive;
|
|
18
|
+
exports.parseEnvBool = parseEnvBool;
|
|
19
|
+
//# sourceMappingURL=env.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env.js","sources":["../../src/util/env.ts"],"sourcesContent":["import Logger from '@/logger';\nimport 'colors';\n\n/** parse a boolean from the environment, warning (and ignoring) when it isn't one */\nexport function parseEnvBool(name: string) {\n const raw = process.env[name];\n if (!raw) return undefined;\n const value = raw.trim().toLowerCase();\n if (['true', '1', 'yes', 'on'].includes(value)) return true;\n if (['false', '0', 'no', 'off'].includes(value)) return false;\n Logger.warnp(`Ignoring ${name.yellow}: ${raw.yellow} is not a boolean`);\n return undefined;\n}\n\n/**\n * Whether omegga is allowed to block on an interactive prompt.\n *\n * Prompts are driven by raw key input, so anything that cannot deliver it\n * (a service manager with stdin on /dev/null, a panel console that submits\n * whole lines) waits at the prompt forever instead of failing. Callers that\n * would prompt should refuse instead when this is true.\n *\n * OMEGGA_NONINTERACTIVE overrides the guess in both directions: hosts that\n * allocate a real TTY but still cannot answer a prompt have to say so, and a\n * caller that really does feed stdin can set it to false.\n */\nexport function isNonInteractive(): boolean {\n return parseEnvBool('OMEGGA_NONINTERACTIVE') ?? !process.stdin.isTTY;\n}\n"],"names":["Logger"],"mappings":";;;;AAIO,SAAS,aAAa,MAAc;AACzC,QAAM,MAAM,QAAQ,IAAI,IAAI;AAC5B,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,QAAQ,IAAI,KAAA,EAAO,YAAA;AACzB,MAAI,CAAC,QAAQ,KAAK,OAAO,IAAI,EAAE,SAAS,KAAK,EAAG,QAAO;AACvD,MAAI,CAAC,SAAS,KAAK,MAAM,KAAK,EAAE,SAAS,KAAK,EAAG,QAAO;AACxDA,iBAAO,MAAM,YAAY,KAAK,MAAM,KAAK,IAAI,MAAM,mBAAmB;AACtE,SAAO;AACT;AAcO,SAAS,mBAA4B;AAC1C,SAAO,aAAa,uBAAuB,KAAK,CAAC,QAAQ,MAAM;AACjE;;;"}
|
package/docs/SUMMARY.md
CHANGED
package/docs/containers.md
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
Release tags publish an image to `ghcr.io/brickadia-community/omegga`.
|
|
4
4
|
|
|
5
|
+
To run that image under a Pterodactyl panel instead of directly, see
|
|
6
|
+
[Pterodactyl](guides/pterodactyl.md). Wings imposes its own user, working
|
|
7
|
+
directory, and console behaviour, and the egg in `docker/pterodactyl` handles
|
|
8
|
+
them.
|
|
9
|
+
|
|
5
10
|
```sh
|
|
6
11
|
docker run -it --rm \
|
|
7
12
|
-v omegga-home:/home/steam \
|
|
@@ -12,7 +17,7 @@ docker run -it --rm \
|
|
|
12
17
|
ghcr.io/brickadia-community/omegga
|
|
13
18
|
```
|
|
14
19
|
|
|
15
|
-
Generate a hosting token at https://brickadia.com/account/tokens
|
|
20
|
+
Generate a hosting token at https://brickadia.com/account/tokens. Without one omegga falls back to an interactive auth prompt, which needs a tty: it stops there under `docker run -it`, and exits with the token URL when there is no tty to prompt on. Set `OMEGGA_NONINTERACTIVE=true` to get that same refusal on a host that does allocate a tty but cannot answer an arrow-key prompt. Arguments are passed through, so `omegga --debug` and `bash` both work in place of the default command. Omegga handles `SIGINT` and `SIGTERM`, so ctrl+c and `docker stop` shut down gracefully - add `--init` if you also want zombie reaping.
|
|
16
21
|
|
|
17
22
|
Omegga is baked into the image, so it updates by pulling a new one rather than through npm:
|
|
18
23
|
|
package/docs/env.md
CHANGED
|
@@ -18,8 +18,9 @@ These can be set in your shell or in a `.env` file the same directory as a `omeg
|
|
|
18
18
|
- `STEAM_APP_ID` - Set the Steam App ID for Brickadia (default `3017590`)
|
|
19
19
|
- `STEAM_USERNAME` - Set the Steam username for downloading Brickadia via steamcmd. Run `omegga steamlogin` to authenticate with Steam Guard
|
|
20
20
|
- `STEAM_PASSWORD` - (Optional) Steam password; if not set, you will be prompted interactively
|
|
21
|
-
- `VERBOSE` - Set to `true` to enable verbose logging (default `false`)
|
|
21
|
+
- `VERBOSE` - Set to `true` to enable verbose logging, equivalent to the `--verbose` flag (default `false`)
|
|
22
22
|
- `PACKAGE_NOTIFIER` - When set to `false`, disables the npm update notifier
|
|
23
23
|
- `STEAM_NOTIFIER` - When set to `false`, disables the SteamCMD update notifier
|
|
24
24
|
- `SKIP_STEAMCMD_PROMPT` - When set to `true`, agrees to installing SteamCMD without prompting
|
|
25
|
-
- `BRICKADIA_DEBUG` -
|
|
25
|
+
- `BRICKADIA_DEBUG` - Set to `true` to enable debug logging, equivalent to the `--debug` flag (default `false`)
|
|
26
|
+
- `OMEGGA_NONINTERACTIVE` - Set to `true` to fail instead of prompting for authentication. Defaults to `true` when stdin is not a terminal; set it explicitly on hosts that provide a terminal that cannot answer a prompt, such as a game panel console that only submits whole lines
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# Pterodactyl
|
|
2
|
+
|
|
3
|
+
[Pterodactyl](https://pterodactyl.io/) runs game servers as Docker containers
|
|
4
|
+
managed by a web panel. An egg tells it how to install and run one.
|
|
5
|
+
[`docker/pterodactyl/egg-omegga.json`](https://github.com/brickadia-community/omegga/blob/master/docker/pterodactyl/egg-omegga.json)
|
|
6
|
+
in this repository is that egg for Omegga.
|
|
7
|
+
|
|
8
|
+
It runs the published image, so Omegga updates by changing the image tag rather
|
|
9
|
+
than reinstalling. Brickadia is not in the image; Omegga downloads it through
|
|
10
|
+
steamcmd on first start, into the server's own volume.
|
|
11
|
+
|
|
12
|
+
Setting one up takes three steps:
|
|
13
|
+
|
|
14
|
+
1. [Import the egg](#importing-the-egg) into a nest.
|
|
15
|
+
2. [Create a server](#creating-a-server) from it, with two allocations.
|
|
16
|
+
3. [Set a hosting token](#the-hosting-token)
|
|
17
|
+
|
|
18
|
+
## Importing the egg
|
|
19
|
+
|
|
20
|
+
The panel has no CLI or API for importing eggs, so this is a UI operation:
|
|
21
|
+
|
|
22
|
+
1. Download the egg [here](https://raw.githubusercontent.com/brickadia-community/omegga/master/docker/pterodactyl/egg-omegga.json) or with `curl`:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
curl -LO https://raw.githubusercontent.com/brickadia-community/omegga/master/docker/pterodactyl/egg-omegga.json
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
2. **Admin > Nests > Import Egg**
|
|
29
|
+
3. Upload `egg-omegga.json` and pick a nest (create a "Brickadia" nest if you
|
|
30
|
+
do not have one).
|
|
31
|
+
|
|
32
|
+
Both `PTDL_v1` and `PTDL_v2` are accepted by current panels; this egg is
|
|
33
|
+
`PTDL_v2`.
|
|
34
|
+
|
|
35
|
+
## Creating a server
|
|
36
|
+
|
|
37
|
+
Omegga needs **two ports**, so the server needs two allocations:
|
|
38
|
+
|
|
39
|
+
| Allocation | Protocol | Used for |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| primary | UDP | Brickadia. `SERVER_PORT` drives `BRICKADIA_PORT` |
|
|
42
|
+
| second | TCP | the Omegga web UI. Set `OMEGGA_PORT` to this port |
|
|
43
|
+
|
|
44
|
+
Wings publishes each allocation on both TCP and UDP, so one allocation per
|
|
45
|
+
number is enough. They cannot share a number: Brickadia reports its configured
|
|
46
|
+
port to the master server, so the published port has to be the port it runs on.
|
|
47
|
+
|
|
48
|
+
Assign both on the server's **Network** tab, then set `OMEGGA_PORT` on the
|
|
49
|
+
**Startup** tab to the second one. The egg cannot do this for you: an egg
|
|
50
|
+
variable can hold a port number but cannot create the allocation.
|
|
51
|
+
|
|
52
|
+
Give the server at least 2-4 GB of disk for the Brickadia install, plus room
|
|
53
|
+
for worlds and plugins. The node has to be declared large enough in the panel
|
|
54
|
+
too, or the server cannot be placed on it.
|
|
55
|
+
|
|
56
|
+
### The hosting token
|
|
57
|
+
|
|
58
|
+
`BRICKADIA_TOKEN` is required. Generate one at
|
|
59
|
+
<https://brickadia.com/account/tokens> and paste it into **Brickadia hosting
|
|
60
|
+
token** on the Startup tab.
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
Once authentication succeeds the token is stored in the volume
|
|
64
|
+
(`.config/omegga/global_auth_token`), so it survives restarts and reinstalls of
|
|
65
|
+
the container. The egg adds that path to the file denylist to keep it out of
|
|
66
|
+
the file manager.
|
|
67
|
+
|
|
68
|
+
## Variables
|
|
69
|
+
|
|
70
|
+
| Variable | Default | Notes |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `BRICKADIA_TOKEN` | none | Required. Hosting token from brickadia.com/account/tokens |
|
|
73
|
+
| `OMEGGA_PORT` | `8080` | Web UI port; must match a second allocation |
|
|
74
|
+
| `OMEGGA_FLAGS` | empty | Extra flags: `--update`, `--verbose`, `--debug` |
|
|
75
|
+
| `METRICS_ENABLED` | `false` | Prometheus endpoint; needs a third allocation |
|
|
76
|
+
| `METRICS_BIND` | `0.0.0.0` | Must be `0.0.0.0` to be reachable outside the container |
|
|
77
|
+
| `METRICS_PORT` | `9000` | Metrics port |
|
|
78
|
+
| `PUID` | `0` | Do not change; see [Why `PUID=0`](#why-puid0) |
|
|
79
|
+
| `OMEGGA_NONINTERACTIVE` | `true` | Hidden. Refuse auth prompts the console cannot answer |
|
|
80
|
+
| `SKIP_STEAMCMD_PROMPT` | `true` | Hidden. Do not change |
|
|
81
|
+
| `PACKAGE_NOTIFIER` | `false` | Hidden. Omegga comes from the image, not npm |
|
|
82
|
+
| `STEAM_NOTIFIER` | `false` | Hidden |
|
|
83
|
+
|
|
84
|
+
`--update` in `OMEGGA_FLAGS` checks Steam for a Brickadia update on every
|
|
85
|
+
start. It keeps the game current at the cost of not starting at all when Steam
|
|
86
|
+
is unreachable.
|
|
87
|
+
|
|
88
|
+
Debug logging goes through `OMEGGA_FLAGS=--debug`, not the `BRICKADIA_DEBUG`
|
|
89
|
+
environment variable. Omegga treats that variable as set-or-unset, so the
|
|
90
|
+
string `"false"` would enable it, and Pterodactyl materialises every declared
|
|
91
|
+
variable into the environment, with no way to leave one unset.
|
|
92
|
+
|
|
93
|
+
## Ports in the config file
|
|
94
|
+
|
|
95
|
+
The egg drives ports through `BRICKADIA_PORT` and `OMEGGA_PORT` in the
|
|
96
|
+
environment, which override `omegga-config.yml`. It also keeps the two port
|
|
97
|
+
keys in the file itself in sync with the allocations, so the web UI and
|
|
98
|
+
`omegga info` report the ports the server is really on.
|
|
99
|
+
|
|
100
|
+
Everything else in `omegga-config.yml` is yours: edit it from the file manager
|
|
101
|
+
or the web UI. The egg only touches `server.port` and `omegga.port`.
|
|
102
|
+
|
|
103
|
+
## Web UI over HTTPS
|
|
104
|
+
|
|
105
|
+
Omegga's web UI defaults to `https` with a self-signed certificate, so browsers
|
|
106
|
+
warn on first visit. To use a real certificate, put a reverse proxy in front of
|
|
107
|
+
the allocation and see [HTTPS with a real certificate](https.md).
|
|
108
|
+
|
|
109
|
+
## Stopping
|
|
110
|
+
|
|
111
|
+
The egg stops the server by sending `SIGINT` (`^C`), which Omegga handles
|
|
112
|
+
gracefully. Its startup is considered complete when it logs
|
|
113
|
+
`Server has started`.
|
|
114
|
+
|
|
115
|
+
## Limitations
|
|
116
|
+
|
|
117
|
+
- The published image is **amd64 only**. Omegga will not run on ARM nodes.
|
|
118
|
+
- SFTP reaches the server volume, but the Brickadia install lives in `$HOME`
|
|
119
|
+
inside the same volume and is large; avoid syncing it wholesale.
|
|
120
|
+
- The first start downloads Brickadia before the server becomes usable. The
|
|
121
|
+
console shows steamcmd progress during this; it is not stuck.
|
|
122
|
+
|
|
123
|
+
## Why `PUID=0`
|
|
124
|
+
|
|
125
|
+
Wings runs an egg's install script as the install image's **own default user**,
|
|
126
|
+
and mounts the script from a root-owned `0700` directory. The Omegga image's
|
|
127
|
+
entrypoint drops privileges to its unprivileged `steam` user, which then cannot
|
|
128
|
+
read the script:
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
bash: /mnt/install/install.sh: Permission denied
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`PUID=0` tells the entrypoint not to drop, which is the documented way to keep
|
|
135
|
+
it as root (see [Containers](../containers.md#file-ownership)).
|
|
136
|
+
|
|
137
|
+
It has no effect on the server container. Wings sets the container user
|
|
138
|
+
explicitly there, so the entrypoint sees a non-root uid and execs straight
|
|
139
|
+
through without reading `PUID` at all. Wings also chowns the server volume to
|
|
140
|
+
that user on start, so the root-owned files the install script leaves behind
|
|
141
|
+
are corrected before Omegga ever runs.
|
|
142
|
+
|
|
143
|
+
The entrypoint's Pterodactyl branch deliberately does not apply here: install
|
|
144
|
+
scripts arrive as an explicit `bash /mnt/install/install.sh` with `STARTUP` set
|
|
145
|
+
as well, and have to run as given rather than being replaced by the startup
|
|
146
|
+
command.
|