|
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 3s
Adds title, description, type, domain, and tags frontmatter to every doc for improved KB semantic search. The description field is prepended to every search chunk, and domain/type/tags enable filtered queries. Type values: context, guide, runbook, reference, troubleshooting Domain values match directory structure (networking, docker, etc.) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| workflow-templates | ||
| .env.example | ||
| apply_branch_protection.py | ||
| deployment-strategies.md | ||
| harbor-registry-setup.md | ||
| INDEX.md | ||
| README.md | ||
| title | description | type | domain | tags | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Gitea Server Setup and Config | Complete setup and configuration reference for the self-hosted Gitea instance on LXC 225 (10.10.0.225). Covers service management, Gitea Actions CI/CD runner setup, shared composite actions, branch protection, backup/restore, and troubleshooting. | reference | server-configs |
|
Gitea - Self-Hosted Git Server
LXC 225 | 10.10.0.225 | git.manticorum.com
Self-hosted Git server with web UI, Git LFS support, and Gitea Actions for CI/CD pipelines.
Quick Info
| Property | Value |
|---|---|
| Type | LXC Container (Proxmox) |
| OS | Ubuntu 20.04 LTS |
| IP | 10.10.0.225 |
| Public URL | https://git.manticorum.com |
| Gitea Version | 1.22.6 |
| Database | PostgreSQL 12 |
| Reverse Proxy | Nginx Proxy Manager (10.10.0.16) |
Container Specs
- VMID: 225
- CPU: 2 cores
- RAM: 2GB
- Disk: 20GB
- Features: Nesting enabled (for future Docker runner support)
Services
Gitea Web
- Port: 3000 (internal)
- Service:
gitea.service - User:
git - Work Dir:
/var/lib/gitea - Config:
/etc/gitea/app.ini - Data:
/var/lib/gitea/data - Logs:
/var/lib/gitea/log
PostgreSQL
- Version: 12
- Port: 5432 (localhost only)
- Database:
gitea - User:
gitea - Service:
postgresql
Management
Access Container
ssh root@10.10.0.225
# or via Proxmox
pct enter 225
Service Management
# Status
systemctl status gitea
systemctl status postgresql
# Restart
systemctl restart gitea
# Logs
journalctl -u gitea -f
Database Access
# As postgres user
sudo -u postgres psql -d gitea
# As gitea user (from container)
PGPASSWORD=gitea123 psql -U gitea -d gitea -h 127.0.0.1
Configuration
Main Config File
/etc/gitea/app.ini contains all Gitea settings:
- Database connection
- Server domain and URLs
- SSH settings
- LFS configuration
- OAuth2/JWT secrets
- Actions enabled
Permissions:
- Owner:
root:git - Mode:
640 - Directory:
750on/etc/gitea
Admin Account
- Username:
cal - Password: Set during initial setup (change immediately!)
- Email:
cal@manticorum.com
Features Enabled
- ✅ Gitea Actions - Built-in CI/CD (GitHub Actions compatible)
- ✅ Git LFS - Large file storage support
- ✅ SSH Access - Git over SSH on port 22
- ✅ Web UI - Repository browser and management
- ✅ Organizations - Multi-user repository groups
- ✅ Webhooks - Integration with external services
Key app.ini Settings (Actions)
[actions]
DEFAULT_ACTIONS_URL = self # Short-form actions resolve against local Gitea instance
[service]
REQUIRE_SIGNIN_VIEW = false # Public repos (like gitea-actions) cloneable without auth
DEFAULT_ACTIONS_URL=selfmeansuses: cal/gitea-actions/calver@mainresolves locallyREQUIRE_SIGNIN_VIEW=falseonly exposes PUBLIC repos — all private repos remain locked down- The only public repo is
cal/gitea-actions(reusable CI composite actions, no sensitive code)
Backup
What to Backup
- PostgreSQL database:
giteadatabase - Repository data:
/var/lib/gitea/data/gitea-repositories - Configuration:
/etc/gitea/app.ini - Custom files:
/var/lib/gitea/custom(if any)
Backup Commands
# Database dump
sudo -u postgres pg_dump gitea > gitea-backup-$(date +%Y%m%d).sql
# Full data directory
tar -czf gitea-data-$(date +%Y%m%d).tar.gz /var/lib/gitea
# Config only
cp /etc/gitea/app.ini gitea-app-$(date +%Y%m%d).ini
Restore
# Restore database
sudo -u postgres psql -d gitea < gitea-backup.sql
# Restore data
tar -xzf gitea-data.tar.gz -C /
chown -R git:git /var/lib/gitea
Upgrades
Upgrade Gitea
# Stop service
systemctl stop gitea
# Backup current binary
cp /usr/local/bin/gitea /usr/local/bin/gitea.backup
# Download new version
wget -O /usr/local/bin/gitea https://dl.gitea.com/gitea/VERSION/gitea-VERSION-linux-amd64
# Set permissions
chmod +x /usr/local/bin/gitea
# Start service (will auto-migrate database)
systemctl start gitea
# Check logs
journalctl -u gitea -f
Check Version
/usr/local/bin/gitea --version
Setting Up CI/CD with Gitea Actions
Gitea Actions are enabled and the runner is deployed on the same LXC.
Runner Container
# Current production runner setup
docker run -d \
--name gitea-runner \
--restart unless-stopped \
-e GITEA_RUNNER_REGISTRATION_TOKEN=<token-from-gitea-admin> \
-e GITEA_INSTANCE_URL=http://10.10.0.225:3000 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v gitea-runner-data:/data \
-v /etc/gitea/runner-config.yaml:/config.yaml:ro \
gitea/act_runner:latest
CRITICAL: GITEA_INSTANCE_URL must be the internal URL (http://10.10.0.225:3000), not the public domain. The runner uses this for API communication and auth token matching.
Runner Config (/etc/gitea/runner-config.yaml)
Key settings:
container.options: --add-host=git.manticorum.com:host-gateway— lets job containers resolve the public domaincontainer.force_pull: true— always pulls latest runner images- Labels:
ubuntu-latest,ubuntu-22.04,ubuntu-20.04
Shared Composite Actions (cal/gitea-actions)
Reusable CI/CD actions shared across all projects. This repo is public (required for runner auth).
| Action | Purpose |
|---|---|
cal/gitea-actions/calver@main |
Generate CalVer version (YYYY.MM.BUILD) from git tags |
cal/gitea-actions/gitea-tag@main |
Create git tag via Gitea API |
cal/gitea-actions/discord-notify@main |
Send Discord embed notification via webhook |
Action Reference Rules
Because DEFAULT_ACTIONS_URL=self is set:
# Local actions (cal/gitea-actions) — use SHORT FORM
uses: cal/gitea-actions/calver@main
# GitHub actions — use FULL URL (otherwise they'd resolve against local Gitea)
uses: https://github.com/actions/checkout@v4
uses: https://github.com/docker/setup-buildx-action@v3
uses: https://github.com/docker/login-action@v3
uses: https://github.com/docker/build-push-action@v5
Creating a New Workflow
- Copy an existing workflow as a template (e.g., from major-domo-database)
- Use short form for
cal/gitea-actions/*references - Use
https://github.com/prefix for all GitHub action references - Required secrets:
DOCKERHUB_USERNAME,DOCKERHUB_TOKEN,DISCORD_WEBHOOK
Adding Repositories
Via Web UI
- Go to https://git.manticorum.com
- Click "+" → "New Repository"
- Fill in details and create
Via Command Line
# Add remote
git remote add homelab git@git.manticorum.com:cal/repo-name.git
# Or HTTPS
git remote add homelab https://git.manticorum.com/cal/repo-name.git
# Push
git push homelab main
Migrate from GitHub
Gitea has built-in migration:
- New Repository → "Migrate from GitHub"
- Enter GitHub URL and token
- Gitea will clone all commits, branches, tags
Integration with NPM
Reverse proxy is configured on NPM (10.10.0.16):
- Domain: git.manticorum.com
- Forward to: 10.10.0.225:3000
- SSL: Let's Encrypt
- Websockets: Enabled
Troubleshooting
Gitea won't start
# Check logs
journalctl -u gitea -n 50
# Common issues:
# - Permission on /etc/gitea/app.ini (should be 640, root:git)
# - PostgreSQL not running
# - Port 3000 already in use
Can't connect to database
# Check PostgreSQL is running
systemctl status postgresql
# Test connection
PGPASSWORD=gitea123 psql -U gitea -d gitea -h 127.0.0.1 -c "SELECT 1;"
# Check pg_hba.conf allows md5 auth
cat /etc/postgresql/12/main/pg_hba.conf | grep md5
502 Bad Gateway on web
# Check Gitea is listening
ss -tlnp | grep 3000
# Check NPM can reach container
curl http://10.10.0.225:3000
# Verify firewall rules (should allow from 10.10.0.0/24)
Actions runner not working
- Ensure runner is registered in Gitea Admin → Actions → Runners
- Check runner logs:
docker logs gitea-runner - Verify
GITEA_INSTANCE_URLuses internal URL (http://10.10.0.225:3000), NOT the public domain - Ensure runner has network access to Gitea
Actions can't clone composite actions ("authentication required")
- Verify
REQUIRE_SIGNIN_VIEW = falsein app.ini (allows public repo clone without auth) - Verify
DEFAULT_ACTIONS_URL = selfin app.ini - Use short-form references for local actions (
cal/gitea-actions/calver@main) - Use full GitHub URLs for GitHub actions (
https://github.com/actions/checkout@v4) - The
cal/gitea-actionsrepo must be set to public visibility
Security Notes
- Database password is stored in
/etc/gitea/app.ini(secured with 640 permissions) - SSH keys for Git access are stored per-user in Gitea database
- JWT secrets are auto-generated and stored in config
- LXC is unprivileged for better isolation
- PostgreSQL only listens on localhost
REQUIRE_SIGNIN_VIEW=false— only public repos are accessible without login; all private repos remain fully protected- The only public repo is
cal/gitea-actions(audited — contains no secrets or sensitive code)
Related Documentation
Deployment Date
Created: 2026-02-03 By: Claude Code (Proxmox Skill) Initial Version: Gitea 1.22.6 on Ubuntu 20.04
Git Remotes
This repository is mirrored on both GitHub and Gitea for redundancy:
Branch Protection Manager
Automated script to apply consistent branch protection rules across all your Gitea repositories.
Features
- Applies branch protection rules to all repositories for a user/organization
- Supports dry-run mode to preview changes
- Configurable protection rules via environment variables
- Handles updating existing protection rules
- Clear success/error reporting
Requirements
pip install requests
Configuration
The script (apply_branch_protection.py) uses these settings:
- ✅ Disable direct pushes (force PR workflow)
- ✅ Require 1 approval before merge
- ✅ Restrict approvals to whitelisted users
- ✅ Dismiss stale approvals when new commits are pushed
- ✅ Enable status checks (for CI/CD)
- ✅ Restrict merging to whitelisted users
- ✅ Block merge on rejected reviews
- ✅ Block merge if pull request is outdated (critical for DB migrations)
Usage
1. Create a Gitea API Token
- Go to https://git.manticorum.com/user/settings/applications
- Click "Generate New Token"
- Give it a name (e.g., "Branch Protection Script")
- Select permissions:
repo(full control) - Click "Generate Token"
- Copy the token (you won't see it again!)
2. Set Environment Variables
export GITEA_TOKEN='your-api-token-here'
export GITEA_URL='https://git.manticorum.com' # Optional, defaults to this
export GITEA_OWNER='cal' # Optional, defaults to cal
3. Run the Script
Dry run (preview changes without applying):
cd /mnt/NV2/Development/claude-home/server-configs/gitea
python apply_branch_protection.py --dry-run
Apply to all repositories:
python apply_branch_protection.py
Customizing Protection Rules
Edit the BranchProtectionConfig section in main() to customize the rules:
config = BranchProtectionConfig(
branch_name="main", # Branch to protect
enable_push=False, # Disable direct pushes
required_approvals=1, # Number of required approvals
enable_approvals_whitelist=True, # Restrict who can approve
approvals_whitelist_usernames=[GITEA_OWNER],
dismiss_stale_approvals=True, # Dismiss approvals on new commits
enable_status_check=True, # Require status checks to pass
enable_merge_whitelist=True, # Restrict who can merge
merge_whitelist_usernames=[GITEA_OWNER],
block_on_rejected_reviews=True, # Block merge if reviews are rejected
block_on_outdated_branch=True, # Block merge if branch is outdated
require_signed_commits=False, # Require GPG signatures
)
Example Output
============================================================
Gitea Branch Protection Configuration
============================================================
Gitea URL: https://git.manticorum.com
Owner: cal
Branch: main
============================================================
Protection Rules:
• Direct pushes: Disabled
• Required approvals: 1
• Approvals whitelist: cal
• Dismiss stale approvals: True
• Status checks enabled: True
• Merge whitelist: cal
• Block on rejected reviews: True
• Block on outdated branch: True
• Require signed commits: False
============================================================
Applying branch protection to 5 repositories...
📦 major-domo-database
🔄 Updating existing protection...
✅ Successfully applied branch protection
📦 major-domo-bot
✅ Successfully applied branch protection
...
Troubleshooting Branch Protection Script
"GITEA_TOKEN environment variable is required"
- You need to set your API token. See usage step 2 above.
"Error fetching repositories"
- Check that your
GITEA_URLis correct - Verify your API token has
repopermissions - Ensure the
GITEA_OWNERusername is correct
"Could not delete existing protection"
- The script will still try to create the new protection
- If this fails, manually delete the old protection rule from Gitea web UI
"Error: 422 Unprocessable Entity" This usually means:
- The branch doesn't exist in the repository
- Invalid username in whitelist
- Conflicting protection rule settings
API References
This script uses the Gitea API branch protection endpoints: