Skip to content

Commit

Permalink
feat(homeserver): use config.toml
Browse files Browse the repository at this point in the history
  • Loading branch information
Nuhvi committed Aug 23, 2024
1 parent 2f33e55 commit 190d384
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 23 deletions.
82 changes: 82 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pubky-homeserver/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ dirs-next = "2.0.0"
flume = "0.11.0"
futures-util = "0.3.30"
heed = "0.20.3"
hex = "0.4.3"
pkarr = { version = "2.1.0", features = ["async"] }
postcard = { version = "1.0.8", features = ["alloc"] }
pubky-common = { version = "0.1.0", path = "../pubky-common" }
serde = { version = "1.0.204", features = ["derive"] }
tokio = { version = "1.37.0", features = ["full"] }
toml = "0.8.19"
tower-cookies = "0.10.0"
tower-http = { version = "0.5.2", features = ["cors", "trace"] }
tracing = "0.1.40"
Expand Down
23 changes: 23 additions & 0 deletions pubky-homeserver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Pubky Homeserver

## Usage

Use `cargo run`

```bash
cargo run -- --config=./src/config.toml
```

Or Build first then run from target.

Build

```bash
cargo build --release
```

Run with an optional config file

```bash
../target/release/pubky-homeserver --config=./src/config.toml
```
64 changes: 44 additions & 20 deletions pubky-homeserver/src/config.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
//! Configuration for the server
use anyhow::{anyhow, Result};
use anyhow::{anyhow, Context, Result};
use pkarr::Keypair;
use serde::{Deserialize, Deserializer, Serialize};
use std::{
fmt::Debug,
path::{Path, PathBuf},
time::Duration,
};
use tracing::info;
// use serde::{Deserialize, Serialize};
use std::{fmt::Debug, path::PathBuf, time::Duration};

use pubky_common::timestamp::Timestamp;

const DEFAULT_HOMESERVER_PORT: u16 = 6287;
const DEFAULT_STORAGE_DIR: &str = "pubky";

/// Server configuration
#[derive(
// Serialize, Deserialize,
Clone,
)]
#[derive(Serialize, Deserialize, Clone)]
pub struct Config {
port: Option<u16>,
bootstrap: Option<Vec<String>>,
Expand All @@ -24,20 +25,22 @@ pub struct Config {
///
/// Defaults to a directory in the OS data directory
storage: Option<PathBuf>,
keypair: Keypair,
#[serde(deserialize_with = "secret_key_deserialize")]
secret_key: Option<[u8; 32]>,

dht_request_timeout: Option<Duration>,
}

impl Config {
// /// Load the config from a file.
// pub async fn load(path: impl AsRef<Path>) -> Result<Config> {
// let s = tokio::fs::read_to_string(path.as_ref())
// .await
// .with_context(|| format!("failed to read {}", path.as_ref().to_string_lossy()))?;
// let config: Config = toml::from_str(&s)?;
// Ok(config)
// }
/// Load the config from a file.
pub async fn load(path: impl AsRef<Path>) -> Result<Config> {
let s = tokio::fs::read_to_string(path.as_ref())
.await
.with_context(|| format!("failed to read {}", path.as_ref().to_string_lossy()))?;

let config: Config = toml::from_str(&s)?;
Ok(config)
}

/// Testnet configurations
pub fn testnet() -> Self {
Expand All @@ -55,7 +58,6 @@ impl Config {
bootstrap,
storage,
port: Some(15411),
keypair: Keypair::from_secret_key(&[0_u8; 32]),
dht_request_timeout: Some(Duration::from_millis(10)),
..Default::default()
}
Expand Down Expand Up @@ -103,8 +105,8 @@ impl Config {
Ok(dir.join("homeserver"))
}

pub fn keypair(&self) -> &Keypair {
&self.keypair
pub fn keypair(&self) -> Keypair {
Keypair::from_secret_key(&self.secret_key.unwrap_or_default())
}

pub(crate) fn dht_request_timeout(&self) -> Option<Duration> {
Expand All @@ -119,12 +121,34 @@ impl Default for Config {
bootstrap: None,
domain: "localhost".to_string(),
storage: None,
keypair: Keypair::random(),
secret_key: None,
dht_request_timeout: None,
}
}
}

fn secret_key_deserialize<'de, D>(deserializer: D) -> Result<Option<[u8; 32]>, D::Error>
where
D: Deserializer<'de>,
{
let opt: Option<String> = Option::deserialize(deserializer)?;

match opt {
Some(s) => {
let bytes = hex::decode(s).map_err(serde::de::Error::custom)?;

if bytes.len() != 32 {
return Err(serde::de::Error::custom("Expected a 32-byte array"));
}

let mut arr = [0u8; 32];
arr.copy_from_slice(&bytes);
Ok(Some(arr))
}
None => Ok(None),
}
}

impl Debug for Config {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_map()
Expand Down
8 changes: 8 additions & 0 deletions pubky-homeserver/src/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Secret key (in hex) to generate the Homeserver's Keypair
secret_key = "0000000000000000000000000000000000000000000000000000000000000000"
# Domain to be published in Pkarr records for this server to be accessible by.
domain = "localhost"
# Port for the Homeserver to listen on.
port = 6287
# Storage directory Defaults to <System's Data Directory>
# storage = ""
12 changes: 11 additions & 1 deletion pubky-homeserver/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use anyhow::Result;
use pubky_homeserver::{config::Config, Homeserver};

Expand All @@ -8,8 +10,14 @@ struct Cli {
/// [tracing_subscriber::EnvFilter]
#[clap(short, long)]
tracing_env_filter: Option<String>,

/// Run Homeserver in a local testnet
#[clap(long)]
testnet: bool,

/// Optional Path to config file.
#[clap(short, long)]
config: Option<PathBuf>,
}

#[tokio::main]
Expand All @@ -25,8 +33,10 @@ async fn main() -> Result<()> {

let server = Homeserver::start(if args.testnet {
Config::testnet()
} else if let Some(config_path) = args.config {
Config::load(config_path).await?
} else {
Default::default()
Config::default()
})
.await?;

Expand Down
2 changes: 2 additions & 0 deletions pubky-homeserver/src/pkarr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub async fn publish_server_packet(
domain: &str,
port: u16,
) -> anyhow::Result<()> {
// TODO: Try to resolve first before publishing.

let mut packet = Packet::new_reply(0);

let mut svcb = SVCB::new(0, domain.try_into()?);
Expand Down
5 changes: 3 additions & 2 deletions pubky-homeserver/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ impl Homeserver {
pub async fn start(config: Config) -> Result<Self> {
debug!(?config);

let public_key = config.keypair().public_key();
let keypair = config.keypair();
let public_key = keypair.public_key();

let db = DB::open(&config.storage()?)?;

Expand Down Expand Up @@ -72,7 +73,7 @@ impl Homeserver {

info!("Homeserver listening on http://localhost:{port}");

publish_server_packet(pkarr_client, config.keypair(), config.domain(), port).await?;
publish_server_packet(pkarr_client, &keypair, config.domain(), port).await?;

info!("Homeserver listening on pubky://{public_key}");

Expand Down

0 comments on commit 190d384

Please sign in to comment.