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::client::url::Url;
6
use bonsaidb::client::AsyncClient;
7
use bonsaidb::core::connection::AsyncStorageConnection;
8
use bonsaidb::local::config::Builder;
9
use bonsaidb::server::{
10
    DefaultPermissions, Server, ServerConfiguration, LETS_ENCRYPT_STAGING_DIRECTORY,
11
};
12

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

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

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

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

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

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

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

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

            
69
    Ok(())
70
}