Add Template to deploy forgejo.
This template allows deploying a forgejo en either Scaleway or Hetzner (untested) without much knowledge about them. It DOES require knowledge about Terragrunt and ansible. A wizard of sorts is provided but it will not guarantee success without some knowledge about the underlying technology.
This commit is contained in:
parent
a9f546f92a
commit
822e42dbb8
48 changed files with 6846 additions and 2 deletions
569
docs/CONFIGURATION.md
Normal file
569
docs/CONFIGURATION.md
Normal file
|
|
@ -0,0 +1,569 @@
|
|||
# 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 <server-ipv4>
|
||||
git.yourdomain.com. IN AAAA <server-ipv6>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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@<server-public-ip>
|
||||
|
||||
# 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@<tailscale-hostname>: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"
|
||||
```
|
||||
574
docs/OPERATIONS.md
Normal file
574
docs/OPERATIONS.md
Normal file
|
|
@ -0,0 +1,574 @@
|
|||
# Operations Guide - Forgejo Self-Hosting
|
||||
|
||||
Complete guide for day-to-day operations and maintenance.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Daily Operations](#daily-operations)
|
||||
2. [Backup & Recovery](#backup--recovery)
|
||||
3. [Updates & Upgrades](#updates--upgrades)
|
||||
4. [Monitoring](#monitoring)
|
||||
5. [Troubleshooting](#troubleshooting)
|
||||
6. [Security Operations](#security-operations)
|
||||
7. [Scaling](#scaling)
|
||||
8. [Disaster Recovery](#disaster-recovery)
|
||||
|
||||
## Daily Operations
|
||||
|
||||
### Health Checks
|
||||
|
||||
```bash
|
||||
# Quick health check
|
||||
make health
|
||||
|
||||
# Full status
|
||||
make status
|
||||
|
||||
# View recent logs
|
||||
make logs | tail -100
|
||||
```
|
||||
|
||||
### User Management
|
||||
|
||||
```bash
|
||||
# SSH into server
|
||||
make ssh
|
||||
|
||||
# List users
|
||||
docker exec --user git forgejo forgejo admin user list
|
||||
|
||||
# Create user
|
||||
docker exec --user git forgejo forgejo admin user create \
|
||||
--username newuser \
|
||||
--password 'SecureP@ssw0rd' \
|
||||
--email user@example.com
|
||||
|
||||
# Change user password
|
||||
docker exec --user git forgejo forgejo admin user change-password \
|
||||
--username user \
|
||||
--password 'NewP@ssw0rd'
|
||||
|
||||
# Make user admin
|
||||
docker exec --user git forgejo forgejo admin user change-admin \
|
||||
--username user \
|
||||
--admin
|
||||
```
|
||||
|
||||
### Repository Management
|
||||
|
||||
```bash
|
||||
# Sync mirrors
|
||||
docker exec --user git forgejo forgejo admin repo-sync-releases
|
||||
|
||||
# Rebuild indexes
|
||||
docker exec --user git forgejo forgejo admin regenerate hooks
|
||||
docker exec --user git forgejo forgejo admin regenerate keys
|
||||
```
|
||||
|
||||
## Backup & Recovery
|
||||
|
||||
### Manual Backup
|
||||
|
||||
```bash
|
||||
# Create immediate backup
|
||||
make backup
|
||||
|
||||
# Backup with S3 upload
|
||||
make backup-to-s3
|
||||
|
||||
# Verify backup
|
||||
make ssh
|
||||
ls -lh /opt/forgejo/backups/
|
||||
```
|
||||
|
||||
### Automated Backups
|
||||
|
||||
Backups run automatically at 2 AM daily.
|
||||
|
||||
**Check backup status:**
|
||||
```bash
|
||||
make ssh
|
||||
tail -f /var/log/forgejo-backup.log
|
||||
```
|
||||
|
||||
**Modify schedule:**
|
||||
```yaml
|
||||
# In inventory or vars
|
||||
forgejo_backup_schedule: "0 3 * * *" # 3 AM daily
|
||||
```
|
||||
|
||||
### Restore from Backup
|
||||
|
||||
```bash
|
||||
# List available backups
|
||||
make ssh
|
||||
ls /opt/forgejo/backups/
|
||||
|
||||
# Restore (timestamp format: 20240115T120000)
|
||||
make restore
|
||||
# Enter backup timestamp when prompted
|
||||
|
||||
# Force restore without confirmation
|
||||
make restore-force
|
||||
|
||||
# Restore from S3
|
||||
make restore-from-s3
|
||||
```
|
||||
|
||||
### Backup Verification
|
||||
|
||||
```bash
|
||||
# Test restore in separate environment
|
||||
make ssh
|
||||
cd /opt/forgejo/backups
|
||||
|
||||
# Verify database backup
|
||||
gunzip -c database-TIMESTAMP.sql.gz | head -100
|
||||
|
||||
# Verify repositories backup
|
||||
tar -tzf repositories-TIMESTAMP.tar.gz | head -20
|
||||
```
|
||||
|
||||
## Updates & Upgrades
|
||||
|
||||
### Update Forgejo
|
||||
|
||||
```bash
|
||||
# Standard update (includes backup)
|
||||
make update
|
||||
|
||||
# Update without backup (not recommended)
|
||||
make update-no-backup
|
||||
```
|
||||
|
||||
**Update process:**
|
||||
1. Creates pre-update backup
|
||||
2. Stops Forgejo service
|
||||
3. Pulls new Docker image
|
||||
4. Starts service
|
||||
5. Runs database migrations
|
||||
6. Verifies health
|
||||
|
||||
### Update System Packages
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
sudo apt update
|
||||
sudo apt upgrade -y
|
||||
sudo reboot # If kernel updated
|
||||
```
|
||||
|
||||
### Update Infrastructure
|
||||
|
||||
```bash
|
||||
# Review changes
|
||||
make terraform-plan PROVIDER=scaleway
|
||||
|
||||
# Apply updates
|
||||
make terraform-apply PROVIDER=scaleway
|
||||
```
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Log Management
|
||||
|
||||
```bash
|
||||
# Forgejo logs
|
||||
make logs
|
||||
|
||||
# Follow logs (real-time)
|
||||
make logs | tail -f
|
||||
|
||||
# Nginx access logs
|
||||
make logs-nginx
|
||||
|
||||
# System logs
|
||||
make ssh
|
||||
sudo journalctl -u forgejo -f
|
||||
|
||||
# Docker logs
|
||||
docker logs forgejo --tail 100 -f
|
||||
```
|
||||
|
||||
### Performance Monitoring
|
||||
|
||||
```bash
|
||||
# Check resource usage
|
||||
make ssh
|
||||
|
||||
# CPU and memory
|
||||
htop
|
||||
|
||||
# Disk usage
|
||||
df -h
|
||||
du -sh /opt/forgejo/*
|
||||
|
||||
# Docker stats
|
||||
docker stats forgejo
|
||||
|
||||
# PostgreSQL status
|
||||
sudo systemctl status postgresql
|
||||
```
|
||||
|
||||
### Database Monitoring
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
|
||||
# Connect to PostgreSQL
|
||||
sudo -u postgres psql forgejo
|
||||
|
||||
# Check database size
|
||||
SELECT pg_size_pretty(pg_database_size('forgejo'));
|
||||
|
||||
# Check table sizes
|
||||
SELECT
|
||||
schemaname,
|
||||
tablename,
|
||||
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) AS size
|
||||
FROM pg_tables
|
||||
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
|
||||
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC
|
||||
LIMIT 10;
|
||||
|
||||
# Active connections
|
||||
SELECT count(*) FROM pg_stat_activity;
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Service Won't Start
|
||||
|
||||
```bash
|
||||
# Check Docker status
|
||||
make ssh
|
||||
docker ps -a
|
||||
docker logs forgejo
|
||||
|
||||
# Check system resources
|
||||
free -h
|
||||
df -h
|
||||
|
||||
# Restart service
|
||||
make restart
|
||||
|
||||
# Full rebuild if needed
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### Database Connection Issues
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
|
||||
# Check PostgreSQL
|
||||
sudo systemctl status postgresql
|
||||
|
||||
# Check connections
|
||||
sudo -u postgres psql -c "SELECT * FROM pg_stat_activity;"
|
||||
|
||||
# Restart PostgreSQL
|
||||
sudo systemctl restart postgresql
|
||||
|
||||
# Check logs
|
||||
sudo tail -f /var/log/postgresql/postgresql-16-main.log
|
||||
```
|
||||
|
||||
### SSL Certificate Issues
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
|
||||
# Check certificate status
|
||||
sudo certbot certificates
|
||||
|
||||
# Renew manually
|
||||
sudo certbot renew --force-renewal
|
||||
|
||||
# Check Nginx configuration
|
||||
sudo nginx -t
|
||||
sudo systemctl restart nginx
|
||||
|
||||
# Check certificate files
|
||||
sudo ls -la /etc/letsencrypt/live/git.yourdomain.com/
|
||||
```
|
||||
|
||||
### Performance Issues
|
||||
|
||||
```bash
|
||||
# Check slow queries
|
||||
make ssh
|
||||
sudo -u postgres psql forgejo
|
||||
|
||||
# Enable slow query logging
|
||||
ALTER SYSTEM SET log_min_duration_statement = 1000;
|
||||
SELECT pg_reload_conf();
|
||||
|
||||
# View slow queries
|
||||
sudo tail -f /var/log/postgresql/postgresql-16-main.log
|
||||
|
||||
# Vacuum database
|
||||
sudo -u postgres vacuumdb --analyze forgejo
|
||||
```
|
||||
|
||||
### Disk Space Issues
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
|
||||
# Check space
|
||||
df -h
|
||||
|
||||
# Find large directories
|
||||
du -h /opt/forgejo | sort -rh | head -20
|
||||
|
||||
# Clean Docker
|
||||
docker system prune -a
|
||||
|
||||
# Clean old backups
|
||||
find /opt/forgejo/backups -type f -mtime +30 -delete
|
||||
|
||||
# Clean logs
|
||||
sudo journalctl --vacuum-time=7d
|
||||
```
|
||||
|
||||
## Security Operations
|
||||
|
||||
### Security Audit
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
|
||||
# Check for security updates
|
||||
sudo apt update
|
||||
sudo apt list --upgradable
|
||||
|
||||
# Review firewall rules
|
||||
sudo ufw status verbose
|
||||
|
||||
# Check open ports
|
||||
sudo netstat -tulpn
|
||||
|
||||
# Review SSH configuration
|
||||
cat /etc/ssh/sshd_config
|
||||
|
||||
# Check failed login attempts
|
||||
sudo grep "Failed password" /var/log/auth.log | tail -20
|
||||
```
|
||||
|
||||
### Rotate Secrets
|
||||
|
||||
```bash
|
||||
# Generate new secrets
|
||||
openssl rand -base64 48
|
||||
|
||||
# Update vault
|
||||
make ansible-vault-edit
|
||||
|
||||
# Redeploy with new secrets
|
||||
make deploy
|
||||
```
|
||||
|
||||
### SSL Certificate Renewal
|
||||
|
||||
```bash
|
||||
# Auto-renewal is configured, but to force:
|
||||
make ssh
|
||||
sudo certbot renew --force-renewal
|
||||
sudo systemctl reload nginx
|
||||
```
|
||||
|
||||
### Security Updates
|
||||
|
||||
```bash
|
||||
# Enable automatic security updates (already configured)
|
||||
make ssh
|
||||
sudo cat /etc/apt/apt.conf.d/50unattended-upgrades
|
||||
|
||||
# Check update history
|
||||
sudo cat /var/log/unattended-upgrades/unattended-upgrades.log
|
||||
```
|
||||
|
||||
## Scaling
|
||||
|
||||
### Vertical Scaling (More Resources)
|
||||
|
||||
```bash
|
||||
# Update instance type
|
||||
vim terraform/scaleway/compute/terraform.tfvars
|
||||
# Change: instance_type = "DEV1-L" # 8GB RAM
|
||||
|
||||
make terraform-apply PROVIDER=scaleway
|
||||
|
||||
# Service restarts automatically
|
||||
```
|
||||
|
||||
### Database Optimization
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
sudo -u postgres psql forgejo
|
||||
|
||||
# Optimize settings
|
||||
ALTER SYSTEM SET shared_buffers = '512MB';
|
||||
ALTER SYSTEM SET effective_cache_size = '2GB';
|
||||
ALTER SYSTEM SET maintenance_work_mem = '256MB';
|
||||
|
||||
SELECT pg_reload_conf();
|
||||
```
|
||||
|
||||
### Add Storage Volume
|
||||
|
||||
```bash
|
||||
# In inventory
|
||||
forgejo_use_external_volume: true
|
||||
forgejo_volume_device: /dev/sdb
|
||||
|
||||
# Redeploy
|
||||
make deploy-tags TAGS=volume
|
||||
```
|
||||
|
||||
## Disaster Recovery
|
||||
|
||||
### Complete Failure Recovery
|
||||
|
||||
```bash
|
||||
# 1. Create new infrastructure
|
||||
make terraform-apply PROVIDER=scaleway
|
||||
|
||||
# 2. Update inventory with new IP
|
||||
vim ansible/inventory/production/hosts.yml
|
||||
|
||||
# 3. Update DNS records
|
||||
# Point domain to new IP
|
||||
|
||||
# 4. Deploy with restore
|
||||
# First, copy backup timestamp
|
||||
make ssh
|
||||
ls /opt/forgejo/backups/ # Note timestamp
|
||||
|
||||
# Then restore
|
||||
make restore
|
||||
# Enter timestamp when prompted
|
||||
|
||||
# 5. Verify
|
||||
make health
|
||||
```
|
||||
|
||||
### Backup Storage Migration
|
||||
|
||||
```bash
|
||||
# Copy backups to new location
|
||||
make ssh
|
||||
rsync -avz /opt/forgejo/backups/ /new/backup/location/
|
||||
|
||||
# Update backup configuration
|
||||
vim ansible/playbooks/vars/main.yml
|
||||
# forgejo_backup_path: /new/backup/location
|
||||
|
||||
make deploy-tags TAGS=backup
|
||||
```
|
||||
|
||||
### Database Recovery from Corruption
|
||||
|
||||
```bash
|
||||
make ssh
|
||||
|
||||
# Stop Forgejo
|
||||
docker compose down
|
||||
|
||||
# Backup corrupted database
|
||||
sudo -u postgres pg_dump forgejo > /tmp/forgejo-corrupted.sql
|
||||
|
||||
# Drop and recreate
|
||||
sudo -u postgres dropdb forgejo
|
||||
sudo -u postgres createdb forgejo
|
||||
|
||||
# Restore from latest backup
|
||||
gunzip -c /opt/forgejo/backups/database-TIMESTAMP.sql.gz | \
|
||||
sudo -u postgres psql forgejo
|
||||
|
||||
# Restart Forgejo
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Daily Checklist
|
||||
|
||||
- [ ] Check service health: `make health`
|
||||
- [ ] Review logs for errors: `make logs | grep -i error`
|
||||
- [ ] Verify backups ran: `ls -lt /opt/forgejo/backups/ | head -5`
|
||||
- [ ] Check disk space: `df -h`
|
||||
|
||||
### Weekly Checklist
|
||||
|
||||
- [ ] Review security logs: `sudo grep "Failed" /var/log/auth.log`
|
||||
- [ ] Check for updates: `sudo apt update && apt list --upgradable`
|
||||
- [ ] Test backup restore (in dev environment)
|
||||
- [ ] Review performance metrics
|
||||
- [ ] Check SSL certificate expiry
|
||||
|
||||
### Monthly Checklist
|
||||
|
||||
- [ ] Full security audit
|
||||
- [ ] Review and update firewall rules
|
||||
- [ ] Rotate secrets if needed
|
||||
- [ ] Review and optimize database
|
||||
- [ ] Update documentation
|
||||
- [ ] Test disaster recovery procedures
|
||||
|
||||
## Emergency Contacts
|
||||
|
||||
Keep these handy:
|
||||
|
||||
```bash
|
||||
# Quick recovery commands
|
||||
make health # Check status
|
||||
make restart # Restart service
|
||||
make logs # View logs
|
||||
make backup # Create backup
|
||||
make restore # Restore from backup
|
||||
make ssh # SSH access
|
||||
|
||||
# Emergency rollback
|
||||
make update # Includes backup
|
||||
# If issues: make restore # Roll back
|
||||
```
|
||||
|
||||
## Useful Scripts
|
||||
|
||||
### Health Check Script
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Save as: health-check.sh
|
||||
|
||||
echo "=== Forgejo Health Check ==="
|
||||
echo "Date: $(date)"
|
||||
echo ""
|
||||
|
||||
echo "1. Service Status:"
|
||||
docker ps | grep forgejo
|
||||
|
||||
echo ""
|
||||
echo "2. Disk Space:"
|
||||
df -h | grep -E "Filesystem|/dev/vda1|/dev/sda1"
|
||||
|
||||
echo ""
|
||||
echo "3. Memory Usage:"
|
||||
free -h
|
||||
|
||||
echo ""
|
||||
echo "4. Latest Backup:"
|
||||
ls -lth /opt/forgejo/backups/*.tar.gz | head -1
|
||||
|
||||
echo ""
|
||||
echo "5. HTTP Status:"
|
||||
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Remember**: Always test procedures in a development environment first!
|
||||
190
docs/QUICKSTART.md
Normal file
190
docs/QUICKSTART.md
Normal file
|
|
@ -0,0 +1,190 @@
|
|||
# Quick Start Guide - 15 Minutes to Forgejo
|
||||
|
||||
Get your Forgejo instance running in 15 minutes.
|
||||
|
||||
## Prerequisites Check (2 minutes)
|
||||
|
||||
```bash
|
||||
# Install required tools (if not installed)
|
||||
# macOS:
|
||||
brew install terraform terragrunt ansible
|
||||
|
||||
# Ubuntu/Debian:
|
||||
sudo apt-get install terraform ansible # (or look for instructions to do this using a virtualenv for ansible)
|
||||
curl -L https://github.com/gruntwork-io/terragrunt/releases/download/v0.50.0/terragrunt_linux_amd64 -o /usr/local/bin/terragrunt
|
||||
chmod +x /usr/local/bin/terragrunt
|
||||
|
||||
# Verify installations
|
||||
make check-deps
|
||||
```
|
||||
|
||||
## Step 1: Cloud Provider Setup (3 minutes)
|
||||
|
||||
### Option A: Scaleway
|
||||
|
||||
1. Create account at https://console.scaleway.com
|
||||
2. Generate API credentials: Console → IAM → API Keys
|
||||
3. Export credentials:
|
||||
```bash
|
||||
export SCW_ACCESS_KEY="SCW..."
|
||||
export SCW_SECRET_KEY="..."
|
||||
export SCW_DEFAULT_PROJECT_ID="..." #bear in mind, you might want a project ID other than the default
|
||||
```
|
||||
|
||||
### Option B: Hetzner
|
||||
|
||||
1. Create account at https://console.hetzner.cloud
|
||||
2. Generate API token: Security → API Tokens
|
||||
3. Export token:
|
||||
```bash
|
||||
export HCLOUD_TOKEN="..."
|
||||
```
|
||||
|
||||
## Step 2: Configuration (5 minutes)
|
||||
|
||||
### Configure Domain
|
||||
|
||||
```bash
|
||||
# terraform/scaleway/compute/terraform.tfvars (or hetzner)
|
||||
domain_name = "git.yourdomain.com"
|
||||
```
|
||||
|
||||
### Generate Secrets
|
||||
|
||||
```bash
|
||||
# Generate strong passwords
|
||||
openssl rand -base64 32 # Database password
|
||||
openssl rand -base64 32 # Admin password
|
||||
openssl rand -base64 48 # Secret key
|
||||
openssl rand -base64 48 # Internal token
|
||||
openssl rand -base64 48 # JWT secret
|
||||
```
|
||||
|
||||
### Configure Secrets
|
||||
|
||||
```bash
|
||||
cd ansible/playbooks/vars
|
||||
cp secrets.yml.example secrets.yml
|
||||
|
||||
# Edit with generated passwords
|
||||
$EDITOR secrets.yml
|
||||
|
||||
# Encrypt
|
||||
ansible-vault encrypt secrets.yml
|
||||
# Enter vault password (remember this!)
|
||||
```
|
||||
|
||||
### Update Inventory
|
||||
|
||||
```bash
|
||||
$EDITOR ansible/inventory/production/hosts.yml
|
||||
```
|
||||
|
||||
Change:
|
||||
- `forgejo_domain: git.yourdomain.com`
|
||||
- `letsencrypt_email: your@email.com`
|
||||
|
||||
## Step 3: Deploy (5 minutes)
|
||||
|
||||
```bash
|
||||
# Create infrastructure
|
||||
make terraform-apply PROVIDER=scaleway # or hetzner
|
||||
|
||||
# Get server IP
|
||||
make terraform-output PROVIDER=scaleway
|
||||
|
||||
# Create DNS A record
|
||||
# git.yourdomain.com → <server-ip>
|
||||
|
||||
# Wait 2 minutes for DNS propagation
|
||||
|
||||
# Update inventory with server IP
|
||||
$EDITOR ansible/inventory/production/hosts.yml
|
||||
# Change: ansible_host: <your-server-ip>
|
||||
|
||||
# Deploy Forgejo
|
||||
make deploy
|
||||
# Enter vault password when prompted
|
||||
```
|
||||
|
||||
## Step 4: Access (1 minute)
|
||||
|
||||
Visit: `https://git.yourdomain.com`
|
||||
|
||||
**First Login:**
|
||||
|
||||
1. Complete installation wizard
|
||||
2. Login with admin credentials from vault
|
||||
3. Create your first repository!
|
||||
|
||||
## Next Steps
|
||||
|
||||
- [ ] Configure SSH key: Settings → SSH Keys
|
||||
- [ ] Create organization
|
||||
- [ ] Import repositories
|
||||
- [ ] Set up webhooks
|
||||
- [ ] Configure CI/CD with Forgejo Actions
|
||||
- [ ] Invite team members
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
**Can't connect to server?**
|
||||
|
||||
```bash
|
||||
make ansible-ping
|
||||
```
|
||||
|
||||
**SSL certificate not working?**
|
||||
- Wait 5 minutes for Let's Encrypt
|
||||
- Check DNS: `dig git.yourdomain.com`
|
||||
|
||||
**Service not starting?**
|
||||
|
||||
```bash
|
||||
make logs
|
||||
make status
|
||||
```
|
||||
|
||||
**Need to start over?**
|
||||
|
||||
```bash
|
||||
make terraform-destroy PROVIDER=scaleway
|
||||
# Then start from Step 3
|
||||
```
|
||||
|
||||
## Daily Operations
|
||||
|
||||
```bash
|
||||
# Create backup
|
||||
make backup
|
||||
|
||||
# Update Forgejo
|
||||
make update
|
||||
|
||||
# View logs
|
||||
make logs
|
||||
|
||||
# SSH into server
|
||||
make ssh
|
||||
|
||||
# Check health
|
||||
make health
|
||||
```
|
||||
|
||||
## Cost Per Month (in January 2026)
|
||||
|
||||
- **Scaleway**: ~€9/month
|
||||
- **Hetzner**: ~€8/month
|
||||
|
||||
**vs GitHub Enterprise**: €19/user/month
|
||||
|
||||
## Support
|
||||
|
||||
- Check logs: `make logs`
|
||||
- View status: `make status`
|
||||
- Full docs: `README.md`
|
||||
- Troubleshooting: `README.md#troubleshooting`
|
||||
|
||||
---
|
||||
|
||||
That's it! You now have a production-ready Forgejo instance running on European infrastructure. 🎉
|
||||
Loading…
Add table
Add a link
Reference in a new issue