deploy: support runtime env files
This commit is contained in:
@@ -12,6 +12,7 @@ python3 deploy/systemd/install_systemd.py \
|
|||||||
--user mt2.jakubkadlec.dev \
|
--user mt2.jakubkadlec.dev \
|
||||||
--group mt2.jakubkadlec.dev \
|
--group mt2.jakubkadlec.dev \
|
||||||
--runtime-root /home/mt2.jakubkadlec.dev/metin/runtime/server \
|
--runtime-root /home/mt2.jakubkadlec.dev/metin/runtime/server \
|
||||||
|
--env-file /etc/metin/metin.env \
|
||||||
--channel 1 \
|
--channel 1 \
|
||||||
--channel 99 \
|
--channel 99 \
|
||||||
--restart
|
--restart
|
||||||
@@ -30,3 +31,14 @@ python3 deploy/systemd/install_systemd.py \
|
|||||||
- `/usr/local/libexec/metin-wait-port`
|
- `/usr/local/libexec/metin-wait-port`
|
||||||
|
|
||||||
The `metin-db-ready.service` gate waits until the DB socket is actually accepting connections before `auth` and `game` units start.
|
The `metin-db-ready.service` gate waits until the DB socket is actually accepting connections before `auth` and `game` units start.
|
||||||
|
|
||||||
|
## Optional Environment File
|
||||||
|
|
||||||
|
The runtime units support an optional `EnvironmentFile` for host-local overrides:
|
||||||
|
|
||||||
|
- default path: `/etc/metin/metin.env`
|
||||||
|
- it is loaded with `EnvironmentFile=-...`, so the file may be absent
|
||||||
|
- recommended ownership: `root:root`
|
||||||
|
- recommended mode: `0600`
|
||||||
|
|
||||||
|
This is the preferred place for production-only values such as DB credentials and the admin page password.
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ def parse_args() -> argparse.Namespace:
|
|||||||
parser.add_argument("--runtime-root", required=True, help="Absolute path to the live runtime root")
|
parser.add_argument("--runtime-root", required=True, help="Absolute path to the live runtime root")
|
||||||
parser.add_argument("--systemd-dir", default="/etc/systemd/system", help="systemd unit destination")
|
parser.add_argument("--systemd-dir", default="/etc/systemd/system", help="systemd unit destination")
|
||||||
parser.add_argument("--libexec-dir", default="/usr/local/libexec", help="Helper script destination")
|
parser.add_argument("--libexec-dir", default="/usr/local/libexec", help="Helper script destination")
|
||||||
|
parser.add_argument("--env-file", default="/etc/metin/metin.env", help="Optional EnvironmentFile path for runtime overrides")
|
||||||
parser.add_argument("--wait-host", default="127.0.0.1", help="DB readiness host")
|
parser.add_argument("--wait-host", default="127.0.0.1", help="DB readiness host")
|
||||||
parser.add_argument("--wait-port", type=int, default=9000, help="DB readiness port")
|
parser.add_argument("--wait-port", type=int, default=9000, help="DB readiness port")
|
||||||
parser.add_argument("--wait-timeout", type=int, default=30, help="DB readiness timeout in seconds")
|
parser.add_argument("--wait-timeout", type=int, default=30, help="DB readiness timeout in seconds")
|
||||||
@@ -118,6 +119,7 @@ def main() -> int:
|
|||||||
"USER_NAME": args.user,
|
"USER_NAME": args.user,
|
||||||
"GROUP_NAME": group_name,
|
"GROUP_NAME": group_name,
|
||||||
"RUNTIME_ROOT": runtime_root,
|
"RUNTIME_ROOT": runtime_root,
|
||||||
|
"ENV_FILE": args.env_file,
|
||||||
"WAIT_HOST": args.wait_host,
|
"WAIT_HOST": args.wait_host,
|
||||||
"WAIT_PORT": str(args.wait_port),
|
"WAIT_PORT": str(args.wait_port),
|
||||||
"WAIT_TIMEOUT": str(args.wait_timeout),
|
"WAIT_TIMEOUT": str(args.wait_timeout),
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Before=metin-server.service
|
|||||||
Type=simple
|
Type=simple
|
||||||
User={{USER_NAME}}
|
User={{USER_NAME}}
|
||||||
Group={{GROUP_NAME}}
|
Group={{GROUP_NAME}}
|
||||||
|
EnvironmentFile=-{{ENV_FILE}}
|
||||||
WorkingDirectory={{RUNTIME_ROOT}}/channels/auth
|
WorkingDirectory={{RUNTIME_ROOT}}/channels/auth
|
||||||
ExecStart={{RUNTIME_ROOT}}/channels/auth/game_auth
|
ExecStart={{RUNTIME_ROOT}}/channels/auth/game_auth
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Before=metin-server.service
|
|||||||
Type=simple
|
Type=simple
|
||||||
User={{USER_NAME}}
|
User={{USER_NAME}}
|
||||||
Group={{GROUP_NAME}}
|
Group={{GROUP_NAME}}
|
||||||
|
EnvironmentFile=-{{ENV_FILE}}
|
||||||
WorkingDirectory={{RUNTIME_ROOT}}/channels/db
|
WorkingDirectory={{RUNTIME_ROOT}}/channels/db
|
||||||
ExecStart={{RUNTIME_ROOT}}/channels/db/db
|
ExecStart={{RUNTIME_ROOT}}/channels/db/db
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ Before=metin-server.service
|
|||||||
Type=simple
|
Type=simple
|
||||||
User={{USER_NAME}}
|
User={{USER_NAME}}
|
||||||
Group={{GROUP_NAME}}
|
Group={{GROUP_NAME}}
|
||||||
|
EnvironmentFile=-{{ENV_FILE}}
|
||||||
WorkingDirectory={{RUNTIME_ROOT}}
|
WorkingDirectory={{RUNTIME_ROOT}}
|
||||||
ExecStart=/usr/local/libexec/metin-game-instance-start %i
|
ExecStart=/usr/local/libexec/metin-game-instance-start %i
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ For the current Debian VPS:
|
|||||||
- root-only operational wrappers may inject short-lived values locally
|
- root-only operational wrappers may inject short-lived values locally
|
||||||
- headless login healthcheck uses a temporary password via environment, not a command-line literal
|
- headless login healthcheck uses a temporary password via environment, not a command-line literal
|
||||||
- the installed wrapper is root-only and not network-facing
|
- the installed wrapper is root-only and not network-facing
|
||||||
|
- `systemd` units may load a host-local env file from `/etc/metin/metin.env`
|
||||||
|
|
||||||
## Admin Page Password
|
## Admin Page Password
|
||||||
|
|
||||||
@@ -54,3 +55,83 @@ The Debian deployment should eventually move to a clearer contract such as:
|
|||||||
- documented override points
|
- documented override points
|
||||||
|
|
||||||
Until that is done, keep all real secret rotation and secret overrides on the host, not in commits.
|
Until that is done, keep all real secret rotation and secret overrides on the host, not in commits.
|
||||||
|
|
||||||
|
## Environment Override Contract
|
||||||
|
|
||||||
|
The source/runtime stack now supports these host-local environment overrides:
|
||||||
|
|
||||||
|
- `METIN2_ADMINPAGE_PASSWORD`
|
||||||
|
- `METIN2_DB_ADDR`
|
||||||
|
- `METIN2_DB_PORT`
|
||||||
|
- `METIN2_ACCOUNT_SQL_HOST`
|
||||||
|
- `METIN2_ACCOUNT_SQL_USER`
|
||||||
|
- `METIN2_ACCOUNT_SQL_PASSWORD`
|
||||||
|
- `METIN2_ACCOUNT_SQL_DB`
|
||||||
|
- `METIN2_ACCOUNT_SQL_PORT`
|
||||||
|
- `METIN2_PLAYER_SQL_HOST`
|
||||||
|
- `METIN2_PLAYER_SQL_USER`
|
||||||
|
- `METIN2_PLAYER_SQL_PASSWORD`
|
||||||
|
- `METIN2_PLAYER_SQL_DB`
|
||||||
|
- `METIN2_PLAYER_SQL_PORT`
|
||||||
|
- `METIN2_COMMON_SQL_HOST`
|
||||||
|
- `METIN2_COMMON_SQL_USER`
|
||||||
|
- `METIN2_COMMON_SQL_PASSWORD`
|
||||||
|
- `METIN2_COMMON_SQL_DB`
|
||||||
|
- `METIN2_COMMON_SQL_PORT`
|
||||||
|
- `METIN2_LOG_SQL_HOST`
|
||||||
|
- `METIN2_LOG_SQL_USER`
|
||||||
|
- `METIN2_LOG_SQL_PASSWORD`
|
||||||
|
- `METIN2_LOG_SQL_DB`
|
||||||
|
- `METIN2_LOG_SQL_PORT`
|
||||||
|
- `METIN2_HOTBACKUP_SQL_HOST`
|
||||||
|
- `METIN2_HOTBACKUP_SQL_USER`
|
||||||
|
- `METIN2_HOTBACKUP_SQL_PASSWORD`
|
||||||
|
- `METIN2_HOTBACKUP_SQL_DB`
|
||||||
|
- `METIN2_HOTBACKUP_SQL_PORT`
|
||||||
|
|
||||||
|
`game_auth` and `game` consume the `ACCOUNT/PLAYER/COMMON/LOG` variants. The `db` process consumes `ACCOUNT/PLAYER/COMMON/HOTBACKUP`.
|
||||||
|
|
||||||
|
Recommended deployment model:
|
||||||
|
|
||||||
|
- keep git-tracked `share/conf/*.txt` as bootstrap defaults only
|
||||||
|
- install `/etc/metin/metin.env` as `root:root` with mode `0600`
|
||||||
|
- point systemd at that env file via `deploy/systemd/install_systemd.py --env-file /etc/metin/metin.env`
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkdir -p /etc/metin
|
||||||
|
chmod 700 /etc/metin
|
||||||
|
cat >/etc/metin/metin.env <<'EOF'
|
||||||
|
METIN2_ADMINPAGE_PASSWORD=replace-me
|
||||||
|
METIN2_DB_ADDR=127.0.0.1
|
||||||
|
METIN2_DB_PORT=9000
|
||||||
|
METIN2_ACCOUNT_SQL_HOST=127.0.0.1
|
||||||
|
METIN2_ACCOUNT_SQL_USER=mt2
|
||||||
|
METIN2_ACCOUNT_SQL_PASSWORD=replace-me
|
||||||
|
METIN2_ACCOUNT_SQL_DB=account
|
||||||
|
METIN2_ACCOUNT_SQL_PORT=0
|
||||||
|
METIN2_PLAYER_SQL_HOST=127.0.0.1
|
||||||
|
METIN2_PLAYER_SQL_USER=mt2
|
||||||
|
METIN2_PLAYER_SQL_PASSWORD=replace-me
|
||||||
|
METIN2_PLAYER_SQL_DB=player
|
||||||
|
METIN2_PLAYER_SQL_PORT=0
|
||||||
|
METIN2_COMMON_SQL_HOST=127.0.0.1
|
||||||
|
METIN2_COMMON_SQL_USER=mt2
|
||||||
|
METIN2_COMMON_SQL_PASSWORD=replace-me
|
||||||
|
METIN2_COMMON_SQL_DB=common
|
||||||
|
METIN2_COMMON_SQL_PORT=0
|
||||||
|
METIN2_LOG_SQL_HOST=127.0.0.1
|
||||||
|
METIN2_LOG_SQL_USER=mt2
|
||||||
|
METIN2_LOG_SQL_PASSWORD=replace-me
|
||||||
|
METIN2_LOG_SQL_DB=log
|
||||||
|
METIN2_LOG_SQL_PORT=0
|
||||||
|
METIN2_HOTBACKUP_SQL_HOST=127.0.0.1
|
||||||
|
METIN2_HOTBACKUP_SQL_USER=mt2
|
||||||
|
METIN2_HOTBACKUP_SQL_PASSWORD=replace-me
|
||||||
|
METIN2_HOTBACKUP_SQL_DB=hotbackup
|
||||||
|
METIN2_HOTBACKUP_SQL_PORT=0
|
||||||
|
EOF
|
||||||
|
chown root:root /etc/metin/metin.env
|
||||||
|
chmod 600 /etc/metin/metin.env
|
||||||
|
```
|
||||||
|
|||||||
@@ -94,6 +94,19 @@ systemctl restart metin-server
|
|||||||
journalctl -u metin-auth.service -n 100 --no-pager
|
journalctl -u metin-auth.service -n 100 --no-pager
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install or refresh the systemd stack with a host-local env file:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 deploy/systemd/install_systemd.py \
|
||||||
|
--user mt2.jakubkadlec.dev \
|
||||||
|
--group mt2.jakubkadlec.dev \
|
||||||
|
--runtime-root /home/mt2.jakubkadlec.dev/metin/runtime/server \
|
||||||
|
--env-file /etc/metin/metin.env \
|
||||||
|
--channel 1 \
|
||||||
|
--channel 99 \
|
||||||
|
--restart
|
||||||
|
```
|
||||||
|
|
||||||
Rebuild the login smoke utility:
|
Rebuild the login smoke utility:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -109,6 +122,8 @@ Current operational stance:
|
|||||||
- password SSH login is disabled
|
- password SSH login is disabled
|
||||||
- `root` login is allowed only by SSH key
|
- `root` login is allowed only by SSH key
|
||||||
- production helper scripts that touch the DB directly are root-only
|
- production helper scripts that touch the DB directly are root-only
|
||||||
- runtime repo and source repo do not store secrets
|
- git-tracked runtime configs are treated as bootstrap defaults, not as the final secret source of truth
|
||||||
|
|
||||||
Do not store production secrets in markdown, `systemd` templates, or git-tracked shell scripts.
|
Do not store production secrets in markdown, `systemd` templates, or git-tracked shell scripts.
|
||||||
|
|
||||||
|
For production overrides, prefer `/etc/metin/metin.env` with `root:root` ownership and mode `0600`.
|
||||||
|
|||||||
Reference in New Issue
Block a user