Skip to content

Commit

Permalink
Enable redis as a caddy shared storage module (#77)
Browse files Browse the repository at this point in the history
- Lets engineers share letsencrypt storage
- Reduces the amount of calls we make to letsencrypt
- Reduces the amount of rate limits we hit
  • Loading branch information
ostenbom authored Apr 8, 2024
1 parent b4d1ab9 commit 7632234
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 2 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

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

2 changes: 1 addition & 1 deletion linkup-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "linkup-cli"
version = "0.2.11"
version = "0.2.12"
edition = "2021"

[[bin]]
Expand Down
1 change: 1 addition & 0 deletions linkup-cli/src/local_dns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub fn install(config_arg: &Option<String>) -> Result<()> {
ensure_resolver_dir()?;
install_resolvers(&input_config.top_level_domains())?;
services::caddy::install_cloudflare_package()?;
services::caddy::install_redis_package()?;

if fs::write(linkup_file_path(LINKUP_LOCALDNS_INSTALL), "").is_err() {
return Err(CliError::LocalDNSInstall(format!(
Expand Down
59 changes: 59 additions & 0 deletions linkup-cli/src/services/caddy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,44 @@ pub fn install_cloudflare_package() -> Result<()> {
Ok(())
}

pub fn install_redis_package() -> Result<()> {
Command::new("caddy")
.args(["add-package", "github.com/pberkel/caddy-storage-redis"])
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.map_err(|err| CliError::StartCaddy(err.to_string()))?;

Ok(())
}

fn write_caddyfile(domains: &[String]) -> Result<()> {
let mut redis_storage = String::new();

if let Ok(redis_url) = std::env::var("LINKUP_CERT_STORAGE_REDIS_URL") {
// This is worth doing to avoid confusion while the redis storage module is new
check_redis_installed()?;

let url = url::Url::parse(&redis_url)
.map_err(|_| CliError::StartCaddy(format!("Invalid REDIS_URL: {}", redis_url)))?;
redis_storage = format!(
"
storage redis {{
host {}
port {}
username \"{}\"
password \"{}\"
key_prefix \"caddy\"
compression true
}}
",
url.host().unwrap(),
url.port().unwrap_or(6379),
url.username(),
url.password().unwrap(),
);
}

let caddy_template = format!(
"
{{
Expand All @@ -72,6 +109,7 @@ fn write_caddyfile(domains: &[String]) -> Result<()> {
log {{
output file {}
}}
{}
}}
{} {{
Expand All @@ -82,6 +120,7 @@ fn write_caddyfile(domains: &[String]) -> Result<()> {
}}
",
linkup_file_path(LOG_FILE).display(),
redis_storage,
domains.join(", "),
LINKUP_LOCALSERVER_PORT,
LINKUP_CF_TLS_API_ENV_VAR,
Expand All @@ -97,3 +136,23 @@ fn write_caddyfile(domains: &[String]) -> Result<()> {

Ok(())
}

fn check_redis_installed() -> Result<()> {
let output = Command::new("caddy")
.arg("list-modules")
.output()
.map_err(|err| CliError::StartCaddy(err.to_string()))?;

let output_str = String::from_utf8(output.stdout).map_err(|_| {
CliError::StartCaddy("Failed to parse caddy list-modules output".to_string())
})?;

if !output_str.contains("redis") {
println!("Redis shared storage is a new feature! You need to uninstall and reinstall local-dns to use it.");
println!("Run `linkup local-dns uninstall && linkup local-dns install`");

return Err(CliError::StartCaddy("Redis module not found".to_string()));
}

Ok(())
}

0 comments on commit 7632234

Please sign in to comment.