Remove complex SIGHUP reload feature, use simple restart instead

- Remove tokio signal handling and mutex-based TLS acceptor reloading
- Simplify main loop back to basic connection acceptance
- Update systemd service to remove ExecReload
- Change certbot hook to use systemctl restart instead of reload
- Maintain <1s restart time for certificate updates
- Eliminate user confusion about partial config reloading
This commit is contained in:
Jeena 2026-01-16 22:09:51 +00:00
parent caf9d0984f
commit b9380483d2
3 changed files with 24 additions and 76 deletions

22
dist/INSTALL.md vendored
View file

@ -202,7 +202,7 @@ See `config.toml` for all available options. Key settings:
## Certificate Management ## Certificate Management
The server supports automatic certificate reloading via SIGHUP signals. The server uses standard systemd restart for certificate updates. Restart time is less than 1 second.
### Let's Encrypt Integration ### Let's Encrypt Integration
@ -210,28 +210,28 @@ For automatic certificate renewal with certbot:
```bash ```bash
# Create post-renewal hook # Create post-renewal hook
sudo tee /etc/letsencrypt/renewal-hooks/post/reload-pollux.sh > /dev/null << 'EOF' sudo tee /etc/letsencrypt/renewal-hooks/post/restart-pollux.sh > /dev/null << 'EOF'
#!/bin/bash #!/bin/bash
# Reload Pollux after Let's Encrypt certificate renewal # Restart Pollux after Let's Encrypt certificate renewal
systemctl reload pollux systemctl restart pollux
logger -t certbot-pollux-reload "Reloaded pollux after certificate renewal" logger -t certbot-pollux-restart "Restarted pollux after certificate renewal"
EOF EOF
# Make it executable # Make it executable
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/reload-pollux.sh sudo chmod +x /etc/letsencrypt/renewal-hooks/post/restart-pollux.sh
# Test the hook # Test the hook
sudo /etc/letsencrypt/renewal-hooks/post/reload-pollux.sh sudo /etc/letsencrypt/renewal-hooks/post/restart-pollux.sh
``` ```
### Manual Certificate Reload ### Manual Certificate Update
```bash ```bash
# Reload certificates without restarting # Restart server to load new certificates
sudo systemctl reload pollux sudo systemctl restart pollux
# Check reload in logs # Check restart in logs
sudo journalctl -u pollux -f sudo journalctl -u pollux -f
``` ```

1
dist/pollux.service vendored
View file

@ -6,7 +6,6 @@ Wants=network.target
[Service] [Service]
Type=simple Type=simple
ExecStart=/usr/local/bin/pollux ExecStart=/usr/local/bin/pollux
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure Restart=on-failure
RestartSec=5 RestartSec=5
User=gemini User=gemini

View file

@ -8,32 +8,10 @@ use clap::Parser;
use rustls::ServerConfig; use rustls::ServerConfig;
use std::path::Path; use std::path::Path;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::Mutex;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tokio::signal::unix::{signal, SignalKind};
use tokio_rustls::TlsAcceptor; use tokio_rustls::TlsAcceptor;
use logging::init_logging; use logging::init_logging;
async fn reload_tls_acceptor(
cert_path: &str,
key_path: &str,
) -> Result<TlsAcceptor, Box<dyn std::error::Error>> {
tracing::info!("Reloading TLS certificates");
let certs = tls::load_certs(cert_path)?;
let key = tls::load_private_key(key_path)?;
let config = ServerConfig::builder()
.with_safe_defaults()
.with_no_client_auth()
.with_single_cert(certs, key)?;
let acceptor = TlsAcceptor::from(Arc::new(config));
tracing::info!("TLS certificates reloaded successfully");
Ok(acceptor)
}
fn print_startup_info(host: &str, port: u16, root: &str, cert: &str, key: &str, log_level: Option<&str>, max_concurrent: usize) { fn print_startup_info(host: &str, port: u16, root: &str, cert: &str, key: &str, log_level: Option<&str>, max_concurrent: usize) {
println!("Pollux Gemini Server"); println!("Pollux Gemini Server");
println!("Listening on: {}:{}", host, port); println!("Listening on: {}:{}", host, port);
@ -126,56 +104,27 @@ async fn main() {
.with_no_client_auth() .with_no_client_auth()
.with_single_cert(certs, key).unwrap(); .with_single_cert(certs, key).unwrap();
let initial_acceptor = TlsAcceptor::from(Arc::new(config)); let acceptor = TlsAcceptor::from(Arc::new(config));
let acceptor = Arc::new(Mutex::new(initial_acceptor));
let listener = TcpListener::bind(format!("{}:{}", bind_host, port)).await.unwrap(); let listener = TcpListener::bind(format!("{}:{}", bind_host, port)).await.unwrap();
// Create SIGHUP signal handler for certificate reload
let mut sighup = signal(SignalKind::hangup())
.map_err(|e| format!("Failed to create SIGHUP handler: {}", e))
.unwrap();
// Print startup information // Print startup information
print_startup_info(&bind_host, port, &root, &cert_path, &key_path, Some(log_level), max_concurrent_requests); print_startup_info(&bind_host, port, &root, &cert_path, &key_path, Some(log_level), max_concurrent_requests);
loop { loop {
tokio::select! { let (stream, _) = listener.accept().await.unwrap();
// Handle new connections tracing::debug!("Accepted connection from {}", stream.peer_addr().unwrap_or_else(|_| "unknown".parse().unwrap()));
result = listener.accept() => { let acceptor = acceptor.clone();
let (stream, _) = result.unwrap(); let dir = root.clone();
tracing::debug!("Accepted connection from {}", stream.peer_addr().unwrap_or_else(|_| "unknown".parse().unwrap())); let expected_hostname = hostname.clone();
let acceptor = Arc::clone(&acceptor); let max_concurrent = max_concurrent_requests;
let dir = root.clone(); let test_delay = test_processing_delay;
let expected_hostname = hostname.clone(); tokio::spawn(async move {
let max_concurrent = max_concurrent_requests; if let Ok(stream) = acceptor.accept(stream).await {
let test_delay = test_processing_delay; if let Err(e) = server::handle_connection(stream, &dir, &expected_hostname, port, max_concurrent, test_delay).await {
tokio::spawn(async move { tracing::error!("Error handling connection: {}", e);
let acceptor_guard = acceptor.lock().await;
if let Ok(stream) = acceptor_guard.accept(stream).await {
drop(acceptor_guard); // Release lock before long-running handler
if let Err(e) = server::handle_connection(stream, &dir, &expected_hostname, port, max_concurrent, test_delay).await {
tracing::error!("Error handling connection: {}", e);
}
}
});
}
// Handle SIGHUP for certificate reload
_ = sighup.recv() => {
tracing::info!("Received SIGHUP, reloading certificates");
match reload_tls_acceptor(&cert_path, &key_path).await {
Ok(new_acceptor) => {
let mut acceptor_guard = acceptor.lock().await;
*acceptor_guard = new_acceptor;
tracing::info!("TLS certificates reloaded successfully");
}
Err(e) => {
tracing::error!("Failed to reload TLS certificates: {}", e);
// Continue with old certificates
}
} }
} }
} });
} }
} }