Compare commits
5 Commits
cdd0eacdd8
...
797c8fd7f2
Author | SHA1 | Date | |
---|---|---|---|
|
797c8fd7f2 | ||
|
795817f99d | ||
|
4c1f843048 | ||
|
7a9ae81376 | ||
|
ef8c5827a0 |
@ -1,33 +0,0 @@
|
|||||||
origin:
|
|
||||||
store_dir_path: /tmp/domani_dev_env/origin
|
|
||||||
domain:
|
|
||||||
store_dir_path: /tmp/domani_dev_env/domain
|
|
||||||
builtins:
|
|
||||||
bar:
|
|
||||||
kind: git
|
|
||||||
url: a
|
|
||||||
branch_name: b
|
|
||||||
public: true
|
|
||||||
service:
|
|
||||||
http:
|
|
||||||
form_method: GET
|
|
||||||
proxied_domains:
|
|
||||||
foo:
|
|
||||||
url: http://127.0.0.1:9000
|
|
||||||
request_headers:
|
|
||||||
- name: x-foo
|
|
||||||
value: BAR
|
|
||||||
- name: host
|
|
||||||
value: hi
|
|
||||||
- name: user-agent
|
|
||||||
value: ""
|
|
||||||
gemini:
|
|
||||||
proxied_domains:
|
|
||||||
mediocregopher.com:
|
|
||||||
url: gemini://127.0.0.1:1965
|
|
||||||
passphrase: foobar
|
|
||||||
dns_records:
|
|
||||||
- kind: A
|
|
||||||
addr: 127.0.0.1
|
|
||||||
- kind: AAAA
|
|
||||||
addr: ::1
|
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
/target
|
/target
|
||||||
.cargo
|
.cargo
|
||||||
/result
|
/result
|
||||||
|
config.yml
|
||||||
|
@ -153,6 +153,7 @@ In order to open a shell with all necessary tooling (expected rust toolchain
|
|||||||
versions, etc...) simply do:
|
versions, etc...) simply do:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
cp config.yml.tpl config.yml
|
||||||
nix develop
|
nix develop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
14
config.yml.tpl
Normal file
14
config.yml.tpl
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# This is an example configuration file intended for use in development.
|
||||||
|
|
||||||
|
origin:
|
||||||
|
store_dir_path: /tmp/domani_dev_env/origin
|
||||||
|
domain:
|
||||||
|
store_dir_path: /tmp/domani_dev_env/domain
|
||||||
|
service:
|
||||||
|
passphrase: foobar
|
||||||
|
primary_domain: localhost
|
||||||
|
dns_records:
|
||||||
|
- kind: A
|
||||||
|
addr: 127.0.0.1
|
||||||
|
- kind: AAAA
|
||||||
|
addr: ::1
|
@ -48,8 +48,11 @@
|
|||||||
pkgs.nmap # ncat
|
pkgs.nmap # ncat
|
||||||
];
|
];
|
||||||
shellHook = ''
|
shellHook = ''
|
||||||
source $(pwd)/.env.dev
|
|
||||||
export CARGO_HOME=$(pwd)/.cargo
|
export CARGO_HOME=$(pwd)/.cargo
|
||||||
|
|
||||||
|
if [ -f "config.yml" ]; then
|
||||||
|
export DOMANI_CONFIG_PATH=config.yml
|
||||||
|
fi
|
||||||
'';
|
'';
|
||||||
} // opensslEnv);
|
} // opensslEnv);
|
||||||
});
|
});
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
pub mod acme;
|
pub mod acme;
|
||||||
pub mod checker;
|
pub mod checker;
|
||||||
mod config;
|
mod config;
|
||||||
|
pub mod gemini;
|
||||||
pub mod manager;
|
pub mod manager;
|
||||||
mod name;
|
mod name;
|
||||||
mod settings;
|
mod settings;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
|
mod tls;
|
||||||
|
|
||||||
pub use config::*;
|
pub use config::*;
|
||||||
pub use name::*;
|
pub use name::*;
|
||||||
|
@ -1,8 +1,2 @@
|
|||||||
pub mod manager;
|
pub mod manager;
|
||||||
pub mod store;
|
pub mod store;
|
||||||
|
|
||||||
mod private_key;
|
|
||||||
pub use self::private_key::PrivateKey;
|
|
||||||
|
|
||||||
mod certificate;
|
|
||||||
pub use self::certificate::Certificate;
|
|
||||||
|
@ -1,45 +0,0 @@
|
|||||||
use std::convert::{From, TryFrom};
|
|
||||||
use std::fmt;
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
use serde_with::{DeserializeFromStr, SerializeDisplay};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, DeserializeFromStr, SerializeDisplay)]
|
|
||||||
/// DER-encoded X.509, like rustls::Certificate.
|
|
||||||
pub struct Certificate(Vec<u8>);
|
|
||||||
|
|
||||||
impl FromStr for Certificate {
|
|
||||||
type Err = pem::PemError;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
Ok(Certificate(pem::parse(s)?.into_contents()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for Certificate {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
pem::Pem::new("CERTIFICATE", self.0.clone()).fmt(f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&openssl::x509::X509Ref> for Certificate {
|
|
||||||
type Error = openssl::error::ErrorStack;
|
|
||||||
|
|
||||||
fn try_from(c: &openssl::x509::X509Ref) -> Result<Self, Self::Error> {
|
|
||||||
Ok(Certificate(c.to_der()?))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TryFrom<&Certificate> for openssl::x509::X509 {
|
|
||||||
type Error = openssl::error::ErrorStack;
|
|
||||||
|
|
||||||
fn try_from(c: &Certificate) -> Result<Self, Self::Error> {
|
|
||||||
openssl::x509::X509::from_der(&c.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Certificate> for rustls::Certificate {
|
|
||||||
fn from(c: Certificate) -> Self {
|
|
||||||
rustls::Certificate(c.0)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
use std::{sync, time};
|
use std::{sync, time};
|
||||||
|
|
||||||
use crate::domain::acme::{self, Certificate, PrivateKey};
|
use crate::domain::acme;
|
||||||
|
use crate::domain::tls::{Certificate, PrivateKey};
|
||||||
use crate::error::unexpected::{self, Intoable, Mappable};
|
use crate::error::unexpected::{self, Intoable, Mappable};
|
||||||
use crate::{domain, token, util};
|
use crate::{domain, token, util};
|
||||||
|
|
||||||
@ -80,7 +81,7 @@ impl ManagerImpl {
|
|||||||
.await
|
.await
|
||||||
.or_unexpected_while("building account")?;
|
.or_unexpected_while("building account")?;
|
||||||
|
|
||||||
let account_key: acme::PrivateKey = account
|
let account_key: PrivateKey = account
|
||||||
.private_key()
|
.private_key()
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.try_into()
|
.try_into()
|
||||||
@ -105,8 +106,8 @@ impl Manager for ManagerImpl {
|
|||||||
) -> util::BoxFuture<'mgr, Result<(), unexpected::Error>> {
|
) -> util::BoxFuture<'mgr, Result<(), unexpected::Error>> {
|
||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
// if there's an existing cert, and its expiry (determined by the soonest value of
|
// if there's an existing cert, and its expiry (determined by the soonest value of
|
||||||
// not_after amongst its parts) is later than 30 days from now, then we consider it to be
|
// not_after amongst its parts) is later than 30 days from now, then we consider it to
|
||||||
// synced.
|
// be synced.
|
||||||
if let Ok((_, cert)) = self.store.get_certificate(domain.as_str()) {
|
if let Ok((_, cert)) = self.store.get_certificate(domain.as_str()) {
|
||||||
let thirty_days = openssl::asn1::Asn1Time::days_from_now(30)
|
let thirty_days = openssl::asn1::Asn1Time::days_from_now(30)
|
||||||
.expect("parsed thirty days from now as Asn1Time");
|
.expect("parsed thirty days from now as Asn1Time");
|
||||||
@ -242,7 +243,7 @@ impl Manager for ManagerImpl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate an RSA private key for the certificate.
|
// Generate an RSA private key for the certificate.
|
||||||
let pkey = acme::PrivateKey::new();
|
let pkey = PrivateKey::new();
|
||||||
|
|
||||||
let acme2_pkey = (&pkey)
|
let acme2_pkey = (&pkey)
|
||||||
.try_into()
|
.try_into()
|
||||||
@ -287,8 +288,8 @@ impl Manager for ManagerImpl {
|
|||||||
"expected the order to return a certificate",
|
"expected the order to return a certificate",
|
||||||
))?
|
))?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|cert| acme::Certificate::try_from(cert.as_ref()))
|
.map(|cert| Certificate::try_from(cert.as_ref()))
|
||||||
.try_collect::<Vec<acme::Certificate>>()
|
.try_collect::<Vec<Certificate>>()
|
||||||
.or_unexpected_while("parsing certificate")?;
|
.or_unexpected_while("parsing certificate")?;
|
||||||
|
|
||||||
if cert.len() <= 1 {
|
if cert.len() <= 1 {
|
||||||
|
@ -2,7 +2,7 @@ use std::io::{Read, Write};
|
|||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::{fs, path};
|
use std::{fs, path};
|
||||||
|
|
||||||
use crate::domain::acme::{Certificate, PrivateKey};
|
use crate::domain::tls::{Certificate, PrivateKey};
|
||||||
use crate::error::unexpected::{self, Mappable};
|
use crate::error::unexpected::{self, Mappable};
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
||||||
|
101
src/domain/gemini.rs
Normal file
101
src/domain/gemini.rs
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
use crate::domain::tls::{Certificate, PrivateKey};
|
||||||
|
use crate::error::unexpected::{self, Mappable};
|
||||||
|
use crate::{domain, util};
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use std::{fs, path, sync};
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
struct StoredPKeyCert {
|
||||||
|
private_key: PrivateKey,
|
||||||
|
cert: Certificate,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FSStore {
|
||||||
|
cert_dir_path: path::PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FSStore {
|
||||||
|
pub fn new(dir_path: &path::Path) -> unexpected::Result<Self> {
|
||||||
|
let cert_dir_path = dir_path.join("certificates");
|
||||||
|
fs::create_dir_all(&cert_dir_path)
|
||||||
|
.map_unexpected_while(|| format!("creating dir {}", cert_dir_path.display()))?;
|
||||||
|
|
||||||
|
Ok(Self { cert_dir_path })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn pkey_cert_path(&self, domain: &domain::Name) -> path::PathBuf {
|
||||||
|
let mut domain = domain.as_str().to_string();
|
||||||
|
domain.push_str(".json");
|
||||||
|
self.cert_dir_path.join(domain)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_certificate(
|
||||||
|
&self,
|
||||||
|
domain: &domain::Name,
|
||||||
|
) -> unexpected::Result<(PrivateKey, Certificate)> {
|
||||||
|
let path = self.pkey_cert_path(domain);
|
||||||
|
|
||||||
|
let file = match util::open_file(path.as_path())
|
||||||
|
.map_unexpected_while(|| format!("opening file {}", path.display()))?
|
||||||
|
{
|
||||||
|
Some(file) => file,
|
||||||
|
None => {
|
||||||
|
let pkey = PrivateKey::new();
|
||||||
|
let cert = Certificate::new_self_signed(&pkey, domain)
|
||||||
|
.or_unexpected_while("creating self-signed cert")?;
|
||||||
|
|
||||||
|
let file = fs::File::create(path.as_path())
|
||||||
|
.map_unexpected_while(|| format!("creating file {}", path.display()))?;
|
||||||
|
|
||||||
|
let stored = StoredPKeyCert {
|
||||||
|
private_key: pkey,
|
||||||
|
cert,
|
||||||
|
};
|
||||||
|
|
||||||
|
serde_json::to_writer(file, &stored).or_unexpected_while("writing cert to file")?;
|
||||||
|
|
||||||
|
return Ok((stored.private_key, stored.cert));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let stored: StoredPKeyCert =
|
||||||
|
serde_json::from_reader(file).or_unexpected_while("parsing json")?;
|
||||||
|
|
||||||
|
Ok((stored.private_key, stored.cert))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl rustls::server::ResolvesServerCert for FSStore {
|
||||||
|
fn resolve(
|
||||||
|
&self,
|
||||||
|
client_hello: rustls::server::ClientHello<'_>,
|
||||||
|
) -> Option<sync::Arc<rustls::sign::CertifiedKey>> {
|
||||||
|
let domain = client_hello.server_name()?;
|
||||||
|
|
||||||
|
let res: unexpected::Result<Option<sync::Arc<rustls::sign::CertifiedKey>>> = (|| {
|
||||||
|
let domain: domain::Name = domain
|
||||||
|
.parse()
|
||||||
|
.map_unexpected_while(|| format!("parsing domain {domain}"))?;
|
||||||
|
|
||||||
|
let (pkey, cert) = self
|
||||||
|
.get_certificate(&domain)
|
||||||
|
.or_unexpected_while("fetching pkey/cert")?;
|
||||||
|
|
||||||
|
let pkey = rustls::sign::any_supported_type(&pkey.into()).or_unexpected()?;
|
||||||
|
|
||||||
|
Ok(Some(sync::Arc::new(rustls::sign::CertifiedKey {
|
||||||
|
cert: vec![cert.into()],
|
||||||
|
key: pkey,
|
||||||
|
ocsp: None,
|
||||||
|
sct_list: None,
|
||||||
|
})))
|
||||||
|
})();
|
||||||
|
|
||||||
|
res.unwrap_or_else(|err| {
|
||||||
|
log::error!("Unexpected error getting cert for domain {domain}: {err}");
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@ -149,7 +149,7 @@ pub trait Manager: Sync + Send + rustls::server::ResolvesServerCert {
|
|||||||
path: &str,
|
path: &str,
|
||||||
) -> Result<util::BoxByteStream, GetFileError>;
|
) -> Result<util::BoxByteStream, GetFileError>;
|
||||||
|
|
||||||
fn sync_cert<'mgr>(
|
fn sync_https_cert<'mgr>(
|
||||||
&'mgr self,
|
&'mgr self,
|
||||||
domain: domain::Name,
|
domain: domain::Name,
|
||||||
) -> util::BoxFuture<'mgr, Result<(), unexpected::Error>>;
|
) -> util::BoxFuture<'mgr, Result<(), unexpected::Error>>;
|
||||||
@ -256,7 +256,7 @@ impl Manager for ManagerImpl {
|
|||||||
Ok(f)
|
Ok(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sync_cert<'mgr>(
|
fn sync_https_cert<'mgr>(
|
||||||
&'mgr self,
|
&'mgr self,
|
||||||
domain: domain::Name,
|
domain: domain::Name,
|
||||||
) -> util::BoxFuture<'mgr, Result<(), unexpected::Error>> {
|
) -> util::BoxFuture<'mgr, Result<(), unexpected::Error>> {
|
||||||
@ -285,7 +285,7 @@ impl Manager for ManagerImpl {
|
|||||||
|
|
||||||
self.domain_store.set(&domain, &settings)?;
|
self.domain_store.set(&domain, &settings)?;
|
||||||
|
|
||||||
self.sync_cert(domain).await?;
|
self.sync_https_cert(domain).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
5
src/domain/tls.rs
Normal file
5
src/domain/tls.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod private_key;
|
||||||
|
pub use self::private_key::PrivateKey;
|
||||||
|
|
||||||
|
mod certificate;
|
||||||
|
pub use self::certificate::Certificate;
|
109
src/domain/tls/certificate.rs
Normal file
109
src/domain/tls/certificate.rs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
use crate::domain;
|
||||||
|
use crate::domain::tls::PrivateKey;
|
||||||
|
use crate::error::unexpected::{self, Mappable};
|
||||||
|
|
||||||
|
use std::convert::{From, TryFrom};
|
||||||
|
use std::fmt;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
use serde_with::{DeserializeFromStr, SerializeDisplay};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, DeserializeFromStr, SerializeDisplay)]
|
||||||
|
/// DER-encoded X.509, like rustls::Certificate.
|
||||||
|
pub struct Certificate(Vec<u8>);
|
||||||
|
|
||||||
|
impl Certificate {
|
||||||
|
pub fn new_self_signed(
|
||||||
|
pkey: &PrivateKey,
|
||||||
|
domain: &domain::Name,
|
||||||
|
) -> unexpected::Result<Certificate> {
|
||||||
|
use openssl::asn1::*;
|
||||||
|
use openssl::pkey::*;
|
||||||
|
use openssl::x509::extension::SubjectAlternativeName;
|
||||||
|
use openssl::x509::*;
|
||||||
|
|
||||||
|
let name = {
|
||||||
|
let mut builder = X509Name::builder().expect("initializing x509 name builder");
|
||||||
|
builder
|
||||||
|
.append_entry_by_text("CN", domain.as_str())
|
||||||
|
.or_unexpected_while("adding CN")?;
|
||||||
|
builder.build()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut builder = X509::builder().expect("initializing x509 builder");
|
||||||
|
builder
|
||||||
|
.set_subject_name(&name)
|
||||||
|
.or_unexpected_while("setting subject name")?;
|
||||||
|
|
||||||
|
// 9999/07/23
|
||||||
|
let not_after = Asn1Time::from_unix(253388296800).expect("initializing not_after");
|
||||||
|
builder
|
||||||
|
.set_not_after(not_after.as_ref())
|
||||||
|
.or_unexpected_while("setting not_after")?;
|
||||||
|
|
||||||
|
// Add domain as SAN
|
||||||
|
let san_extension = {
|
||||||
|
let mut san = SubjectAlternativeName::new();
|
||||||
|
san.dns(domain.as_str());
|
||||||
|
san.build(&builder.x509v3_context(None, None))
|
||||||
|
.or_unexpected_while("building SAN")?
|
||||||
|
};
|
||||||
|
|
||||||
|
builder
|
||||||
|
.append_extension(san_extension)
|
||||||
|
.or_unexpected_while("appending SAN")?;
|
||||||
|
|
||||||
|
let pkey: PKey<Private> = pkey.try_into().or_unexpected_while("converting PKey")?;
|
||||||
|
|
||||||
|
builder
|
||||||
|
.set_pubkey(pkey.as_ref())
|
||||||
|
.or_unexpected_while("setting pubkey")?;
|
||||||
|
|
||||||
|
builder
|
||||||
|
.sign(pkey.as_ref(), openssl::hash::MessageDigest::sha256())
|
||||||
|
.or_unexpected_while("signing with private key")?;
|
||||||
|
|
||||||
|
let cert = builder.build();
|
||||||
|
|
||||||
|
Ok(cert
|
||||||
|
.as_ref()
|
||||||
|
.try_into()
|
||||||
|
.or_unexpected_while("converting to cert")?)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Certificate {
|
||||||
|
type Err = pem::PemError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
Ok(Certificate(pem::parse(s)?.into_contents()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Certificate {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
pem::Pem::new("CERTIFICATE", self.0.clone()).fmt(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&openssl::x509::X509Ref> for Certificate {
|
||||||
|
type Error = openssl::error::ErrorStack;
|
||||||
|
|
||||||
|
fn try_from(c: &openssl::x509::X509Ref) -> Result<Self, Self::Error> {
|
||||||
|
Ok(Certificate(c.to_der()?))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&Certificate> for openssl::x509::X509 {
|
||||||
|
type Error = openssl::error::ErrorStack;
|
||||||
|
|
||||||
|
fn try_from(c: &Certificate) -> Result<Self, Self::Error> {
|
||||||
|
openssl::x509::X509::from_der(&c.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Certificate> for rustls::Certificate {
|
||||||
|
fn from(c: Certificate) -> Self {
|
||||||
|
rustls::Certificate(c.0)
|
||||||
|
}
|
||||||
|
}
|
@ -11,9 +11,9 @@ pub struct PrivateKey(Vec<u8>);
|
|||||||
impl PrivateKey {
|
impl PrivateKey {
|
||||||
#[allow(clippy::new_without_default)]
|
#[allow(clippy::new_without_default)]
|
||||||
pub fn new() -> PrivateKey {
|
pub fn new() -> PrivateKey {
|
||||||
acme2::gen_rsa_private_key(4096)
|
let rsa = openssl::rsa::Rsa::generate(4096).expect("generating RSA");
|
||||||
.expect("RSA private key generated")
|
let key = openssl::pkey::PKey::from_rsa(rsa).expect("creating private key from RSA");
|
||||||
.as_ref()
|
key.as_ref()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("RSA private key converted to internal representation")
|
.expect("RSA private key converted to internal representation")
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ use clap::Parser;
|
|||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use signal_hook_tokio::Signals;
|
use signal_hook_tokio::Signals;
|
||||||
|
|
||||||
use std::path;
|
use std::{path, sync};
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
#[command(version)]
|
#[command(version)]
|
||||||
@ -128,6 +128,10 @@ async fn main() {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let domain_gemini_store =
|
||||||
|
domani::domain::gemini::FSStore::new(&config.domain.store_dir_path.join("gemini"))
|
||||||
|
.unwrap_or_else(|e| panic!("domain gemini store initialization failed: {e}"));
|
||||||
|
|
||||||
let mut task_stack = domani::task_stack::TaskStack::new();
|
let mut task_stack = domani::task_stack::TaskStack::new();
|
||||||
|
|
||||||
let domain_manager = domani::domain::manager::ManagerImpl::new(
|
let domain_manager = domani::domain::manager::ManagerImpl::new(
|
||||||
@ -147,7 +151,7 @@ async fn main() {
|
|||||||
|
|
||||||
let _ = domani::service::gemini::Service::new(
|
let _ = domani::service::gemini::Service::new(
|
||||||
&mut task_stack,
|
&mut task_stack,
|
||||||
domain_manager.clone(),
|
sync::Arc::new(domain_gemini_store),
|
||||||
config.service,
|
config.service,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ pub async fn cert_refresher(
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ = domain_manager
|
_ = domain_manager
|
||||||
.sync_cert(primary_domain.clone())
|
.sync_https_cert(primary_domain.clone())
|
||||||
.await
|
.await
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| {
|
||||||
log::error!(
|
log::error!(
|
||||||
@ -141,7 +141,7 @@ pub async fn cert_refresher(
|
|||||||
|
|
||||||
for domain in domains_iter.unwrap().into_iter() {
|
for domain in domains_iter.unwrap().into_iter() {
|
||||||
let _ = domain_manager
|
let _ = domain_manager
|
||||||
.sync_cert(domain.clone())
|
.sync_https_cert(domain.clone())
|
||||||
.await
|
.await
|
||||||
.inspect_err(|err| {
|
.inspect_err(|err| {
|
||||||
log::error!("Error while getting cert for {}: {err}", domain.as_str(),)
|
log::error!("Error while getting cert for {}: {err}", domain.as_str(),)
|
||||||
|
3
static/foo.gmi
Normal file
3
static/foo.gmi
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# FOO
|
||||||
|
|
||||||
|
This is foo
|
7
static/foo.html
Normal file
7
static/foo.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>FOO</h1>
|
||||||
|
<p>This is the foo page</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
9
static/index.gmi
Normal file
9
static/index.gmi
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# INDEX
|
||||||
|
|
||||||
|
This is the gemini index.
|
||||||
|
|
||||||
|
=> foo /foo.gmi
|
||||||
|
|
||||||
|
=> bar /subdir/bar.gmi
|
||||||
|
|
||||||
|
=> penguin /penguin.jpg
|
9
static/index.html
Normal file
9
static/index.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>INDEX</h1>
|
||||||
|
<p>This is the index page.</p>
|
||||||
|
<p>Check out <a href="/foo.html">foo</a>.</p>
|
||||||
|
<p>Check out <a href="/subdir/foo.html">bar</a>.</p>
|
||||||
|
<img src="/penguin.jpg" />
|
||||||
|
</body>
|
||||||
|
</html>
|
BIN
static/penguin.jpg
Normal file
BIN
static/penguin.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 669 KiB |
3
static/subdir/bar.gmi
Normal file
3
static/subdir/bar.gmi
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# BAR
|
||||||
|
|
||||||
|
This is bar
|
7
static/subdir/bar.html
Normal file
7
static/subdir/bar.html
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>BAR</h1>
|
||||||
|
<p>This is the bar page</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
3
static/subdir/index.gmi
Normal file
3
static/subdir/index.gmi
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
# INDEX
|
||||||
|
|
||||||
|
This is the gemini index of the subdir.
|
6
static/subdir/index.html
Normal file
6
static/subdir/index.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<h1>INDEX</h1>
|
||||||
|
<p>This is the index page of the subdir</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Reference in New Issue
Block a user