Skip to content
Draft

V2 #3

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}
88 changes: 85 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,90 @@
# Watchman

Our internal project for managing docker containers via Discord.
Our internal project for managing compose stacks via Discord slash commands.

For the config, just check out `_config.json`! It's quite self-documenting and includes two example bots.
## Root Configuration (`config.json`)

If you use the containerized version, make sure to mount `/var/run/docker.sock`!
To enable Keycloak SSO RBAC, add the following parameters to your root `config.json`:

```json
{
"token": "YOUR_DISCORD_BOT_TOKEN",
"botGroupId": "YOUR_DISCORD_GUILD_ID",
"services": {
"main-bot": {
"root": "/etc/buildtheearth/main-bot"
}
},
"roles": [],
"users": [],

"keycloak_enabled": true,
"keycloak_server_url": "https://sso.example.com",
"keycloak_realm": "staff",
"keycloak_client_id": "watchman",
"keycloak_client_secret": "YOUR_KEYCLOAK_CLIENT_SECRET",
"keycloak_idp_alias": "discord",
"keycloak_root_role": "watchman-user",
"keycloak_admin_role": "watchman-admin"
}
```

---

## Service Configs (`watchman.json`)

Each service root folder must contain a `watchman.json` and a `compose.yml` (or `docker-compose.yml`) file.

### Permissions Syntax

Permissions must be defined under the nested `"permissions"` key. You can also specify `status_commands_require_access` to control visibility on a per-service level:

```json
{
"name": "main-bot",
"icon": "https://example.com/icon.png",
"permissions": {
"roles": ["main-bot-operator", "sso-role-name"],
"users": ["123456789012345678"],
"status_commands_require_access": false
},
"hooks": {
"pre_up": "infisical run -- docker compose config > /dev/null",
"pre_update": "infisical run -- env | head -n 1",
"strict": true
},
"compose_commands": {
"up": "infisical run -- docker compose up -d",
"pull": "infisical run -- docker compose pull"
}
}
```

- **`permissions.roles`** (`list`): Keycloak realm or client roles that grant mutation access (start, stop, restart, update) for this service.
- **`permissions.users`** (`list`): Discord user IDs for local bypass or fallback access.
- **`permissions.status_commands_require_access`** (`bool`):
- If `true`, only users with the mutation role (or admins) can check this service's status or see it listed.
- If `false` (default), anyone with the Keycloak `root_role` can see the service in `/wm status` and `/wm service list` as read-only. Read-only services are decorated with a `🔒` emoji, while write-accessible services are decorated with a `🔓` emoji.

---

## Slash Commands

- `/wm help`: Displays the help menu.
- `/wm status [service]`: Check the status of all stacks or filter by a specific service.
- `/wm start <service>`: Start a compose stack.
- `/wm stop <service>`: Stop a compose stack.
- `/wm restart <service>`: Restart a compose stack.
- `/wm update <service>`: Pull images and update a stack.
- `/wm service list`: List registered services and roots.
- `/wm service validate <service>`: Check validation of `watchman.json` and compose file.
- `/wm service add <root>`: Add a service (Admins only).
- `/wm service remove <service>`: Remove a service (Admins only).
- `/wm debug`: Prints diagnostic info showing your Keycloak identity, roles, gateway permissions, and service-by-service access breakdown.

---

## Notes

- Mount `/var/run/docker.sock` if running Watchman containerized.
- Watchman tries `docker compose` first, then falls back to `docker-compose`.
38 changes: 12 additions & 26 deletions _config.json
Original file line number Diff line number Diff line change
@@ -1,39 +1,25 @@
{
"prefix": "=wm ",
"token": "",
"botGroupId": "",
"bots": {
"services": {
"main-bot": {
"icon": "",
"image": "buildtheearth/main-bot",
"network": "bot-network",
"volumes": {
"/etc/buildtheearth/main-bot/config/config.json5": "/etc/buildtheearth/main-bot/config/config.json5"
},
"ports": {
},
"restart_policy": "unless-stopped"
"root": "/etc/buildtheearth/main-bot"
},
"support-bot": {
"icon": "",
"image": "buildtheearth/support-bot",
"network": "bot-network",
"volumes": {
"/etc/buildtheearth/support-bot/config.ini": "/etc/buildtheearth/support-bot/config.ini"
},
"ports": {
"8890/tcp": "8890/tcp"
},
"restart_policy": "unless-stopped"
"root": "/etc/buildtheearth/support-bot"
}
},
"roles": [
"id1",
"id2"
],
"users": [
"user1id",
"user2id"
],
"error_channel": "watchman_log"
"keycloak_enabled": false,
"keycloak_server_url": "https://sso.example.com",
"keycloak_realm": "staff",
"keycloak_client_id": "watchman",
"keycloak_client_secret": "client-secret-here",
"keycloak_idp_alias": "discord",
"keycloak_root_role": "watchman-user",
"keycloak_admin_role": "watchman-admin",
"status_commands_require_access": false
}
Loading