# Configuration Reference This document explains all configuration options for the Forgejo self-hosting setup. ## Table of Contents - [Domain Configuration](#domain-configuration) - [Secrets (Vault Variables)](#secrets-vault-variables) - [Feature Flags](#feature-flags) - [Security (Tailscale + UFW)](#security-tailscale--ufw) - [S3/Object Storage](#s3object-storage) - [Database Configuration](#database-configuration) - [Email Configuration](#email-configuration) - [Monitoring (Prometheus)](#monitoring-prometheus) - [Backup Configuration](#backup-configuration) --- ## Domain Configuration The domain is configured in **one primary location**: **File:** `ansible/inventory/production/hosts.yml` ```yaml forgejo_domain: git.yourdomain.com ``` This domain is used for: - HTTPS certificate (automatically obtained via Caddy/Let's Encrypt) - Forgejo web interface URL - Git clone URLs: `https://git.yourdomain.com/user/repo.git` - SSH clone URLs: `git@git.yourdomain.com:user/repo.git` - Email "From" addresses **Before deployment**, ensure your DNS is configured: ``` git.yourdomain.com. IN A git.yourdomain.com. IN AAAA ``` --- ## Secrets (Vault Variables) All secrets are stored in `ansible/playbooks/vars/secrets.yml` encrypted with Ansible Vault. ### How to Set Up Secrets ```bash # 1. Copy the example file cp ansible/playbooks/vars/secrets.yml.example ansible/playbooks/vars/secrets.yml # 2. Edit with your values nano ansible/playbooks/vars/secrets.yml # 3. Encrypt it ansible-vault encrypt ansible/playbooks/vars/secrets.yml # 4. To edit later ansible-vault edit ansible/playbooks/vars/secrets.yml ``` ### Secret Variables Explained | Variable | Purpose | How to Generate | |----------|---------|-----------------| | `vault_forgejo_db_password` | PostgreSQL database password for Forgejo | `openssl rand -base64 32` | | `vault_forgejo_admin_password` | Initial admin account password | Choose a strong password | | `vault_forgejo_secret_key` | Used for CSRF tokens, session cookies, and encryption. Must be 64+ characters. | `openssl rand -base64 48` | | `vault_forgejo_internal_token` | Used for internal API calls between Forgejo components | `openssl rand -base64 48` | | `vault_forgejo_jwt_secret` | Signs JWT tokens for OAuth2 and API authentication | `openssl rand -base64 32` | | `vault_forgejo_metrics_token` | Required to access `/metrics` endpoint (if Prometheus enabled) | `openssl rand -base64 32` | | `vault_email_password` | SMTP password (if email enabled) | Your email provider password | | `vault_s3_access_key` | S3-compatible storage access key (if S3 enabled) | From your cloud provider | | `vault_s3_secret_key` | S3-compatible storage secret key (if S3 enabled) | From your cloud provider | ### Example secrets.yml ```yaml --- vault_forgejo_db_password: "xK9mN2pL8qR5tW7vY3zB1cD4fG6hJ0kM" vault_forgejo_admin_password: "MySecureAdminPassword123!" vault_forgejo_secret_key: "aB3cD5eF7gH9iJ1kL3mN5oP7qR9sT1uV3wX5yZ7aB9cD1eF3gH5iJ7kL9mN1oP" vault_forgejo_internal_token: "qW2eR4tY6uI8oP0aS2dF4gH6jK8lZ0xC2vB4nM6qW8eR0tY2uI4oP6aS8dF0g" vault_forgejo_jwt_secret: "mN3bV5cX7zL9kJ1hG3fD5sA7pO9iU1yT" vault_forgejo_metrics_token: "pR0mE7hEuS_t0K3n_H3r3" vault_email_password: "" vault_s3_access_key: "" vault_s3_secret_key: "" ``` --- ## Feature Flags Configure features in `ansible/inventory/production/hosts.yml`: ### Core Features | Flag | Default | Description | |------|---------|-------------| | `forgejo_enable_letsencrypt` | `true` | Automatic HTTPS via Let's Encrypt (handled by Caddy) | | `forgejo_enable_lfs` | `true` | Git Large File Storage support | | `forgejo_enable_2fa` | `true` | Allow users to enable Two-Factor Authentication | | `forgejo_use_redis` | `true` | Use Redis for caching (recommended for performance) | | `forgejo_enable_backups` | `true` | Enable automated daily backups | | `forgejo_enable_prometheus` | `false` | Enable internal Prometheus metrics collection | ### Access Control | Flag | Default | Description | |------|---------|-------------| | `forgejo_disable_registration` | `false` | Disable public user registration (invite-only) | | `forgejo_require_signin_view` | `false` | Require login to view public repositories | ### Optional Services | Flag | Default | Description | |------|---------|-------------| | `forgejo_enable_email` | `false` | Enable email notifications (requires SMTP config) | | `forgejo_enable_s3` | `false` | Use S3-compatible storage for LFS and attachments | ### Example Configuration ```yaml # In ansible/inventory/production/hosts.yml forgejo_prod: # ... other settings ... # Enable all recommended features forgejo_enable_letsencrypt: true forgejo_enable_lfs: true forgejo_enable_2fa: true forgejo_use_redis: true forgejo_enable_backups: true # Enable monitoring forgejo_enable_prometheus: true # Private instance (no public registration) forgejo_disable_registration: true forgejo_require_signin_view: false ``` --- ## Security (Tailscale + UFW) This setup uses Tailscale VPN and UFW firewall to secure your Forgejo instance: - **SSH access**: Only via Tailscale (not exposed to the public internet) - **Git SSH (port 2222)**: Only via Tailscale - **Web interface**: Public via HTTPS (ports 80/443) - **Internal services**: Only via Tailscale (Prometheus, database, etc.) ### Enable Security Features ```yaml # In ansible/inventory/production/hosts.yml forgejo_enable_tailscale: true forgejo_enable_ufw: true ``` ### How It Works 1. **Tailscale** creates a secure mesh VPN network 2. **UFW** is configured to: - Allow all traffic on the `tailscale0` interface - Allow only HTTP/HTTPS (80/443) from the public internet - Block SSH from the public internet ### Post-Deployment: Authenticate Tailscale After deployment, SSH into the server (while SSH is still open) and authenticate Tailscale: ```bash # SSH into server (before UFW locks down SSH) ssh root@ # Authenticate Tailscale sudo tailscale up --ssh # This will print a URL - open it in your browser to authenticate ``` For headless/automated setup, use an auth key: ```bash sudo tailscale up --authkey=tskey-auth-XXXXX ``` Generate auth keys at: https://login.tailscale.com/admin/settings/keys ### Accessing Your Server After Setup Once UFW is configured, SSH is only accessible via Tailscale: ```bash # Via Tailscale IP ssh root@100.x.x.x # Via Tailscale hostname (from admin console) ssh root@your-server.tailnet-name.ts.net # Via Tailscale SSH (if enabled with --ssh) tailscale ssh root@your-server ``` ### Git Clone URLs | Method | URL | Access | |--------|-----|--------| | HTTPS | `https://git.yourdomain.com/user/repo.git` | Public | | SSH | `git@:user/repo.git` | Tailscale only | ### Firewall Rules Summary | Port | Protocol | Access | Purpose | |------|----------|--------|---------| | 80 | TCP | Public | HTTP (redirects to HTTPS) | | 443 | TCP | Public | HTTPS (Forgejo web) | | 22 | TCP | Tailscale only | System SSH | | 2222 | TCP | Tailscale only | Git SSH | | 3000 | TCP | Tailscale only | Forgejo internal | | 9090 | TCP | Tailscale only | Prometheus | ### Disabling Security Features If you need public SSH access (not recommended): ```yaml forgejo_enable_tailscale: false forgejo_enable_ufw: false ``` Or configure UFW manually after deployment. --- ## S3/Object Storage S3-compatible object storage can be used for: 1. **Git LFS** - Large file storage 2. **Backups** - Off-site backup storage 3. **Attachments** - Issue/PR attachments (future) ### What is S3? S3 (Simple Storage Service) is an object storage protocol. Both **Scaleway** and **Hetzner** offer S3-compatible storage: - **Scaleway**: Object Storage (S3-compatible) - **Hetzner**: Object Storage (S3-compatible, in beta) ### Setting Up S3 Storage #### For Scaleway 1. **Create storage via Terraform** (already included): ```bash make terraform-apply PROVIDER=scaleway ``` 2. **Get credentials from Terraform output**: ```bash cd terraform/scaleway/storage terragrunt output access_key terragrunt output secret_key ``` 3. **Configure in inventory**: ```yaml forgejo_enable_s3: true forgejo_s3_endpoint: https://s3.fr-par.scw.cloud forgejo_s3_bucket: your-project-production-lfs forgejo_s3_region: fr-par ``` 4. **Add credentials to secrets.yml**: ```yaml vault_s3_access_key: "SCWXXXXXXXXXXXXXXXXX" vault_s3_secret_key: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" ``` #### For Hetzner Hetzner Object Storage is S3-compatible: 1. **Create a storage box** in Hetzner Cloud Console 2. **Configure in inventory**: ```yaml forgejo_enable_s3: true forgejo_s3_endpoint: https://fsn1.your-objectstorage.com forgejo_s3_bucket: forgejo-lfs forgejo_s3_region: fsn1 ``` 3. **Add credentials to secrets.yml** ### S3 for Backups To upload backups to S3: ```yaml # In inventory forgejo_backup_to_s3: true forgejo_backup_s3_bucket: your-project-production-backups ``` Then run: ```bash make backup-to-s3 ``` --- ## Database Configuration PostgreSQL is the recommended database. ### Settings | Variable | Default | Description | |----------|---------|-------------| | `forgejo_db_type` | `postgres` | Database type (postgres recommended) | | `forgejo_db_host` | `localhost` | Database host | | `forgejo_db_port` | `5432` | Database port | | `forgejo_db_name` | `forgejo` | Database name | | `forgejo_db_user` | `forgejo` | Database user | The password is in `vault_forgejo_db_password`. ### PostgreSQL Tuning Default tuning in `ansible/roles/forgejo/defaults/main.yml`: ```yaml postgres_version: "16" postgres_max_connections: 100 postgres_shared_buffers: "256MB" postgres_effective_cache_size: "1GB" ``` For larger instances, adjust these based on available RAM. --- ## Email Configuration Enable email for notifications, password resets, and registration confirmation. ### Settings ```yaml # In inventory forgejo_enable_email: true forgejo_email_host: smtp.example.com forgejo_email_port: 587 forgejo_email_user: noreply@yourdomain.com # In secrets.yml vault_email_password: "your-smtp-password" ``` ### Common SMTP Providers **Gmail (with App Password)**: ```yaml forgejo_email_host: smtp.gmail.com forgejo_email_port: 587 forgejo_email_user: your-email@gmail.com ``` **Mailgun**: ```yaml forgejo_email_host: smtp.mailgun.org forgejo_email_port: 587 forgejo_email_user: postmaster@your-domain.mailgun.org ``` **SendGrid**: ```yaml forgejo_email_host: smtp.sendgrid.net forgejo_email_port: 587 forgejo_email_user: apikey # vault_email_password should be your SendGrid API key ``` --- ## Monitoring (Prometheus) Internal Prometheus monitoring for your Forgejo instance. ### Enable Monitoring ```yaml # In inventory forgejo_enable_prometheus: true ``` ### What Gets Monitored - **Forgejo metrics**: HTTP requests, Git operations, users, repos, issues - **Prometheus self-monitoring**: Scrape health ### Accessing Metrics Prometheus is **internal only** (bound to localhost:9090). To access: 1. **SSH tunnel**: ```bash ssh -L 9090:localhost:9090 root@your-server ``` Then open http://localhost:9090 2. **Forgejo metrics endpoint**: ``` https://git.yourdomain.com/metrics?token=YOUR_METRICS_TOKEN ``` The token is `vault_forgejo_metrics_token`. ### Adding Grafana (Optional) To add Grafana dashboards, extend the monitoring setup: ```yaml # Create docker-compose.grafana.yml manually services: grafana: image: grafana/grafana:latest container_name: grafana ports: - "127.0.0.1:3001:3000" volumes: - grafana-data:/var/lib/grafana environment: - GF_SECURITY_ADMIN_PASSWORD=your-grafana-password networks: - forgejo-network ``` --- ## Backup Configuration ### Settings | Variable | Default | Description | |----------|---------|-------------| | `forgejo_enable_backups` | `true` | Enable automated backups | | `forgejo_backup_schedule` | `0 2 * * *` | Cron schedule (default: 2 AM daily) | | `forgejo_backup_retention_days` | `30` | Days to keep local backups | | `forgejo_backup_to_s3` | `false` | Upload backups to S3 | | `forgejo_backup_s3_bucket` | `""` | S3 bucket for backups | ### What Gets Backed Up 1. **PostgreSQL database** - Full SQL dump 2. **Git repositories** - All repository data 3. **Configuration** - app.ini, docker-compose.yml 4. **User data** - Attachments, LFS files, avatars ### Backup Commands ```bash # Manual backup make backup # Backup and upload to S3 make backup-to-s3 # Restore from backup make restore # You'll be prompted for the backup timestamp ``` ### Backup Location Local backups are stored in: `/opt/forgejo/backups/` Files: - `database-TIMESTAMP.sql.gz` - `repositories-TIMESTAMP.tar.gz` - `config-TIMESTAMP.tar.gz` - `data-TIMESTAMP.tar.gz` --- ## Quick Reference: Enable Everything For a fully-featured setup with all options enabled: ```yaml # ansible/inventory/production/hosts.yml forgejo-prod: ansible_host: YOUR_SERVER_IP ansible_user: root # Domain forgejo_domain: git.yourdomain.com # Core forgejo_version: "9.0.2" forgejo_enable_letsencrypt: true forgejo_enable_lfs: true forgejo_enable_2fa: true forgejo_use_redis: true # Database forgejo_db_type: postgres # Backups forgejo_enable_backups: true forgejo_backup_retention_days: 30 forgejo_backup_to_s3: true forgejo_backup_s3_bucket: your-backup-bucket # S3 Storage forgejo_enable_s3: true forgejo_s3_endpoint: https://s3.fr-par.scw.cloud forgejo_s3_bucket: your-lfs-bucket forgejo_s3_region: fr-par # Email forgejo_enable_email: true forgejo_email_host: smtp.mailgun.org forgejo_email_port: 587 forgejo_email_user: noreply@yourdomain.com # Monitoring forgejo_enable_prometheus: true # Access forgejo_disable_registration: false # Set to true for invite-only forgejo_require_signin_view: false ``` Then in `ansible/playbooks/vars/secrets.yml`: ```yaml vault_forgejo_db_password: "GENERATED_PASSWORD" vault_forgejo_admin_password: "YOUR_ADMIN_PASSWORD" vault_forgejo_secret_key: "64_CHAR_GENERATED_KEY" vault_forgejo_internal_token: "GENERATED_TOKEN" vault_forgejo_jwt_secret: "GENERATED_SECRET" vault_forgejo_metrics_token: "GENERATED_TOKEN" vault_email_password: "YOUR_SMTP_PASSWORD" vault_s3_access_key: "YOUR_S3_ACCESS_KEY" vault_s3_secret_key: "YOUR_S3_SECRET_KEY" ```