feat(opnsense-config): add caddy module with configuration management

Introduce a new Caddy module within opnsense-config to manage Caddy server configurations. This includes enabling/disabling Caddy, setting ports, and reloading/restarting the service via OPNsense shell commands. Additionally, provide a sample Caddy configuration file for PXE booting and a test file in the pxe-http-files directory.
This commit is contained in:
2025-01-07 17:12:39 -05:00
parent 925e84e4d2
commit 81d40ec163
17 changed files with 342 additions and 17 deletions

View File

@@ -3,7 +3,7 @@ use std::{sync::Arc, time::Duration};
use crate::{
config::{SshConfigManager, SshCredentials, SshOPNSenseShell},
error::Error,
modules::{dhcp::DhcpConfig, dns::DnsConfig, load_balancer::LoadBalancerConfig, tftp::TftpConfig},
modules::{caddy::CaddyConfig, dhcp::DhcpConfig, dns::DnsConfig, load_balancer::LoadBalancerConfig, tftp::TftpConfig},
};
use log::{info, trace};
use opnsense_config_xml::OPNsense;
@@ -42,6 +42,10 @@ impl Config {
TftpConfig::new(&mut self.opnsense, self.shell.clone())
}
pub fn caddy(&mut self) -> CaddyConfig {
CaddyConfig::new(&mut self.opnsense, self.shell.clone())
}
pub fn load_balancer(&mut self) -> LoadBalancerConfig {
LoadBalancerConfig::new(&mut self.opnsense, self.shell.clone())
}
@@ -50,6 +54,17 @@ impl Config {
self.shell.upload_folder(source, destination).await
}
// Here maybe we should take ownership of `mut self` instead of `&mut self`
// I don't think there can be faulty pointers to previous versions of the config but I have a
// hard time wrapping my head around it right now :
// - the caller has a mutable reference to us
// - caller gets a reference to a piece of configuration (.haproxy.general.servers[0])
// - caller calls install_package wich reloads the config from remote
// - haproxy.general.servers[0] does not exist anymore
// - broken?
//
// Although I did not try explicitely the above workflow so maybe rust prevents taking a
// read-only reference across the &mut call
pub async fn install_package(&mut self, package_name: &str) -> Result<(), Error> {
info!("Installing opnsense package {package_name}");
let output = self.shell

View File

@@ -0,0 +1,49 @@
use std::sync::Arc;
use opnsense_config_xml::{Caddy, OPNsense, Pischem};
use crate::{config::OPNsenseShell, Error};
pub struct CaddyConfig<'a> {
opnsense: &'a mut OPNsense,
opnsense_shell: Arc<dyn OPNsenseShell>,
}
impl<'a> CaddyConfig<'a> {
pub fn new(opnsense: &'a mut OPNsense, opnsense_shell: Arc<dyn OPNsenseShell>) -> Self {
Self {
opnsense,
opnsense_shell,
}
}
pub fn get_full_config(&self) -> &Option<Pischem> {
&self.opnsense.pischem
}
fn with_caddy<F, R>(&mut self, f: F) -> R
where
F: FnOnce(&mut Caddy) -> R,
{
match &mut self.opnsense.pischem.as_mut() {
Some(pischem) => f(&mut pischem.caddy),
None => unimplemented!("Accessing caddy config is not supported when not available yet"),
}
}
pub fn enable(&mut self, enabled: bool) {
self.with_caddy(|caddy| {caddy.general.enabled = enabled as u8;
caddy.general.http_port = Some(8080);
caddy.general.https_port = Some(8443);
});
}
pub async fn reload_restart(&self) -> Result<(), Error> {
self.opnsense_shell.exec("configctl caddy stop").await?;
self.opnsense_shell.exec("configctl template reload OPNsense/Caddy").await?;
self.opnsense_shell.exec("configctl template reload OPNsense/Caddy/rc.conf.d").await?;
self.opnsense_shell.exec("configctl caddy validate").await?;
self.opnsense_shell.exec("configctl caddy start").await?;
Ok(())
}
}

View File

@@ -2,3 +2,4 @@ pub mod dhcp;
pub mod dns;
pub mod load_balancer;
pub mod tftp;
pub mod caddy;