ScuttleBot

security: loopback defaults, require_sasl, default_channel_modes API and MCP servers now bind to 127.0.0.1 by default (were :8080/:8081). Container deployments set SCUTTLEBOT_API_ADDR=:8080 via Dockerfile ENV. Docker Compose and K8s already had explicit overrides — unaffected. New Ergo config options surfaced in ircdconfig.go template: - ergo.require_sasl: reject unauthenticated IRC connections at connect time - ergo.default_channel_modes: channel modes on creation (default +n, set +Rn to restrict joins to registered nicks) Also fixes carried forward from docs accuracy pass: - relays.md: Codex install section had copy-paste error (claude paths) - config docs: warden fields corrected, datastore section reflects implementation - deployment.md: production example includes require_sasl and +Rn modes

lmata 2026-04-03 01:35 trunk
Commit c669cc37ee4a8f5e69ca628ac3ef342c1f1677ffd624d88a786243b4493ecd59
--- deploy/docker/Dockerfile
+++ deploy/docker/Dockerfile
@@ -16,8 +16,14 @@
1616
1717
RUN apk add --no-cache ca-certificates tzdata
1818
1919
COPY --from=builder /scuttlebot /usr/local/bin/scuttlebot
2020
21
+# In a container, bind to all interfaces so port mapping works.
22
+# Override with SCUTTLEBOT_API_ADDR / SCUTTLEBOT_MCP_ADDR if needed.
23
+ENV SCUTTLEBOT_API_ADDR=:8080
24
+ENV SCUTTLEBOT_MCP_ADDR=:8081
25
+
2126
EXPOSE 8080
27
+EXPOSE 8081
2228
2329
ENTRYPOINT ["scuttlebot"]
2430
--- deploy/docker/Dockerfile
+++ deploy/docker/Dockerfile
@@ -16,8 +16,14 @@
16
17 RUN apk add --no-cache ca-certificates tzdata
18
19 COPY --from=builder /scuttlebot /usr/local/bin/scuttlebot
20
 
 
 
 
 
21 EXPOSE 8080
 
22
23 ENTRYPOINT ["scuttlebot"]
24
--- deploy/docker/Dockerfile
+++ deploy/docker/Dockerfile
@@ -16,8 +16,14 @@
16
17 RUN apk add --no-cache ca-certificates tzdata
18
19 COPY --from=builder /scuttlebot /usr/local/bin/scuttlebot
20
21 # In a container, bind to all interfaces so port mapping works.
22 # Override with SCUTTLEBOT_API_ADDR / SCUTTLEBOT_MCP_ADDR if needed.
23 ENV SCUTTLEBOT_API_ADDR=:8080
24 ENV SCUTTLEBOT_MCP_ADDR=:8081
25
26 EXPOSE 8080
27 EXPOSE 8081
28
29 ENTRYPOINT ["scuttlebot"]
30
--- deploy/standalone/scuttlebot.yaml.example
+++ deploy/standalone/scuttlebot.yaml.example
@@ -4,19 +4,25 @@
44
ergo:
55
# binary_path: ergo # path to ergo binary; auto-downloaded if not found
66
# data_dir: ./data/ergo # where ergo stores ircd.db and generated config
77
# network_name: scuttlebot # IRC network name
88
# server_name: irc.scuttlebot.local
9
- # irc_addr: 127.0.0.1:6667 # IRC listen address
10
- # api_addr: 127.0.0.1:8089 # ergo HTTP API address
9
+ # irc_addr: 127.0.0.1:6667 # IRC listen address (set to :6667 to accept external connections)
10
+ # api_addr: 127.0.0.1:8089 # ergo HTTP API — keep on loopback
1111
# api_token: "" # auto-generated if blank
12
+
13
+ # Security for public deployments:
14
+ # require_sasl: true # reject IRC connections that don't authenticate
15
+ # default_channel_modes: "+Rn" # restrict channel joins to registered nicks
16
+
1217
history:
1318
# enabled: false
1419
# postgres_dsn: postgres://user:pass@localhost/scuttlebot?sslmode=disable
1520
1621
datastore:
1722
# driver: sqlite # "sqlite" or "postgres"
1823
# dsn: ./data/scuttlebot.db
1924
20
-# api_addr: :8080 # scuttlebot REST API listen address
25
+# api_addr: 127.0.0.1:8080 # bind to loopback; use a reverse proxy for external access
26
+# mcp_addr: 127.0.0.1:8081
2127
2228
# topology: (see scuttlebot.yaml for full annotated example)
2329
--- deploy/standalone/scuttlebot.yaml.example
+++ deploy/standalone/scuttlebot.yaml.example
@@ -4,19 +4,25 @@
4 ergo:
5 # binary_path: ergo # path to ergo binary; auto-downloaded if not found
6 # data_dir: ./data/ergo # where ergo stores ircd.db and generated config
7 # network_name: scuttlebot # IRC network name
8 # server_name: irc.scuttlebot.local
9 # irc_addr: 127.0.0.1:6667 # IRC listen address
10 # api_addr: 127.0.0.1:8089 # ergo HTTP API address
11 # api_token: "" # auto-generated if blank
 
 
 
 
 
12 history:
13 # enabled: false
14 # postgres_dsn: postgres://user:pass@localhost/scuttlebot?sslmode=disable
15
16 datastore:
17 # driver: sqlite # "sqlite" or "postgres"
18 # dsn: ./data/scuttlebot.db
19
20 # api_addr: :8080 # scuttlebot REST API listen address
 
21
22 # topology: (see scuttlebot.yaml for full annotated example)
23
--- deploy/standalone/scuttlebot.yaml.example
+++ deploy/standalone/scuttlebot.yaml.example
@@ -4,19 +4,25 @@
4 ergo:
5 # binary_path: ergo # path to ergo binary; auto-downloaded if not found
6 # data_dir: ./data/ergo # where ergo stores ircd.db and generated config
7 # network_name: scuttlebot # IRC network name
8 # server_name: irc.scuttlebot.local
9 # irc_addr: 127.0.0.1:6667 # IRC listen address (set to :6667 to accept external connections)
10 # api_addr: 127.0.0.1:8089 # ergo HTTP API — keep on loopback
11 # api_token: "" # auto-generated if blank
12
13 # Security for public deployments:
14 # require_sasl: true # reject IRC connections that don't authenticate
15 # default_channel_modes: "+Rn" # restrict channel joins to registered nicks
16
17 history:
18 # enabled: false
19 # postgres_dsn: postgres://user:pass@localhost/scuttlebot?sslmode=disable
20
21 datastore:
22 # driver: sqlite # "sqlite" or "postgres"
23 # dsn: ./data/scuttlebot.db
24
25 # api_addr: 127.0.0.1:8080 # bind to loopback; use a reverse proxy for external access
26 # mcp_addr: 127.0.0.1:8081
27
28 # topology: (see scuttlebot.yaml for full annotated example)
29
--- docs/architecture/overview.md
+++ docs/architecture/overview.md
@@ -80,11 +80,11 @@
8080
8181
1. Reads `scuttlebot.yaml` (all fields optional; defaults apply)
8282
2. Downloads an Ergo binary if one is not present
8383
3. Writes Ergo's `ircd.yaml` from scuttlebot's config
8484
4. Starts Ergo as a subprocess and monitors it
85
-5. Starts the HTTP API on `:8080`
85
+5. Starts the HTTP API on `127.0.0.1:8080`
8686
6. Starts enabled system bots via the bot manager
8787
7. Prints the API token to stderr (stable across restarts once written to disk)
8888
8989
### Ergo IRC server (`internal/ergo/`)
9090
9191
--- docs/architecture/overview.md
+++ docs/architecture/overview.md
@@ -80,11 +80,11 @@
80
81 1. Reads `scuttlebot.yaml` (all fields optional; defaults apply)
82 2. Downloads an Ergo binary if one is not present
83 3. Writes Ergo's `ircd.yaml` from scuttlebot's config
84 4. Starts Ergo as a subprocess and monitors it
85 5. Starts the HTTP API on `:8080`
86 6. Starts enabled system bots via the bot manager
87 7. Prints the API token to stderr (stable across restarts once written to disk)
88
89 ### Ergo IRC server (`internal/ergo/`)
90
91
--- docs/architecture/overview.md
+++ docs/architecture/overview.md
@@ -80,11 +80,11 @@
80
81 1. Reads `scuttlebot.yaml` (all fields optional; defaults apply)
82 2. Downloads an Ergo binary if one is not present
83 3. Writes Ergo's `ircd.yaml` from scuttlebot's config
84 4. Starts Ergo as a subprocess and monitors it
85 5. Starts the HTTP API on `127.0.0.1:8080`
86 6. Starts enabled system bots via the bot manager
87 7. Prints the API token to stderr (stable across restarts once written to disk)
88
89 ### Ergo IRC server (`internal/ergo/`)
90
91
--- docs/getting-started/configuration.md
+++ docs/getting-started/configuration.md
@@ -32,12 +32,12 @@
3232
3333
## Top-level fields
3434
3535
| Field | Type | Default | Description |
3636
|-------|------|---------|-------------|
37
-| `api_addr` | string | `:8080` | Listen address for scuttlebot's HTTP API and web UI. Overridden by `SCUTTLEBOT_API_ADDR`. When `tls.domain` is set this is ignored — HTTPS runs on `:443` and HTTP on `:80`. |
38
-| `mcp_addr` | string | `:8081` | Listen address for the MCP server. Overridden by `SCUTTLEBOT_MCP_ADDR`. |
37
+| `api_addr` | string | `127.0.0.1:8080` | Listen address for scuttlebot's HTTP API and web UI. Binds to loopback by default — use a reverse proxy (nginx, Caddy) to expose publicly. Overridden by `SCUTTLEBOT_API_ADDR`. When `tls.domain` is set this is ignored — HTTPS runs on `:443` and HTTP on `:80`. |
38
+| `mcp_addr` | string | `127.0.0.1:8081` | Listen address for the MCP server. Binds to loopback by default. Overridden by `SCUTTLEBOT_MCP_ADDR`. |
3939
4040
---
4141
4242
## `ergo`
4343
@@ -66,10 +66,12 @@
6666
| `network_name` | string | `scuttlebot` | Human-readable IRC network name displayed in clients. Overridden by `SCUTTLEBOT_ERGO_NETWORK_NAME`. |
6767
| `server_name` | string | `irc.scuttlebot.local` | IRC server hostname (shown in `/whois` etc). Overridden by `SCUTTLEBOT_ERGO_SERVER_NAME`. |
6868
| `irc_addr` | string | `127.0.0.1:6667` | Address ergo listens for IRC connections. Loopback by default — agents connect here. Overridden by `SCUTTLEBOT_ERGO_IRC_ADDR`. |
6969
| `api_addr` | string | `127.0.0.1:8089` | Address of ergo's HTTP management API. loopback only by default. Overridden by `SCUTTLEBOT_ERGO_API_ADDR`. |
7070
| `api_token` | string | *(auto-generated)* | Bearer token for ergo's HTTP API. scuttlebot generates this on first start and stores it in `data/ergo/api_token`. Overridden by `SCUTTLEBOT_ERGO_API_TOKEN`. |
71
+| `require_sasl` | bool | `false` | Require SASL authentication for all IRC connections. When `true`, only accounts registered through scuttlebot can connect — unregistered clients are rejected at connection time. Recommended for public deployments. |
72
+| `default_channel_modes` | string | `+n` | Channel modes applied when a new channel is created. `+n` prevents external messages. Set to `+Rn` to additionally require a registered NickServ account to join. |
7173
7274
### `ergo.history`
7375
7476
Persistent message history is stored by ergo (separate from scribe's structured log).
7577
@@ -85,22 +87,24 @@
8587
8688
---
8789
8890
## `datastore`
8991
90
-scuttlebot's own state database — stores agent registry, admin accounts, and audit log. Separate from ergo's `ircd.db`.
92
+scuttlebot's own persistent state store — agent registry, admin accounts, and policies. When configured, this supersedes the default JSON file storage in `data/`.
9193
9294
```yaml
9395
datastore:
9496
driver: sqlite
9597
dsn: ./data/scuttlebot.db
9698
```
9799
98100
| Field | Type | Default | Description |
99101
|-------|------|---------|-------------|
100
-| `driver` | string | `sqlite` | `"sqlite"` or `"postgres"`. Overridden by `SCUTTLEBOT_DB_DRIVER`. |
102
+| `driver` | string | — | `"sqlite"` or `"postgres"`. Leave empty to use JSON files (default). Overridden by `SCUTTLEBOT_DB_DRIVER`. |
101103
| `dsn` | string | `./data/scuttlebot.db` | Data source name. For SQLite: path to the `.db` file. For PostgreSQL: a standard `postgres://` connection string. Overridden by `SCUTTLEBOT_DB_DSN`. |
104
+
105
+When `driver` is unset (the default), state is stored as JSON files (`registry.json`, `admins.json`, `policies.json`) in the Ergo data directory. JSON file storage requires no additional configuration and is suitable for most deployments. Configure `datastore` when you need SQL-level access, multi-instance deployments sharing a database, or PostgreSQL for larger fleets.
102106
103107
---
104108
105109
## `bridge`
106110
@@ -145,11 +149,11 @@
145149
| `email` | string | — | Email address for Let's Encrypt expiry notifications. |
146150
| `cert_dir` | string | `{ergo.data_dir}/certs` | Directory to cache the certificate. |
147151
| `allow_insecure` | bool | `true` | Keep HTTP running on `:80` alongside HTTPS. The ACME HTTP-01 challenge always runs on `:80` regardless of this setting. |
148152
149153
!!! note "Local dev"
150
- Leave `tls.domain` empty for local development. The HTTP API on `:8080` is used instead.
154
+ Leave `tls.domain` empty for local development. The HTTP API on `127.0.0.1:8080` is used instead.
151155
152156
---
153157
154158
## `llm`
155159
@@ -287,25 +291,29 @@
287291
288292
```yaml
289293
# scuttlebot.yaml
290294
291295
# HTTP API and web UI
292
-api_addr: :8080
296
+api_addr: 127.0.0.1:8080
293297
294298
# MCP server
295
-mcp_addr: :8081
299
+mcp_addr: 127.0.0.1:8081
296300
297301
ergo:
298302
# Manage ergo as a subprocess (default).
299303
# Set external: true if ergo runs separately (Docker, etc.)
300304
external: false
301305
network_name: myfleet
302306
server_name: irc.myfleet.internal
303
- irc_addr: 127.0.0.1:6667
304
- api_addr: 127.0.0.1:8089
307
+ irc_addr: 127.0.0.1:6667 # set to :6667 or :6697 to expose IRC publicly
308
+ api_addr: 127.0.0.1:8089 # keep on loopback — no auth layer on this port
305309
# api_token is auto-generated on first start
306310
311
+ # Security (recommended for public deployments):
312
+ require_sasl: false # set to true to reject unauthenticated IRC connections
313
+ default_channel_modes: "+n" # set to "+Rn" to restrict joins to registered nicks
314
+
307315
# Optional: persistent IRC history in PostgreSQL
308316
history:
309317
enabled: true
310318
postgres_dsn: postgres://scuttlebot:secret@localhost/scuttlebot?sslmode=disable
311319
312320
--- docs/getting-started/configuration.md
+++ docs/getting-started/configuration.md
@@ -32,12 +32,12 @@
32
33 ## Top-level fields
34
35 | Field | Type | Default | Description |
36 |-------|------|---------|-------------|
37 | `api_addr` | string | `:8080` | Listen address for scuttlebot's HTTP API and web UI. Overridden by `SCUTTLEBOT_API_ADDR`. When `tls.domain` is set this is ignored — HTTPS runs on `:443` and HTTP on `:80`. |
38 | `mcp_addr` | string | `:8081` | Listen address for the MCP server. Overridden by `SCUTTLEBOT_MCP_ADDR`. |
39
40 ---
41
42 ## `ergo`
43
@@ -66,10 +66,12 @@
66 | `network_name` | string | `scuttlebot` | Human-readable IRC network name displayed in clients. Overridden by `SCUTTLEBOT_ERGO_NETWORK_NAME`. |
67 | `server_name` | string | `irc.scuttlebot.local` | IRC server hostname (shown in `/whois` etc). Overridden by `SCUTTLEBOT_ERGO_SERVER_NAME`. |
68 | `irc_addr` | string | `127.0.0.1:6667` | Address ergo listens for IRC connections. Loopback by default — agents connect here. Overridden by `SCUTTLEBOT_ERGO_IRC_ADDR`. |
69 | `api_addr` | string | `127.0.0.1:8089` | Address of ergo's HTTP management API. loopback only by default. Overridden by `SCUTTLEBOT_ERGO_API_ADDR`. |
70 | `api_token` | string | *(auto-generated)* | Bearer token for ergo's HTTP API. scuttlebot generates this on first start and stores it in `data/ergo/api_token`. Overridden by `SCUTTLEBOT_ERGO_API_TOKEN`. |
 
 
71
72 ### `ergo.history`
73
74 Persistent message history is stored by ergo (separate from scribe's structured log).
75
@@ -85,22 +87,24 @@
85
86 ---
87
88 ## `datastore`
89
90 scuttlebot's own state database — stores agent registry, admin accounts, and audit log. Separate from ergo's `ircd.db`.
91
92 ```yaml
93 datastore:
94 driver: sqlite
95 dsn: ./data/scuttlebot.db
96 ```
97
98 | Field | Type | Default | Description |
99 |-------|------|---------|-------------|
100 | `driver` | string | `sqlite` | `"sqlite"` or `"postgres"`. Overridden by `SCUTTLEBOT_DB_DRIVER`. |
101 | `dsn` | string | `./data/scuttlebot.db` | Data source name. For SQLite: path to the `.db` file. For PostgreSQL: a standard `postgres://` connection string. Overridden by `SCUTTLEBOT_DB_DSN`. |
 
 
102
103 ---
104
105 ## `bridge`
106
@@ -145,11 +149,11 @@
145 | `email` | string | — | Email address for Let's Encrypt expiry notifications. |
146 | `cert_dir` | string | `{ergo.data_dir}/certs` | Directory to cache the certificate. |
147 | `allow_insecure` | bool | `true` | Keep HTTP running on `:80` alongside HTTPS. The ACME HTTP-01 challenge always runs on `:80` regardless of this setting. |
148
149 !!! note "Local dev"
150 Leave `tls.domain` empty for local development. The HTTP API on `:8080` is used instead.
151
152 ---
153
154 ## `llm`
155
@@ -287,25 +291,29 @@
287
288 ```yaml
289 # scuttlebot.yaml
290
291 # HTTP API and web UI
292 api_addr: :8080
293
294 # MCP server
295 mcp_addr: :8081
296
297 ergo:
298 # Manage ergo as a subprocess (default).
299 # Set external: true if ergo runs separately (Docker, etc.)
300 external: false
301 network_name: myfleet
302 server_name: irc.myfleet.internal
303 irc_addr: 127.0.0.1:6667
304 api_addr: 127.0.0.1:8089
305 # api_token is auto-generated on first start
306
 
 
 
 
307 # Optional: persistent IRC history in PostgreSQL
308 history:
309 enabled: true
310 postgres_dsn: postgres://scuttlebot:secret@localhost/scuttlebot?sslmode=disable
311
312
--- docs/getting-started/configuration.md
+++ docs/getting-started/configuration.md
@@ -32,12 +32,12 @@
32
33 ## Top-level fields
34
35 | Field | Type | Default | Description |
36 |-------|------|---------|-------------|
37 | `api_addr` | string | `127.0.0.1:8080` | Listen address for scuttlebot's HTTP API and web UI. Binds to loopback by default — use a reverse proxy (nginx, Caddy) to expose publicly. Overridden by `SCUTTLEBOT_API_ADDR`. When `tls.domain` is set this is ignored — HTTPS runs on `:443` and HTTP on `:80`. |
38 | `mcp_addr` | string | `127.0.0.1:8081` | Listen address for the MCP server. Binds to loopback by default. Overridden by `SCUTTLEBOT_MCP_ADDR`. |
39
40 ---
41
42 ## `ergo`
43
@@ -66,10 +66,12 @@
66 | `network_name` | string | `scuttlebot` | Human-readable IRC network name displayed in clients. Overridden by `SCUTTLEBOT_ERGO_NETWORK_NAME`. |
67 | `server_name` | string | `irc.scuttlebot.local` | IRC server hostname (shown in `/whois` etc). Overridden by `SCUTTLEBOT_ERGO_SERVER_NAME`. |
68 | `irc_addr` | string | `127.0.0.1:6667` | Address ergo listens for IRC connections. Loopback by default — agents connect here. Overridden by `SCUTTLEBOT_ERGO_IRC_ADDR`. |
69 | `api_addr` | string | `127.0.0.1:8089` | Address of ergo's HTTP management API. loopback only by default. Overridden by `SCUTTLEBOT_ERGO_API_ADDR`. |
70 | `api_token` | string | *(auto-generated)* | Bearer token for ergo's HTTP API. scuttlebot generates this on first start and stores it in `data/ergo/api_token`. Overridden by `SCUTTLEBOT_ERGO_API_TOKEN`. |
71 | `require_sasl` | bool | `false` | Require SASL authentication for all IRC connections. When `true`, only accounts registered through scuttlebot can connect — unregistered clients are rejected at connection time. Recommended for public deployments. |
72 | `default_channel_modes` | string | `+n` | Channel modes applied when a new channel is created. `+n` prevents external messages. Set to `+Rn` to additionally require a registered NickServ account to join. |
73
74 ### `ergo.history`
75
76 Persistent message history is stored by ergo (separate from scribe's structured log).
77
@@ -85,22 +87,24 @@
87
88 ---
89
90 ## `datastore`
91
92 scuttlebot's own persistent state store — agent registry, admin accounts, and policies. When configured, this supersedes the default JSON file storage in `data/`.
93
94 ```yaml
95 datastore:
96 driver: sqlite
97 dsn: ./data/scuttlebot.db
98 ```
99
100 | Field | Type | Default | Description |
101 |-------|------|---------|-------------|
102 | `driver` | string | — | `"sqlite"` or `"postgres"`. Leave empty to use JSON files (default). Overridden by `SCUTTLEBOT_DB_DRIVER`. |
103 | `dsn` | string | `./data/scuttlebot.db` | Data source name. For SQLite: path to the `.db` file. For PostgreSQL: a standard `postgres://` connection string. Overridden by `SCUTTLEBOT_DB_DSN`. |
104
105 When `driver` is unset (the default), state is stored as JSON files (`registry.json`, `admins.json`, `policies.json`) in the Ergo data directory. JSON file storage requires no additional configuration and is suitable for most deployments. Configure `datastore` when you need SQL-level access, multi-instance deployments sharing a database, or PostgreSQL for larger fleets.
106
107 ---
108
109 ## `bridge`
110
@@ -145,11 +149,11 @@
149 | `email` | string | — | Email address for Let's Encrypt expiry notifications. |
150 | `cert_dir` | string | `{ergo.data_dir}/certs` | Directory to cache the certificate. |
151 | `allow_insecure` | bool | `true` | Keep HTTP running on `:80` alongside HTTPS. The ACME HTTP-01 challenge always runs on `:80` regardless of this setting. |
152
153 !!! note "Local dev"
154 Leave `tls.domain` empty for local development. The HTTP API on `127.0.0.1:8080` is used instead.
155
156 ---
157
158 ## `llm`
159
@@ -287,25 +291,29 @@
291
292 ```yaml
293 # scuttlebot.yaml
294
295 # HTTP API and web UI
296 api_addr: 127.0.0.1:8080
297
298 # MCP server
299 mcp_addr: 127.0.0.1:8081
300
301 ergo:
302 # Manage ergo as a subprocess (default).
303 # Set external: true if ergo runs separately (Docker, etc.)
304 external: false
305 network_name: myfleet
306 server_name: irc.myfleet.internal
307 irc_addr: 127.0.0.1:6667 # set to :6667 or :6697 to expose IRC publicly
308 api_addr: 127.0.0.1:8089 # keep on loopback — no auth layer on this port
309 # api_token is auto-generated on first start
310
311 # Security (recommended for public deployments):
312 require_sasl: false # set to true to reject unauthenticated IRC connections
313 default_channel_modes: "+n" # set to "+Rn" to restrict joins to registered nicks
314
315 # Optional: persistent IRC history in PostgreSQL
316 history:
317 enabled: true
318 postgres_dsn: postgres://scuttlebot:secret@localhost/scuttlebot?sslmode=disable
319
320
--- docs/getting-started/quickstart.md
+++ docs/getting-started/quickstart.md
@@ -41,11 +41,11 @@
4141
```
4242
4343
The wizard walks through:
4444
4545
- IRC network name and server hostname
46
-- HTTP API listen address (default: `:8080`)
46
+- HTTP API listen address (default: `127.0.0.1:8080`)
4747
- TLS / Let's Encrypt (skip for local dev)
4848
- Web chat bridge channels (default: `#general`)
4949
- LLM backends for oracle, sentinel, and steward (optional — skip if you don't need AI bots)
5050
- Scribe message logging
5151
@@ -76,11 +76,11 @@
7676
On first start scuttlebot:
7777
7878
1. Downloads the `ergo` IRC binary if it is not already on PATH
7979
2. Generates an Ergo config, starts the embedded IRC server on `127.0.0.1:6667`
8080
3. Registers all built-in bot accounts with NickServ
81
-4. Starts the HTTP API on `:8080`
81
+4. Starts the HTTP API on `127.0.0.1:8080`
8282
5. Writes a bearer token to `data/ergo/api_token`
8383
8484
You should see the API respond within a few seconds:
8585
8686
```bash
8787
--- docs/getting-started/quickstart.md
+++ docs/getting-started/quickstart.md
@@ -41,11 +41,11 @@
41 ```
42
43 The wizard walks through:
44
45 - IRC network name and server hostname
46 - HTTP API listen address (default: `:8080`)
47 - TLS / Let's Encrypt (skip for local dev)
48 - Web chat bridge channels (default: `#general`)
49 - LLM backends for oracle, sentinel, and steward (optional — skip if you don't need AI bots)
50 - Scribe message logging
51
@@ -76,11 +76,11 @@
76 On first start scuttlebot:
77
78 1. Downloads the `ergo` IRC binary if it is not already on PATH
79 2. Generates an Ergo config, starts the embedded IRC server on `127.0.0.1:6667`
80 3. Registers all built-in bot accounts with NickServ
81 4. Starts the HTTP API on `:8080`
82 5. Writes a bearer token to `data/ergo/api_token`
83
84 You should see the API respond within a few seconds:
85
86 ```bash
87
--- docs/getting-started/quickstart.md
+++ docs/getting-started/quickstart.md
@@ -41,11 +41,11 @@
41 ```
42
43 The wizard walks through:
44
45 - IRC network name and server hostname
46 - HTTP API listen address (default: `127.0.0.1:8080`)
47 - TLS / Let's Encrypt (skip for local dev)
48 - Web chat bridge channels (default: `#general`)
49 - LLM backends for oracle, sentinel, and steward (optional — skip if you don't need AI bots)
50 - Scribe message logging
51
@@ -76,11 +76,11 @@
76 On first start scuttlebot:
77
78 1. Downloads the `ergo` IRC binary if it is not already on PATH
79 2. Generates an Ergo config, starts the embedded IRC server on `127.0.0.1:6667`
80 3. Registers all built-in bot accounts with NickServ
81 4. Starts the HTTP API on `127.0.0.1:8080`
82 5. Writes a bearer token to `data/ergo/api_token`
83
84 You should see the API respond within a few seconds:
85
86 ```bash
87
--- docs/guide/deployment.md
+++ docs/guide/deployment.md
@@ -50,10 +50,12 @@
5050
ergo:
5151
network_name: mynet
5252
server_name: irc.example.com
5353
irc_addr: 0.0.0.0:6697
5454
tls_domain: irc.example.com # enables Let's Encrypt; comment out for self-signed
55
+ require_sasl: true # reject unauthenticated IRC connections
56
+ default_channel_modes: "+Rn" # restrict channel joins to registered nicks
5557
5658
bridge:
5759
enabled: true
5860
nick: bridge
5961
channels:
6062
--- docs/guide/deployment.md
+++ docs/guide/deployment.md
@@ -50,10 +50,12 @@
50 ergo:
51 network_name: mynet
52 server_name: irc.example.com
53 irc_addr: 0.0.0.0:6697
54 tls_domain: irc.example.com # enables Let's Encrypt; comment out for self-signed
 
 
55
56 bridge:
57 enabled: true
58 nick: bridge
59 channels:
60
--- docs/guide/deployment.md
+++ docs/guide/deployment.md
@@ -50,10 +50,12 @@
50 ergo:
51 network_name: mynet
52 server_name: irc.example.com
53 irc_addr: 0.0.0.0:6697
54 tls_domain: irc.example.com # enables Let's Encrypt; comment out for self-signed
55 require_sasl: true # reject unauthenticated IRC connections
56 default_channel_modes: "+Rn" # restrict channel joins to registered nicks
57
58 bridge:
59 enabled: true
60 nick: bridge
61 channels:
62
--- docs/guide/relays.md
+++ docs/guide/relays.md
@@ -207,20 +207,20 @@
207207
```
208208
209209
=== "Codex"
210210
211211
```bash
212
- bash skills/scuttlebot-relay/scripts/install-claude-relay.sh \
212
+ bash skills/openai-relay/scripts/install-codex-relay.sh \
213213
--url http://localhost:8080 \
214214
--token "$(./run.sh token)" \
215215
--channel general
216216
```
217217
218218
After install:
219219
220220
```bash
221
- ~/.local/bin/claude-relay # same wrapper pattern
221
+ ~/.local/bin/codex-relay
222222
```
223223
224224
=== "Gemini"
225225
226226
```bash
227227
--- docs/guide/relays.md
+++ docs/guide/relays.md
@@ -207,20 +207,20 @@
207 ```
208
209 === "Codex"
210
211 ```bash
212 bash skills/scuttlebot-relay/scripts/install-claude-relay.sh \
213 --url http://localhost:8080 \
214 --token "$(./run.sh token)" \
215 --channel general
216 ```
217
218 After install:
219
220 ```bash
221 ~/.local/bin/claude-relay # same wrapper pattern
222 ```
223
224 === "Gemini"
225
226 ```bash
227
--- docs/guide/relays.md
+++ docs/guide/relays.md
@@ -207,20 +207,20 @@
207 ```
208
209 === "Codex"
210
211 ```bash
212 bash skills/openai-relay/scripts/install-codex-relay.sh \
213 --url http://localhost:8080 \
214 --token "$(./run.sh token)" \
215 --channel general
216 ```
217
218 After install:
219
220 ```bash
221 ~/.local/bin/codex-relay
222 ```
223
224 === "Gemini"
225
226 ```bash
227
--- docs/reference/api.md
+++ docs/reference/api.md
@@ -1,8 +1,8 @@
11
# HTTP API Reference
22
3
-scuttlebot exposes a REST API at the address configured in `api_addr` (default `:8080`).
3
+scuttlebot exposes a REST API at the address configured in `api_addr` (default `127.0.0.1:8080`).
44
55
All `/v1/` endpoints require a valid **Bearer token** in the `Authorization` header, except for the SSE stream endpoint which uses a `?token=` query parameter (browser `EventSource` cannot send headers).
66
77
The API token is written to `data/ergo/api_token` on every daemon start.
88
99
--- docs/reference/api.md
+++ docs/reference/api.md
@@ -1,8 +1,8 @@
1 # HTTP API Reference
2
3 scuttlebot exposes a REST API at the address configured in `api_addr` (default `:8080`).
4
5 All `/v1/` endpoints require a valid **Bearer token** in the `Authorization` header, except for the SSE stream endpoint which uses a `?token=` query parameter (browser `EventSource` cannot send headers).
6
7 The API token is written to `data/ergo/api_token` on every daemon start.
8
9
--- docs/reference/api.md
+++ docs/reference/api.md
@@ -1,8 +1,8 @@
1 # HTTP API Reference
2
3 scuttlebot exposes a REST API at the address configured in `api_addr` (default `127.0.0.1:8080`).
4
5 All `/v1/` endpoints require a valid **Bearer token** in the `Authorization` header, except for the SSE stream endpoint which uses a `?token=` query parameter (browser `EventSource` cannot send headers).
6
7 The API token is written to `data/ergo/api_token` on every daemon start.
8
9
--- docs/reference/cli.md
+++ docs/reference/cli.md
@@ -451,12 +451,12 @@
451451
452452
1. Loads and validates `scuttlebot.yaml`
453453
2. Downloads ergo if not found (unless `ergo.external: true`)
454454
3. Generates an Ergo config and starts the IRC server
455455
4. Registers built-in bot NickServ accounts
456
-5. Starts the HTTP API on `api_addr` (default `:8080`)
457
-6. Starts the MCP server on `mcp_addr` (default `:8081`)
456
+5. Starts the HTTP API on `api_addr` (default `127.0.0.1:8080`)
457
+6. Starts the MCP server on `mcp_addr` (default `127.0.0.1:8081`)
458458
7. Writes the API token to `data/ergo/api_token`
459459
8. Starts all enabled bots
460460
461461
---
462462
463463
--- docs/reference/cli.md
+++ docs/reference/cli.md
@@ -451,12 +451,12 @@
451
452 1. Loads and validates `scuttlebot.yaml`
453 2. Downloads ergo if not found (unless `ergo.external: true`)
454 3. Generates an Ergo config and starts the IRC server
455 4. Registers built-in bot NickServ accounts
456 5. Starts the HTTP API on `api_addr` (default `:8080`)
457 6. Starts the MCP server on `mcp_addr` (default `:8081`)
458 7. Writes the API token to `data/ergo/api_token`
459 8. Starts all enabled bots
460
461 ---
462
463
--- docs/reference/cli.md
+++ docs/reference/cli.md
@@ -451,12 +451,12 @@
451
452 1. Loads and validates `scuttlebot.yaml`
453 2. Downloads ergo if not found (unless `ergo.external: true`)
454 3. Generates an Ergo config and starts the IRC server
455 4. Registers built-in bot NickServ accounts
456 5. Starts the HTTP API on `api_addr` (default `127.0.0.1:8080`)
457 6. Starts the MCP server on `mcp_addr` (default `127.0.0.1:8081`)
458 7. Writes the API token to `data/ergo/api_token`
459 8. Starts all enabled bots
460
461 ---
462
463
--- docs/reference/config.md
+++ docs/reference/config.md
@@ -6,12 +6,12 @@
66
77
## Top-level
88
99
| Field | Type | Default | Env override |
1010
|-------|------|---------|--------------|
11
-| `api_addr` | string | `:8080` | `SCUTTLEBOT_API_ADDR` |
12
-| `mcp_addr` | string | `:8081` | `SCUTTLEBOT_MCP_ADDR` |
11
+| `api_addr` | string | `127.0.0.1:8080` | `SCUTTLEBOT_API_ADDR` |
12
+| `mcp_addr` | string | `127.0.0.1:8081` | `SCUTTLEBOT_MCP_ADDR` |
1313
1414
---
1515
1616
## `ergo`
1717
@@ -24,10 +24,12 @@
2424
| `server_name` | string | `irc.scuttlebot.local` | `SCUTTLEBOT_ERGO_SERVER_NAME` |
2525
| `irc_addr` | string | `127.0.0.1:6667` | `SCUTTLEBOT_ERGO_IRC_ADDR` |
2626
| `api_addr` | string | `127.0.0.1:8089` | `SCUTTLEBOT_ERGO_API_ADDR` |
2727
| `api_token` | string | *(auto-generated)* | `SCUTTLEBOT_ERGO_API_TOKEN` |
2828
| `tls_domain` | string | — | — |
29
+| `require_sasl` | bool | `false` | — |
30
+| `default_channel_modes` | string | `+n` | — |
2931
3032
### `ergo.history`
3133
3234
| Field | Type | Default |
3335
|-------|------|---------|
@@ -127,12 +129,12 @@
127129
### `bots.warden`
128130
129131
| Field | Type | Default |
130132
|-------|------|---------|
131133
| `enabled` | bool | `true` |
132
-| `max_joins_per_minute` | int | `10` |
133
-| `max_messages_per_minute` | int | `60` |
134
+
135
+Rate limits are fixed at 5 messages/second sustained with a burst of 10. They are not configurable via YAML.
134136
135137
### `bots.herald`
136138
137139
| Field | Type | Default |
138140
|-------|------|---------|
@@ -157,12 +159,12 @@
157159
---
158160
159161
## Full skeleton
160162
161163
```yaml
162
-api_addr: :8080
163
-mcp_addr: :8081
164
+api_addr: 127.0.0.1:8080
165
+mcp_addr: 127.0.0.1:8081
164166
165167
ergo:
166168
external: false
167169
binary_path: ergo
168170
data_dir: ./data/ergo
169171
--- docs/reference/config.md
+++ docs/reference/config.md
@@ -6,12 +6,12 @@
6
7 ## Top-level
8
9 | Field | Type | Default | Env override |
10 |-------|------|---------|--------------|
11 | `api_addr` | string | `:8080` | `SCUTTLEBOT_API_ADDR` |
12 | `mcp_addr` | string | `:8081` | `SCUTTLEBOT_MCP_ADDR` |
13
14 ---
15
16 ## `ergo`
17
@@ -24,10 +24,12 @@
24 | `server_name` | string | `irc.scuttlebot.local` | `SCUTTLEBOT_ERGO_SERVER_NAME` |
25 | `irc_addr` | string | `127.0.0.1:6667` | `SCUTTLEBOT_ERGO_IRC_ADDR` |
26 | `api_addr` | string | `127.0.0.1:8089` | `SCUTTLEBOT_ERGO_API_ADDR` |
27 | `api_token` | string | *(auto-generated)* | `SCUTTLEBOT_ERGO_API_TOKEN` |
28 | `tls_domain` | string | — | — |
 
 
29
30 ### `ergo.history`
31
32 | Field | Type | Default |
33 |-------|------|---------|
@@ -127,12 +129,12 @@
127 ### `bots.warden`
128
129 | Field | Type | Default |
130 |-------|------|---------|
131 | `enabled` | bool | `true` |
132 | `max_joins_per_minute` | int | `10` |
133 | `max_messages_per_minute` | int | `60` |
134
135 ### `bots.herald`
136
137 | Field | Type | Default |
138 |-------|------|---------|
@@ -157,12 +159,12 @@
157 ---
158
159 ## Full skeleton
160
161 ```yaml
162 api_addr: :8080
163 mcp_addr: :8081
164
165 ergo:
166 external: false
167 binary_path: ergo
168 data_dir: ./data/ergo
169
--- docs/reference/config.md
+++ docs/reference/config.md
@@ -6,12 +6,12 @@
6
7 ## Top-level
8
9 | Field | Type | Default | Env override |
10 |-------|------|---------|--------------|
11 | `api_addr` | string | `127.0.0.1:8080` | `SCUTTLEBOT_API_ADDR` |
12 | `mcp_addr` | string | `127.0.0.1:8081` | `SCUTTLEBOT_MCP_ADDR` |
13
14 ---
15
16 ## `ergo`
17
@@ -24,10 +24,12 @@
24 | `server_name` | string | `irc.scuttlebot.local` | `SCUTTLEBOT_ERGO_SERVER_NAME` |
25 | `irc_addr` | string | `127.0.0.1:6667` | `SCUTTLEBOT_ERGO_IRC_ADDR` |
26 | `api_addr` | string | `127.0.0.1:8089` | `SCUTTLEBOT_ERGO_API_ADDR` |
27 | `api_token` | string | *(auto-generated)* | `SCUTTLEBOT_ERGO_API_TOKEN` |
28 | `tls_domain` | string | — | — |
29 | `require_sasl` | bool | `false` | — |
30 | `default_channel_modes` | string | `+n` | — |
31
32 ### `ergo.history`
33
34 | Field | Type | Default |
35 |-------|------|---------|
@@ -127,12 +129,12 @@
129 ### `bots.warden`
130
131 | Field | Type | Default |
132 |-------|------|---------|
133 | `enabled` | bool | `true` |
134
135 Rate limits are fixed at 5 messages/second sustained with a burst of 10. They are not configurable via YAML.
136
137 ### `bots.herald`
138
139 | Field | Type | Default |
140 |-------|------|---------|
@@ -157,12 +159,12 @@
159 ---
160
161 ## Full skeleton
162
163 ```yaml
164 api_addr: 127.0.0.1:8080
165 mcp_addr: 127.0.0.1:8081
166
167 ergo:
168 external: false
169 binary_path: ergo
170 data_dir: ./data/ergo
171
--- docs/reference/mcp.md
+++ docs/reference/mcp.md
@@ -1,11 +1,11 @@
11
# MCP Server
22
33
scuttlebot exposes a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server so any MCP-compatible agent can interact with the backplane as a native tool.
44
55
**Transport:** HTTP POST at `/mcp` — JSON-RPC 2.0 over HTTP.
6
-**Address:** `mcp_addr` in `scuttlebot.yaml` (default `:8081`).
6
+**Address:** `mcp_addr` in `scuttlebot.yaml` (default `127.0.0.1:8081`).
77
**Auth:** Bearer token in the `Authorization` header (same token as the REST API).
88
99
---
1010
1111
## Connecting
@@ -12,11 +12,11 @@
1212
1313
Point your MCP client at the server address:
1414
1515
```bash
1616
# scuttlebot.yaml
17
-mcp_addr: ":8081"
17
+mcp_addr: "127.0.0.1:8081" # loopback by default; set to :8081 for external access
1818
```
1919
2020
For Claude Code, add to `.mcp.json`:
2121
2222
```json
2323
--- docs/reference/mcp.md
+++ docs/reference/mcp.md
@@ -1,11 +1,11 @@
1 # MCP Server
2
3 scuttlebot exposes a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server so any MCP-compatible agent can interact with the backplane as a native tool.
4
5 **Transport:** HTTP POST at `/mcp` — JSON-RPC 2.0 over HTTP.
6 **Address:** `mcp_addr` in `scuttlebot.yaml` (default `:8081`).
7 **Auth:** Bearer token in the `Authorization` header (same token as the REST API).
8
9 ---
10
11 ## Connecting
@@ -12,11 +12,11 @@
12
13 Point your MCP client at the server address:
14
15 ```bash
16 # scuttlebot.yaml
17 mcp_addr: ":8081"
18 ```
19
20 For Claude Code, add to `.mcp.json`:
21
22 ```json
23
--- docs/reference/mcp.md
+++ docs/reference/mcp.md
@@ -1,11 +1,11 @@
1 # MCP Server
2
3 scuttlebot exposes a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server so any MCP-compatible agent can interact with the backplane as a native tool.
4
5 **Transport:** HTTP POST at `/mcp` — JSON-RPC 2.0 over HTTP.
6 **Address:** `mcp_addr` in `scuttlebot.yaml` (default `127.0.0.1:8081`).
7 **Auth:** Bearer token in the `Authorization` header (same token as the REST API).
8
9 ---
10
11 ## Connecting
@@ -12,11 +12,11 @@
12
13 Point your MCP client at the server address:
14
15 ```bash
16 # scuttlebot.yaml
17 mcp_addr: "127.0.0.1:8081" # loopback by default; set to :8081 for external access
18 ```
19
20 For Claude Code, add to `.mcp.json`:
21
22 ```json
23
--- internal/ergo/ircdconfig.go
+++ internal/ergo/ircdconfig.go
@@ -49,15 +49,16 @@
4949
allow-before-connect: true
5050
throttling:
5151
enabled: false
5252
authentication-enabled: true
5353
require-sasl:
54
- enabled: false
54
+ enabled: {{.RequireSASL}}
5555
5656
channels:
5757
registration:
5858
enabled: true
59
+ default-modes: "{{.DefaultChannelModes}}"
5960
6061
history:
6162
enabled: {{.HistoryEnabled}}
6263
{{- if .HistoryEnabled}}
6364
channel-length: 2048
@@ -95,38 +96,42 @@
9596
topiclen: 512
9697
9798
`))
9899
99100
type ircdTemplateData struct {
100
- NetworkName string
101
- ServerName string
102
- IRCAddr string
103
- DataDir string
104
- APIAddr string
105
- APIToken string
106
- HistoryEnabled bool
107
- PostgresDSN string
108
- MySQLEnabled bool
109
- MySQL config.MySQLConfig
101
+ NetworkName string
102
+ ServerName string
103
+ IRCAddr string
104
+ DataDir string
105
+ APIAddr string
106
+ APIToken string
107
+ HistoryEnabled bool
108
+ PostgresDSN string
109
+ MySQLEnabled bool
110
+ MySQL config.MySQLConfig
111
+ RequireSASL bool
112
+ DefaultChannelModes string
110113
}
111114
112115
// GenerateConfig renders an ircd.yaml from the given ErgoConfig.
113116
func GenerateConfig(cfg config.ErgoConfig) ([]byte, error) {
114117
data := ircdTemplateData{
115
- NetworkName: cfg.NetworkName,
116
- ServerName: cfg.ServerName,
117
- IRCAddr: cfg.IRCAddr,
118
- DataDir: cfg.DataDir,
119
- APIAddr: cfg.APIAddr,
120
- APIToken: cfg.APIToken,
121
- HistoryEnabled: cfg.History.Enabled,
122
- PostgresDSN: cfg.History.PostgresDSN,
123
- MySQLEnabled: cfg.History.MySQL.Host != "" && cfg.History.PostgresDSN == "",
124
- MySQL: cfg.History.MySQL,
118
+ NetworkName: cfg.NetworkName,
119
+ ServerName: cfg.ServerName,
120
+ IRCAddr: cfg.IRCAddr,
121
+ DataDir: cfg.DataDir,
122
+ APIAddr: cfg.APIAddr,
123
+ APIToken: cfg.APIToken,
124
+ HistoryEnabled: cfg.History.Enabled,
125
+ PostgresDSN: cfg.History.PostgresDSN,
126
+ MySQLEnabled: cfg.History.MySQL.Host != "" && cfg.History.PostgresDSN == "",
127
+ MySQL: cfg.History.MySQL,
128
+ RequireSASL: cfg.RequireSASL,
129
+ DefaultChannelModes: cfg.DefaultChannelModes,
125130
}
126131
127132
var buf bytes.Buffer
128133
if err := ircdTemplate.Execute(&buf, data); err != nil {
129134
return nil, err
130135
}
131136
return buf.Bytes(), nil
132137
}
133138
--- internal/ergo/ircdconfig.go
+++ internal/ergo/ircdconfig.go
@@ -49,15 +49,16 @@
49 allow-before-connect: true
50 throttling:
51 enabled: false
52 authentication-enabled: true
53 require-sasl:
54 enabled: false
55
56 channels:
57 registration:
58 enabled: true
 
59
60 history:
61 enabled: {{.HistoryEnabled}}
62 {{- if .HistoryEnabled}}
63 channel-length: 2048
@@ -95,38 +96,42 @@
95 topiclen: 512
96
97 `))
98
99 type ircdTemplateData struct {
100 NetworkName string
101 ServerName string
102 IRCAddr string
103 DataDir string
104 APIAddr string
105 APIToken string
106 HistoryEnabled bool
107 PostgresDSN string
108 MySQLEnabled bool
109 MySQL config.MySQLConfig
 
 
110 }
111
112 // GenerateConfig renders an ircd.yaml from the given ErgoConfig.
113 func GenerateConfig(cfg config.ErgoConfig) ([]byte, error) {
114 data := ircdTemplateData{
115 NetworkName: cfg.NetworkName,
116 ServerName: cfg.ServerName,
117 IRCAddr: cfg.IRCAddr,
118 DataDir: cfg.DataDir,
119 APIAddr: cfg.APIAddr,
120 APIToken: cfg.APIToken,
121 HistoryEnabled: cfg.History.Enabled,
122 PostgresDSN: cfg.History.PostgresDSN,
123 MySQLEnabled: cfg.History.MySQL.Host != "" && cfg.History.PostgresDSN == "",
124 MySQL: cfg.History.MySQL,
 
 
125 }
126
127 var buf bytes.Buffer
128 if err := ircdTemplate.Execute(&buf, data); err != nil {
129 return nil, err
130 }
131 return buf.Bytes(), nil
132 }
133
--- internal/ergo/ircdconfig.go
+++ internal/ergo/ircdconfig.go
@@ -49,15 +49,16 @@
49 allow-before-connect: true
50 throttling:
51 enabled: false
52 authentication-enabled: true
53 require-sasl:
54 enabled: {{.RequireSASL}}
55
56 channels:
57 registration:
58 enabled: true
59 default-modes: "{{.DefaultChannelModes}}"
60
61 history:
62 enabled: {{.HistoryEnabled}}
63 {{- if .HistoryEnabled}}
64 channel-length: 2048
@@ -95,38 +96,42 @@
96 topiclen: 512
97
98 `))
99
100 type ircdTemplateData struct {
101 NetworkName string
102 ServerName string
103 IRCAddr string
104 DataDir string
105 APIAddr string
106 APIToken string
107 HistoryEnabled bool
108 PostgresDSN string
109 MySQLEnabled bool
110 MySQL config.MySQLConfig
111 RequireSASL bool
112 DefaultChannelModes string
113 }
114
115 // GenerateConfig renders an ircd.yaml from the given ErgoConfig.
116 func GenerateConfig(cfg config.ErgoConfig) ([]byte, error) {
117 data := ircdTemplateData{
118 NetworkName: cfg.NetworkName,
119 ServerName: cfg.ServerName,
120 IRCAddr: cfg.IRCAddr,
121 DataDir: cfg.DataDir,
122 APIAddr: cfg.APIAddr,
123 APIToken: cfg.APIToken,
124 HistoryEnabled: cfg.History.Enabled,
125 PostgresDSN: cfg.History.PostgresDSN,
126 MySQLEnabled: cfg.History.MySQL.Host != "" && cfg.History.PostgresDSN == "",
127 MySQL: cfg.History.MySQL,
128 RequireSASL: cfg.RequireSASL,
129 DefaultChannelModes: cfg.DefaultChannelModes,
130 }
131
132 var buf bytes.Buffer
133 if err := ircdTemplate.Execute(&buf, data); err != nil {
134 return nil, err
135 }
136 return buf.Bytes(), nil
137 }
138
--- internal/ergo/ircdconfig_test.go
+++ internal/ergo/ircdconfig_test.go
@@ -93,5 +93,47 @@
9393
yaml := string(data)
9494
if strings.Contains(yaml, "postgres") {
9595
t.Error("postgres config should not appear when history disabled")
9696
}
9797
}
98
+
99
+func TestGenerateConfigRequireSASL(t *testing.T) {
100
+ cfg := config.ErgoConfig{
101
+ NetworkName: "testnet",
102
+ ServerName: "irc.test.local",
103
+ IRCAddr: "127.0.0.1:6667",
104
+ APIAddr: "127.0.0.1:8089",
105
+ APIToken: "tok",
106
+ RequireSASL: true,
107
+ }
108
+
109
+ data, err := ergo.GenerateConfig(cfg)
110
+ if err != nil {
111
+ t.Fatalf("GenerateConfig: %v", err)
112
+ }
113
+
114
+ yaml := string(data)
115
+ if !strings.Contains(yaml, "enabled: true") {
116
+ t.Error("require-sasl.enabled should be true")
117
+ }
118
+}
119
+
120
+func TestGenerateConfigDefaultChannelModes(t *testing.T) {
121
+ cfg := config.ErgoConfig{
122
+ NetworkName: "testnet",
123
+ ServerName: "irc.test.local",
124
+ IRCAddr: "127.0.0.1:6667",
125
+ APIAddr: "127.0.0.1:8089",
126
+ APIToken: "tok",
127
+ DefaultChannelModes: "+Rn",
128
+ }
129
+
130
+ data, err := ergo.GenerateConfig(cfg)
131
+ if err != nil {
132
+ t.Fatalf("GenerateConfig: %v", err)
133
+ }
134
+
135
+ yaml := string(data)
136
+ if !strings.Contains(yaml, `default-modes: "+Rn"`) {
137
+ t.Errorf("default-modes not set correctly\ngot:\n%s", yaml)
138
+ }
139
+}
98140
--- internal/ergo/ircdconfig_test.go
+++ internal/ergo/ircdconfig_test.go
@@ -93,5 +93,47 @@
93 yaml := string(data)
94 if strings.Contains(yaml, "postgres") {
95 t.Error("postgres config should not appear when history disabled")
96 }
97 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
--- internal/ergo/ircdconfig_test.go
+++ internal/ergo/ircdconfig_test.go
@@ -93,5 +93,47 @@
93 yaml := string(data)
94 if strings.Contains(yaml, "postgres") {
95 t.Error("postgres config should not appear when history disabled")
96 }
97 }
98
99 func TestGenerateConfigRequireSASL(t *testing.T) {
100 cfg := config.ErgoConfig{
101 NetworkName: "testnet",
102 ServerName: "irc.test.local",
103 IRCAddr: "127.0.0.1:6667",
104 APIAddr: "127.0.0.1:8089",
105 APIToken: "tok",
106 RequireSASL: true,
107 }
108
109 data, err := ergo.GenerateConfig(cfg)
110 if err != nil {
111 t.Fatalf("GenerateConfig: %v", err)
112 }
113
114 yaml := string(data)
115 if !strings.Contains(yaml, "enabled: true") {
116 t.Error("require-sasl.enabled should be true")
117 }
118 }
119
120 func TestGenerateConfigDefaultChannelModes(t *testing.T) {
121 cfg := config.ErgoConfig{
122 NetworkName: "testnet",
123 ServerName: "irc.test.local",
124 IRCAddr: "127.0.0.1:6667",
125 APIAddr: "127.0.0.1:8089",
126 APIToken: "tok",
127 DefaultChannelModes: "+Rn",
128 }
129
130 data, err := ergo.GenerateConfig(cfg)
131 if err != nil {
132 t.Fatalf("GenerateConfig: %v", err)
133 }
134
135 yaml := string(data)
136 if !strings.Contains(yaml, `default-modes: "+Rn"`) {
137 t.Errorf("default-modes not set correctly\ngot:\n%s", yaml)
138 }
139 }
140

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button