Advanced Configuration
This guide covers advanced configuration options for production deployments and specialized use cases.
Integrations
Outline supports various third-party integrations for enhanced functionality.
OpenAI Integration
Enable AI-powered features with OpenAI:
integrations:
openAI:
enabled: true
url: "https://api.openai.com/v1"
apiKey: "your-openai-api-key"
vectorDatabaseUrl: "postgresql://user:pass@host:port/db"
Slack Integration
Enable Slack notifications and message actions:
integrations:
slack:
enabled: true
verificationToken: "your-slack-verification-token"
appId: "your-slack-app-id"
messageActions: true
Sentry Integration
Enable error tracking and monitoring:
integrations:
sentry:
enabled: true
dsn: "https://your-sentry-dsn"
tunnel: "https://your-sentry-tunnel"
PDF Export Integration
Enable PDF export functionality:
integrations:
pdfExport:
enabled: true
gotenbergUrl: "http://gotenberg:3000"
Iframely Integration
Enable link previews and metadata extraction:
integrations:
iframely:
enabled: true
url: "https://iframely.yourdomain.com"
apiKey: "your-iframely-api-key"
Dropbox Integration
Enable Dropbox file integration:
integrations:
dropbox:
enabled: true
appKey: "your-dropbox-app-key"
SMTP Configuration
Configure email notifications and user invitations.
Basic SMTP Setup
smtp:
host: "smtp.gmail.com"
port: 587
username: "your-email@gmail.com"
password: "your-app-password"
fromEmail: "outline@yourdomain.com"
replyEmail: "no-reply@yourdomain.com"
secure: true
SMTP with Existing Secret
smtp:
host: "smtp.yourdomain.com"
port: 587
username: "outline"
existingSecret: "outline-smtp-secret" # Must contain smtp-password key
fromEmail: "outline@yourdomain.com"
replyEmail: "no-reply@yourdomain.com"
secure: true
Advanced SMTP Configuration
smtp:
host: "smtp.yourdomain.com"
port: 587
username: "outline"
password: "strongpassword"
fromEmail: "outline@yourdomain.com"
replyEmail: "no-reply@yourdomain.com"
secure: true
tlsCiphers: "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384"
Monitoring and Observability
Health Checks
Configure custom health check endpoints:
livenessProbe:
httpGet:
path: /_health
port: http
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /_health
port: http
initialDelaySeconds: 10
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
Prometheus Monitoring
Add Prometheus annotations for monitoring:
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "3000"
prometheus.io/path: "/_health"
Resource Monitoring
Configure resource requests and limits:
resources:
limits:
cpu: "2000m"
memory: "4Gi"
requests:
cpu: "1000m"
memory: "2Gi"
Security Configuration
Pod Security Context
Configure security context for enhanced security:
podSecurityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
fsGroupChangePolicy: OnRootMismatch
supplementalGroups: []
sysctls: []
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: false
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
capabilities:
drop:
- ALL
Network Policies
Create network policies for enhanced security:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: outline-network-policy
spec:
podSelector:
matchLabels:
app.kubernetes.io/name: outline
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 3000
egress:
- to:
- namespaceSelector:
matchLabels:
name: postgresql
ports:
- protocol: TCP
port: 5432
- to:
- namespaceSelector:
matchLabels:
name: redis
ports:
- protocol: TCP
port: 6379
High Availability Configuration
Multi-Replica Deployment
replicaCount: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: "25%"
maxUnavailable: "25%"
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- outline
topologyKey: kubernetes.io/hostname
Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: outline-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: outline
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
Custom Environment Variables
Add custom environment variables:
extraEnvVars:
NODE_ENV: "production"
TZ: "UTC"
DEBUG: "false"
CUSTOM_FEATURE_FLAG: "enabled"
Using Existing Secrets
Reference existing secrets for environment variables:
extraSecretNamesForEnvFrom:
- my-custom-secret
- another-secret
Custom Volumes and Volume Mounts
Add custom volumes and mounts:
volumes:
- name: custom-config
configMap:
name: outline-custom-config
- name: shared-storage
persistentVolumeClaim:
claimName: outline-shared-storage
volumeMounts:
- name: custom-config
mountPath: /app/custom-config
readOnly: true
- name: shared-storage
mountPath: /app/shared
Node Selection and Tolerations
Node Selector
nodeSelector:
node-type: application
environment: production
Tolerations
tolerations:
- key: "dedicated"
operator: "Equal"
value: "outline"
effect: "NoSchedule"
Affinity Rules
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/os
operator: In
values:
- linux
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- outline
topologyKey: kubernetes.io/hostname
Custom Init Containers
Add custom init containers:
initContainers:
- name: wait-for-database
image: postgres:15
command:
- /bin/sh
- -c
- |
until pg_isready -h $PGHOST -p $PGPORT -U $PGUSER; do
echo "Waiting for database..."
sleep 2
done
env:
- name: PGHOST
value: "outline-postgresql"
- name: PGPORT
value: "5432"
- name: PGUSER
value: "outline"
- name: PGPASSWORD
valueFrom:
secretKeyRef:
name: outline-postgresql
key: password
Custom Sidecar Containers
Add sidecar containers for additional functionality:
extraContainers:
- name: nginx-sidecar
image: nginx:alpine
ports:
- name: nginx
containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
resources:
requests:
memory: "64Mi"
cpu: "50m"
limits:
memory: "128Mi"
cpu: "100m"
Service Account Configuration
Custom Service Account
serviceAccount:
create: true
name: "outline-service-account"
annotations:
eks.amazonaws.com/role-arn: "arn:aws:iam::123456789012:role/outline-role"
iam.gke.io/gcp-service-account: "outline@project.iam.gserviceaccount.com"
Ingress Advanced Configuration
Multiple Hosts and Paths
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
hosts:
- host: outline.yourdomain.com
paths:
- path: /
pathType: ImplementationSpecific
- host: wiki.yourdomain.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: outline-tls
hosts:
- outline.yourdomain.com
- wiki.yourdomain.com
Custom Ingress Annotations
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
nginx.ingress.kubernetes.io/rate-limit: "100"
nginx.ingress.kubernetes.io/rate-limit-window: "1m"
Complete Production Example
Here's a comprehensive production configuration:
# Production deployment
replicaCount: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: "25%"
maxUnavailable: "25%"
# Image configuration
image:
repository: outlinewiki/outline
pullPolicy: IfNotPresent
# Web configuration
web:
concurrency: 2
forceHttps: true
skipSSLVerification: false
# URL and language
url: "https://outline.yourdomain.com"
defaultLanguage: en_US
# Rate limiting
rateLimiter:
enabled: true
limit: 100
window: 60
# Auto updates
autoUpdate:
enabled: false
telemetry: false
# Logging
logging:
level: info
extraDebug: []
# Resources
resources:
limits:
cpu: 2000m
memory: 4Gi
requests:
cpu: 1000m
memory: 2Gi
# Security
podSecurityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
fsGroupChangePolicy: OnRootMismatch
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
runAsNonRoot: true
runAsUser: 1001
runAsGroup: 1001
# Ingress
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: outline.yourdomain.com
paths:
- path: /
pathType: ImplementationSpecific
tls:
- secretName: outline-tls
hosts:
- outline.yourdomain.com
# Database
postgresql:
enabled: true
architecture: replication
auth:
username: outline
password: strongpassword
database: outline
primary:
persistence:
enabled: true
size: 50Gi
storageClass: "fast-ssd"
readReplicas:
persistence:
enabled: true
size: 50Gi
storageClass: "fast-ssd"
# Redis
redis:
enabled: true
architecture: standalone
auth:
enabled: true
master:
persistence:
enabled: true
size: 8Gi
# Storage
fileStorage:
mode: s3
s3:
bucket: outline-prod
region: us-east-1
existingSecret: "outline-s3-secret"
forcePathStyle: true
acl: private
# Authentication
auth:
google:
enabled: true
clientId: "your-google-client-id"
clientSecret: "your-google-client-secret"
# SMTP
smtp:
host: "smtp.yourdomain.com"
port: 587
username: "outline"
existingSecret: "outline-smtp-secret"
fromEmail: "outline@yourdomain.com"
replyEmail: "no-reply@yourdomain.com"
secure: true
# Integrations
integrations:
sentry:
enabled: true
dsn: "https://your-sentry-dsn"
slack:
enabled: true
verificationToken: "your-slack-token"
appId: "your-slack-app-id"
# Affinity
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- outline
topologyKey: kubernetes.io/hostname
# Monitoring
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "3000"
Next Steps
- Learn about troubleshooting common issues
- Configure authentication methods
- Set up storage options
- Configure database settings