1
1
//! Shows how to use ACME to automatically acquire a TLS certificate for your BonsaiDb server.
2

            
3
use std::time::Duration;
4

            
5
use bonsaidb::{
6
    client::{url::Url, Client},
7
    core::connection::AsyncStorageConnection,
8
    local::config::Builder,
9
    server::{DefaultPermissions, Server, ServerConfiguration, LETS_ENCRYPT_STAGING_DIRECTORY},
10
};
11

            
12
const DOMAIN: &str = "example.com";
13

            
14
#[tokio::main]
15
async fn main() -> anyhow::Result<()> {
16
    env_logger::init();
17
    let server = Server::open(
18
        ServerConfiguration::new("acme-server-data.bonsaidb")
19
            .server_name(DOMAIN)
20
            .default_permissions(DefaultPermissions::AllowAll)
21
            .acme_contact_email("mailto:netops@example.com")
22
            .acme_directory(LETS_ENCRYPT_STAGING_DIRECTORY)
23
            .with_schema::<()>()?,
24
    )
25
    .await?;
26

            
27
    // The ACME registration is done via the TLS-ALPN-01 challenge, which occurs
28
    // on port 443 for LetsEncrypt. With the feature enabled, listening for
29
    // HTTPS traffic will automatically.
30
    let task_server = server.clone();
31
    tokio::spawn(async move {
32
        // This call is equivalent to listen_for_websockets_on("0.0.0.0:443",
33
        // true). This example, however, is meant to work with or without
34
        // websockets.
35
        task_server
36
            .listen_for_secure_tcp_on("0.0.0.0:443", ())
37
            .await
38
    });
39

            
40
    // Once the ACME process has succeded, the certificate_chain will be able to
41
    // be retrieved.
42
    while server.certificate_chain().await.is_err() {
43
        tokio::time::sleep(Duration::from_secs(1)).await;
44
    }
45

            
46
    // Spawn our QUIC-based protocol listener. This will use the same
47
    // certificate as the HTTPS port.
48
    let task_server = server.clone();
49
    tokio::spawn(async move { task_server.listen_on(5645).await });
50

            
51
    // Give a moment for the QUIC listener to start.
52
    tokio::time::sleep(Duration::from_millis(10)).await;
53

            
54
    // Test connecting using both clients.
55
    let client = Client::build(Url::parse(&format!("bonsaidb://{}", DOMAIN))?).finish()?;
56
    client.create_database::<()>("test-database", true).await?;
57

            
58
    #[cfg(feature = "websockets")]
59
    {
60
        let websockets = Client::build(Url::parse(&format!("wss://{}", DOMAIN))?)
61
            .finish()
62
            .await?;
63
        websockets
64
            .create_database::<()>("test-database", true)
65
            .await?;
66
    }
67

            
68
    Ok(())
69
}