Files
gitea-infrastructure/ARTICLE-gitea-deployment.md
Alex 4a4a0351aa 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
2026-02-16 19:40:19 +00:00

9.7 KiB

Deploying Gitea with 1Password Secrets Management and Caddy on Bigbox

Date: February 16, 2026
Author: Infrastructure Team
Tags: gitea, 1password, caddy, docker, tailscale, devops

Executive Summary

This article documents the deployment of a production-ready Gitea instance on bigbox server, featuring enterprise-grade security with 1Password secrets management, Caddy reverse proxy with automatic HTTPS, and network isolation via Tailscale.

Architecture Overview

┌─────────────────────────────────────────────────────────────────┐
│                         Internet                                 │
│                          │                                       │
│                          ▼                                       │
│              ┌──────────────────────┐                           │
│              │   Caddy (bigbox)     │                           │
│              │   :443/:80           │                           │
│              └──────────┬───────────┘                           │
│                         │                                        │
│          ┌──────────────┼──────────────┐                        │
│          │              │              │                        │
│          ▼              ▼              ▼                        │
│  workflows.     git.terraphim.    *.terraphim.                  │
│  terraphim.      cloud (NEW)        cloud                       │
│     cloud          │                (catchall)                  │
│                    ▼                                            │
│            ┌──────────────┐                                    │
│            │   Gitea      │                                    │
│            │   :3000      │                                    │
│            └──────┬───────┘                                    │
│                   │                                             │
└───────────────────┼─────────────────────────────────────────────┘
                    │
        ┌───────────┴───────────┐
        │      Tailscale VPN     │
        │    (100.106.66.0/8)    │
        └───────────┬───────────┘
                    │
        ┌───────────┼───────────┐
        ▼           ▼           ▼
   Prometheus     S3 API    SeaweedFS
   :9000         :8333      (Internal)

Key Features

1. Security-First Design

  • No hardcoded secrets - All credentials stored in 1Password
  • 1Password integration - Secrets injected at runtime via op inject
  • Template-based configuration - .template files in git, resolved configs excluded
  • Network isolation - Internal services not exposed to internet

2. Multi-Layer Network Security

Service Exposure Access Method
Gitea Web Public HTTPS via Caddy (git.terraphim.cloud)
Gitea SSH Public Port 222 direct
Prometheus Tailscale only http://100.106.66.7:9000
S3 API Tailscale only http://100.106.66.7:8333
PostgreSQL Internal only Docker network
SeaweedFS Internal only Docker network

3. Technology Stack

  • Gitea 1.22.6 - Git hosting with Actions support
  • PostgreSQL 15 - Database
  • SeaweedFS - Distributed S3-compatible object storage
  • Prometheus - Metrics and monitoring
  • Caddy - Reverse proxy with automatic HTTPS
  • 1Password CLI - Secrets management
  • Tailscale - VPN for internal services

Deployment Process

Prerequisites

  • SSH access to bigbox
  • 1Password service account configured (~/op_zesticai_non_prod.sh)
  • Caddy already running on bigbox
  • Docker and Docker Compose installed

Step 1: Create 1Password Vault Items

eval $(op signin)

# Create PostgreSQL credentials
op item create \
  --vault="TerraphimPlatform" \
  --category=login \
  --title="gitea-postgres" \
  --generate-password=20,letters,digits \
  username=gitea

# Create S3 credentials
op item create \
  --vault="TerraphimPlatform" \
  --category=custom \
  --title="gitea-s3" \
  access-key="$(openssl rand -hex 20)" \
  secret-key="$(openssl rand -hex 40)"

Step 2: Template Configuration Files

Create .template files with 1Password references:

docker-compose.yml.template:

version: "3"

services:
  server:
    image: gitea/gitea:1.22.6
    environment:
      - GITEA__database__PASSWD=op://TerraphimPlatform/gitea-postgres/password
      - GITEA__storage__MINIO_ACCESS_KEY_ID=op://TerraphimPlatform/gitea-s3/access-key
      - GITEA__storage__MINIO_SECRET_ACCESS_KEY=op://TerraphimPlatform/gitea-s3/secret-key
      # ... other config

s3_config.json.template:

{
  "identities": [{
    "name": "gitea",
    "credentials": [{
      "accessKey": "op://TerraphimPlatform/gitea-s3/access-key",
      "secretKey": "op://TerraphimPlatform/gitea-s3/secret-key"
    }]
  }]
}

Step 3: Inject Secrets and Deploy

# Source 1Password credentials
source ~/op_zesticai_non_prod.sh

# Inject secrets into configuration files
op inject --in-file docker-compose.yml.template --out-file docker-compose.yml
op inject --in-file s3_config.json.template --out-file s3_config.json

# Start services
docker compose up -d

Step 4: Configure Caddy

Add Gitea route to existing Caddy instance:

# Add route via Caddy Admin API
curl -X POST http://localhost:2019/config/apps/http/servers/srv0/routes \
  -H "Content-Type: application/json" \
  -d '{
    "@id": "gitea_route",
    "match": [{"host": ["git.terraphim.cloud"]}],
    "handle": [{
      "handler": "subroute",
      "routes": [{
        "handle": [{
          "handler": "reverse_proxy",
          "upstreams": [{"dial": "localhost:3000"}]
        }]
      }]
    }],
    "terminal": true
  }'

Important: Route order matters! Add specific routes before wildcard routes.

Network Configuration Details

Port Bindings

Gitea (Public):

  • 127.0.0.1:3000:3000 - HTTP via Caddy
  • 0.0.0.0:222:22 - SSH direct access

Prometheus (Tailscale only):

  • 100.106.66.7:9000:9090 - Only accessible via Tailscale

S3 API (Tailscale only):

  • 100.106.66.7:8333:8333 - Only accessible via Tailscale
  • 100.106.66.7:9327:9327 - Prometheus metrics

Docker Compose Network Isolation

networks:
  gitea:
    external: false  # Internal Docker network only

services:
  db:
    networks:
      - gitea  # No external ports
  
  master:
    # No ports exposed - internal only
  
  volume:
    # No ports exposed - internal only
  
  filer:
    # No ports exposed - internal only

Security Considerations

1. Secrets Management

  • No secrets in Git repository
  • No secrets in Docker images
  • Secrets injected at runtime
  • Easy rotation via 1Password

2. Network Security

  • Public services behind Caddy with automatic HTTPS
  • Internal services on Tailscale VPN
  • Database isolated in Docker network
  • SSH on non-standard port (222)

3. Access Control

  • Prometheus and S3 require Tailscale connection
  • Gitea accessible publicly via HTTPS
  • SSH access available on port 222

Troubleshooting

Permission Denied Errors

If Gitea shows permission errors:

sudo chown -R 1000:1000 gitea/
sudo chmod -R 755 gitea/
docker compose restart server

Route Not Working

Check Caddy route order:

curl -s http://localhost:2019/config/apps/http/servers/srv0/routes | \
  jq '.[] | select(.match[0].host[0] | contains("terraphim")) | .match[0].host[0]'

Specific routes must come before wildcard routes.

1Password Authentication

Verify service account:

source ~/op_zesticai_non_prod.sh
op vault list

Maintenance

Backup

# Backup data directories
rsync -avz bigbox:~/gitea-stack/gitea ./backup/
rsync -avz bigbox:~/gitea-stack/postgres ./backup/
rsync -avz bigbox:~/gitea-stack/seaweedfs ./backup/

Update Images

cd ~/gitea-stack
docker compose pull
docker compose up -d

Rotate Secrets

  1. Update in 1Password vault
  2. Re-run deployment:
    source ~/op_zesticai_non_prod.sh
    op inject --in-file docker-compose.yml.template --out-file docker-compose.yml
    docker compose up -d
    

Access Points

Public URLs

Tailscale-only URLs

Connect to Tailscale first: tailscale up

Conclusion

This deployment demonstrates production-ready practices:

  • Zero hardcoded secrets
  • Defense in depth with network isolation
  • Automatic HTTPS via Caddy
  • Easy maintenance with Docker Compose
  • Centralized secrets management with 1Password

The architecture balances security (Tailscale isolation, 1Password integration) with usability (public HTTPS access to Gitea, direct SSH access).

References


Repository: [Private terraphim repo with configuration]