Skip to content

Commit 0ec76d7

Browse files
committed
feat: [#415] add GF_SERVER_ROOT_URL to Grafana service in generated docker-compose
1 parent f2040e3 commit 0ec76d7

5 files changed

Lines changed: 48 additions & 1 deletion

File tree

src/application/services/rendering/docker_compose.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,18 @@ impl DockerComposeTemplateRenderingService {
318318
/// Apply Grafana credentials to environment context if Grafana is configured
319319
fn apply_grafana_env_context(env_context: EnvContext, user_inputs: &UserInputs) -> EnvContext {
320320
if let Some(grafana_config) = user_inputs.grafana() {
321+
let server_root_url = grafana_config.domain().map(|domain| {
322+
let scheme = if grafana_config.use_tls_proxy() {
323+
"https"
324+
} else {
325+
"http"
326+
};
327+
format!("{scheme}://{}", domain.as_str())
328+
});
321329
env_context.with_grafana(
322330
grafana_config.admin_user().to_string(),
323331
grafana_config.admin_password().expose_secret().to_string(),
332+
server_root_url,
324333
)
325334
} else {
326335
env_context

src/infrastructure/templating/docker_compose/template/wrappers/docker_compose/context/grafana.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ pub struct GrafanaServiceContext {
2323
/// Flattened for template compatibility - serializes ports/networks at top level.
2424
#[serde(flatten)]
2525
pub topology: ServiceTopology,
26+
27+
/// Server root URL for public dashboard share links (optional)
28+
///
29+
/// When set, this is injected as `GF_SERVER_ROOT_URL` env var so that
30+
/// Grafana generates correct absolute URLs for shared dashboards.
31+
/// Derived from the configured domain and TLS setting.
32+
#[serde(skip_serializing_if = "Option::is_none")]
33+
pub server_root_url: Option<String>,
2634
}
2735

2836
impl GrafanaServiceContext {
@@ -43,8 +51,17 @@ impl GrafanaServiceContext {
4351
.iter()
4452
.map(PortDefinition::from)
4553
.collect();
54+
let server_root_url = config.domain().map(|domain| {
55+
let scheme = if config.use_tls_proxy() {
56+
"https"
57+
} else {
58+
"http"
59+
};
60+
format!("{scheme}://{}", domain.as_str())
61+
});
4662
Self {
4763
topology: ServiceTopology::new(ports, networks),
64+
server_root_url,
4865
}
4966
}
5067

src/infrastructure/templating/docker_compose/template/wrappers/env/context.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,12 @@ pub struct GrafanaServiceConfig {
4949
pub admin_user: String,
5050
/// Grafana admin password (exposed from secrecy wrapper)
5151
pub admin_password: String,
52+
/// Grafana server root URL for correct public dashboard share links (optional)
53+
///
54+
/// Derived from the configured domain and TLS setting.
55+
/// Maps to the `GF_SERVER_ROOT_URL` environment variable.
56+
#[serde(skip_serializing_if = "Option::is_none")]
57+
pub server_root_url: Option<String>,
5258
}
5359

5460
/// Context for rendering the .env template
@@ -186,11 +192,19 @@ impl EnvContext {
186192
///
187193
/// * `admin_user` - Grafana admin username
188194
/// * `admin_password` - Grafana admin password (plain String, already exposed)
195+
/// * `server_root_url` - Optional full URL (e.g. `https://grafana.example.com`) for
196+
/// public dashboard share links; derived from domain + TLS setting
189197
#[must_use]
190-
pub fn with_grafana(mut self, admin_user: String, admin_password: String) -> Self {
198+
pub fn with_grafana(
199+
mut self,
200+
admin_user: String,
201+
admin_password: String,
202+
server_root_url: Option<String>,
203+
) -> Self {
191204
self.grafana = Some(GrafanaServiceConfig {
192205
admin_user,
193206
admin_password,
207+
server_root_url,
194208
});
195209
self
196210
}

templates/docker-compose/.env.tera

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,8 @@ MYSQL_PASSWORD='{{ mysql.password }}'
5555
# WARNING: Change default credentials in production deployments for security
5656
GF_SECURITY_ADMIN_USER='{{ grafana.admin_user }}'
5757
GF_SECURITY_ADMIN_PASSWORD='{{ grafana.admin_password }}'
58+
{%- if grafana.server_root_url %}
59+
# Grafana server root URL — used to generate correct public dashboard share links
60+
GF_SERVER_ROOT_URL='{{ grafana.server_root_url }}'
61+
{%- endif %}
5862
{%- endif %}

templates/docker-compose/docker-compose.yml.tera

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ services:
173173
environment:
174174
- GF_SECURITY_ADMIN_USER=${GF_SECURITY_ADMIN_USER}
175175
- GF_SECURITY_ADMIN_PASSWORD=${GF_SECURITY_ADMIN_PASSWORD}
176+
{%- if grafana.server_root_url %}
177+
- GF_SERVER_ROOT_URL=${GF_SERVER_ROOT_URL}
178+
{%- endif %}
176179
volumes:
177180
- ./storage/grafana/data:/var/lib/grafana
178181
- ./storage/grafana/provisioning:/etc/grafana/provisioning:ro

0 commit comments

Comments
 (0)