feat: Gitea deployment with 1Password and Caddy

Complete infrastructure deployment including:
- Docker Compose templates with 1Password integration (op://)
- Caddy reverse proxy configuration for git.terraphim.cloud
- Automated deployment script (deploy-to-bigbox.sh)
- Comprehensive documentation and deployment article
- Network isolation: Public (Gitea) + Tailscale (Prometheus/S3)
- Security: No hardcoded secrets, all via 1Password

Services deployed:
- Gitea 1.22.6 (Git hosting)
- PostgreSQL 15 (Database)
- SeaweedFS (S3-compatible storage)
- Prometheus (Monitoring)

Excludes:
- docker-compose.yml (contains resolved secrets)
- s3_config.json (contains resolved secrets)
- Data directories (gitea/, postgres/, seaweedfs/)

Refs: Private deployment on bigbox with TerraphimPlatform vault
This commit is contained in:
Alex
2026-02-16 19:40:19 +00:00
parent 850d8b7680
commit 4a4a0351aa
13 changed files with 2620 additions and 200 deletions
+322
View File
@@ -0,0 +1,322 @@
# Research Document: Gitea Deployment to Bigbox with 1Password Secrets Management
**Status**: Draft
**Author**: Claude
**Date**: 2026-02-16
**Reviewers**: [Pending]
## Executive Summary
This project deploys a comprehensive Gitea-based development infrastructure stack including Git hosting (Gitea), object storage (SeaweedFS), monitoring (Prometheus), and PostgreSQL database to a remote server called "bigbox". This deployment uses **1Password secrets management** via `op inject` to securely manage credentials and includes **Caddy reverse proxy** for SSL termination and routing. The environment is configured using the `op_zesticai_non_prod.sh` script for 1Password authentication.
## Essential Questions Check
| Question | Answer | Evidence |
|----------|--------|----------|
| Energizing? | Yes | Provides self-hosted Git infrastructure with production-grade secrets management |
| Leverages strengths? | Yes | Uses 1Password (already configured), Docker Compose patterns, SSH deployment |
| Meets real need? | Yes | Creates secure build machine with proper secrets management and reverse proxy |
**Proceed**: Yes - All 3 questions answered YES
## Problem Statement
### Description
Deploy a Gitea-based development infrastructure stack to a remote server (bigbox) using SSH with:
- **1Password secrets management** for all credentials (no hardcoded secrets)
- **Caddy reverse proxy** for SSL termination and routing
- **Secure credential injection** via `op inject`
- Environment authentication via `source op_zesticai_non_prod.sh`
The stack includes:
- Gitea (Git hosting with Actions support)
- PostgreSQL (database)
- SeaweedFS (distributed object storage with S3 API)
- Prometheus (monitoring)
- Caddy (reverse proxy with automatic HTTPS)
### Impact
Who is affected:
- Developers needing self-hosted Git repository management
- Teams requiring production-grade security with proper secrets management
- Projects needing S3-compatible object storage with secure credential handling
### Success Criteria
- [ ] All services start successfully on bigbox
- [ ] Gitea accessible via HTTPS (via Caddy reverse proxy)
- [ ] SeaweedFS S3 API accessible with secure credentials
- [ ] Prometheus monitoring accessible (via Caddy or directly)
- [ ] Data persistence across container restarts
- [ ] Services communicate properly within Docker network
- [ ] No hardcoded credentials in configuration files
- [ ] Caddy configured with proper reverse proxy rules
- [ ] 1Password secrets injected via `op inject`
## Current State Analysis
### Existing Implementation
The project uses Docker Compose with the following services:
| Component | Location | Purpose |
|-----------|----------|---------|
| Gitea | `docker-compose.yml:8` | Git hosting server with Actions and LFS support |
| PostgreSQL | `docker-compose.yml:46` | Database for Gitea |
| SeaweedFS Master | `docker-compose.yml:57` | Metadata management for distributed storage |
| SeaweedFS Volume | `docker-compose.yml:68` | Data storage nodes |
| SeaweedFS Filer | `docker-compose.yml:81` | File metadata and directory operations |
| SeaweedFS S3 | `docker-compose.yml:101` | S3-compatible API gateway |
| Prometheus | `docker-compose.yml:145` | Metrics collection and monitoring |
| **Caddy** | **NEW** | Reverse proxy with automatic HTTPS |
### Bigbox Environment Verified
- **1Password CLI**: Installed (`/usr/bin/op`)
- **1Password Service Account**: `~/op_zesticai_non_prod.sh` configured with `OP_SERVICE_ACCOUNT_TOKEN`
- **Docker**: 28.1.1 installed
- **Docker Compose**: v2.35.1 installed
- **Caddy**: Installed but no service configured
- **Hardware**: 125GB RAM, 3.5TB disk (367GB free)
### Secrets Management Architecture
```
1Password Vault (non-prod)
│ op inject
op_zesticai_non_prod.sh ←── Export OP_SERVICE_ACCOUNT_TOKEN
docker-compose.yml.template
│ op inject --in-file docker-compose.yml.template --out-file docker-compose.yml
docker-compose.yml (secrets populated)
Containers (receive secrets as environment variables)
```
### Data Flow
```
Internet ──▶ Caddy (:443/:80)
├──▶ Gitea (:3000)
│ └──▶ PostgreSQL (:5432)
├──▶ SeaweedFS S3 (:8333)
│ └──▶ Filer (:8888) ──▶ Master (:9333) + Volume (:8080)
└──▶ Prometheus (:9000)
```
### Integration Points
- Gitea uses SeaweedFS S3 for LFS and attachment storage
- Prometheus scrapes metrics from all SeaweedFS components
- Services communicate via internal Docker network "gitea"
- Caddy terminates SSL and routes to services
- 1Password injects secrets at deployment time
## Constraints
### Technical Constraints
- **Docker Compose Version**: Uses version 3 syntax
- **Container Images**: Fixed versions (gitea:1.22.6, postgres:15, prom/prometheus:v2.21.0)
- **SeaweedFS**: Uses "latest" tag (chrislusf/seaweedfs)
- **1Password CLI**: Must be available and authenticated via service account
- **Caddy**: Installed but needs configuration
- **Port Requirements**:
- 80/443 (Caddy - external)
- 3000 (Gitea HTTP - internal)
- 222 (Gitea SSH - external)
- 8333 (S3 API - internal or external via Caddy)
- 9000 (Prometheus - internal or external via Caddy)
### Security Constraints
- **No Hardcoded Secrets**: All credentials must come from 1Password
- **Service Account Authentication**: Must source `op_zesticai_non_prod.sh` before `op inject`
- **Template Files**: Use `.template` extension for files with 1Password references
- **Secret Rotation**: Support easy rotation via 1Password updates
### Non-Functional Requirements
| Requirement | Target | Current |
|-------------|--------|---------|
| Security | No hardcoded secrets | Hardcoded credentials exist |
| Secrets Management | 1Password integration | Not implemented |
| SSL/TLS | Automatic via Caddy | Not configured |
| Availability | 99% uptime | Not measured |
## Vital Few (Essentialism)
### Essential Constraints (Max 3)
| Constraint | Why It's Vital | Evidence |
|------------|----------------|----------|
| 1Password CLI and service account | Required for secrets injection | `/usr/bin/op` and `~/op_zesticai_non_prod.sh` verified |
| Caddy reverse proxy | SSL termination and routing | Production-grade deployment requirement |
| SSH Access to bigbox | Required for deployment | `ssh -G bigbox` confirms configuration |
### Eliminated from Scope
| Eliminated Item | Why Eliminated |
|-----------------|----------------|
| Gitea Runners (TODO) | Listed as future work in README |
| Earthly Buildkit | Listed as future work in README |
| Nginx S3 Gateway | Caddy replaces this need |
| Panamax (crates mirror) | Commented out in compose file |
| Automated backups | Out of scope for initial deployment |
| Custom domain SSL certs | Caddy handles automatic HTTPS |
## Dependencies
### Internal Dependencies
| Dependency | Impact | Risk |
|------------|--------|------|
| Gitea | Depends on PostgreSQL and S3 | High - core service |
| SeaweedFS S3 | Depends on Filer, Volume, Master | High - storage layer |
| Caddy | Depends on all web services | High - external access |
| 1Password | Required for secrets injection | High - security dependency |
| Prometheus | Depends on all services | Low - monitoring only |
### External Dependencies
| Dependency | Version | Risk | Alternative |
|------------|---------|------|-------------|
| Gitea | 1.22.6 | Low | Upgrade path available |
| PostgreSQL | 15 | Low | Well established |
| SeaweedFS | latest | Medium | Version pinning recommended |
| Prometheus | v2.21.0 | Low | Established monitoring |
| Caddy | latest | Low | Stable reverse proxy |
| 1Password CLI | latest | Low | Enterprise secrets management |
## Risks and Unknowns
### Known Risks
| Risk | Likelihood | Impact | Mitigation |
|------|------------|--------|------------|
| 1Password authentication failure | Low | High | Verify service account token before deployment |
| Caddy configuration errors | Medium | High | Test config with `caddy validate` |
| Port conflicts on bigbox | Medium | High | Verify ports before deployment |
| Secrets injection failure | Low | High | Validate templates before deployment |
| SSL certificate issues | Low | Medium | Caddy handles automatically |
### Open Questions
1. What 1Password vault/items contain the required secrets? - [Need to document]
2. What domain/subdomain will Caddy use? - [Need to determine]
3. Are required ports available (80/443)? - [Port scan required]
4. Existing Caddy configuration on bigbox? - [Verified: none active]
### Assumptions Explicitly Stated
| Assumption | Basis | Risk if Wrong | Verified? |
|------------|-------|---------------|-----------|
| 1Password CLI available on bigbox | `/usr/bin/op` exists | Secrets injection fails | Yes |
| op_zesticai_non_prod.sh has valid token | File exists with token | Authentication fails | Yes (token present) |
| Caddy installed and working | `/usr/bin/caddy` exists | Reverse proxy fails | Yes |
| Docker is installed on bigbox | Docker 28.1.1 verified | Deployment fails | Yes |
| Sufficient disk space available | 367GB available verified | Out of space | Yes |
| Network ports are available | Not verified | Port conflicts | No |
### Multiple Interpretations Considered
| Interpretation | Implications | Why Chosen/Rejected |
|----------------|--------------|---------------------|
| 1Password Connect Server | Centralized secret serving | Rejected - adds infrastructure complexity |
| Docker Secrets | Native Docker secrets | Rejected - requires Swarm mode |
| op inject with templates | Simple, effective | Chosen - minimal complexity, works with Compose |
| Caddy with Docker Compose | Containerized Caddy | Alternative - but native Caddy is simpler |
## Research Findings
### Key Insights
1. **Production-Ready Security**: 1Password integration eliminates hardcoded credentials
2. **Caddy Simplification**: Automatic HTTPS eliminates SSL certificate management
3. **Service Account Auth**: `op_zesticai_non_prod.sh` provides secure 1Password access
4. **Template Pattern**: `.template` files with 1Password references enable secure deployment
5. **Complete Stack**: Full infrastructure with proper secrets management and reverse proxy
### 1Password Secrets Required
Based on current configuration, the following secrets must exist in 1Password:
| Secret | Purpose | Current Hardcoded Value |
|--------|---------|------------------------|
| `op://zesticai-non-prod/gitea-postgres/password` | PostgreSQL password | gitea |
| `op://zesticai-non-prod/gitea-s3/access-key` | S3 access key | REDACTED_S3_ACCESS_KEY |
| `op://zesticai-non-prod/gitea-s3/secret-key` | S3 secret key | REDACTED_S3_SECRET_KEY |
| `op://zesticai-non-prod/gitea-jwt/secret` | Gitea JWT secret | (not currently set) |
### Caddy Configuration Requirements
```caddyfile
# Caddyfile for gitea-stack
gitea.bigbox.example.com {
reverse_proxy localhost:3000
}
s3.bigbox.example.com {
reverse_proxy localhost:8333
}
prometheus.bigbox.example.com {
reverse_proxy localhost:9000
}
```
### Technical Spikes Needed
| Spike | Purpose | Estimated Effort |
|-------|---------|------------------|
| Verify 1Password vault structure | Confirm required secrets exist | 30 minutes |
| Test op inject workflow | Validate secrets injection | 30 minutes |
| Design Caddy configuration | Determine routing rules | 1 hour |
| Test Caddy with services | Validate reverse proxy | 1 hour |
## Recommendations
### Proceed/No-Proceed
**Proceed** - Bigbox has all required tools (1Password CLI, Docker, Caddy), and the 1Password service account is already configured.
### Scope Recommendations
1. **Phase 1**: Implement 1Password secrets management
2. **Phase 2**: Add Caddy reverse proxy configuration
3. **Phase 3**: Deploy and validate all services
### Risk Mitigation Recommendations
1. Test 1Password authentication before deployment
2. Validate Caddy configuration with `caddy validate`
3. Create backup of existing data before deployment
4. Use staging/test domain initially for SSL validation
5. Document all 1Password vault items required
## Next Steps
If approved:
1. Create 1Password vault items for all required secrets
2. Create Implementation Plan with 1Password and Caddy integration
3. Test `op inject` workflow locally
4. Execute deployment following plan
5. Validate all services and Caddy routing
## Appendix
### Reference Materials
- docker-compose.yml: Main deployment configuration
- s3_config.json: SeaweedFS S3 gateway credentials (to be replaced with 1Password)
- prometheus/prometheus.yml: Monitoring configuration
- README.md: Project overview and TODOs
- op_zesticai_non_prod.sh: 1Password service account configuration
### 1Password CLI Usage
```bash
# Source the service account token
source ~/op_zesticai_non_prod.sh
# Inject secrets into template
op inject --in-file docker-compose.yml.template --out-file docker-compose.yml
# Or run with op run
op run --env-file=.env -- docker compose up -d
```
### Caddy Commands
```bash
# Validate configuration
caddy validate --config /etc/caddy/Caddyfile
# Start Caddy (as service or directly)
sudo caddy run --config /etc/caddy/Caddyfile
# Reload configuration
sudo caddy reload --config /etc/caddy/Caddyfile
```