diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..fda9b44
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,45 @@
+# Git
+.git/
+.gitignore
+.github/
+
+# IDE
+.idea/
+.vscode/
+*.swp
+*.swo
+*~
+
+# Rust
+target/
+Cargo.lock
+
+# Build artifacts
+*.db
+*.db-shm
+*.db-wal
+
+# Data directories
+data/
+crabidp.db
+
+# Documentation
+README.md
+CONTRIBUTING.md
+CLAUDE.md
+docs/
+
+# Tests
+tests/
+
+# CI/CD
+.github/
+
+# Config
+.config/
+.claude/
+
+# Temporary files
+tmp/
+*.tmp
+*.log
diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md
new file mode 100644
index 0000000..aa39775
--- /dev/null
+++ b/DEPLOYMENT.md
@@ -0,0 +1,444 @@
+# Deployment Guide
+
+This guide covers deploying Barycenter OpenID Connect Identity Provider on various platforms.
+
+## Table of Contents
+
+- [Docker](#docker)
+- [Docker Compose](#docker-compose)
+- [Kubernetes (Helm)](#kubernetes-helm)
+- [Linux (systemd)](#linux-systemd)
+- [FreeBSD](#freebsd)
+- [illumos/Solaris](#illumossolaris)
+- [Configuration](#configuration)
+- [Security Considerations](#security-considerations)
+
+---
+
+## Docker
+
+### Building the Image
+
+```bash
+docker build -t barycenter:latest .
+```
+
+### Running the Container
+
+```bash
+docker run -d \
+ --name barycenter \
+ -p 8080:8080 \
+ -v barycenter-data:/app/data \
+ -e RUST_LOG=info \
+ barycenter:latest
+```
+
+### Custom Configuration
+
+Mount a custom config file:
+
+```bash
+docker run -d \
+ --name barycenter \
+ -p 8080:8080 \
+ -v ./config.toml:/app/config/config.toml:ro \
+ -v barycenter-data:/app/data \
+ barycenter:latest
+```
+
+---
+
+## Docker Compose
+
+### Quick Start
+
+```bash
+# Start the service
+docker-compose up -d
+
+# View logs
+docker-compose logs -f
+
+# Stop the service
+docker-compose down
+```
+
+### Production Configuration
+
+Edit `docker-compose.yml` to customize:
+
+```yaml
+environment:
+ - RUST_LOG=info
+ - CRABIDP__SERVER__PUBLIC_BASE_URL=https://idp.example.com
+```
+
+---
+
+## Kubernetes (Helm)
+
+### Prerequisites
+
+- Kubernetes cluster (1.19+)
+- Helm 3.x
+- kubectl configured
+
+### Installation
+
+1. **Install the Helm chart:**
+
+```bash
+helm install barycenter ./deploy/helm/barycenter \
+ --create-namespace \
+ --namespace barycenter
+```
+
+2. **With custom values:**
+
+```bash
+helm install barycenter ./deploy/helm/barycenter \
+ --namespace barycenter \
+ --set ingress.enabled=true \
+ --set ingress.hosts[0].host=idp.example.com \
+ --set config.server.publicBaseUrl=https://idp.example.com
+```
+
+3. **Using a values file:**
+
+Create `my-values.yaml`:
+
+```yaml
+ingress:
+ enabled: true
+ className: nginx
+ annotations:
+ cert-manager.io/cluster-issuer: letsencrypt-prod
+ hosts:
+ - host: idp.example.com
+ paths:
+ - path: /
+ pathType: Prefix
+ tls:
+ - secretName: barycenter-tls
+ hosts:
+ - idp.example.com
+
+config:
+ server:
+ publicBaseUrl: "https://idp.example.com"
+
+persistence:
+ enabled: true
+ size: 20Gi
+ storageClass: fast-ssd
+
+resources:
+ limits:
+ cpu: 2000m
+ memory: 1Gi
+ requests:
+ cpu: 200m
+ memory: 256Mi
+```
+
+Install with:
+
+```bash
+helm install barycenter ./deploy/helm/barycenter \
+ --namespace barycenter \
+ --values my-values.yaml
+```
+
+### Management
+
+**Upgrade:**
+```bash
+helm upgrade barycenter ./deploy/helm/barycenter \
+ --namespace barycenter \
+ --values my-values.yaml
+```
+
+**Uninstall:**
+```bash
+helm uninstall barycenter --namespace barycenter
+```
+
+**Check status:**
+```bash
+helm status barycenter --namespace barycenter
+kubectl get pods -n barycenter
+```
+
+---
+
+## Linux (systemd)
+
+### Installation
+
+See detailed instructions in [`deploy/systemd/README.md`](deploy/systemd/README.md).
+
+**Quick steps:**
+
+1. Build and install binary:
+```bash
+cargo build --release
+sudo cp target/release/barycenter /usr/local/bin/
+```
+
+2. Create user and directories:
+```bash
+sudo useradd -r -s /bin/false -d /var/lib/barycenter barycenter
+sudo mkdir -p /etc/barycenter /var/lib/barycenter/data
+sudo chown -R barycenter:barycenter /var/lib/barycenter
+```
+
+3. Install configuration:
+```bash
+sudo cp config.toml /etc/barycenter/
+# Edit /etc/barycenter/config.toml to update paths
+```
+
+4. Install and start service:
+```bash
+sudo cp deploy/systemd/barycenter.service /etc/systemd/system/
+sudo systemctl daemon-reload
+sudo systemctl enable --now barycenter
+```
+
+### Management
+
+```bash
+# Status
+sudo systemctl status barycenter
+
+# Logs
+sudo journalctl -u barycenter -f
+
+# Restart
+sudo systemctl restart barycenter
+```
+
+---
+
+## FreeBSD
+
+### Installation
+
+See detailed instructions in [`deploy/freebsd/README.md`](deploy/freebsd/README.md).
+
+**Quick steps:**
+
+1. Build and install:
+```bash
+cargo build --release
+sudo install -m 755 target/release/barycenter /usr/local/bin/
+```
+
+2. Create user and directories:
+```bash
+sudo pw useradd barycenter -d /var/db/barycenter -s /usr/sbin/nologin
+sudo mkdir -p /usr/local/etc/barycenter /var/db/barycenter/data
+sudo chown -R barycenter:barycenter /var/db/barycenter
+```
+
+3. Install configuration:
+```bash
+sudo cp config.toml /usr/local/etc/barycenter/
+# Edit /usr/local/etc/barycenter/config.toml
+```
+
+4. Install and enable service:
+```bash
+sudo install -m 755 deploy/freebsd/barycenter /usr/local/etc/rc.d/
+echo 'barycenter_enable="YES"' | sudo tee -a /etc/rc.conf
+sudo service barycenter start
+```
+
+---
+
+## illumos/Solaris
+
+### Installation
+
+See detailed instructions in [`deploy/illumos/README.md`](deploy/illumos/README.md).
+
+**Quick steps:**
+
+1. Build and install:
+```bash
+cargo build --release
+sudo mkdir -p /opt/barycenter/bin
+sudo cp target/release/barycenter /opt/barycenter/bin/
+```
+
+2. Create user and directories:
+```bash
+sudo useradd -d /var/barycenter -s /usr/bin/false barycenter
+sudo mkdir -p /etc/barycenter /var/barycenter/data
+sudo chown -R barycenter:barycenter /var/barycenter
+```
+
+3. Install configuration:
+```bash
+sudo cp config.toml /etc/barycenter/
+# Edit /etc/barycenter/config.toml
+```
+
+4. Import and enable SMF service:
+```bash
+sudo svccfg import deploy/illumos/barycenter.xml
+sudo svcadm enable barycenter
+```
+
+---
+
+## Configuration
+
+### Environment Variables
+
+All configuration can be overridden using environment variables with the `CRABIDP__` prefix:
+
+```bash
+# Override server settings
+export CRABIDP__SERVER__PORT=9090
+export CRABIDP__SERVER__PUBLIC_BASE_URL=https://idp.example.com
+
+# Override database
+export CRABIDP__DATABASE__URL=sqlite:///custom/path/db.sqlite
+
+# Set logging
+export RUST_LOG=debug
+```
+
+### Configuration File
+
+The `config.toml` file structure:
+
+```toml
+[server]
+host = "0.0.0.0"
+port = 8080
+public_base_url = "https://idp.example.com" # Required in production
+
+[database]
+url = "sqlite://crabidp.db?mode=rwc"
+
+[keys]
+jwks_path = "data/jwks.json"
+private_key_path = "data/private_key.pem"
+alg = "RS256"
+
+[federation]
+trust_anchors = []
+```
+
+### Production Checklist
+
+- [ ] Set `public_base_url` to your actual domain
+- [ ] Use HTTPS/TLS (via reverse proxy or ingress)
+- [ ] Configure proper logging (`RUST_LOG=info`)
+- [ ] Set up persistent storage for database and keys
+- [ ] Configure backups for database and private keys
+- [ ] Set appropriate file permissions (600 for keys, 640 for config)
+- [ ] Run as non-root user
+- [ ] Configure firewall rules
+- [ ] Set up monitoring and health checks
+- [ ] Review and apply security hardening settings
+
+---
+
+## Security Considerations
+
+### TLS/HTTPS
+
+Barycenter should always run behind a TLS-terminating reverse proxy or load balancer in production. Never expose it directly on HTTP.
+
+**Options:**
+- **Kubernetes:** Use Ingress with cert-manager for automatic TLS
+- **Linux:** Use nginx, Caddy, or Traefik as reverse proxy
+- **Cloud:** Use cloud load balancers (ALB, GCE LB, etc.)
+
+### Reverse Proxy Example (nginx)
+
+```nginx
+server {
+ listen 443 ssl http2;
+ server_name idp.example.com;
+
+ ssl_certificate /path/to/cert.pem;
+ ssl_certificate_key /path/to/key.pem;
+
+ location / {
+ proxy_pass http://localhost:8080;
+ proxy_set_header Host $host;
+ proxy_set_header X-Real-IP $remote_addr;
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto $scheme;
+ }
+}
+```
+
+### File Permissions
+
+```bash
+# Configuration (readable by service, writable by root)
+chmod 640 /etc/barycenter/config.toml
+chown root:barycenter /etc/barycenter/config.toml
+
+# Private key (readable only by service)
+chmod 600 /var/lib/barycenter/data/private_key.pem
+chown barycenter:barycenter /var/lib/barycenter/data/private_key.pem
+
+# Data directory
+chmod 750 /var/lib/barycenter
+chown barycenter:barycenter /var/lib/barycenter
+```
+
+### Backup Strategy
+
+**Critical files to backup:**
+1. Private RSA key (`private_key.pem`)
+2. Database (`crabidp.db`)
+3. Configuration (`config.toml`)
+
+**Backup script example:**
+
+```bash
+#!/bin/bash
+BACKUP_DIR=/backup/barycenter/$(date +%Y%m%d)
+mkdir -p $BACKUP_DIR
+
+# Backup database
+sqlite3 /var/lib/barycenter/crabidp.db ".backup '$BACKUP_DIR/crabidp.db'"
+
+# Backup keys and config
+cp /var/lib/barycenter/data/private_key.pem $BACKUP_DIR/
+cp /etc/barycenter/config.toml $BACKUP_DIR/
+
+# Encrypt and upload to remote storage
+tar czf - $BACKUP_DIR | gpg -e -r admin@example.com | \
+ aws s3 cp - s3://backups/barycenter-$(date +%Y%m%d).tar.gz.gpg
+```
+
+### Monitoring
+
+**Health check endpoint:**
+```bash
+curl http://localhost:8080/.well-known/openid-configuration
+```
+
+**Metrics to monitor:**
+- HTTP response times
+- Error rates (4xx, 5xx)
+- Database connection status
+- Disk usage (for SQLite file)
+- Memory/CPU usage
+
+---
+
+## Support
+
+For issues and questions:
+- GitHub Issues: https://github.com/yourusername/barycenter/issues
+- Documentation: See `README.md` and `CLAUDE.md`
diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..00deea3
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,56 @@
+# Multi-stage build for Barycenter OpenID Connect IdP
+# Build stage
+FROM rust:1.83-bookworm AS builder
+
+WORKDIR /build
+
+# Copy manifests
+COPY Cargo.toml Cargo.lock ./
+
+# Copy source code
+COPY src ./src
+
+# Build release binary
+RUN --mount=type=cache,target=/usr/local/cargo/registry \
+ --mount=type=cache,target=/build/target \
+ cargo build --release && \
+ cp target/release/barycenter /barycenter
+
+# Runtime stage
+FROM debian:bookworm-slim
+
+# Install runtime dependencies
+RUN apt-get update && \
+ apt-get install -y --no-install-recommends \
+ ca-certificates \
+ && rm -rf /var/lib/apt/lists/*
+
+# Create non-root user
+RUN useradd -r -u 1000 -s /bin/false barycenter && \
+ mkdir -p /app/data /app/config && \
+ chown -R barycenter:barycenter /app
+
+WORKDIR /app
+
+# Copy binary from builder
+COPY --from=builder /barycenter /usr/local/bin/barycenter
+
+# Copy default configuration
+COPY config.toml /app/config/config.toml
+
+# Set ownership
+RUN chown -R barycenter:barycenter /app
+
+# Switch to non-root user
+USER barycenter
+
+# Expose default port
+EXPOSE 8080
+
+# Health check
+HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
+ CMD ["/bin/sh", "-c", "test -f /proc/self/exe || exit 1"]
+
+# Default command
+ENTRYPOINT ["/usr/local/bin/barycenter"]
+CMD ["--config", "/app/config/config.toml"]
diff --git a/deploy/freebsd/README.md b/deploy/freebsd/README.md
new file mode 100644
index 0000000..7da7610
--- /dev/null
+++ b/deploy/freebsd/README.md
@@ -0,0 +1,108 @@
+# FreeBSD Deployment
+
+This directory contains rc.d script for running Barycenter on FreeBSD systems.
+
+## Installation
+
+1. **Install Rust and build the binary:**
+ ```bash
+ pkg install rust
+ cargo build --release
+ ```
+
+2. **Create the barycenter user:**
+ ```bash
+ pw useradd barycenter -d /var/db/barycenter -s /usr/sbin/nologin -c "Barycenter IdP"
+ ```
+
+3. **Create required directories:**
+ ```bash
+ mkdir -p /usr/local/etc/barycenter
+ mkdir -p /var/db/barycenter/data
+ chown -R barycenter:barycenter /var/db/barycenter
+ ```
+
+4. **Install the binary:**
+ ```bash
+ install -m 755 target/release/barycenter /usr/local/bin/
+ ```
+
+5. **Install the configuration:**
+ ```bash
+ cp config.toml /usr/local/etc/barycenter/config.toml
+ chown root:barycenter /usr/local/etc/barycenter/config.toml
+ chmod 640 /usr/local/etc/barycenter/config.toml
+ ```
+
+ Edit `/usr/local/etc/barycenter/config.toml` and update paths:
+ ```toml
+ [database]
+ url = "sqlite:///var/db/barycenter/crabidp.db?mode=rwc"
+
+ [keys]
+ jwks_path = "/var/db/barycenter/data/jwks.json"
+ private_key_path = "/var/db/barycenter/data/private_key.pem"
+ ```
+
+6. **Install the rc.d script:**
+ ```bash
+ install -m 755 deploy/freebsd/barycenter /usr/local/etc/rc.d/
+ ```
+
+7. **Enable the service in /etc/rc.conf:**
+ ```bash
+ echo 'barycenter_enable="YES"' >> /etc/rc.conf
+ ```
+
+ Optional configuration:
+ ```bash
+ echo 'barycenter_config="/usr/local/etc/barycenter/config.toml"' >> /etc/rc.conf
+ echo 'barycenter_env="RUST_LOG=info"' >> /etc/rc.conf
+ ```
+
+8. **Start the service:**
+ ```bash
+ service barycenter start
+ ```
+
+## Management
+
+**Check status:**
+```bash
+service barycenter status
+```
+
+**View logs:**
+```bash
+tail -f /var/log/messages | grep barycenter
+```
+
+**Restart service:**
+```bash
+service barycenter restart
+```
+
+**Stop service:**
+```bash
+service barycenter stop
+```
+
+## Configuration Options
+
+All configuration options are set in `/etc/rc.conf`:
+
+- `barycenter_enable` - Enable/disable the service (YES/NO)
+- `barycenter_user` - User to run as (default: barycenter)
+- `barycenter_group` - Group to run as (default: barycenter)
+- `barycenter_config` - Path to config file
+- `barycenter_env` - Environment variables (e.g., "RUST_LOG=debug")
+
+## Logging
+
+By default, output goes to syslog. To configure separate log file, update newsyslog:
+
+```bash
+echo "/var/log/barycenter.log barycenter:barycenter 644 7 * @T00 JC" >> /etc/newsyslog.conf
+touch /var/log/barycenter.log
+chown barycenter:barycenter /var/log/barycenter.log
+```
diff --git a/deploy/freebsd/barycenter b/deploy/freebsd/barycenter
new file mode 100644
index 0000000..fe6037e
--- /dev/null
+++ b/deploy/freebsd/barycenter
@@ -0,0 +1,59 @@
+#!/bin/sh
+#
+# PROVIDE: barycenter
+# REQUIRE: NETWORKING DAEMON
+# KEYWORD: shutdown
+#
+# Add the following lines to /etc/rc.conf to enable barycenter:
+#
+# barycenter_enable="YES"
+# barycenter_config="/usr/local/etc/barycenter/config.toml" # optional
+# barycenter_user="barycenter" # optional
+# barycenter_group="barycenter" # optional
+# barycenter_env="RUST_LOG=info" # optional
+
+. /etc/rc.subr
+
+name="barycenter"
+rcvar=barycenter_enable
+
+load_rc_config $name
+
+: ${barycenter_enable:="NO"}
+: ${barycenter_user:="barycenter"}
+: ${barycenter_group:="barycenter"}
+: ${barycenter_config:="/usr/local/etc/barycenter/config.toml"}
+: ${barycenter_env:=""}
+
+pidfile="/var/run/${name}.pid"
+command="/usr/local/bin/barycenter"
+command_args="--config ${barycenter_config}"
+
+# Daemon management
+barycenter_start_precmd()
+{
+ # Check if binary exists
+ if [ ! -x "${command}" ]; then
+ err 1 "${command} not found or not executable"
+ fi
+
+ # Check if config exists
+ if [ ! -f "${barycenter_config}" ]; then
+ err 1 "Config file ${barycenter_config} not found"
+ fi
+
+ # Ensure data directory exists
+ if [ ! -d "/var/db/barycenter" ]; then
+ mkdir -p /var/db/barycenter
+ chown ${barycenter_user}:${barycenter_group} /var/db/barycenter
+ fi
+}
+
+start_precmd="barycenter_start_precmd"
+
+# Use daemon to run in background
+command_interpreter="/usr/sbin/daemon"
+command="/usr/sbin/daemon"
+command_args="-f -p ${pidfile} -u ${barycenter_user} ${barycenter_env:+-o ${barycenter_env}} /usr/local/bin/barycenter --config ${barycenter_config}"
+
+run_rc_command "$1"
diff --git a/deploy/helm/barycenter/.helmignore b/deploy/helm/barycenter/.helmignore
new file mode 100644
index 0000000..0e8a0eb
--- /dev/null
+++ b/deploy/helm/barycenter/.helmignore
@@ -0,0 +1,23 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/deploy/helm/barycenter/Chart.yaml b/deploy/helm/barycenter/Chart.yaml
new file mode 100644
index 0000000..ba7f2bf
--- /dev/null
+++ b/deploy/helm/barycenter/Chart.yaml
@@ -0,0 +1,17 @@
+apiVersion: v2
+name: barycenter
+description: OpenID Connect Identity Provider with federation and auto-registration
+type: application
+version: 0.1.0
+appVersion: "0.1.0"
+keywords:
+ - openid
+ - oauth2
+ - identity
+ - authentication
+ - idp
+home: https://github.com/yourusername/barycenter
+sources:
+ - https://github.com/yourusername/barycenter
+maintainers:
+ - name: Barycenter Team
diff --git a/deploy/helm/barycenter/templates/NOTES.txt b/deploy/helm/barycenter/templates/NOTES.txt
new file mode 100644
index 0000000..116b32b
--- /dev/null
+++ b/deploy/helm/barycenter/templates/NOTES.txt
@@ -0,0 +1,36 @@
+Thank you for installing {{ .Chart.Name }}!
+
+Your Barycenter OpenID Connect Identity Provider has been deployed.
+
+1. Get the application URL by running these commands:
+{{- if .Values.ingress.enabled }}
+{{- range $host := .Values.ingress.hosts }}
+ {{- range .paths }}
+ http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }}
+ {{- end }}
+{{- end }}
+{{- else if contains "NodePort" .Values.service.type }}
+ export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "barycenter.fullname" . }})
+ export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
+ echo http://$NODE_IP:$NODE_PORT
+{{- else if contains "LoadBalancer" .Values.service.type }}
+ NOTE: It may take a few minutes for the LoadBalancer IP to be available.
+ You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "barycenter.fullname" . }}'
+ export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "barycenter.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
+ echo http://$SERVICE_IP:{{ .Values.service.port }}
+{{- else if contains "ClusterIP" .Values.service.type }}
+ export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "barycenter.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
+ export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
+ echo "Visit http://127.0.0.1:8080 to use your application"
+ kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
+{{- end }}
+
+2. Check the OpenID configuration:
+ curl http://YOUR_URL/.well-known/openid-configuration
+
+3. To register a client:
+ curl -X POST http://YOUR_URL/connect/register \
+ -H "Content-Type: application/json" \
+ -d '{"redirect_uris": ["http://localhost:3000/callback"]}'
+
+For more information, visit the documentation.
diff --git a/deploy/helm/barycenter/templates/_helpers.tpl b/deploy/helm/barycenter/templates/_helpers.tpl
new file mode 100644
index 0000000..f270fa4
--- /dev/null
+++ b/deploy/helm/barycenter/templates/_helpers.tpl
@@ -0,0 +1,60 @@
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "barycenter.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Create a default fully qualified app name.
+*/}}
+{{- define "barycenter.fullname" -}}
+{{- if .Values.fullnameOverride }}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default .Chart.Name .Values.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "barycenter.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "barycenter.labels" -}}
+helm.sh/chart: {{ include "barycenter.chart" . }}
+{{ include "barycenter.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "barycenter.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "barycenter.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "barycenter.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "barycenter.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/deploy/helm/barycenter/templates/configmap.yaml b/deploy/helm/barycenter/templates/configmap.yaml
new file mode 100644
index 0000000..89d72d8
--- /dev/null
+++ b/deploy/helm/barycenter/templates/configmap.yaml
@@ -0,0 +1,25 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: {{ include "barycenter.fullname" . }}
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+data:
+ config.toml: |
+ [server]
+ host = {{ .Values.config.server.host | quote }}
+ port = {{ .Values.config.server.port }}
+ {{- if .Values.config.server.publicBaseUrl }}
+ public_base_url = {{ .Values.config.server.publicBaseUrl | quote }}
+ {{- end }}
+
+ [database]
+ url = {{ .Values.config.database.url | quote }}
+
+ [keys]
+ jwks_path = {{ .Values.config.keys.jwksPath | quote }}
+ private_key_path = {{ .Values.config.keys.privateKeyPath | quote }}
+ alg = {{ .Values.config.keys.alg | quote }}
+
+ [federation]
+ trust_anchors = {{ .Values.config.federation.trustAnchors | toJson }}
diff --git a/deploy/helm/barycenter/templates/deployment.yaml b/deploy/helm/barycenter/templates/deployment.yaml
new file mode 100644
index 0000000..537a4bb
--- /dev/null
+++ b/deploy/helm/barycenter/templates/deployment.yaml
@@ -0,0 +1,85 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ include "barycenter.fullname" . }}
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+spec:
+ {{- if not .Values.autoscaling.enabled }}
+ replicas: {{ .Values.replicaCount }}
+ {{- end }}
+ strategy:
+ type: Recreate # Use Recreate for SQLite (single writer)
+ selector:
+ matchLabels:
+ {{- include "barycenter.selectorLabels" . | nindent 6 }}
+ template:
+ metadata:
+ annotations:
+ checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
+ {{- with .Values.podAnnotations }}
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ labels:
+ {{- include "barycenter.selectorLabels" . | nindent 8 }}
+ spec:
+ {{- with .Values.imagePullSecrets }}
+ imagePullSecrets:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ serviceAccountName: {{ include "barycenter.serviceAccountName" . }}
+ securityContext:
+ {{- toYaml .Values.podSecurityContext | nindent 8 }}
+ containers:
+ - name: {{ .Chart.Name }}
+ securityContext:
+ {{- toYaml .Values.securityContext | nindent 12 }}
+ image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+ imagePullPolicy: {{ .Values.image.pullPolicy }}
+ ports:
+ - name: http
+ containerPort: {{ .Values.config.server.port }}
+ protocol: TCP
+ env:
+ {{- range .Values.env }}
+ - name: {{ .name }}
+ value: {{ .value | quote }}
+ {{- end }}
+ volumeMounts:
+ - name: config
+ mountPath: /app/config
+ readOnly: true
+ {{- if .Values.persistence.enabled }}
+ - name: data
+ mountPath: /app/data
+ {{- end }}
+ livenessProbe:
+ {{- toYaml .Values.livenessProbe | nindent 10 }}
+ readinessProbe:
+ {{- toYaml .Values.readinessProbe | nindent 10 }}
+ resources:
+ {{- toYaml .Values.resources | nindent 10 }}
+ volumes:
+ - name: config
+ configMap:
+ name: {{ include "barycenter.fullname" . }}
+ {{- if .Values.persistence.enabled }}
+ - name: data
+ persistentVolumeClaim:
+ claimName: {{ include "barycenter.fullname" . }}-data
+ {{- else }}
+ - name: data
+ emptyDir: {}
+ {{- end }}
+ {{- with .Values.nodeSelector }}
+ nodeSelector:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.affinity }}
+ affinity:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
+ {{- with .Values.tolerations }}
+ tolerations:
+ {{- toYaml . | nindent 8 }}
+ {{- end }}
diff --git a/deploy/helm/barycenter/templates/hpa.yaml b/deploy/helm/barycenter/templates/hpa.yaml
new file mode 100644
index 0000000..61da975
--- /dev/null
+++ b/deploy/helm/barycenter/templates/hpa.yaml
@@ -0,0 +1,32 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+ name: {{ include "barycenter.fullname" . }}
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+spec:
+ scaleTargetRef:
+ apiVersion: apps/v1
+ kind: Deployment
+ name: {{ include "barycenter.fullname" . }}
+ minReplicas: {{ .Values.autoscaling.minReplicas }}
+ maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+ metrics:
+ {{- if .Values.autoscaling.targetCPUUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: cpu
+ target:
+ type: Utilization
+ averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }}
+ {{- end }}
+ {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ - type: Resource
+ resource:
+ name: memory
+ target:
+ type: Utilization
+ averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }}
+ {{- end }}
+{{- end }}
diff --git a/deploy/helm/barycenter/templates/ingress.yaml b/deploy/helm/barycenter/templates/ingress.yaml
new file mode 100644
index 0000000..6f50ca3
--- /dev/null
+++ b/deploy/helm/barycenter/templates/ingress.yaml
@@ -0,0 +1,41 @@
+{{- if .Values.ingress.enabled -}}
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+ name: {{ include "barycenter.fullname" . }}
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+ {{- with .Values.ingress.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ {{- if .Values.ingress.className }}
+ ingressClassName: {{ .Values.ingress.className }}
+ {{- end }}
+ {{- if .Values.ingress.tls }}
+ tls:
+ {{- range .Values.ingress.tls }}
+ - hosts:
+ {{- range .hosts }}
+ - {{ . | quote }}
+ {{- end }}
+ secretName: {{ .secretName }}
+ {{- end }}
+ {{- end }}
+ rules:
+ {{- range .Values.ingress.hosts }}
+ - host: {{ .host | quote }}
+ http:
+ paths:
+ {{- range .paths }}
+ - path: {{ .path }}
+ pathType: {{ .pathType }}
+ backend:
+ service:
+ name: {{ include "barycenter.fullname" $ }}
+ port:
+ name: http
+ {{- end }}
+ {{- end }}
+{{- end }}
diff --git a/deploy/helm/barycenter/templates/pvc.yaml b/deploy/helm/barycenter/templates/pvc.yaml
new file mode 100644
index 0000000..958a778
--- /dev/null
+++ b/deploy/helm/barycenter/templates/pvc.yaml
@@ -0,0 +1,21 @@
+{{- if .Values.persistence.enabled }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: {{ include "barycenter.fullname" . }}-data
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+ {{- with .Values.persistence.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ accessModes:
+ - {{ .Values.persistence.accessMode }}
+ {{- if .Values.persistence.storageClass }}
+ storageClassName: {{ .Values.persistence.storageClass | quote }}
+ {{- end }}
+ resources:
+ requests:
+ storage: {{ .Values.persistence.size }}
+{{- end }}
diff --git a/deploy/helm/barycenter/templates/service.yaml b/deploy/helm/barycenter/templates/service.yaml
new file mode 100644
index 0000000..8dfeaad
--- /dev/null
+++ b/deploy/helm/barycenter/templates/service.yaml
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: {{ include "barycenter.fullname" . }}
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+ {{- with .Values.service.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+spec:
+ type: {{ .Values.service.type }}
+ ports:
+ - port: {{ .Values.service.port }}
+ targetPort: http
+ protocol: TCP
+ name: http
+ selector:
+ {{- include "barycenter.selectorLabels" . | nindent 4 }}
diff --git a/deploy/helm/barycenter/templates/serviceaccount.yaml b/deploy/helm/barycenter/templates/serviceaccount.yaml
new file mode 100644
index 0000000..c4611dd
--- /dev/null
+++ b/deploy/helm/barycenter/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ include "barycenter.serviceAccountName" . }}
+ labels:
+ {{- include "barycenter.labels" . | nindent 4 }}
+ {{- with .Values.serviceAccount.annotations }}
+ annotations:
+ {{- toYaml . | nindent 4 }}
+ {{- end }}
+{{- end }}
diff --git a/deploy/helm/barycenter/values.yaml b/deploy/helm/barycenter/values.yaml
new file mode 100644
index 0000000..d1b8495
--- /dev/null
+++ b/deploy/helm/barycenter/values.yaml
@@ -0,0 +1,131 @@
+# Default values for barycenter Helm chart
+
+replicaCount: 1
+
+image:
+ repository: barycenter
+ pullPolicy: IfNotPresent
+ tag: "latest"
+
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+serviceAccount:
+ create: true
+ annotations: {}
+ name: ""
+
+podAnnotations: {}
+
+podSecurityContext:
+ runAsNonRoot: true
+ runAsUser: 1000
+ fsGroup: 1000
+ seccompProfile:
+ type: RuntimeDefault
+
+securityContext:
+ allowPrivilegeEscalation: false
+ readOnlyRootFilesystem: false
+ runAsNonRoot: true
+ runAsUser: 1000
+ capabilities:
+ drop:
+ - ALL
+
+service:
+ type: ClusterIP
+ port: 8080
+ annotations: {}
+
+ingress:
+ enabled: false
+ className: "nginx"
+ annotations: {}
+ # cert-manager.io/cluster-issuer: letsencrypt-prod
+ # nginx.ingress.kubernetes.io/ssl-redirect: "true"
+ hosts:
+ - host: idp.example.com
+ paths:
+ - path: /
+ pathType: Prefix
+ tls: []
+ # - secretName: barycenter-tls
+ # hosts:
+ # - idp.example.com
+
+resources:
+ limits:
+ cpu: 1000m
+ memory: 512Mi
+ requests:
+ cpu: 100m
+ memory: 128Mi
+
+autoscaling:
+ enabled: false
+ minReplicas: 1
+ maxReplicas: 10
+ targetCPUUtilizationPercentage: 80
+ # targetMemoryUtilizationPercentage: 80
+
+nodeSelector: {}
+
+tolerations: []
+
+affinity: {}
+
+# Barycenter-specific configuration
+config:
+ server:
+ host: "0.0.0.0"
+ port: 8080
+ # publicBaseUrl: "https://idp.example.com"
+
+ database:
+ url: "sqlite:///app/data/crabidp.db?mode=rwc"
+
+ keys:
+ jwksPath: "/app/data/jwks.json"
+ privateKeyPath: "/app/data/private_key.pem"
+ alg: "RS256"
+
+ federation:
+ trustAnchors: []
+
+# Environment variables
+env:
+ - name: RUST_LOG
+ value: "info"
+ # Add additional environment variables here
+ # - name: CRABIDP__SERVER__PUBLIC_BASE_URL
+ # value: "https://idp.example.com"
+
+# Persistence for database and keys
+persistence:
+ enabled: true
+ # storageClass: ""
+ accessMode: ReadWriteOnce
+ size: 10Gi
+ annotations: {}
+
+# Liveness probe configuration
+livenessProbe:
+ httpGet:
+ path: /.well-known/openid-configuration
+ port: http
+ initialDelaySeconds: 10
+ periodSeconds: 30
+ timeoutSeconds: 3
+ failureThreshold: 3
+
+# Readiness probe configuration
+readinessProbe:
+ httpGet:
+ path: /.well-known/openid-configuration
+ port: http
+ initialDelaySeconds: 5
+ periodSeconds: 10
+ timeoutSeconds: 3
+ failureThreshold: 3
diff --git a/deploy/illumos/README.md b/deploy/illumos/README.md
new file mode 100644
index 0000000..3dffe5a
--- /dev/null
+++ b/deploy/illumos/README.md
@@ -0,0 +1,150 @@
+# illumos/Solaris Deployment
+
+This directory contains SMF (Service Management Facility) manifest for running Barycenter on illumos and Solaris systems.
+
+## Installation
+
+1. **Install Rust and build the binary:**
+ ```bash
+ # On OmniOS/OpenIndiana, install rust from pkgsrc
+ pkg install rust
+ cargo build --release
+ ```
+
+2. **Create the barycenter user:**
+ ```bash
+ useradd -d /var/barycenter -s /usr/bin/false -c "Barycenter IdP" barycenter
+ ```
+
+3. **Create required directories:**
+ ```bash
+ mkdir -p /opt/barycenter/bin
+ mkdir -p /etc/barycenter
+ mkdir -p /var/barycenter/data
+ chown -R barycenter:barycenter /var/barycenter
+ ```
+
+4. **Install the binary:**
+ ```bash
+ cp target/release/barycenter /opt/barycenter/bin/
+ chmod 755 /opt/barycenter/bin/barycenter
+ ```
+
+5. **Install the configuration:**
+ ```bash
+ cp config.toml /etc/barycenter/config.toml
+ chown root:barycenter /etc/barycenter/config.toml
+ chmod 640 /etc/barycenter/config.toml
+ ```
+
+ Edit `/etc/barycenter/config.toml` and update paths:
+ ```toml
+ [database]
+ url = "sqlite:///var/barycenter/crabidp.db?mode=rwc"
+
+ [keys]
+ jwks_path = "/var/barycenter/data/jwks.json"
+ private_key_path = "/var/barycenter/data/private_key.pem"
+ ```
+
+6. **Import the SMF manifest:**
+ ```bash
+ svccfg import deploy/illumos/barycenter.xml
+ ```
+
+7. **Enable the service:**
+ ```bash
+ svcadm enable barycenter
+ ```
+
+## Management
+
+**Check status:**
+```bash
+svcs -l barycenter
+```
+
+**View logs:**
+```bash
+svcs -L barycenter # Show log file location
+tail -f /var/svc/log/application-barycenter:default.log
+```
+
+**Restart service:**
+```bash
+svcadm restart barycenter
+```
+
+**Stop service:**
+```bash
+svcadm disable barycenter
+```
+
+**Clear maintenance state:**
+```bash
+svcadm clear barycenter
+```
+
+## Configuration
+
+### Modifying Service Properties
+
+To change the config file location:
+```bash
+svccfg -s barycenter setprop application/config_file = /custom/path/config.toml
+svcadm refresh barycenter
+svcadm restart barycenter
+```
+
+To change the data directory:
+```bash
+svccfg -s barycenter setprop application/data_dir = /custom/data/dir
+svcadm refresh barycenter
+svcadm restart barycenter
+```
+
+### Environment Variables
+
+To set environment variables, edit the manifest and modify the `method_environment` section:
+
+```xml
+
+
+
+
+```
+
+Then reimport:
+```bash
+svccfg import deploy/illumos/barycenter.xml
+svcadm refresh barycenter
+svcadm restart barycenter
+```
+
+## Troubleshooting
+
+**Service won't start:**
+```bash
+# Check the service log
+svcs -L barycenter
+tail -50 /var/svc/log/application-barycenter:default.log
+
+# Check service state
+svcs -x barycenter
+```
+
+**Permission issues:**
+Ensure the barycenter user has write access to the data directory:
+```bash
+chown -R barycenter:barycenter /var/barycenter
+chmod 755 /var/barycenter
+```
+
+## SMF Features
+
+SMF provides:
+- Automatic restart on failure
+- Dependency management
+- Log file rotation
+- Process contract management
+- Property-based configuration
diff --git a/deploy/illumos/barycenter.xml b/deploy/illumos/barycenter.xml
new file mode 100644
index 0000000..dacf4c6
--- /dev/null
+++ b/deploy/illumos/barycenter.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Barycenter OpenID Connect IdP
+
+
+
+ Barycenter OpenID Connect Identity Provider with federation support
+
+
+
+
+
+
+
+
+
+
diff --git a/deploy/systemd/README.md b/deploy/systemd/README.md
new file mode 100644
index 0000000..2ca4b79
--- /dev/null
+++ b/deploy/systemd/README.md
@@ -0,0 +1,94 @@
+# systemd Deployment
+
+This directory contains systemd service files for running Barycenter on Linux systems.
+
+## Installation
+
+1. **Create the barycenter user:**
+ ```bash
+ sudo useradd -r -s /bin/false -d /var/lib/barycenter barycenter
+ ```
+
+2. **Create required directories:**
+ ```bash
+ sudo mkdir -p /etc/barycenter /var/lib/barycenter/data
+ sudo chown -R barycenter:barycenter /var/lib/barycenter
+ ```
+
+3. **Install the binary:**
+ ```bash
+ sudo cargo build --release
+ sudo cp target/release/barycenter /usr/local/bin/
+ sudo chmod +x /usr/local/bin/barycenter
+ ```
+
+4. **Install the configuration:**
+ ```bash
+ sudo cp config.toml /etc/barycenter/config.toml
+ sudo chown root:barycenter /etc/barycenter/config.toml
+ sudo chmod 640 /etc/barycenter/config.toml
+ ```
+
+ Edit `/etc/barycenter/config.toml` and update paths:
+ ```toml
+ [database]
+ url = "sqlite:///var/lib/barycenter/crabidp.db?mode=rwc"
+
+ [keys]
+ jwks_path = "/var/lib/barycenter/data/jwks.json"
+ private_key_path = "/var/lib/barycenter/data/private_key.pem"
+ ```
+
+5. **Install the systemd service:**
+ ```bash
+ sudo cp deploy/systemd/barycenter.service /etc/systemd/system/
+ sudo systemctl daemon-reload
+ ```
+
+6. **Enable and start the service:**
+ ```bash
+ sudo systemctl enable barycenter
+ sudo systemctl start barycenter
+ ```
+
+## Management
+
+**Check status:**
+```bash
+sudo systemctl status barycenter
+```
+
+**View logs:**
+```bash
+sudo journalctl -u barycenter -f
+```
+
+**Restart service:**
+```bash
+sudo systemctl restart barycenter
+```
+
+**Stop service:**
+```bash
+sudo systemctl stop barycenter
+```
+
+## Security
+
+The service runs with extensive security hardening:
+- Runs as non-root user
+- Private /tmp directory
+- Read-only filesystem (except data directory)
+- System call filtering
+- Memory protections
+- No new privileges
+
+## Environment Variables
+
+You can override configuration using environment variables in the service file:
+
+```ini
+[Service]
+Environment="CRABIDP__SERVER__PUBLIC_BASE_URL=https://idp.example.com"
+Environment="RUST_LOG=debug"
+```
diff --git a/deploy/systemd/barycenter.service b/deploy/systemd/barycenter.service
new file mode 100644
index 0000000..b3dc091
--- /dev/null
+++ b/deploy/systemd/barycenter.service
@@ -0,0 +1,55 @@
+[Unit]
+Description=Barycenter OpenID Connect Identity Provider
+Documentation=https://github.com/yourusername/barycenter
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+Type=simple
+User=barycenter
+Group=barycenter
+
+# Paths
+WorkingDirectory=/var/lib/barycenter
+ExecStart=/usr/local/bin/barycenter --config /etc/barycenter/config.toml
+
+# Security hardening
+NoNewPrivileges=true
+PrivateTmp=true
+ProtectSystem=strict
+ProtectHome=true
+ReadWritePaths=/var/lib/barycenter
+ProtectKernelTunables=true
+ProtectKernelModules=true
+ProtectControlGroups=true
+RestrictRealtime=true
+RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
+LockPersonality=true
+MemoryDenyWriteExecute=true
+RestrictNamespaces=true
+SystemCallFilter=@system-service
+SystemCallErrorNumber=EPERM
+SystemCallArchitectures=native
+
+# Resource limits
+LimitNOFILE=65535
+LimitNPROC=512
+
+# Logging
+StandardOutput=journal
+StandardError=journal
+SyslogIdentifier=barycenter
+
+# Environment
+Environment="RUST_LOG=info"
+# Override config with environment variables:
+# Environment="CRABIDP__SERVER__PUBLIC_BASE_URL=https://idp.example.com"
+
+# Restart policy
+Restart=on-failure
+RestartSec=5s
+StartLimitInterval=60s
+StartLimitBurst=3
+
+[Install]
+WantedBy=multi-user.target
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..a8f5c62
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,59 @@
+version: '3.8'
+
+services:
+ barycenter:
+ build:
+ context: .
+ dockerfile: Dockerfile
+ image: barycenter:latest
+ container_name: barycenter
+ restart: unless-stopped
+
+ ports:
+ - "8080:8080"
+
+ environment:
+ # Override config via environment variables
+ # Use CRABIDP__ prefix with double underscores for nested keys
+ - RUST_LOG=info
+ # Example: CRABIDP__SERVER__PORT=8080
+ # Example: CRABIDP__SERVER__PUBLIC_BASE_URL=https://idp.example.com
+ # Example: CRABIDP__DATABASE__URL=sqlite:///app/data/crabidp.db?mode=rwc
+
+ volumes:
+ # Persist database and keys
+ - barycenter-data:/app/data
+ # Optional: override config file
+ # - ./config.toml:/app/config/config.toml:ro
+
+ healthcheck:
+ test: ["CMD", "curl", "-f", "http://localhost:8080/.well-known/openid-configuration"]
+ interval: 30s
+ timeout: 3s
+ retries: 3
+ start_period: 10s
+
+ # Security options
+ security_opt:
+ - no-new-privileges:true
+
+ # Read-only root filesystem (except data volume)
+ read_only: false
+
+ # Drop all capabilities and add only required ones
+ cap_drop:
+ - ALL
+
+ # Resource limits
+ deploy:
+ resources:
+ limits:
+ cpus: '1'
+ memory: 512M
+ reservations:
+ cpus: '0.25'
+ memory: 128M
+
+volumes:
+ barycenter-data:
+ driver: local