From db1893900a5cb816cf258065c07ad4fa03d087c0 Mon Sep 17 00:00:00 2001 From: Moritz Schlarb Date: Fri, 30 Jan 2026 12:24:13 +0100 Subject: [PATCH 1/2] Introduce new MDCacheDir directive in config Mostly copied from MDStoreDir handling, but e.g. using ap_runtime_dir_relative where possible. --- src/mod_md.c | 3 ++- src/mod_md_config.c | 28 +++++++++++++++++++++++++++- src/mod_md_config.h | 2 ++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/mod_md.c b/src/mod_md.c index 349d187..9394a5d 100644 --- a/src/mod_md.c +++ b/src/mod_md.c @@ -277,10 +277,11 @@ static apr_status_t check_group_dir(md_store_t *store, md_store_group_t group, static apr_status_t setup_store(md_store_t **pstore, md_mod_conf_t *mc, apr_pool_t *p, server_rec *s) { - const char *base_dir; + const char *base_dir, *cache_dir; apr_status_t rv; base_dir = ap_server_root_relative(p, mc->base_dir); + cache_dir = ap_server_root_relative(p, mc->cache_dir); if (APR_SUCCESS != (rv = md_store_fs_init(pstore, p, base_dir))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10046)"setup store for %s", base_dir); diff --git a/src/mod_md_config.c b/src/mod_md_config.c index 9688714..237b44c 100644 --- a/src/mod_md_config.c +++ b/src/mod_md_config.c @@ -60,6 +60,11 @@ static md_mod_conf_t defmc = { NULL, /* base dirm by default state-dir-relative */ #else MD_DEFAULT_BASE_DIR, +#endif +#if AP_MODULE_MAGIC_AT_LEAST(20120211, 2) + NULL, /* cache dirm by default runtime-dir-relative */ +#else + MD_DEFAULT_BASE_DIR, #endif NULL, /* proxy url for outgoing http */ NULL, /* md_reg_t */ @@ -890,6 +895,19 @@ static const char *md_config_set_store_dir(cmd_parms *cmd, void *arg, const char return NULL; } +static const char *md_config_set_cache_dir(cmd_parms *cmd, void *arg, const char *value) +{ + md_srv_conf_t *sc = md_config_get(cmd->server); + const char *err; + + if ((err = md_conf_check_location(cmd, MD_LOC_NOT_MD))) { + return err; + } + sc->mc->cache_dir = value; + (void)arg; + return NULL; +} + static const char *set_port_map(md_mod_conf_t *mc, const char *value) { int net_port, local_port; @@ -1349,6 +1367,8 @@ const command_rec md_cmds[] = { "URL of a HTTP(S) proxy to use for outgoing connections"), AP_INIT_TAKE1("MDStoreDir", md_config_set_store_dir, NULL, RSRC_CONF, "the directory for file system storage of managed domain data."), + AP_INIT_TAKE1("MDCacheDir", md_config_set_cache_dir, NULL, RSRC_CONF, + "the directory for file system storage of temporary data."), AP_INIT_TAKE1("MDRenewWindow", md_config_set_renew_window, NULL, RSRC_CONF, "Time length for renewal before certificate expires (defaults to days)."), AP_INIT_TAKE1("MDRequireHttps", md_config_set_require_https, NULL, RSRC_CONF|OR_AUTHCFG, @@ -1428,7 +1448,11 @@ apr_status_t md_config_post_config(server_rec *s, apr_pool_t *p) mc->base_dir = ap_state_dir_relative(p, MD_DEFAULT_BASE_DIR); } #endif - +#if AP_MODULE_MAGIC_AT_LEAST(20120211, 2) + if (mc->cache_dir == NULL) { + mc->cache_dir = ap_runtime_dir_relative(p, MD_DEFAULT_BASE_DIR); + } +#endif return APR_SUCCESS; } @@ -1471,6 +1495,8 @@ const char *md_config_gets(const md_srv_conf_t *sc, md_config_var_t var) return sc->ca_proto? sc->ca_proto : defconf.ca_proto; case MD_CONFIG_BASE_DIR: return sc->mc->base_dir; + case MD_CONFIG_CACHE_DIR: + return sc->mc->cache_dir; case MD_CONFIG_PROXY: return sc->mc->proxy_url; case MD_CONFIG_CA_AGREEMENT: diff --git a/src/mod_md_config.h b/src/mod_md_config.h index 3159ec6..e531160 100644 --- a/src/mod_md_config.h +++ b/src/mod_md_config.h @@ -27,6 +27,7 @@ typedef enum { MD_CONFIG_CA_CONTACT, MD_CONFIG_CA_PROTO, MD_CONFIG_BASE_DIR, + MD_CONFIG_CACHE_DIR, MD_CONFIG_CA_AGREEMENT, MD_CONFIG_DRIVE_MODE, MD_CONFIG_RENEW_WINDOW, @@ -53,6 +54,7 @@ typedef struct md_mod_conf_t md_mod_conf_t; struct md_mod_conf_t { apr_array_header_t *mds; /* all md_t* defined in the config, shared */ const char *base_dir; /* base dir for store */ + const char *cache_dir; /* base dir for cache */ const char *proxy_url; /* proxy url to use (or NULL) */ struct md_reg_t *reg; /* md registry instance */ struct md_ocsp_reg_t *ocsp; /* ocsp status registry */ From 1740aefab974e2831a60b5148983f408e5a49310 Mon Sep 17 00:00:00 2001 From: Moritz Schlarb Date: Fri, 30 Jan 2026 14:53:04 +0100 Subject: [PATCH 2/2] Introduce cache_dir to more internals --- src/md_cmd.h | 1 + src/md_cmd_main.c | 2 +- src/md_store.h | 3 +++ src/md_store_fs.c | 21 +++++++++++++++++---- src/md_store_fs.h | 2 +- src/mod_md.c | 3 +-- 6 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/md_cmd.h b/src/md_cmd.h index eeeafc3..53d0452 100644 --- a/src/md_cmd.h +++ b/src/md_cmd.h @@ -34,6 +34,7 @@ struct md_cmd_ctx { apr_pool_t *p; const char *base_dir; + const char *cache_dir; const char *ca_url; const char *ca_file; struct apr_table_t *env; diff --git a/src/md_cmd_main.c b/src/md_cmd_main.c index 4329e28..379dc3f 100644 --- a/src/md_cmd_main.c +++ b/src/md_cmd_main.c @@ -174,7 +174,7 @@ static apr_status_t cmd_process(md_cmd_ctx *ctx, const md_cmd_t *cmd) fprintf(stderr, "need store directory for command: %s\n", cmd->name); return APR_EINVAL; } - if (APR_SUCCESS != (rv = md_store_fs_init(&ctx->store, ctx->p, ctx->base_dir))) { + if (APR_SUCCESS != (rv = md_store_fs_init(&ctx->store, ctx->p, ctx->base_dir, ctx->cache_dir))) { fprintf(stderr, "error %d creating store for: %s\n", rv, ctx->base_dir); return APR_EINVAL; } diff --git a/src/md_store.h b/src/md_store.h index 73c840f..dad5526 100644 --- a/src/md_store.h +++ b/src/md_store.h @@ -71,6 +71,9 @@ typedef enum { MD_SG_COUNT, /* number of storage groups, used in setups */ } md_store_group_t; +/* Test whether group is supposed to be in the ephemeral cache directory */ +#define MD_SG_CACHE(group) ((group == MD_SG_CHALLENGES) || (group == MD_SG_STAGING) || (group == MD_SG_TMP) || (group == MD_SG_OCSP)) + #define MD_FN_MD "md.json" #define MD_FN_JOB "job.json" #define MD_FN_HTTPD_JSON "httpd.json" diff --git a/src/md_store_fs.c b/src/md_store_fs.c index 77063bf..5facdaa 100644 --- a/src/md_store_fs.c +++ b/src/md_store_fs.c @@ -51,6 +51,7 @@ struct md_store_fs_t { md_store_t s; const char *base; /* base directory of store */ + const char *cache; /* base directory of cache */ perms_t def_perms; perms_t group_perms[MD_SG_COUNT]; md_store_fs_cb *event_cb; @@ -292,7 +293,8 @@ static apr_status_t setup_store_file(void *baton, apr_pool_t *p, apr_pool_t *pte return rv; } -apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *path) +apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, + const char *store_path, const char *cache_path) { md_store_fs_t *s_fs; apr_status_t rv = APR_SUCCESS; @@ -331,7 +333,8 @@ apr_status_t md_store_fs_init(md_store_t **pstore, apr_pool_t *p, const char *pa s_fs->group_perms[MD_SG_OCSP].dir = MD_FPROT_D_UALL_WREAD; s_fs->group_perms[MD_SG_OCSP].file = MD_FPROT_F_UALL_WREAD; - s_fs->base = apr_pstrdup(p, path); + s_fs->base = apr_pstrdup(p, store_path); + s_fs->cache = apr_pstrdup(p, cache_path); rv = md_util_is_dir(s_fs->base, p); if (APR_STATUS_IS_ENOENT(rv)) { @@ -411,8 +414,14 @@ static apr_status_t fs_get_fname(const char **pfname, if (group == MD_SG_NONE) { return md_util_path_merge(pfname, p, s_fs->base, aspect, NULL); } - return md_util_path_merge(pfname, p, - s_fs->base, md_store_group_name(group), name, aspect, NULL); + + if MD_SG_CACHE(group) { + return md_util_path_merge(pfname, p, s_fs->cache, + md_store_group_name(group), name, aspect, NULL); + } + + return md_util_path_merge(pfname, p, s_fs->base, + md_store_group_name(group), name, aspect, NULL); } static apr_status_t fs_get_dname(const char **pdname, @@ -424,6 +433,10 @@ static apr_status_t fs_get_dname(const char **pdname, *pdname = s_fs->base; return APR_SUCCESS; } + if MD_SG_CACHE(group) { + return md_util_path_merge(pdname, p, s_fs->cache, md_store_group_name(group), name, NULL); + } + return md_util_path_merge(pdname, p, s_fs->base, md_store_group_name(group), name, NULL); } diff --git a/src/md_store_fs.h b/src/md_store_fs.h index dcdb897..ab56044 100644 --- a/src/md_store_fs.h +++ b/src/md_store_fs.h @@ -39,7 +39,7 @@ struct md_store_t; #define MD_FPROT_D_UALL_WREAD (MD_FPROT_D_UALL_GREAD|APR_FPROT_WREAD|APR_FPROT_WEXECUTE) apr_status_t md_store_fs_init(struct md_store_t **pstore, apr_pool_t *p, - const char *path); + const char *store_path, const char *cache_path); apr_status_t md_store_fs_default_perms_set(struct md_store_t *store, diff --git a/src/mod_md.c b/src/mod_md.c index 9394a5d..88c5c04 100644 --- a/src/mod_md.c +++ b/src/mod_md.c @@ -283,7 +283,7 @@ static apr_status_t setup_store(md_store_t **pstore, md_mod_conf_t *mc, base_dir = ap_server_root_relative(p, mc->base_dir); cache_dir = ap_server_root_relative(p, mc->cache_dir); - if (APR_SUCCESS != (rv = md_store_fs_init(pstore, p, base_dir))) { + if (APR_SUCCESS != (rv = md_store_fs_init(pstore, p, base_dir, cache_dir))) { ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, APLOGNO(10046)"setup store for %s", base_dir); goto leave; } @@ -1598,4 +1598,3 @@ static void md_hooks(apr_pool_t *pool) #error "This version of mod_md requires Apache httpd 2.4.48 or newer." #endif /* AP_MODULE_MAGIC_AT_LEAST() */ } -