commit f2716b52aefe4da80629ae555ab13466d3044286
parent d410cf28ae2c3e098c54505ebe0ed79769367c71
Author: triesap <tyson@radroots.org>
Date: Sun, 22 Mar 2026 19:09:09 +0000
config: allow localhost http discovery templates
Diffstat:
3 files changed, 42 insertions(+), 22 deletions(-)
diff --git a/.env.example b/.env.example
@@ -5,29 +5,29 @@ MYC_SERVICE_INSTANCE_NAME=myc
MYC_LOGGING_FILTER=info,myc=info
MYC_PATHS_STATE_DIR=var
-MYC_PATHS_SIGNER_IDENTITY_PATH=identity.json
-MYC_PATHS_USER_IDENTITY_PATH=user-identity.json
+MYC_PATHS_SIGNER_IDENTITY_PATH=var/signer-identity.json
+MYC_PATHS_USER_IDENTITY_PATH=var/user-identity.json
MYC_AUDIT_DEFAULT_READ_LIMIT=200
MYC_AUDIT_MAX_ACTIVE_FILE_BYTES=262144
MYC_AUDIT_MAX_ARCHIVED_FILES=8
MYC_DISCOVERY_ENABLED=true
-MYC_DISCOVERY_DOMAIN=signer.example.com
+MYC_DISCOVERY_DOMAIN=localhost
MYC_DISCOVERY_HANDLER_IDENTIFIER=myc
-MYC_DISCOVERY_APP_IDENTITY_PATH=app-identity.json
-MYC_DISCOVERY_PUBLIC_RELAYS=wss://relay.example.com
-MYC_DISCOVERY_PUBLISH_RELAYS=wss://relay.example.com
-MYC_DISCOVERY_NOSTRCONNECT_URL_TEMPLATE=https://signer.example.com/connect?uri=<nostrconnect>
-MYC_DISCOVERY_NIP05_OUTPUT_PATH=public/.well-known/nostr.json
+MYC_DISCOVERY_APP_IDENTITY_PATH=var/app-identity.json
+MYC_DISCOVERY_PUBLIC_RELAYS=ws://localhost:8080
+MYC_DISCOVERY_PUBLISH_RELAYS=ws://localhost:8080
+MYC_DISCOVERY_NOSTRCONNECT_URL_TEMPLATE=http://localhost/connect?uri=<nostrconnect>
+MYC_DISCOVERY_NIP05_OUTPUT_PATH=var/public/.well-known/nostr.json
MYC_DISCOVERY_METADATA_NAME=myc
-MYC_DISCOVERY_METADATA_DISPLAY_NAME=Mycorrhiza
-MYC_DISCOVERY_METADATA_ABOUT=NIP-46 signer
-MYC_DISCOVERY_METADATA_WEBSITE=https://signer.example.com
-MYC_DISCOVERY_METADATA_PICTURE=https://signer.example.com/logo.png
+MYC_DISCOVERY_METADATA_DISPLAY_NAME=Radroots Signer
+MYC_DISCOVERY_METADATA_ABOUT=Radroots NIP-46 signer
+MYC_DISCOVERY_METADATA_WEBSITE=https://radroots.org
+MYC_DISCOVERY_METADATA_PICTURE=
MYC_POLICY_CONNECTION_APPROVAL=explicit_user
MYC_TRANSPORT_ENABLED=true
MYC_TRANSPORT_CONNECT_TIMEOUT_SECS=10
-MYC_TRANSPORT_RELAYS=wss://relay.example.com
+MYC_TRANSPORT_RELAYS=ws://localhost:8080
diff --git a/src/audit.rs b/src/audit.rs
@@ -709,6 +709,8 @@ fn now_unix_secs() -> u64 {
#[cfg(test)]
mod tests {
+ use std::fs;
+
use radroots_nostr_signer::prelude::RadrootsNostrSignerConnectionId;
use crate::config::MycAuditConfig;
diff --git a/src/config.rs b/src/config.rs
@@ -694,18 +694,24 @@ fn validate_nostrconnect_url_template(template: &str) -> Result<(), MycError> {
.to_owned(),
));
}
- if !trimmed.starts_with("https://") {
- return Err(MycError::InvalidConfig(
- "discovery.nostrconnect_url_template must start with `https://`".to_owned(),
- ));
- }
let candidate = trimmed.replace("<nostrconnect>", "nostrconnect%3A%2F%2Fclient");
- nostr::Url::parse(&candidate).map_err(|source| {
+ let url = nostr::Url::parse(&candidate).map_err(|source| {
MycError::InvalidConfig(format!(
"discovery.nostrconnect_url_template is invalid: {source}"
))
})?;
- Ok(())
+
+ match url.scheme() {
+ "https" => Ok(()),
+ "http" if discovery_host_is_local(url.host_str()) => Ok(()),
+ _ => Err(MycError::InvalidConfig(
+ "discovery.nostrconnect_url_template must use `https://`, except loopback hosts may use `http://`".to_owned(),
+ )),
+ }
+}
+
+fn discovery_host_is_local(host: Option<&str>) -> bool {
+ matches!(host, Some("localhost" | "127.0.0.1" | "::1"))
}
#[cfg(test)]
@@ -894,6 +900,18 @@ MYC_UNKNOWN=nope
}
#[test]
+ fn discovery_validation_allows_localhost_http_nostrconnect_template() {
+ let mut config = MycConfig::default();
+ config.discovery.enabled = true;
+ config.discovery.domain = Some("localhost".to_owned());
+ config.discovery.public_relays = vec!["ws://localhost:8080".to_owned()];
+ config.discovery.nostrconnect_url_template =
+ Some("http://localhost/connect?uri=<nostrconnect>".to_owned());
+
+ config.validate().expect("localhost http template");
+ }
+
+ #[test]
fn discovery_validation_rejects_invalid_nostrconnect_template() {
let mut config = MycConfig::default();
config.discovery.enabled = true;
@@ -920,12 +938,12 @@ MYC_UNKNOWN=nope
assert!(config.discovery.enabled);
assert_eq!(
config.discovery.domain.as_deref(),
- Some("signer.example.com")
+ Some("localhost")
);
assert_eq!(config.discovery.handler_identifier, "myc");
assert_eq!(
config.discovery.nip05_output_path,
- Some(PathBuf::from("public/.well-known/nostr.json"))
+ Some(PathBuf::from("var/public/.well-known/nostr.json"))
);
}
}