Harden deploy token and config handling

This commit is contained in:
MiTHRAL 2026-05-13 22:13:26 -04:00
parent c415e82500
commit 991ccdbbb1
2 changed files with 24 additions and 0 deletions

View file

@ -42,6 +42,8 @@ Edit `.env` and set:
- `DASHBOARD_USERNAME`
- `DASHBOARD_PASSWORD_HASH`
Use the raw Discord bot token value. Do not include a `Bot ` prefix.
Generate the dashboard password hash:
```sh
@ -95,9 +97,21 @@ Sign in with `DASHBOARD_USERNAME` and the password you used when generating `DAS
```sh
cp .env.deploy.example .env
cp services.example.json services.json
python3 status_bot.py --hash-password
docker compose up -d --build
```
Paste the generated password hash into `.env` before starting the container.
Make sure Docker can read the service config and write runtime state:
```sh
chmod 600 .env
chmod 644 services.json
mkdir -p state
chmod 755 state
```
The bot stores the Discord message ID in `state/status-message.json`. Keep that file mounted so the bot edits the same message after restarts.
The deploy compose joins your existing reverse-proxy network:

View file

@ -167,6 +167,13 @@ def env(name: str, default: str | None = None) -> str:
return value.strip()
def normalize_discord_token(token: str) -> str:
cleaned = token.strip().strip("\"'")
if cleaned.lower().startswith("bot "):
cleaned = cleaned[4:].strip()
return cleaned
def load_dotenv(path: Path = Path(".env")) -> None:
if not path.exists():
return
@ -189,6 +196,8 @@ def load_json(path: Path) -> dict[str, Any]:
data = json.load(handle)
except FileNotFoundError as exc:
raise ValueError(f"Config file not found: {path}") from exc
except PermissionError as exc:
raise ValueError(f"Config file is not readable: {path}") from exc
except json.JSONDecodeError as exc:
raise ValueError(f"Invalid JSON in {path}: {exc}") from exc
@ -876,6 +885,7 @@ def main() -> int:
return 0
token = env("DISCORD_BOT_TOKEN")
token = normalize_discord_token(token)
channel_id = env("DISCORD_CHANNEL_ID")
config_path = Path(env("ARCHIVE_STATUS_CONFIG", "services.json"))
state_path = Path(env("ARCHIVE_STATUS_STATE", "state/status-message.json"))