Tweak config format

This commit is contained in:
Jon Staab
2025-09-29 12:07:29 -07:00
parent 7eb6d22362
commit 001771cb6c
6 changed files with 54 additions and 32 deletions
+7 -9
View File
@@ -12,21 +12,19 @@ Zooid supports a few environment variables, which configure shared resources lik
- `PORT` - the port the server will listen on for all requests. Defaults to `3334`.
- `DATA` - the location of the directory for storing database files and media. Defaults to `./data`.
- `CONF` - the location of the directory for storing relay configuration files. Defaults to `./conf`.
## Configuration
Configuration files are written using [toml](https://toml.io) files placed in the `./config` directory. The name of the configuration file should be the hostname the relay serves, for example `relay.example.com`. Config files contain the following sections:
### `[self]`
Contains information for populating the relay's `nip11` document.
Required:
Configuration files are written using [toml](https://toml.io) files placed in the `CONF` directory. Top level configuration options are required:
- `host` - a hostname to serve this relay on.
- `schema` - a string that identifies this relay. This cannot be changed, and must be usable as a sqlite identifier.
- `secret` - the nostr secret key of the relay. Will be used to populate the relay's NIP 11 `self` field and sign generated events.
Optional:
### `[info]`
Contains information for populating the relay's `nip11` document.
- `name` - the name of your relay.
- `icon` - an icon for your relay.
@@ -37,7 +35,7 @@ Optional:
Contains policy and access related configuration.
- `strip_signatures` - whether to remove signatures when serving events. This requires clients/users to trust the relay to properly authenticate signatures. Be cautious about using this; a malicious relay will be able to execute all kinds of attacks, including potentially serving events unrelated to a community use case.
- `strip_signatures` - whether to remove signatures when serving events to non-admins. This requires clients/users to trust the relay to properly authenticate signatures. Be cautious about using this; a malicious relay will be able to execute all kinds of attacks, including potentially serving events unrelated to a community use case.
### `[groups]`
+21 -9
View File
@@ -15,12 +15,12 @@ type Role struct {
}
type Config struct {
Host string
Secret nostr.SecretKey
Self struct {
Host string `toml:"host"`
Schema string `toml:"schema"`
Secret string `toml:"secret"`
Info struct {
Name string `toml:"name"`
Icon string `toml:"icon"`
Schema string `toml:"schema"`
Secret string `toml:"secret"`
Pubkey string `toml:"pubkey"`
Description string `toml:"description"`
@@ -46,6 +46,9 @@ type Config struct {
} `toml:"blossom"`
Roles map[string]Role `toml:"roles"`
// Private/parsed values
secret nostr.SecretKey
}
func LoadConfig(hostname string) (*Config, error) {
@@ -56,23 +59,32 @@ func LoadConfig(hostname string) (*Config, error) {
return nil, fmt.Errorf("failed to parse config file %s: %w", path, err)
}
secret, err := nostr.SecretKeyFromHex(config.Self.Secret)
secret, err := nostr.SecretKeyFromHex(config.Secret)
if err != nil {
return nil, err
}
config.Host = hostname
config.Secret = secret
// Make the secret... secret
config.Secret = ""
config.secret = secret
return &config, nil
}
func (config *Config) GetSelf() nostr.PubKey {
return config.secret.Public()
}
func (config *Config) IsSelf(pubkey nostr.PubKey) bool {
return pubkey == nostr.MustSecretKeyFromHex(config.Self.Secret).Public()
return pubkey == config.GetSelf()
}
func (config *Config) Sign(event *nostr.Event) error {
return event.Sign(config.secret)
}
func (config *Config) IsOwner(pubkey nostr.PubKey) bool {
return pubkey == nostr.MustPubKeyFromHex(config.Self.Pubkey)
return pubkey == nostr.MustPubKeyFromHex(config.Info.Pubkey)
}
func (config *Config) GetRolesForPubkey(pubkey nostr.PubKey) []Role {
+1
View File
@@ -17,6 +17,7 @@ func Env(k string, fallback ...string) (v string) {
env["PORT"] = "3334"
env["DATA"] = "./data"
env["CONF"] = "./conf"
for _, item := range os.Environ() {
parts := strings.SplitN(item, "=", 2)
+4 -1
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"iter"
"log"
"fiatjaf.com/nostr"
"fiatjaf.com/nostr/eventstore"
@@ -356,7 +357,9 @@ func (events *EventStore) GetOrCreateApplicationSpecificData(d string) nostr.Eve
},
}
event.Sign(events.Config.Secret)
if err := events.Config.Sign(&event); err != nil {
log.Println("Failed to sign application specific event: %w", err)
}
events.SaveEvent(event)
+19 -11
View File
@@ -5,6 +5,7 @@ import (
"iter"
"log"
"net/http"
"os"
"path/filepath"
"slices"
"strings"
@@ -50,6 +51,12 @@ func GetInstance(hostname string) (*Instance, error) {
}
func MonitorInstances() {
dir := Env("CONF")
if err := os.MkdirAll(dir, 0755); err != nil {
log.Fatal("Failed to create config directory: %v", err)
}
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Printf("Failed to create file watcher: %v", err)
@@ -57,7 +64,7 @@ func MonitorInstances() {
}
defer watcher.Close()
if err := watcher.Add("./config"); err != nil {
if err := watcher.Add(dir); err != nil {
log.Printf("Failed to watch config directory: %v", err)
return
}
@@ -108,7 +115,7 @@ func MakeInstance(hostname string) (*Instance, error) {
return nil, err
}
pubkey, err := nostr.PubKeyFromHex(config.Self.Pubkey)
pubkey, err := nostr.PubKeyFromHex(config.Info.Pubkey)
if err != nil {
return nil, err
}
@@ -116,7 +123,7 @@ func MakeInstance(hostname string) (*Instance, error) {
events := &EventStore{
Config: config,
Schema: &Schema{
Name: slug.Make(config.Self.Schema),
Name: slug.Make(config.Schema),
},
}
@@ -139,10 +146,10 @@ func MakeInstance(hostname string) (*Instance, error) {
}
instance.Relay.Negentropy = true
instance.Relay.Info.Name = config.Self.Name
instance.Relay.Info.Icon = config.Self.Icon
instance.Relay.Info.Name = config.Info.Name
instance.Relay.Info.Icon = config.Info.Icon
instance.Relay.Info.PubKey = &pubkey
instance.Relay.Info.Description = config.Self.Description
instance.Relay.Info.Description = config.Info.Description
// instance.Relay.Info.Self = nostr.GetPublicKey(secret)
instance.Relay.Info.Software = "https://github.com/coracle-social/zooid"
instance.Relay.Info.Version = "v0.1.0"
@@ -285,11 +292,12 @@ func (instance *Instance) GenerateInviteEvent(pubkey nostr.PubKey) nostr.Event {
},
}
event.Sign(instance.Config.Secret)
if err := instance.Config.Sign(&event); err != nil {
log.Printf("Failed to sign invite event: %v", err)
}
err := instance.Events.SaveEvent(event)
if err != nil {
log.Printf("Failed to generate invite event: %v", err)
if err := instance.Events.SaveEvent(event); err != nil {
log.Printf("Failed to save invite event: %v", err)
}
return event
@@ -427,7 +435,7 @@ func (instance *Instance) DeleteEvent(ctx context.Context, id nostr.ID) error {
func (instance *Instance) OnEventSaved(ctx context.Context, event nostr.Event) {
addEvent := func(newEvent nostr.Event) {
if err := newEvent.Sign(instance.Config.Secret); err != nil {
if err := instance.Config.Sign(&newEvent); err != nil {
log.Println(err)
} else {
if err := instance.Events.SaveEvent(newEvent); err != nil {
+2 -2
View File
@@ -167,12 +167,12 @@ func (m *ManagementStore) Enable(instance *Instance) {
reasons := make([]nip86.PubKeyReason, 0)
reasons = append(reasons, nip86.PubKeyReason{
PubKey: nostr.MustPubKeyFromHex(m.Config.Self.Pubkey),
PubKey: nostr.MustPubKeyFromHex(m.Config.Info.Pubkey),
Reason: "relay owner",
})
reasons = append(reasons, nip86.PubKeyReason{
PubKey: m.Config.Secret.Public(),
PubKey: m.Config.GetSelf(),
Reason: "relay self",
})