Loading plugins/letsencrypt/letsencrypt.cpp +28 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include "plugin.h" #include "conf.h" #include "blogi.h" namespace blogi { Loading Loading @@ -175,6 +176,9 @@ namespace blogi { // Initial delay to let the server start std::this_thread::sleep_for(std::chrono::seconds(10)); // On startup, load existing certs if present loadExistingCerts(); while (_running) { for (const auto &domain : _domains) { if (!_running) break; Loading @@ -194,6 +198,19 @@ namespace blogi { } } void loadExistingCerts() { // Check if any domain already has valid certs and load them for (const auto &domain : _domains) { std::string certFile = _certDir + "/" + domain + "/fullchain.pem"; std::string keyFile = _certDir + "/" + domain + "/privkey.pem"; if (std::filesystem::exists(certFile) && std::filesystem::exists(keyFile)) { if (Blogi::reloadSSL(certFile, keyFile)) { std::cerr << "[letsencrypt] Loaded existing cert for: " << domain << std::endl; } } } } bool needsRenewal(const std::string &domain) { std::string certPath = _certDir + "/" + domain + "/fullchain.pem"; if (!std::filesystem::exists(certPath)) Loading Loading @@ -250,6 +267,17 @@ namespace blogi { // For now, log that renewal was attempted std::cerr << "[letsencrypt] Certificate request for " << domain << " requires ACME v2 client implementation." << std::endl; // After successful cert acquisition, reload SSL in the running server std::string certFile = domainDir + "/fullchain.pem"; std::string keyFile = domainDir + "/privkey.pem"; if (std::filesystem::exists(certFile) && std::filesystem::exists(keyFile)) { if (Blogi::reloadSSL(certFile, keyFile)) { std::cerr << "[letsencrypt] SSL certificates reloaded for: " << domain << std::endl; } else { std::cerr << "[letsencrypt] Failed to reload SSL for: " << domain << std::endl; } } } static std::vector<uint8_t> generateP256Key() { Loading src/blogi.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,12 @@ static std::string cookieDomain(libhttppp::HttpRequest &req) { } std::unique_ptr<blogi::Config> blogi::Blogi::Cfg; libhttppp::HttpD *blogi::Blogi::HttpServer = nullptr; bool blogi::Blogi::reloadSSL(const std::string &certpath, const std::string &keypath, const std::string &password) { if (!HttpServer) return false; return HttpServer->reloadCertificates(certpath, keypath, password); } blogi::Blogi::Blogi(std::vector<netplus::socket*> serversocket,bool debug) : HttpEvent(serversocket){ Loading Loading @@ -2510,6 +2516,16 @@ void blogi::Blogi::ResponseEvent(libhttppp::HttpRequest& curreq,const int tid,UL if(PlgArgs->theme->Response(tid,curreq)) return; // First pass: try well-known paths (e.g. ACME challenges) against all plugins if(curreq.getRequestURL().compare(0, 12, "/.well-known/") == 0){ for(const blogi::Plugin::PluginData *curplg=BlogiPlg->getFirstPlugin(); curplg; curplg=curplg->getNextPlg()){ PluginApi *api=curplg->getInstace(); if(api->Response(tid,curreq)){ return; } } } for(const blogi::Plugin::PluginData *curplg=BlogiPlg->getFirstPlugin(); curplg; curplg=curplg->getNextPlg()){ PluginApi *api=curplg->getInstace(); std::string url=PlgArgs->config->getprefix(); Loading @@ -2534,6 +2550,7 @@ public: blogi::Blogi::Cfg->getsslkeypath(), blogi::Blogi::Cfg->getsslpassword() ){ blogi::Blogi::HttpServer = this; libhttppp::HTTPException httpexception; try { Loading src/blogi.h +4 −0 Original line number Diff line number Diff line Loading @@ -63,7 +63,11 @@ namespace blogi { DomainContext *resolveDomain(libhttppp::HttpRequest &curreq); // Reload SSL certificates at runtime (called after cert renewal) static bool reloadSSL(const std::string &certpath, const std::string &keypath, const std::string &password = ""); static std::unique_ptr<blogi::Config> Cfg; static libhttppp::HttpD *HttpServer; private: void initDomainContext(DomainContext &ctx, const DomainConfig &dcfg, bool debug); // Default domain (single-domain backward compat or fallback) Loading Loading
plugins/letsencrypt/letsencrypt.cpp +28 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ #include "plugin.h" #include "conf.h" #include "blogi.h" namespace blogi { Loading Loading @@ -175,6 +176,9 @@ namespace blogi { // Initial delay to let the server start std::this_thread::sleep_for(std::chrono::seconds(10)); // On startup, load existing certs if present loadExistingCerts(); while (_running) { for (const auto &domain : _domains) { if (!_running) break; Loading @@ -194,6 +198,19 @@ namespace blogi { } } void loadExistingCerts() { // Check if any domain already has valid certs and load them for (const auto &domain : _domains) { std::string certFile = _certDir + "/" + domain + "/fullchain.pem"; std::string keyFile = _certDir + "/" + domain + "/privkey.pem"; if (std::filesystem::exists(certFile) && std::filesystem::exists(keyFile)) { if (Blogi::reloadSSL(certFile, keyFile)) { std::cerr << "[letsencrypt] Loaded existing cert for: " << domain << std::endl; } } } } bool needsRenewal(const std::string &domain) { std::string certPath = _certDir + "/" + domain + "/fullchain.pem"; if (!std::filesystem::exists(certPath)) Loading Loading @@ -250,6 +267,17 @@ namespace blogi { // For now, log that renewal was attempted std::cerr << "[letsencrypt] Certificate request for " << domain << " requires ACME v2 client implementation." << std::endl; // After successful cert acquisition, reload SSL in the running server std::string certFile = domainDir + "/fullchain.pem"; std::string keyFile = domainDir + "/privkey.pem"; if (std::filesystem::exists(certFile) && std::filesystem::exists(keyFile)) { if (Blogi::reloadSSL(certFile, keyFile)) { std::cerr << "[letsencrypt] SSL certificates reloaded for: " << domain << std::endl; } else { std::cerr << "[letsencrypt] Failed to reload SSL for: " << domain << std::endl; } } } static std::vector<uint8_t> generateP256Key() { Loading
src/blogi.cpp +17 −0 Original line number Diff line number Diff line Loading @@ -96,6 +96,12 @@ static std::string cookieDomain(libhttppp::HttpRequest &req) { } std::unique_ptr<blogi::Config> blogi::Blogi::Cfg; libhttppp::HttpD *blogi::Blogi::HttpServer = nullptr; bool blogi::Blogi::reloadSSL(const std::string &certpath, const std::string &keypath, const std::string &password) { if (!HttpServer) return false; return HttpServer->reloadCertificates(certpath, keypath, password); } blogi::Blogi::Blogi(std::vector<netplus::socket*> serversocket,bool debug) : HttpEvent(serversocket){ Loading Loading @@ -2510,6 +2516,16 @@ void blogi::Blogi::ResponseEvent(libhttppp::HttpRequest& curreq,const int tid,UL if(PlgArgs->theme->Response(tid,curreq)) return; // First pass: try well-known paths (e.g. ACME challenges) against all plugins if(curreq.getRequestURL().compare(0, 12, "/.well-known/") == 0){ for(const blogi::Plugin::PluginData *curplg=BlogiPlg->getFirstPlugin(); curplg; curplg=curplg->getNextPlg()){ PluginApi *api=curplg->getInstace(); if(api->Response(tid,curreq)){ return; } } } for(const blogi::Plugin::PluginData *curplg=BlogiPlg->getFirstPlugin(); curplg; curplg=curplg->getNextPlg()){ PluginApi *api=curplg->getInstace(); std::string url=PlgArgs->config->getprefix(); Loading @@ -2534,6 +2550,7 @@ public: blogi::Blogi::Cfg->getsslkeypath(), blogi::Blogi::Cfg->getsslpassword() ){ blogi::Blogi::HttpServer = this; libhttppp::HTTPException httpexception; try { Loading
src/blogi.h +4 −0 Original line number Diff line number Diff line Loading @@ -63,7 +63,11 @@ namespace blogi { DomainContext *resolveDomain(libhttppp::HttpRequest &curreq); // Reload SSL certificates at runtime (called after cert renewal) static bool reloadSSL(const std::string &certpath, const std::string &keypath, const std::string &password = ""); static std::unique_ptr<blogi::Config> Cfg; static libhttppp::HttpD *HttpServer; private: void initDomainContext(DomainContext &ctx, const DomainConfig &dcfg, bool debug); // Default domain (single-domain backward compat or fallback) Loading