Tweak config format
This commit is contained in:
@@ -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`.
|
- `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`.
|
- `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
|
||||||
|
|
||||||
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:
|
Configuration files are written using [toml](https://toml.io) files placed in the `CONF` directory. Top level configuration options are required:
|
||||||
|
|
||||||
### `[self]`
|
|
||||||
|
|
||||||
Contains information for populating the relay's `nip11` document.
|
|
||||||
|
|
||||||
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.
|
- `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.
|
- `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.
|
- `name` - the name of your relay.
|
||||||
- `icon` - an icon for your relay.
|
- `icon` - an icon for your relay.
|
||||||
@@ -37,7 +35,7 @@ Optional:
|
|||||||
|
|
||||||
Contains policy and access related configuration.
|
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]`
|
### `[groups]`
|
||||||
|
|
||||||
|
|||||||
+21
-9
@@ -15,12 +15,12 @@ type Role struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Host string
|
Host string `toml:"host"`
|
||||||
Secret nostr.SecretKey
|
Schema string `toml:"schema"`
|
||||||
Self struct {
|
Secret string `toml:"secret"`
|
||||||
|
Info struct {
|
||||||
Name string `toml:"name"`
|
Name string `toml:"name"`
|
||||||
Icon string `toml:"icon"`
|
Icon string `toml:"icon"`
|
||||||
Schema string `toml:"schema"`
|
|
||||||
Secret string `toml:"secret"`
|
Secret string `toml:"secret"`
|
||||||
Pubkey string `toml:"pubkey"`
|
Pubkey string `toml:"pubkey"`
|
||||||
Description string `toml:"description"`
|
Description string `toml:"description"`
|
||||||
@@ -46,6 +46,9 @@ type Config struct {
|
|||||||
} `toml:"blossom"`
|
} `toml:"blossom"`
|
||||||
|
|
||||||
Roles map[string]Role `toml:"roles"`
|
Roles map[string]Role `toml:"roles"`
|
||||||
|
|
||||||
|
// Private/parsed values
|
||||||
|
secret nostr.SecretKey
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig(hostname string) (*Config, error) {
|
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)
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Host = hostname
|
// Make the secret... secret
|
||||||
config.Secret = secret
|
config.Secret = ""
|
||||||
|
config.secret = secret
|
||||||
|
|
||||||
return &config, nil
|
return &config, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (config *Config) GetSelf() nostr.PubKey {
|
||||||
|
return config.secret.Public()
|
||||||
|
}
|
||||||
|
|
||||||
func (config *Config) IsSelf(pubkey nostr.PubKey) bool {
|
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 {
|
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 {
|
func (config *Config) GetRolesForPubkey(pubkey nostr.PubKey) []Role {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ func Env(k string, fallback ...string) (v string) {
|
|||||||
|
|
||||||
env["PORT"] = "3334"
|
env["PORT"] = "3334"
|
||||||
env["DATA"] = "./data"
|
env["DATA"] = "./data"
|
||||||
|
env["CONF"] = "./conf"
|
||||||
|
|
||||||
for _, item := range os.Environ() {
|
for _, item := range os.Environ() {
|
||||||
parts := strings.SplitN(item, "=", 2)
|
parts := strings.SplitN(item, "=", 2)
|
||||||
|
|||||||
+4
-1
@@ -5,6 +5,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"iter"
|
"iter"
|
||||||
|
"log"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"fiatjaf.com/nostr/eventstore"
|
"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)
|
events.SaveEvent(event)
|
||||||
|
|
||||||
|
|||||||
+19
-11
@@ -5,6 +5,7 @@ import (
|
|||||||
"iter"
|
"iter"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -50,6 +51,12 @@ func GetInstance(hostname string) (*Instance, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MonitorInstances() {
|
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()
|
watcher, err := fsnotify.NewWatcher()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Failed to create file watcher: %v", err)
|
log.Printf("Failed to create file watcher: %v", err)
|
||||||
@@ -57,7 +64,7 @@ func MonitorInstances() {
|
|||||||
}
|
}
|
||||||
defer watcher.Close()
|
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)
|
log.Printf("Failed to watch config directory: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -108,7 +115,7 @@ func MakeInstance(hostname string) (*Instance, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
pubkey, err := nostr.PubKeyFromHex(config.Self.Pubkey)
|
pubkey, err := nostr.PubKeyFromHex(config.Info.Pubkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -116,7 +123,7 @@ func MakeInstance(hostname string) (*Instance, error) {
|
|||||||
events := &EventStore{
|
events := &EventStore{
|
||||||
Config: config,
|
Config: config,
|
||||||
Schema: &Schema{
|
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.Negentropy = true
|
||||||
instance.Relay.Info.Name = config.Self.Name
|
instance.Relay.Info.Name = config.Info.Name
|
||||||
instance.Relay.Info.Icon = config.Self.Icon
|
instance.Relay.Info.Icon = config.Info.Icon
|
||||||
instance.Relay.Info.PubKey = &pubkey
|
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.Self = nostr.GetPublicKey(secret)
|
||||||
instance.Relay.Info.Software = "https://github.com/coracle-social/zooid"
|
instance.Relay.Info.Software = "https://github.com/coracle-social/zooid"
|
||||||
instance.Relay.Info.Version = "v0.1.0"
|
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 := instance.Events.SaveEvent(event); err != nil {
|
||||||
if err != nil {
|
log.Printf("Failed to save invite event: %v", err)
|
||||||
log.Printf("Failed to generate invite event: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return event
|
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) {
|
func (instance *Instance) OnEventSaved(ctx context.Context, event nostr.Event) {
|
||||||
addEvent := func(newEvent 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)
|
log.Println(err)
|
||||||
} else {
|
} else {
|
||||||
if err := instance.Events.SaveEvent(newEvent); err != nil {
|
if err := instance.Events.SaveEvent(newEvent); err != nil {
|
||||||
|
|||||||
+2
-2
@@ -167,12 +167,12 @@ func (m *ManagementStore) Enable(instance *Instance) {
|
|||||||
reasons := make([]nip86.PubKeyReason, 0)
|
reasons := make([]nip86.PubKeyReason, 0)
|
||||||
|
|
||||||
reasons = append(reasons, nip86.PubKeyReason{
|
reasons = append(reasons, nip86.PubKeyReason{
|
||||||
PubKey: nostr.MustPubKeyFromHex(m.Config.Self.Pubkey),
|
PubKey: nostr.MustPubKeyFromHex(m.Config.Info.Pubkey),
|
||||||
Reason: "relay owner",
|
Reason: "relay owner",
|
||||||
})
|
})
|
||||||
|
|
||||||
reasons = append(reasons, nip86.PubKeyReason{
|
reasons = append(reasons, nip86.PubKeyReason{
|
||||||
PubKey: m.Config.Secret.Public(),
|
PubKey: m.Config.GetSelf(),
|
||||||
Reason: "relay self",
|
Reason: "relay self",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user