Skip to content

Commit 5879f07

Browse files
committed
feature/nanocld: value of cockroachDB cert in a secret
1 parent 238dd29 commit 5879f07

12 files changed

Lines changed: 139 additions & 32 deletions

File tree

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,10 @@ Modern teams need faster iteration loops, secure multi‑tenant isolation, and a
7474
- Batteries included CLI & daemon.
7575
- Minimal host footprint; modular optional services.
7676

77+
See the [health-check documentation](https://docs.next-hat.com/docs/guides/nanocl/advanced-usage/health-checks)
78+
for rolling update readiness behavior and [TLS secret documentation](https://docs.next-hat.com/docs/guides/nanocl/advanced-usage/secret-tls)
79+
for certificate persistence.
80+
7781
## Installation
7882

7983
Nanocl supports **Linux**, **macOS**, and **Windows**. See the [Installation guide][nanocl_install_guide].
@@ -122,6 +126,7 @@ Next: explore [Get Started][nanocl_get_started].
122126
123127
## Latest news
124128

129+
- **Release**: [Nanocl 0.18.0](./doc/releases/nanocl-0.18.0.md)
125130
- **Blog**: [Automating deployment with GitHub Actions](https://docs.next-hat.com/blog/automating-deployment-with-github-actions-and-nanocl) on 24.11.2024
126131
- **Release**: [End to End TLS encryption and first step for network meshing](https://docs.next-hat.com/blog/nanocl-0.16) on 01.11.2024
127132
- **Release**: [Man page, Backup, Remove Orphans and more](https://docs.next-hat.com/blog/nanocl-0.15) on 11.06.2024

bin/nanocl/changelog.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Upgrade dependencies
1313

14+
### Added
15+
16+
- Cargo health status in command output.
17+
- Start and delete cargo instances on a specific node.
18+
19+
### Changed
20+
21+
- Statefile rendering and argument handling support required, multiple, described and default values.
22+
1423
## [0.17.1] - 17-09-2025
1524

1625
### Fixed
@@ -267,4 +276,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
267276
- Uninstall command
268277
- Upgrade command
269278
- Installer fetch template from our official repo or can take custom template path
270-

bin/nanocld/changelog.md

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1010
### Added
1111

1212
- Docker daemon background thread health check to restart nanocld if docker is not reachable.
13-
- Check docker health check to send correct even to delete old containers when updating a cargo.
13+
- Health-aware cargo rollouts: wait for replacement containers to become healthy before removing previous instances, and restore the previous instances when a replacement becomes unhealthy.
14+
- Persist CockroachDB TLS certificate, private-key and CA PEM values instead of filesystem paths; readable legacy path records are migrated at daemon startup.
15+
- Node placement and resource requirements for cargoes, and commands to start or delete a cargo on a specific node.
16+
17+
### Changed
18+
19+
- Use init containers for VM image handling.
1420

1521
## [0.17.0] - 2025-09-12
1622

@@ -264,4 +270,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
264270
- Namespace network information
265271
- Upgrade ncproxy to 0.3
266272
- Upgrade nproxy to 1.23.4.0
267-

bin/nanocld/specs/swagger.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6387,15 +6387,15 @@ components:
63876387
properties:
63886388
Certificate:
63896389
type: string
6390-
description: Path to the certificate
6390+
description: Certificate PEM contents
63916391
CertificateKey:
63926392
type: string
6393-
description: Path to the certificate key
6393+
description: Private-key PEM contents
63946394
CertificateClient:
63956395
type:
63966396
- string
63976397
- 'null'
6398-
description: Path to the certificate client
6398+
description: Certificate-authority PEM contents
63996399
VerifyClient:
64006400
type:
64016401
- boolean
@@ -6405,7 +6405,7 @@ components:
64056405
type:
64066406
- string
64076407
- 'null'
6408-
description: Path to the dhparam file
6408+
description: DH parameter contents
64096409
additionalProperties: false
64106410
ProxyStreamProtocol:
64116411
type: string

bin/nanocld/src/utils/store.rs

Lines changed: 91 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{net::ToSocketAddrs, time::Duration};
1+
use std::{fs, net::ToSocketAddrs, path::Path, time::Duration};
22

33
use diesel::{
44
PgConnection,
@@ -11,14 +11,77 @@ use ntex::{rt, time, web};
1111

1212
use nanocl_error::io::{IoError, IoResult};
1313
use nanocl_stubs::{
14-
config::DaemonConfig, proxy::ProxySslConfig, secret::SecretPartial,
14+
config::DaemonConfig,
15+
proxy::ProxySslConfig,
16+
secret::{SecretPartial, SecretUpdate},
1517
};
1618

1719
use crate::{
1820
models::{DBConn, Pool, SecretDb},
1921
repositories::generic::*,
2022
};
2123

24+
const DB_CERT_SECRET_NAME: &str = "cert.db.nanocl.io";
25+
26+
/// Read a legacy certificate path once, otherwise retain its PEM value.
27+
///
28+
/// The store URL still needs paths while creating the initial database
29+
/// connection. The persisted TLS secret must not retain those paths.
30+
fn load_certificate_value(
31+
value: &str,
32+
field: &str,
33+
) -> IoResult<(String, bool)> {
34+
let path = Path::new(value);
35+
if !path.is_file() {
36+
return Ok((value.to_owned(), false));
37+
}
38+
let value = fs::read_to_string(path).map_err(|err| {
39+
IoError::interrupted(
40+
"Database certificate",
41+
&format!("Unable to read {field} from {}: {err}", path.display()),
42+
)
43+
})?;
44+
Ok((value, true))
45+
}
46+
47+
fn load_db_tls_config(
48+
config: ProxySslConfig,
49+
) -> IoResult<(ProxySslConfig, bool)> {
50+
let (certificate, certificate_changed) =
51+
load_certificate_value(&config.certificate, "certificate")?;
52+
let (certificate_key, certificate_key_changed) =
53+
load_certificate_value(&config.certificate_key, "private key")?;
54+
let (certificate_client, certificate_client_changed) =
55+
match config.certificate_client {
56+
Some(certificate_client) => {
57+
let (value, changed) =
58+
load_certificate_value(&certificate_client, "certificate authority")?;
59+
(Some(value), changed)
60+
}
61+
None => (None, false),
62+
};
63+
let (dhparam, dhparam_changed) = match config.dhparam {
64+
Some(dhparam) => {
65+
let (value, changed) = load_certificate_value(&dhparam, "DH parameters")?;
66+
(Some(value), changed)
67+
}
68+
None => (None, false),
69+
};
70+
Ok((
71+
ProxySslConfig {
72+
certificate,
73+
certificate_key,
74+
certificate_client,
75+
verify_client: config.verify_client,
76+
dhparam,
77+
},
78+
certificate_changed
79+
|| certificate_key_changed
80+
|| certificate_client_changed
81+
|| dhparam_changed,
82+
))
83+
}
84+
2285
/// Create a pool connection to the store `cockroachdb`
2386
pub async fn create_pool(store_addr: &str) -> IoResult<Pool> {
2487
let store_addr = store_addr.to_owned();
@@ -91,10 +154,20 @@ async fn wait(store_addr: &str) -> IoResult<()> {
91154
}
92155

93156
async fn save_db_cert(store_addr: &str, pool: &Pool) -> IoResult<()> {
94-
if SecretDb::read_by_pk("cert.db.nanocl.io", pool)
95-
.await
96-
.is_ok()
97-
{
157+
if let Ok(existing) = SecretDb::read_by_pk(DB_CERT_SECRET_NAME, pool).await {
158+
let config = serde_json::from_value::<ProxySslConfig>(existing.data)?;
159+
let (config, changed) = load_db_tls_config(config)?;
160+
if changed {
161+
SecretDb::update_pk(
162+
DB_CERT_SECRET_NAME,
163+
&SecretUpdate {
164+
data: serde_json::to_value(config)?,
165+
metadata: None,
166+
},
167+
pool,
168+
)
169+
.await?;
170+
}
98171
return Ok(());
99172
}
100173
let url = url::Url::parse(store_addr).map_err(|err| {
@@ -103,7 +176,9 @@ async fn save_db_cert(store_addr: &str, pool: &Pool) -> IoResult<()> {
103176
&format!("invalid address format {err}"),
104177
)
105178
})?;
106-
// extract sslcert sslkey sslrootcert from query params
179+
// Extract sslcert, sslkey and sslrootcert from query parameters. These
180+
// paths are only used to establish this first connection; their PEM values
181+
// are what is persisted in CockroachDB.
107182
let mut query_pairs = url.query_pairs();
108183
let sslcert = query_pairs.find(|(k, _)| k == "sslcert").map(|(_, v)| v);
109184
let sslkey = query_pairs.find(|(k, _)| k == "sslkey").map(|(_, v)| v);
@@ -112,16 +187,21 @@ async fn save_db_cert(store_addr: &str, pool: &Pool) -> IoResult<()> {
112187
.map(|(_, v)| v);
113188
match (sslcert, sslkey, sslrootcert) {
114189
(Some(sslcert), Some(sslkey), Some(sslrootcert)) => {
190+
let (certificate, _) = load_certificate_value(&sslcert, "certificate")?;
191+
let (certificate_key, _) =
192+
load_certificate_value(&sslkey, "private key")?;
193+
let (certificate_client, _) =
194+
load_certificate_value(&sslrootcert, "certificate authority")?;
115195
SecretDb::create_from(
116196
&SecretPartial {
117-
name: "cert.db.nanocl.io".to_owned(),
197+
name: DB_CERT_SECRET_NAME.to_owned(),
118198
kind: "nanocl.io/tls".to_owned(),
119199
immutable: false,
120200
metadata: None,
121201
data: serde_json::to_value(ProxySslConfig {
122-
certificate: sslcert.to_string(),
123-
certificate_key: sslkey.to_string(),
124-
certificate_client: Some(sslrootcert.to_string()),
202+
certificate,
203+
certificate_key,
204+
certificate_client: Some(certificate_client),
125205
verify_client: None,
126206
dhparam: None,
127207
})?,

bin/ncdns/changelog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Core
1111

12+
- Integrated dnsmasq data plane and health endpoint; DNS rule updates no longer require a separate `ndns` container or `docker exec`.
13+
1214
## [0.9.0] - 2025-09-12
1315

1416
### Fixed
@@ -116,4 +118,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
116118
- Remove an existing rule
117119
- Default config ignore resolv.conf and hosts
118120
- Entry IpAddress can target a namespace with a syntax like: `{namespace name}.nsp`
119-

bin/ncproxy/changelog.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Default server with reuseport to avoid binding problem
1313
- More header in logs to support cloudflare real ip
14+
- Integrated Nginx data plane and health endpoint; proxy rules no longer require updates through a separate `nproxy` container.
1415

1516
### Changed
1617

1718
- Drop old ssl version support
19+
- Improve the default global Nginx configuration and HTTP 502 page.
1820

1921

2022
## [0.14.0] - 2025-09-12
@@ -204,4 +206,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
204206

205207
- Event Watching from nanocl daemon
206208
- Proxy Rule accept namespace as network
207-

bin/ncproxy/specs/swagger.yaml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -394,15 +394,15 @@ components:
394394
properties:
395395
Certificate:
396396
type: string
397-
description: Path to the certificate
397+
description: Certificate PEM contents
398398
CertificateKey:
399399
type: string
400-
description: Path to the certificate key
400+
description: Private-key PEM contents
401401
CertificateClient:
402402
type:
403403
- string
404404
- 'null'
405-
description: Path to the certificate client
405+
description: Certificate-authority PEM contents
406406
VerifyClient:
407407
type:
408408
- boolean
@@ -412,7 +412,7 @@ components:
412412
type:
413413
- string
414414
- 'null'
415-
description: Path to the dhparam file
415+
description: DH parameter contents
416416
additionalProperties: false
417417
ProxyStreamProtocol:
418418
type: string

bin/ndns/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
- Upgrade dependencies
1313

14+
### Removed
15+
16+
- The standalone DNS data plane is superseded by the dnsmasq integration in `ncdns`.
17+
1418
## [2.91.0-n0.9.0] - 2025-09-11
1519

1620
### Core

bin/nproxy/changelog.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1515

1616
- Default html page with 502
1717

18+
### Removed
19+
20+
- The standalone proxy data plane is superseded by the Nginx integration in `ncproxy`.
21+
1822
## [1.28.0-n0.14.0] - 2025-09-11
1923

2024
### Core

0 commit comments

Comments
 (0)