Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.17.0
version: v4.0.2

- name: Helm lint
run: |
Expand Down Expand Up @@ -49,7 +49,7 @@ jobs:
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.17.0
version: v4.0.2

- name: Create kind cluster
uses: helm/kind-action@v1
Expand Down Expand Up @@ -82,7 +82,7 @@ jobs:
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.17.0
version: v4.0.2

- name: Create kind cluster
uses: helm/kind-action@v1
Expand Down Expand Up @@ -117,7 +117,7 @@ jobs:
- name: Set up Helm
uses: azure/setup-helm@v4
with:
version: v3.17.0
version: v4.0.2

- name: Create kind cluster
uses: helm/kind-action@v1
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
*.tgz
charts/*/charts/*.tgz

CLAUDE.md
34 changes: 34 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/),
and this project adheres to [Semantic Versioning](https://semver.org/).

## Unreleased

### Changed

- **Breaking:** Replaced raw DSN secret (`server.secrets.storeDsn`) with structured
`database.*` configuration. The chart now constructs the DSN internally from
`database.type`, `database.host`, `database.port`, `database.user`, `database.name`,
and `database.passwordSecret`. Users no longer need to build DSN strings.
- **Breaking:** Removed `server.config.store.engine`. Use `database.type` instead
(`sqlite`, `postgresql`, `mysql`).

### Added

- Structured database configuration via `database.*` values with per-engine defaults
(port 5432 for postgresql, 3306 for mysql).
- `database.sslMode` for PostgreSQL SSL mode control (default: `disable`).
- Initium `wait-for` init container: waits for external database to be reachable
before starting the server (TCP probe with 120s timeout and exponential backoff).
- Initium `seed` init container: creates the target database if it does not exist
via a declarative seed spec (`create_if_missing: true`).
- `DB_PASSWORD` environment variable injected into config-init via `secretKeyRef`
for DSN construction at render time.
- Seed spec rendered as `seed.yaml` in the server ConfigMap for non-sqlite engines.
- Unit tests for init container ordering, env var injection, and database-specific
rendering (120 tests, up from 110).
- CHANGELOG.md.

79 changes: 75 additions & 4 deletions charts/netbird/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ This chart deploys the NetBird self-hosted stack as two components:

The server uses a single `config.yaml` that is rendered from a ConfigMap template with sensitive values injected at pod startup from Kubernetes Secrets via [Initium](https://github.com/KitStream/initium)'s `render` subcommand (envsubst mode).

For external databases (PostgreSQL, MySQL), the chart automatically:
1. **Waits** for the database to be reachable (`initium wait-for`)
2. **Creates** the database if it doesn't exist (`initium seed --spec`)
3. **Constructs** the DSN internally from structured `database.*` values — you never need to build a DSN string

## Prerequisites

- Kubernetes 1.24+
Expand All @@ -30,7 +35,55 @@ helm install netbird ./charts/netbird \

## Minimal Configuration Example

### SQLite (default)

```yaml
server:
config:
exposedAddress: "https://netbird.example.com"
auth:
issuer: "https://auth.example.com"
dashboardRedirectURIs:
- "https://netbird.example.com/nb-auth"
- "https://netbird.example.com/nb-silent-auth"
```

### PostgreSQL

```yaml
database:
type: postgresql
host: postgres.database.svc.cluster.local
port: 5432
user: netbird
name: netbird
passwordSecret:
secretName: netbird-db-password
secretKey: password

server:
config:
exposedAddress: "https://netbird.example.com"
auth:
issuer: "https://auth.example.com"
dashboardRedirectURIs:
- "https://netbird.example.com/nb-auth"
- "https://netbird.example.com/nb-silent-auth"
```

### MySQL

```yaml
database:
type: mysql
host: mysql.database.svc.cluster.local
port: 3306
user: netbird
name: netbird
passwordSecret:
secretName: netbird-db-password
secretKey: password

server:
config:
exposedAddress: "https://netbird.example.com"
Expand All @@ -39,6 +92,14 @@ server:
dashboardRedirectURIs:
- "https://netbird.example.com/nb-auth"
- "https://netbird.example.com/nb-silent-auth"
```

The chart automatically constructs the DSN and adds init containers to wait for the database and create it if needed.

For all configurations, add ingress settings:

```yaml
server:
ingress:
enabled: true
hosts:
Expand Down Expand Up @@ -112,6 +173,19 @@ dashboard:
| `serviceAccount.annotations` | object | `{}` | ServiceAccount annotations |
| `serviceAccount.name` | string | `""` | ServiceAccount name override |

### Database

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `database.type` | string | `"sqlite"` | Database engine (`sqlite`, `postgresql`, `mysql`) |
| `database.host` | string | `""` | Database hostname (required for postgresql/mysql) |
| `database.port` | string | `""` | Database port (defaults: 5432 for postgresql, 3306 for mysql) |
| `database.user` | string | `""` | Database user (required for postgresql/mysql) |
| `database.name` | string | `""` | Database name (required for postgresql/mysql) |
| `database.passwordSecret.secretName` | string | `""` | Secret containing the database password |
| `database.passwordSecret.secretKey` | string | `"password"` | Key in the Secret |
| `database.sslMode` | string | `"disable"` | SSL mode for PostgreSQL (ignored for mysql/sqlite) |

### Server

| Key | Type | Default | Description |
Expand All @@ -121,7 +195,7 @@ dashboard:
| `server.image.tag` | string | `""` (appVersion) | Server image tag |
| `server.image.pullPolicy` | string | `"IfNotPresent"` | Image pull policy |
| `server.initImage.repository` | string | `"ghcr.io/kitstream/initium"` | Init container image ([Initium](https://github.com/KitStream/initium)) |
| `server.initImage.tag` | string | `"0.1.2"` | Init container image tag |
| `server.initImage.tag` | string | `"1.0.0"` | Init container image tag |
| `server.imagePullSecrets` | list | `[]` | Component-level pull secrets |

#### Server Configuration
Expand All @@ -140,7 +214,6 @@ dashboard:
| `server.config.auth.signKeyRefreshEnabled` | bool | `true` | Auto-refresh IdP signing keys |
| `server.config.auth.dashboardRedirectURIs` | list | `[]` | Dashboard OAuth2 redirect URIs |
| `server.config.auth.cliRedirectURIs` | list | `["http://localhost:53000/"]` | CLI redirect URIs |
| `server.config.store.engine` | string | `"sqlite"` | Database engine (sqlite, postgres, mysql) |

#### Server Secrets

Expand All @@ -152,8 +225,6 @@ dashboard:
| `server.secrets.storeEncryptionKey.secretName` | string | `""` | Existing Secret name (empty = auto-generate) |
| `server.secrets.storeEncryptionKey.secretKey` | string | `"encryptionKey"` | Key in the Secret |
| `server.secrets.storeEncryptionKey.autoGenerate` | bool | `true` | Auto-generate on first install |
| `server.secrets.storeDsn.secretName` | string | `""` | Secret containing the database DSN |
| `server.secrets.storeDsn.secretKey` | string | `"dsn"` | Key in the DSN Secret |

#### Server Storage

Expand Down
23 changes: 12 additions & 11 deletions charts/netbird/ci/e2e-values-mysql.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
# E2E test values — MySQL backend in a kind cluster.
#
# Requires: MySQL deployed in the same namespace before chart install.
# The e2e script deploys mysql via a simple Deployment + Service.
# The e2e script deploys mysql via a simple Deployment + Service
# and creates the password secret before chart install.

database:
type: mysql
host: "mysql.netbird-e2e.svc.cluster.local"
port: 3306
user: netbird
name: netbird
passwordSecret:
secretName: netbird-db-password
secretKey: password

server:
persistentVolume:
Expand All @@ -17,13 +27,6 @@ server:
dashboardRedirectURIs:
- "https://netbird.localhost/nb-auth"
- "https://netbird.localhost/nb-silent-auth"
store:
engine: mysql

secrets:
storeDsn:
secretName: netbird-db-dsn
secretKey: dsn

livenessProbe:
failureThreshold: 10
Expand All @@ -47,5 +50,3 @@ dashboard:
authAuthority: "https://auth.localhost"
authClientId: "test-client"
authAudience: "test-audience"


23 changes: 13 additions & 10 deletions charts/netbird/ci/e2e-values-postgres.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
# E2E test values — PostgreSQL backend in a kind cluster.
#
# Requires: PostgreSQL deployed in the same namespace before chart install.
# The e2e script deploys postgres via a simple Deployment + Service.
# The e2e script deploys postgres via a simple Deployment + Service
# and creates the password secret before chart install.

database:
type: postgresql
host: "postgres.netbird-e2e.svc.cluster.local"
port: 5432
user: netbird
name: netbird
passwordSecret:
secretName: netbird-db-password
secretKey: password
sslMode: disable

server:
persistentVolume:
Expand All @@ -17,13 +28,6 @@ server:
dashboardRedirectURIs:
- "https://netbird.localhost/nb-auth"
- "https://netbird.localhost/nb-silent-auth"
store:
engine: postgres

secrets:
storeDsn:
secretName: netbird-db-dsn
secretKey: dsn

livenessProbe:
failureThreshold: 10
Expand All @@ -48,4 +52,3 @@ dashboard:
authClientId: "test-client"
authAudience: "test-audience"


6 changes: 3 additions & 3 deletions charts/netbird/ci/e2e-values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
# - Uses sqlite engine with auto-generated secrets
# - Sets dummy auth values (server will start but auth won't be functional)

database:
type: sqlite

server:
persistentVolume:
enabled: false
Expand All @@ -21,8 +24,6 @@ server:
dashboardRedirectURIs:
- "https://netbird.localhost/nb-auth"
- "https://netbird.localhost/nb-silent-auth"
store:
engine: sqlite

# Lower probe thresholds for faster feedback in CI
livenessProbe:
Expand All @@ -47,4 +48,3 @@ dashboard:
authAuthority: "https://auth.localhost"
authClientId: "test-client"
authAudience: "test-audience"

2 changes: 1 addition & 1 deletion charts/netbird/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ Components:
{{- end }}
{{- end }}

Database: {{ .Values.server.config.store.engine }}
Database: {{ .Values.database.type }}
Loading