freeleaps-ops/docs/PostgreSQL_Gitea_Integration_Guide.md

1056 lines
34 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🐘 PostgreSQL & Gitea Integration Guide
> **Complete Guide to PostgreSQL Database Support for Gitea in Your FreeLeaps Kubernetes Environment**
> *From configuration to data access to troubleshooting*
---
## 📋 **Table of Contents**
1. [🎯 **Overview**](#-overview)
2. [🏗️ **Your Current Setup**](#-your-current-setup)
3. [🔧 **Database Configuration**](#-database-configuration)
4. [📊 **Data Access Methods**](#-data-access-methods)
5. [🔍 **Database Monitoring**](#-database-monitoring)
6. [🚨 **Troubleshooting**](#-troubleshooting)
7. [💾 **Backup & Recovery**](#-backup--recovery)
8. [🔒 **Security Best Practices**](#-security-best-practices)
9. [📈 **Performance Optimization**](#-performance-optimization)
10. [🛠️ **Maintenance Procedures**](#-maintenance-procedures)
---
## 🎯 **Overview**
### **What is PostgreSQL in Your Gitea Setup?**
PostgreSQL serves as the **primary database backend** for your Gitea installation, storing all critical data including:
- **User accounts** and authentication information
- **Repository metadata** and settings
- **Issues, pull requests, and comments**
- **Wiki pages** and documentation
- **Activity logs** and audit trails
- **Organization and team data**
- **Webhook configurations** and integrations
### **Why PostgreSQL Instead of SQLite?**
Your setup uses PostgreSQL for several important reasons:
1. **Production Reliability** - Better for concurrent access and high availability
2. **Data Integrity** - ACID compliance and transaction support
3. **Scalability** - Can handle larger datasets and more users
4. **Backup & Recovery** - Better tools for data protection
5. **Performance** - Optimized for complex queries and indexing
---
## 🏗️ **Your Current Setup**
### **🌐 Environment-Specific Configurations**
#### **Alpha Environment** (`freeleaps-alpha`)
```yaml
# Location: freeleaps-ops/freeleaps/helm-pkg/3rd/gitea/values.alpha.yaml
postgresql-ha:
enabled: false # ❌ High Availability disabled
postgresql:
enabled: true # ✅ Standard PostgreSQL enabled
global:
postgresql:
auth:
password: r8sA8CPHD9!bt6d
database: gitea
username: gitea
service:
ports:
postgresql: 5432
primary:
persistence:
size: 5Gi # 5GB storage for alpha
volumePermissions:
enabled: true
```
#### **Production Environment** (`freeleaps-prod`)
```yaml
# Location: freeleaps-ops/freeleaps/helm-pkg/3rd/gitea/values.prod.yaml
postgresql-ha:
enabled: true # ✅ High Availability enabled
global:
postgresql:
database: gitea
password: HFf#Xo4QtfK^CW?@
username: gitea
clusterDomain: freeleaps.cluster
postgresql:
image:
repository: freeleaps/postgresql-repmgr
tag: 16.3.0-debian-12-r20
repmgrPassword: WGZ47gbUTLvo
postgresPassword: X9H2*9M2ZWYmuZ
password: bhYmZ3ivfD@udWc@8jrB4@
pgpool:
adminPassword: Rk(*4vc%wFVu5>C|
persistence:
size: 25Gi # 25GB storage for production
postgresql:
enabled: false # ❌ Standard PostgreSQL disabled
```
### **🔧 Architecture Comparison**
#### **Alpha Environment (Standard PostgreSQL)**
```
┌─────────────────────────────────────────────────────────────┐
│ ALPHA ENVIRONMENT │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Gitea Pod │ │ PostgreSQL │ │ Redis │ │
│ │ (Web UI) │ │ (Database) │ │ (Cache) │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ │ │ │ │
│ │ TCP 5432 │ │ │
│ └────────────────────┘ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Single PostgreSQL Instance │ │
│ │ - Database: gitea │ │
│ │ - User: gitea │ │
│ │ - Storage: 5Gi │ │
│ │ - No replication │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
#### **Production Environment (PostgreSQL HA)**
```
┌─────────────────────────────────────────────────────────────┐
│ PRODUCTION ENVIRONMENT │
├─────────────────────────────────────────────────────────────┤
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
│ │ Gitea Pod │ │ PostgreSQL │ │ Redis │ │
│ │ (Web UI) │ │ HA Cluster │ │ (Cache) │ │
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
│ │ │ │ │
│ │ TCP 5432 │ │ │
│ └────────────────────┘ │ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ PostgreSQL HA Cluster │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Primary │ │ Replica │ │ PgPool │ │ │
│ │ │ Node │ │ Node │ │ (Proxy) │ │ │
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
│ │ - Database: gitea │ │
│ │ - User: gitea │ │
│ │ - Storage: 25Gi │ │
│ │ - Automatic failover │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
---
## 🔧 **Database Configuration**
### **📋 How Gitea Connects to PostgreSQL**
#### **Connection Configuration**
Gitea automatically configures its database connection based on your Helm values:
```yaml
# Gitea database configuration (auto-generated)
database:
DB_TYPE: postgres
HOST: <postgresql-service-name>.<namespace>.svc.cluster.local
NAME: gitea
USER: gitea
PASSWD: <password-from-values>
PORT: 5432
```
#### **Service Discovery**
```bash
# Alpha Environment
HOST: gitea-postgresql.freeleaps-alpha.svc.cluster.local
# Production Environment
HOST: gitea-postgresql-ha-pgpool.freeleaps-prod.svc.cluster.local
```
### **🔍 Database Schema**
#### **Key Gitea Tables**
```sql
-- User management
user -- User accounts and profiles
public_key -- SSH public keys
access_token -- API access tokens
-- Repository management
repository -- Repository metadata
mirror -- Repository mirrors
repo_unit -- Repository permissions
repo_watch -- Repository watching
-- Issue tracking
issue -- Issues and pull requests
comment -- Comments on issues/PRs
label -- Issue labels
milestone -- Project milestones
-- Activity and logs
action -- User activity logs
webhook -- Webhook configurations
hook_task -- Webhook execution history
-- Wiki and documentation
wiki_page -- Wiki pages
wiki_revision -- Wiki page revisions
```
---
## 📊 **Data Access Methods**
### **🔑 Direct Database Access**
#### **Method 1: Port Forward (Recommended)**
```bash
# Alpha Environment
kubectl port-forward svc/gitea-postgresql -n freeleaps-alpha 5432:5432
# Production Environment
kubectl port-forward svc/gitea-postgresql-ha-pgpool -n freeleaps-prod 5432:5432
# Connect with psql
psql -h localhost -p 5432 -U gitea -d gitea
# Password: r8sA8CPHD9!bt6d (alpha) or HFf#Xo4QtfK^CW?@ (prod)
```
#### **Method 2: Direct Pod Access**
```bash
# Alpha Environment
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea
# Production Environment
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- psql -U gitea -d gitea
```
#### **Method 3: Using kubectl exec with psql**
```bash
# Alpha Environment
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "SELECT * FROM user LIMIT 5;"
# Production Environment
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- psql -U gitea -d gitea -c "SELECT * FROM user LIMIT 5;"
```
### **🔍 Useful Database Queries**
#### **User Management**
```sql
-- List all users
SELECT id, name, email, created_unix, is_admin FROM user;
-- Find admin users
SELECT id, name, email FROM user WHERE is_admin = true;
-- Count total users
SELECT COUNT(*) as total_users FROM user;
-- Find recently created users
SELECT name, email, created_unix
FROM user
WHERE created_unix > extract(epoch from now() - interval '30 days')
ORDER BY created_unix DESC;
```
#### **Repository Management**
```sql
-- List all repositories
SELECT id, owner_id, name, description, created_unix
FROM repository
ORDER BY created_unix DESC;
-- Find repositories by owner
SELECT r.id, r.name, r.description, u.name as owner_name
FROM repository r
JOIN user u ON r.owner_id = u.id
WHERE u.name = 'your-username';
-- Count repositories per user
SELECT u.name, COUNT(r.id) as repo_count
FROM user u
LEFT JOIN repository r ON u.id = r.owner_id
GROUP BY u.id, u.name
ORDER BY repo_count DESC;
```
#### **Issue Tracking**
```sql
-- List recent issues
SELECT i.id, i.title, i.created_unix, u.name as creator
FROM issue i
JOIN user u ON i.poster_id = u.id
WHERE i.is_closed = false
ORDER BY i.created_unix DESC
LIMIT 10;
-- Count issues by status
SELECT
CASE WHEN is_closed = true THEN 'Closed' ELSE 'Open' END as status,
COUNT(*) as count
FROM issue
GROUP BY is_closed;
-- Find issues with most comments
SELECT i.id, i.title, COUNT(c.id) as comment_count
FROM issue i
LEFT JOIN comment c ON i.id = c.issue_id
GROUP BY i.id, i.title
ORDER BY comment_count DESC
LIMIT 10;
```
#### **Activity Monitoring**
```sql
-- Recent user activity
SELECT a.id, a.user_id, a.op_type, a.repo_id, a.created_unix, u.name as user_name
FROM action a
JOIN user u ON a.user_id = u.id
ORDER BY a.created_unix DESC
LIMIT 20;
-- Most active users
SELECT u.name, COUNT(a.id) as activity_count
FROM user u
JOIN action a ON u.id = a.user_id
WHERE a.created_unix > extract(epoch from now() - interval '7 days')
GROUP BY u.id, u.name
ORDER BY activity_count DESC
LIMIT 10;
```
### **📊 Database Monitoring Queries**
#### **Performance Metrics**
```sql
-- Database size
SELECT
pg_size_pretty(pg_database_size('gitea')) as database_size;
-- Table sizes
SELECT
schemaname,
tablename,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
-- Connection count
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE state = 'active';
```
---
## 🔍 **Database Monitoring**
### **📊 Key Metrics to Monitor**
#### **1. Connection Health**
```bash
# Check if Gitea can connect to PostgreSQL
kubectl logs -f deployment/gitea -n freeleaps-alpha | grep -i "database\|postgres"
# Check PostgreSQL service status
kubectl get svc -n freeleaps-alpha | grep postgresql
kubectl get pods -n freeleaps-alpha | grep postgresql
```
#### **2. Performance Metrics**
```bash
# Check PostgreSQL resource usage
kubectl top pods -n freeleaps-alpha | grep postgresql
# Check storage usage
kubectl get pvc -n freeleaps-alpha | grep postgresql
```
#### **3. Production HA Monitoring**
```bash
# Check HA cluster status (Production only)
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr cluster show
# Check PgPool status (Production only)
kubectl exec -it deployment/gitea-postgresql-ha-pgpool -n freeleaps-prod -- pgpool -c "SHOW pool_status;"
```
### **🚨 Monitoring Alerts**
#### **Critical Alerts**
```yaml
# Database connection failures
- Alert: GiteaDatabaseConnectionFailed
Condition: Gitea cannot connect to PostgreSQL
Action: Check PostgreSQL pod status and logs
# High connection count
- Alert: PostgreSQLHighConnections
Condition: Active connections > 80% of max_connections
Action: Investigate connection leaks or scaling needs
# Storage warnings
- Alert: PostgreSQLStorageWarning
Condition: Storage usage > 80%
Action: Plan storage expansion
```
---
## 🚨 **Troubleshooting**
### **🔍 Common Issues & Solutions**
#### **1. Gitea Cannot Connect to Database**
##### **Problem**: Gitea fails to start due to database connection issues
```bash
# Symptoms:
# - Gitea pod stuck in CrashLoopBackOff
# - Logs show "database connection failed"
# - Gitea web UI shows database error
# Diagnosis:
kubectl logs -f deployment/gitea -n freeleaps-alpha
kubectl describe pod -l app=gitea -n freeleaps-alpha
# Solutions:
# 1. Check PostgreSQL pod status
kubectl get pods -n freeleaps-alpha | grep postgresql
# 2. Check PostgreSQL logs
kubectl logs -f deployment/gitea-postgresql -n freeleaps-alpha
# 3. Test database connectivity
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "SELECT 1;"
# 4. Verify credentials
kubectl get secret gitea-postgresql -n freeleaps-alpha -o yaml
```
#### **2. Database Performance Issues**
##### **Problem**: Slow database queries or high resource usage
```bash
# Symptoms:
# - Slow Gitea web interface
# - High CPU/memory usage on PostgreSQL pod
# - Timeout errors in logs
# Diagnosis:
# 1. Check resource usage
kubectl top pods -n freeleaps-alpha | grep postgresql
# 2. Check slow queries
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT query, mean_time, calls
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;"
# 3. Check table statistics
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT schemaname, tablename, n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC;"
# Solutions:
# 1. Optimize slow queries
# 2. Add database indexes
# 3. Increase resource limits
# 4. Consider read replicas (Production)
```
#### **3. Storage Issues**
##### **Problem**: Database running out of storage space
```bash
# Symptoms:
# - PostgreSQL pod shows storage errors
# - PVC shows high usage
# - Database operations fail
# Diagnosis:
# 1. Check PVC usage
kubectl get pvc -n freeleaps-alpha | grep postgresql
# 2. Check database size
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT pg_size_pretty(pg_database_size('gitea'));"
# 3. Check table sizes
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename)) as size
FROM pg_tables
WHERE schemaname = 'public'
ORDER BY pg_total_relation_size(tablename) DESC;"
# Solutions:
# 1. Increase PVC size
kubectl patch pvc gitea-postgresql -n freeleaps-alpha -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
# 2. Clean up old data
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "VACUUM FULL;"
# 3. Archive old repositories/issues
```
#### **4. Production HA Issues**
##### **Problem**: PostgreSQL HA cluster not healthy
```bash
# Symptoms:
# - Primary node down
# - Replication lag
# - PgPool connection errors
# Diagnosis:
# 1. Check cluster status
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr cluster show
# 2. Check node status
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr node status
# 3. Check PgPool status
kubectl exec -it deployment/gitea-postgresql-ha-pgpool -n freeleaps-prod -- pgpool -c "SHOW pool_status;"
# Solutions:
# 1. Restart problematic nodes
kubectl delete pod gitea-postgresql-ha-postgresql-1 -n freeleaps-prod
# 2. Rejoin cluster if needed
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-1 -n freeleaps-prod -- repmgr node rejoin
# 3. Check replication lag
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr cluster show
```
### **🛠️ Debugging Commands**
#### **Essential Debugging Commands**
```bash
# Check PostgreSQL status
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_isready -U gitea -d gitea
# Check database connections
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE state = 'active';"
# Check database locks
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT * FROM pg_locks WHERE NOT granted;"
# Check slow queries
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT query, mean_time, calls
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 5;"
# Check table bloat
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT schemaname, tablename, n_dead_tup, n_live_tup,
CASE WHEN n_live_tup > 0 THEN round(100.0 * n_dead_tup / n_live_tup, 2) ELSE 0 END as bloat_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 0
ORDER BY bloat_ratio DESC;"
```
---
## 💾 **Backup & Recovery**
### **📦 Backup Strategies**
#### **1. Automated Backups**
```bash
# Create backup script
#!/bin/bash
# scripts/backup-gitea-database.sh
NAMESPACE="freeleaps-alpha"
BACKUP_DIR="/tmp/gitea-backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
echo "📦 Creating Gitea database backup..."
# Create database backup
kubectl exec -it deployment/gitea-postgresql -n $NAMESPACE -- pg_dump -U gitea -d gitea --format=custom --file=/tmp/gitea-backup-$DATE.dump
# Copy backup file
kubectl cp $NAMESPACE/deployment/gitea-postgresql:/tmp/gitea-backup-$DATE.dump $BACKUP_DIR/
echo "✅ Backup created: $BACKUP_DIR/gitea-backup-$DATE.dump"
```
#### **2. Manual Backups**
```bash
# Alpha Environment
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_dump -U gitea -d gitea > gitea-backup-$(date +%Y%m%d).sql
# Production Environment
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- pg_dump -U gitea -d gitea > gitea-prod-backup-$(date +%Y%m%d).sql
```
#### **3. Backup Verification**
```bash
# Verify backup integrity
pg_restore --list gitea-backup-20241201.dump
# Test restore to temporary database
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "CREATE DATABASE gitea_test;"
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_restore -U gitea -d gitea_test gitea-backup-20241201.dump
```
### **🔄 Recovery Procedures**
#### **1. Full Database Restore**
```bash
# Stop Gitea
kubectl scale deployment gitea -n freeleaps-alpha --replicas=0
# Restore database
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_restore -U gitea -d gitea --clean --if-exists gitea-backup-20241201.dump
# Restart Gitea
kubectl scale deployment gitea -n freeleaps-alpha --replicas=1
```
#### **2. Selective Data Recovery**
```bash
# Restore specific tables
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
-- Restore only user table
\copy user FROM '/tmp/user_backup.csv' WITH CSV HEADER;
-- Restore only repository table
\copy repository FROM '/tmp/repository_backup.csv' WITH CSV HEADER;"
```
#### **3. Point-in-Time Recovery**
```bash
# Enable WAL archiving for point-in-time recovery
# This requires additional PostgreSQL configuration
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
-- Restore to specific timestamp
SELECT pg_wal_replay_resume();
SELECT pg_wal_replay_pause();"
```
---
## 🔒 **Security Best Practices**
### **🛡️ Current Security Analysis**
#### **✅ Security Strengths**
1. **Network isolation** - PostgreSQL runs in Kubernetes namespace
2. **Resource limits** - CPU and memory limits set
3. **Non-root user** - Runs as postgres user in container
4. **TLS support** - SSL/TLS configuration available (Production)
#### **⚠️ Security Weaknesses**
1. **Hardcoded passwords** - Passwords in values files
2. **Default permissions** - Overly permissive user access
3. **No audit logging** - Limited security event tracking
4. **No network policies** - No ingress/egress restrictions
### **🔧 Security Improvements**
#### **1. Secret Management**
```yaml
# Use Kubernetes secrets instead of hardcoded values
apiVersion: v1
kind: Secret
metadata:
name: gitea-postgresql-credentials
namespace: freeleaps-alpha
type: Opaque
data:
username: Z2l0ZWE= # base64 encoded
password: <base64-encoded-password>
---
# Reference in Helm values
postgresql:
global:
postgresql:
auth:
existingSecret: gitea-postgresql-credentials
secretKeys:
usernameKey: username
passwordKey: password
```
#### **2. Network Policies**
```yaml
# Restrict network access to PostgreSQL
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: gitea-postgresql-network-policy
namespace: freeleaps-alpha
spec:
podSelector:
matchLabels:
app: postgresql
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: freeleaps-alpha
ports:
- protocol: TCP
port: 5432
```
#### **3. Database Hardening**
```sql
-- Limit database connections
ALTER SYSTEM SET max_connections = 100;
-- Enable SSL (Production)
ALTER SYSTEM SET ssl = on;
ALTER SYSTEM SET ssl_cert_file = '/etc/ssl/certs/server.crt';
ALTER SYSTEM SET ssl_key_file = '/etc/ssl/private/server.key';
-- Enable audit logging
CREATE EXTENSION pgaudit;
ALTER SYSTEM SET pgaudit.log = 'all';
ALTER SYSTEM SET pgaudit.log_level = 'log';
```
---
## 📈 **Performance Optimization**
### **🎯 Performance Tuning**
#### **1. Database Configuration**
```yaml
# Optimize PostgreSQL settings
postgresql:
primary:
extendedConfiguration: |-
# Memory settings
shared_buffers = 256MB
effective_cache_size = 1GB
work_mem = 4MB
maintenance_work_mem = 64MB
# Checkpoint settings
checkpoint_completion_target = 0.9
wal_buffers = 16MB
# Query optimization
random_page_cost = 1.1
effective_io_concurrency = 200
# Logging
log_min_duration_statement = 1000
log_checkpoints = on
log_connections = on
log_disconnections = on
```
#### **2. Index Optimization**
```sql
-- Create indexes for common queries
CREATE INDEX CONCURRENTLY idx_user_email ON user(email);
CREATE INDEX CONCURRENTLY idx_repository_owner ON repository(owner_id);
CREATE INDEX CONCURRENTLY idx_issue_repo ON issue(repo_id);
CREATE INDEX CONCURRENTLY idx_action_user_time ON action(user_id, created_unix);
-- Analyze table statistics
ANALYZE user;
ANALYZE repository;
ANALYZE issue;
ANALYZE action;
```
#### **3. Query Optimization**
```sql
-- Monitor slow queries
SELECT query, mean_time, calls, total_time
FROM pg_stat_statements
WHERE mean_time > 1000
ORDER BY mean_time DESC;
-- Optimize specific queries
-- Example: Optimize user search query
EXPLAIN ANALYZE SELECT * FROM user WHERE name ILIKE '%search%';
```
### **📊 Performance Monitoring**
#### **Key Performance Indicators**
1. **Query Response Time** - Average query execution time
2. **Connection Count** - Active database connections
3. **Cache Hit Ratio** - Buffer cache efficiency
4. **I/O Wait Time** - Disk I/O performance
5. **Lock Wait Time** - Database contention
#### **Performance Benchmarks**
```bash
# Your expected performance:
# - Query response time: < 100ms for simple queries
# - Connection count: < 80% of max_connections
# - Cache hit ratio: > 90%
# - I/O wait: < 5% of total time
# - Lock wait: < 1% of total time
```
---
## 🛠️ **Maintenance Procedures**
### **📅 Regular Maintenance Tasks**
#### **Daily Tasks**
```bash
# 1. Check database health
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_isready -U gitea -d gitea
# 2. Monitor connection count
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE state = 'active';"
# 3. Check for long-running queries
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active'
AND now() - pg_stat_activity.query_start > interval '5 minutes';"
```
#### **Weekly Tasks**
```bash
# 1. Analyze table statistics
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
ANALYZE user;
ANALYZE repository;
ANALYZE issue;
ANALYZE action;"
# 2. Check table bloat
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT schemaname, tablename, n_dead_tup, n_live_tup,
CASE WHEN n_live_tup > 0 THEN round(100.0 * n_dead_tup / n_live_tup, 2) ELSE 0 END as bloat_ratio
FROM pg_stat_user_tables
WHERE n_dead_tup > 0
ORDER BY bloat_ratio DESC;"
# 3. Review slow queries
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT query, mean_time, calls
FROM pg_stat_statements
ORDER BY mean_time DESC
LIMIT 10;"
```
#### **Monthly Tasks**
```bash
# 1. Full database backup
./scripts/backup-gitea-database.sh
# 2. Vacuum and reindex
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
VACUUM FULL;
REINDEX DATABASE gitea;"
# 3. Review and optimize indexes
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
FROM pg_stat_user_indexes
ORDER BY idx_scan DESC;"
```
### **🔧 Maintenance Scripts**
#### **Health Check Script**
```bash
#!/bin/bash
# scripts/gitea-database-health-check.sh
NAMESPACE="freeleaps-alpha"
POD_NAME=$(kubectl get pods -n $NAMESPACE -l app=postgresql -o jsonpath='{.items[0].metadata.name}')
echo "🐘 Gitea Database Health Check - $(date)"
echo "=================================="
# Check database connectivity
echo "📊 Database Connectivity:"
kubectl exec -it $POD_NAME -n $NAMESPACE -- pg_isready -U gitea -d gitea
# Check active connections
echo "🔗 Active Connections:"
kubectl exec -it $POD_NAME -n $NAMESPACE -- psql -U gitea -d gitea -c "
SELECT count(*) as active_connections
FROM pg_stat_activity
WHERE state = 'active';"
# Check database size
echo "💾 Database Size:"
kubectl exec -it $POD_NAME -n $NAMESPACE -- psql -U gitea -d gitea -c "
SELECT pg_size_pretty(pg_database_size('gitea'));"
# Check table statistics
echo "📋 Table Statistics:"
kubectl exec -it $POD_NAME -n $NAMESPACE -- psql -U gitea -d gitea -c "
SELECT schemaname, tablename, n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup
FROM pg_stat_user_tables
ORDER BY n_dead_tup DESC
LIMIT 5;"
```
#### **Backup Script**
```bash
#!/bin/bash
# scripts/gitea-database-backup.sh
NAMESPACE="freeleaps-alpha"
BACKUP_DIR="/tmp/gitea-backups"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
echo "📦 Creating Gitea database backup..."
# Create database backup
kubectl exec -it deployment/gitea-postgresql -n $NAMESPACE -- pg_dump -U gitea -d gitea --format=custom --file=/tmp/gitea-backup-$DATE.dump
# Copy backup file
kubectl cp $NAMESPACE/deployment/gitea-postgresql:/tmp/gitea-backup-$DATE.dump $BACKUP_DIR/
# Verify backup
kubectl exec -it deployment/gitea-postgresql -n $NAMESPACE -- pg_restore --list /tmp/gitea-backup-$DATE.dump > /dev/null
if [ $? -eq 0 ]; then
echo "✅ Backup created successfully: $BACKUP_DIR/gitea-backup-$DATE.dump"
else
echo "❌ Backup verification failed"
exit 1
fi
```
### **🚨 Emergency Procedures**
#### **1. Database Corruption Recovery**
```bash
# If database corruption is detected:
# 1. Stop Gitea
kubectl scale deployment gitea -n freeleaps-alpha --replicas=0
# 2. Restore from latest backup
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_restore -U gitea -d gitea --clean --if-exists /tmp/gitea-backup-latest.dump
# 3. Restart Gitea
kubectl scale deployment gitea -n freeleaps-alpha --replicas=1
```
#### **2. Performance Emergency**
```bash
# If database performance is severely degraded:
# 1. Check for long-running queries
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE state = 'active'
AND now() - pg_stat_activity.query_start > interval '5 minutes';"
# 2. Kill problematic queries
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "SELECT pg_terminate_backend(pid);"
# 3. Restart PostgreSQL if needed
kubectl rollout restart deployment/gitea-postgresql -n freeleaps-alpha
```
---
## 🎯 **Summary & Next Steps**
### **📊 Current State Assessment**
#### **✅ Strengths**
1. **Production-ready setup** - HA clustering in production
2. **Helm-based deployment** - Consistent and repeatable
3. **Environment separation** - Alpha vs Production configurations
4. **Integration working** - Gitea successfully using PostgreSQL
5. **Monitoring available** - Basic health checks and metrics
#### **⚠️ Areas for Improvement**
1. **Security hardening** - Remove hardcoded passwords, implement secrets
2. **Backup automation** - Implement automated backup procedures
3. **Performance tuning** - Optimize database settings for your workload
4. **Monitoring enhancement** - Add comprehensive monitoring and alerting
5. **Documentation** - Create runbooks for common operations
### **🚀 Recommended Actions**
#### **Immediate (This Week)**
1. **Implement secret management** - Move passwords to Kubernetes secrets
2. **Set up automated backups** - Create daily backup scripts
3. **Add basic monitoring** - Set up database health checks
4. **Document procedures** - Create runbooks for common operations
#### **Short Term (Next Month)**
1. **Security audit** - Review and improve security posture
2. **Performance tuning** - Optimize settings based on usage patterns
3. **Monitoring enhancement** - Add comprehensive metrics and alerting
4. **Training** - Train team on database management and troubleshooting
#### **Long Term (Next Quarter)**
1. **Advanced monitoring** - Implement predictive analytics and alerting
2. **Disaster recovery** - Set up automated backup and recovery procedures
3. **Performance optimization** - Implement query optimization and indexing
4. **Capacity planning** - Plan for growth and scaling
### **📚 Additional Resources**
#### **Official Documentation**
- **[PostgreSQL Documentation](https://www.postgresql.org/docs/)** - Official PostgreSQL guides
- **[Gitea Database Documentation](https://docs.gitea.com/installation/database-prep)** - Database setup guide
- **[Bitnami PostgreSQL Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql)** - Helm chart documentation
#### **Community Resources**
- **[PostgreSQL Slack](https://postgresql-slack.herokuapp.com/)** - Community support (Note: May require invitation)
- **[Gitea Community](https://gitea.com/gitea/helm-gitea)** - Gitea Helm chart community
- **[PostgreSQL Wiki](https://wiki.postgresql.org/wiki/)** - Community wiki
#### **Books & Courses**
- **"PostgreSQL: Up and Running"** by Regina Obe and Leo Hsu
- **"Gitea Documentation"** - Official Gitea guides
- **PostgreSQL Tutorials** - Official tutorial series
---
**🎉 You now have a comprehensive understanding of how PostgreSQL supports Gitea in your Kubernetes environment! Use this guide to maintain, monitor, and optimize your database infrastructure.**
---
*Last updated: $(date)*
*Maintained by: FreeLeaps DevOps Team*