- Add automatic git tag creation after successful builds/deployments - Tags match VERSION file and include deployment metadata - Remove emojis from all Discord notifications and console output - Add git tag links to Discord success notifications - Update troubleshooting section with git tag issues - Add customization checklist for git email configuration Benefits: - Immutable version markers in git history - Easy version checkout and rollback (git checkout v1.2.3) - Clean, professional notification messages - Enable changelog generation between tags Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| workflow-templates | ||
| .env.example | ||
| apply_branch_protection.py | ||
| deployment-strategies.md | ||
| harbor-registry-setup.md | ||
| INDEX.md | ||
| README.md | ||
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
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 ready to use. To set up a runner:
Option 1: Docker Runner (Recommended)
Since the LXC has nesting enabled, you can run a Docker-based Actions runner:
# Install Docker in the LXC
curl -fsSL https://get.docker.com | sh
# Run Gitea Actions runner
docker run -d \
--name gitea-runner \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
-e GITEA_INSTANCE_URL=https://git.manticorum.com \
-e GITEA_RUNNER_REGISTRATION_TOKEN=<token-from-gitea-admin> \
gitea/act_runner:latest
Option 2: Separate Runner LXC
Create a dedicated LXC for running Actions with more isolation.
Using Actions
Create .gitea/workflows/main.yml in your repository:
name: CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Run tests
run: |
npm install
npm test
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_URL is correct
- Ensure runner has network access to Gitea
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
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: