defaults: raise max/defaults (OPENAI_MAX_TOKENS=128000, larger summarizer timeouts/limits, DIGEST_WINDOW=24h, RETENTION=365); docs: add inline env option, defaults table; compose: bind 127.0.0.1:8080

This commit is contained in:
Thomas Cravey 2025-08-16 12:29:58 -05:00
parent 9ecf4f4f4c
commit 00ddd9e460
4 changed files with 150 additions and 19 deletions

6
.dockerignore Normal file
View file

@ -0,0 +1,6 @@
# Exclude secrets and non-essential files from Docker build context
.env
.env.*
.git
.gitignore
**/*.md

145
README.md
View file

@ -144,7 +144,11 @@ docker inspect --format='{{json .State.Health}}' sojuboy | jq
Compose includes a healthcheck calling the binarys `--health` flag, which returns 0 only when `/ready` is 200.
## Configuration (.env example)
## Configuration options
You can configure via a `.env` file or inline `environment:` in your compose YAML. Both approaches are shown below. Defaults for all variables are listed in the table after the examples.
### Option A: .env file (recommended for development)
Below shows maximum or large/reasonable values. Defaults are noted where they are also the maximum or when relevant.
@ -178,20 +182,20 @@ LLM_PROVIDER=openai
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.openai.com/v1
OPENAI_MODEL=gpt-5
# Max completion (output) tokens for GPT5 is ~128k (model limit). Default 700.
# Max completion (output) tokens for GPT5 is ~128k (model limit). Default 128000.
OPENAI_MAX_TOKENS=128000
# Summarizer tuning
SUMM_FOLLOW_LINKS=true # default true
SUMM_LINK_TIMEOUT=20s # no hard max; example large
SUMM_LINK_MAX_BYTES=1048576 # no hard max; example large (1 MiB/article)
SUMM_GROUP_WINDOW=120s # no hard max; example large grouping window
SUMM_MAX_LINKS=20 # no strict max; example large
SUMM_MAX_GROUPS=20000 # 0=no cap; example large
SUMM_TIMEOUT=10m # request timeout; default 5m
SUMM_LINK_TIMEOUT=20s # default 20s
SUMM_LINK_MAX_BYTES=1048576 # default 1048576 (1 MiB/article)
SUMM_GROUP_WINDOW=120s # default 120s
SUMM_MAX_LINKS=20 # default 20
SUMM_MAX_GROUPS=20000 # default 0 (no cap); example large
SUMM_TIMEOUT=10m # request timeout; default 10m
# Digests
DIGEST_CRON=0 */6 * * * # every 6 hours
DIGEST_WINDOW=24h # no hard max; example large window
DIGEST_WINDOW=24h # default 24h
QUIET_HOURS= # e.g., 22:00-07:00
# Mentions/alerts
@ -207,12 +211,133 @@ HTTP_TOKEN=put-a-long-random-token-here
# Storage
STORE_PATH=/data/app.db
STORE_RETENTION_DAYS=365 # example large retention
STORE_RETENTION_DAYS=365 # default 365
# Logging
LOG_LEVEL=info
```
Compose (with localhost bind suitable for Synology reverse proxy):
```yaml
services:
sojuboy:
image: code.cravey.net/your-user/sojuboy:v0.1.0-beta1
restart: unless-stopped
env_file: .env
ports:
- "127.0.0.1:8080:8080" # bind only to localhost; fronted by DSM Reverse Proxy
volumes:
- /volume1/docker/sojuboy/data:/data
healthcheck:
test: ["CMD", "/sojuboy", "--health"]
interval: 30s
timeout: 3s
retries: 3
```
### Option B: Inline environment in compose (no .env)
```yaml
services:
sojuboy:
image: code.cravey.net/your-user/sojuboy:v0.1.0-beta1
restart: unless-stopped
ports:
- "127.0.0.1:8080:8080" # bind only to localhost; fronted by DSM Reverse Proxy
volumes:
- /volume1/docker/sojuboy/data:/data
environment:
SOJU_HOST: "bnc.example.org" # default 127.0.0.1
SOJU_PORT: "6697" # default 6697
SOJU_TLS: "true" # default true
SOJU_NETWORK: "your-network" # default ""
IRC_NICK: "yourNick" # default sojuboy
IRC_USERNAME: "yourUser/your-network@sojuboy" # default IRC_NICK
IRC_REALNAME: "Your Real Name" # default sojuboy
IRC_PASSWORD: "yourSojuClientPassword" # default ""
CHANNELS: "#animaniacs,#general" # default "" (none)
KEYWORDS: "yourNick,YourCompany" # default IRC_NICK
SOJU_AUTH: "raw" # default sasl (hint only)
NOTIFIER: "pushover" # default pushover
PUSHOVER_USER_KEY: "..." # default ""
PUSHOVER_API_TOKEN: "..." # default ""
LLM_PROVIDER: "openai" # default openai
OPENAI_API_KEY: "sk-..." # default ""
OPENAI_BASE_URL: "https://api.openai.com/v1" # default ""
OPENAI_MODEL: "gpt-5" # default gpt-5
OPENAI_MAX_TOKENS: "128000" # default 128000
SUMM_FOLLOW_LINKS: "true" # default true
SUMM_LINK_TIMEOUT: "20s" # default 20s
SUMM_LINK_MAX_BYTES: "1048576" # default 1048576
SUMM_GROUP_WINDOW: "120s" # default 120s
SUMM_MAX_LINKS: "20" # default 20
SUMM_MAX_GROUPS: "20000" # default 0 (no cap)
SUMM_TIMEOUT: "10m" # default 10m
DIGEST_CRON: "0 */6 * * *" # default 0 */6 * * *
DIGEST_WINDOW: "24h" # default 24h
QUIET_HOURS: "" # default ""
NOTIFY_BACKFILL: "false" # default false
MENTION_MIN_INTERVAL: "30s" # default 30s
MENTIONS_ONLY_CHANNELS: "" # default ""
MENTIONS_DENY_CHANNELS: "" # default ""
URGENT_KEYWORDS: "urgent,priority" # default ""
HTTP_LISTEN: ":8080" # default :8080
HTTP_TOKEN: "<long-random-token>" # default ""
STORE_PATH: "/data/app.db" # default /data/app.db
STORE_RETENTION_DAYS: "365" # default 365
LOG_LEVEL: "info" # default info
healthcheck:
test: ["CMD", "/sojuboy", "--health"]
interval: 30s
timeout: 3s
retries: 3
```
### Defaults reference
| Variable | Default |
|---|---|
| SOJU_HOST | 127.0.0.1 |
| SOJU_PORT | 6697 |
| SOJU_TLS | true |
| IRC_NICK | sojuboy |
| IRC_USERNAME | IRC_NICK |
| IRC_REALNAME | sojuboy |
| IRC_PASSWORD | (empty) |
| SOJU_NETWORK | (empty) |
| CHANNELS | (empty) |
| KEYWORDS | IRC_NICK |
| SOJU_AUTH | sasl |
| NOTIFIER | pushover |
| PUSHOVER_USER_KEY | (empty) |
| PUSHOVER_API_TOKEN | (empty) |
| LLM_PROVIDER | openai |
| OPENAI_API_KEY | (empty) |
| OPENAI_BASE_URL | (empty) |
| OPENAI_MODEL | gpt-5 |
| OPENAI_MAX_TOKENS | 700 |
| SUMM_FOLLOW_LINKS | true |
| SUMM_LINK_TIMEOUT | 6s |
| SUMM_LINK_MAX_BYTES | 262144 |
| SUMM_GROUP_WINDOW | 90s |
| SUMM_MAX_LINKS | 5 |
| SUMM_MAX_GROUPS | 0 |
| SUMM_TIMEOUT | 5m |
| DIGEST_CRON | 0 */6 * * * |
| DIGEST_WINDOW | 6h |
| QUIET_HOURS | (empty) |
| NOTIFY_BACKFILL | false |
| MENTION_MIN_INTERVAL | 30s |
| MENTIONS_ONLY_CHANNELS | (empty) |
| MENTIONS_DENY_CHANNELS | (empty) |
| URGENT_KEYWORDS | (empty) |
| HTTP_LISTEN | :8080 |
| HTTP_TOKEN | (empty) |
| STORE_PATH | /data/app.db |
| STORE_RETENTION_DAYS | 7 |
| LOG_LEVEL | info |
## Pushover setup
1) Install Pushover iOS app and log in

View file

@ -6,7 +6,7 @@ services:
restart: unless-stopped
env_file: .env
ports:
- "8080:8080"
- "127.0.0.1:8080:8080"
volumes:
- sojuboy_data:/data
healthcheck:

View file

@ -86,17 +86,17 @@ func FromEnv() Config {
cfg.OpenAIAPIKey = getEnv("OPENAI_API_KEY", "")
cfg.OpenAIBaseURL = getEnv("OPENAI_BASE_URL", "")
cfg.OpenAIModel = getEnv("OPENAI_MODEL", "gpt-5")
cfg.OpenAIMaxTokens = getEnvInt("OPENAI_MAX_TOKENS", 700)
cfg.OpenAIMaxTokens = getEnvInt("OPENAI_MAX_TOKENS", 128000)
cfg.SummFollowLinks = getEnvBool("SUMM_FOLLOW_LINKS", true)
cfg.SummLinkTimeout = getEnvDuration("SUMM_LINK_TIMEOUT", 6*time.Second)
cfg.SummLinkMaxBytes = getEnvInt("SUMM_LINK_MAX_BYTES", 262144)
cfg.SummGroupWindow = getEnvDuration("SUMM_GROUP_WINDOW", 90*time.Second)
cfg.SummMaxLinks = getEnvInt("SUMM_MAX_LINKS", 5)
cfg.SummLinkTimeout = getEnvDuration("SUMM_LINK_TIMEOUT", 20*time.Second)
cfg.SummLinkMaxBytes = getEnvInt("SUMM_LINK_MAX_BYTES", 1048576)
cfg.SummGroupWindow = getEnvDuration("SUMM_GROUP_WINDOW", 120*time.Second)
cfg.SummMaxLinks = getEnvInt("SUMM_MAX_LINKS", 20)
cfg.SummMaxGroups = getEnvInt("SUMM_MAX_GROUPS", 0)
cfg.SummarizerTimeout = getEnvDuration("SUMM_TIMEOUT", 5*time.Minute)
cfg.SummarizerTimeout = getEnvDuration("SUMM_TIMEOUT", 10*time.Minute)
cfg.DigestCron = getEnv("DIGEST_CRON", "0 */6 * * *")
cfg.DigestWindow = getEnvDuration("DIGEST_WINDOW", 6*time.Hour)
cfg.DigestWindow = getEnvDuration("DIGEST_WINDOW", 24*time.Hour)
cfg.QuietHours = getEnv("QUIET_HOURS", "")
cfg.NotifyBackfill = getEnvBool("NOTIFY_BACKFILL", false)
cfg.MentionMinInterval = getEnvDuration("MENTION_MIN_INTERVAL", 30*time.Second)
@ -108,7 +108,7 @@ func FromEnv() Config {
cfg.HTTPToken = getEnv("HTTP_TOKEN", "")
cfg.StorePath = getEnv("STORE_PATH", "/data/app.db")
cfg.RetentionDays = getEnvInt("STORE_RETENTION_DAYS", 7)
cfg.RetentionDays = getEnvInt("STORE_RETENTION_DAYS", 365)
cfg.LogLevel = getEnv("LOG_LEVEL", "info")