Per file detail:
backup.yml
- Added role defaults loading with proper precedence (inventory > vars > defaults)
- Fixed pg_dump permissions: now dumps to /tmp first, then moves to backup directory
update.yml
- Added role defaults loading with proper precedence
- Fixed docker exec commands to use --user {{ forgejo_user }}
- Added monitoring compose file detection and handling
restore.yml
- Added role defaults loading with proper precedence
- Added monitoring compose file detection and handling
- Fixed docker exec for doctor command to use --user {{ forgejo_user }}
Makefile
- Updated .PHONY with new targets
- Replaced auto-generated help with structured categorized help
- Added backup-cron and backup-cron-s3 targets for non-interactive backups
- Added cron job example in help output
310 lines
16 KiB
Makefile
310 lines
16 KiB
Makefile
# Forgejo Self-Hosting Automation Makefile
|
|
# Provides convenient commands for deployment, updates, backups, and maintenance
|
|
|
|
.PHONY: help install deploy update backup backup-cron backup-to-s3 backup-cron-s3 restore ssh terraform-init terraform-plan terraform-apply terraform-destroy ansible-ping ansible-setup check-deps
|
|
|
|
# Default target
|
|
.DEFAULT_GOAL := help
|
|
|
|
# Configuration
|
|
TERRAFORM_DIR ?= terraform
|
|
ANSIBLE_DIR ?= ansible
|
|
PROVIDER ?= scaleway
|
|
ENVIRONMENT ?= production
|
|
INVENTORY ?= $(ANSIBLE_DIR)/inventory/$(ENVIRONMENT)/hosts.yml
|
|
PLAYBOOK_DIR ?= $(ANSIBLE_DIR)/playbooks
|
|
VAULT_PASSWORD_FILE ?= $(ANSIBLE_DIR)/.vault_password
|
|
SSH_KEY ?= ~/.ssh/id_ed25519
|
|
ANSIBLE_USER ?= root
|
|
|
|
# Point Ansible to our config file
|
|
export ANSIBLE_CONFIG := $(ANSIBLE_DIR)/ansible.cfg
|
|
|
|
# Colors for output
|
|
GREEN := \033[0;32m
|
|
YELLOW := \033[0;33m
|
|
RED := \033[0;31m
|
|
NC := \033[0m # No Color
|
|
|
|
# Help target
|
|
help: ## Show this help message
|
|
@echo "$(GREEN)════════════════════════════════════════════════════════════════════$(NC)"
|
|
@echo "$(GREEN) Forgejo Self-Hosting - Available Commands$(NC)"
|
|
@echo "$(GREEN)════════════════════════════════════════════════════════════════════$(NC)"
|
|
@echo ""
|
|
@echo "$(YELLOW)First time? Run:$(NC) ./setup-wizard.sh"
|
|
@echo ""
|
|
@echo "$(GREEN)── SETUP & INSTALLATION ──$(NC)"
|
|
@echo " $(YELLOW)wizard$(NC) Run interactive setup wizard (first-time setup)"
|
|
@echo " $(YELLOW)check-deps$(NC) Verify all required tools are installed"
|
|
@echo " $(YELLOW)install$(NC) Full install: create infrastructure + deploy Forgejo"
|
|
@echo ""
|
|
@echo "$(GREEN)── DEPLOYMENT ──$(NC)"
|
|
@echo " $(YELLOW)deploy$(NC) Deploy/update Forgejo configuration (full)"
|
|
@echo " $(YELLOW)deploy-quick$(NC) Quick deploy without dependency checks"
|
|
@echo " $(YELLOW)deploy-tags$(NC) Deploy specific components (TAGS=forgejo,caddy,ufw)"
|
|
@echo " $(YELLOW)deploy-check$(NC) Dry-run deployment (no changes made)"
|
|
@echo ""
|
|
@echo "$(GREEN)── INFRASTRUCTURE (Terraform) ──$(NC)"
|
|
@echo " $(YELLOW)terraform-init$(NC) Initialize Terraform/Terragrunt"
|
|
@echo " $(YELLOW)terraform-plan$(NC) Preview infrastructure changes"
|
|
@echo " $(YELLOW)terraform-apply$(NC) Create/update cloud infrastructure"
|
|
@echo " $(YELLOW)terraform-output$(NC) Show infrastructure details (IPs, etc.)"
|
|
@echo " $(YELLOW)terraform-destroy$(NC) Destroy all infrastructure (DANGEROUS!)"
|
|
@echo ""
|
|
@echo "$(GREEN)── BACKUP & RESTORE ──$(NC)"
|
|
@echo " $(YELLOW)backup$(NC) Create backup (interactive)"
|
|
@echo " $(YELLOW)backup-cron$(NC) Create backup (non-interactive, for cron jobs)"
|
|
@echo " $(YELLOW)backup-to-s3$(NC) Create backup and upload to S3 (interactive)"
|
|
@echo " $(YELLOW)backup-cron-s3$(NC) Create backup and upload to S3 (for cron jobs)"
|
|
@echo " $(YELLOW)restore$(NC) Restore from backup (interactive)"
|
|
@echo " $(YELLOW)restore-from-s3$(NC) Restore from S3 backup"
|
|
@echo ""
|
|
@echo "$(GREEN)── UPDATES ──$(NC)"
|
|
@echo " $(YELLOW)update$(NC) Update Forgejo to latest version (with backup)"
|
|
@echo " $(YELLOW)update-no-backup$(NC) Update Forgejo without creating backup"
|
|
@echo ""
|
|
@echo "$(GREEN)── MONITORING & MAINTENANCE ──$(NC)"
|
|
@echo " $(YELLOW)status$(NC) Show Forgejo container status"
|
|
@echo " $(YELLOW)health$(NC) Check Forgejo health endpoint"
|
|
@echo " $(YELLOW)logs$(NC) View Forgejo logs (live, Ctrl+C to exit)"
|
|
@echo " $(YELLOW)logs-caddy$(NC) View Caddy/HTTPS logs (live)"
|
|
@echo " $(YELLOW)restart$(NC) Restart Forgejo container"
|
|
@echo ""
|
|
@echo "$(GREEN)── SSH & CONNECTIVITY ──$(NC)"
|
|
@echo " $(YELLOW)ssh$(NC) SSH into the Forgejo server"
|
|
@echo " $(YELLOW)ssh-agent-start$(NC) Start SSH agent and load key"
|
|
@echo " $(YELLOW)ssh-agent-check$(NC) Verify SSH agent has keys loaded"
|
|
@echo " $(YELLOW)ansible-ping$(NC) Test Ansible connection to server"
|
|
@echo ""
|
|
@echo "$(GREEN)── SECRETS & CONFIGURATION ──$(NC)"
|
|
@echo " $(YELLOW)ansible-vault-edit$(NC) Edit encrypted secrets file"
|
|
@echo " $(YELLOW)ansible-vault-create$(NC) Create new encrypted secrets file"
|
|
@echo " $(YELLOW)validate$(NC) Validate all configuration files"
|
|
@echo ""
|
|
@echo "$(GREEN)── INFORMATION ──$(NC)"
|
|
@echo " $(YELLOW)info$(NC) Show current project configuration"
|
|
@echo " $(YELLOW)version$(NC) Show versions of all tools"
|
|
@echo " $(YELLOW)clean$(NC) Remove temporary/cache files"
|
|
@echo ""
|
|
@echo "$(GREEN)── DANGEROUS OPERATIONS ──$(NC)"
|
|
@echo " $(YELLOW)rebuild$(NC) Destroy and recreate everything (DATA LOSS!)"
|
|
@echo " $(YELLOW)terraform-destroy$(NC) Destroy all cloud infrastructure (DATA LOSS!)"
|
|
@echo ""
|
|
@echo "$(GREEN)════════════════════════════════════════════════════════════════════$(NC)"
|
|
@echo "$(GREEN)Examples:$(NC)"
|
|
@echo " ./setup-wizard.sh # First-time interactive setup"
|
|
@echo " make deploy # Deploy configuration changes"
|
|
@echo " make deploy-tags TAGS=forgejo # Update only Forgejo config"
|
|
@echo " make backup-cron # Backup (for cron jobs)"
|
|
@echo " make PROVIDER=hetzner terraform-plan # Plan Hetzner infrastructure"
|
|
@echo ""
|
|
@echo "$(GREEN)Cron example (daily backup at 2 AM):$(NC)"
|
|
@echo " 0 2 * * * cd /path/to/forgejo-selfhosting && make backup-cron >> /var/log/forgejo-backup.log 2>&1"
|
|
@echo ""
|
|
|
|
## Setup Wizard
|
|
wizard: ## Run interactive setup wizard (recommended for first-time setup)
|
|
@./setup-wizard.sh
|
|
|
|
## Dependency Checks
|
|
check-deps: ## Check if all required tools are installed
|
|
@echo "$(GREEN)Checking dependencies...$(NC)"
|
|
@command -v terraform >/dev/null 2>&1 || { echo "$(RED)Error: terraform not installed$(NC)"; exit 1; }
|
|
@command -v terragrunt >/dev/null 2>&1 || { echo "$(RED)Error: terragrunt not installed$(NC)"; exit 1; }
|
|
@command -v ansible >/dev/null 2>&1 || { echo "$(RED)Error: ansible not installed$(NC)"; exit 1; }
|
|
@command -v ansible-playbook >/dev/null 2>&1 || { echo "$(RED)Error: ansible-playbook not installed$(NC)"; exit 1; }
|
|
@command -v ssh-agent >/dev/null 2>&1 || { echo "$(RED)Error: ssh-agent not found$(NC)"; exit 1; }
|
|
@test -f $(SSH_KEY) || { echo "$(RED)Error: SSH key not found at $(SSH_KEY)$(NC)"; exit 1; }
|
|
@echo "$(GREEN)✓ All dependencies installed$(NC)"
|
|
|
|
## SSH Management
|
|
ssh-agent-start: ## Start SSH agent and add key
|
|
@echo "$(GREEN)Starting SSH agent...$(NC)"
|
|
@eval $$(ssh-agent -s) && ssh-add $(SSH_KEY)
|
|
|
|
ssh-agent-check: ## Check if SSH agent has keys loaded
|
|
@ssh-add -l >/dev/null 2>&1 || { echo "$(YELLOW)No SSH keys loaded. Run 'make ssh-agent-start'$(NC)"; exit 1; }
|
|
@echo "$(GREEN)✓ SSH agent has keys loaded$(NC)"
|
|
|
|
ssh: ssh-agent-check ## SSH into the Forgejo server
|
|
@echo "$(GREEN)Connecting to Forgejo server...$(NC)"
|
|
@ssh -i $(SSH_KEY) $(ANSIBLE_USER)@$$(cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output -raw server_ipv4 2>/dev/null || terragrunt output -raw server_ip)
|
|
|
|
## Terraform Commands
|
|
terraform-init: check-deps ## Initialize Terraform/Terragrunt
|
|
@echo "$(GREEN)Initializing Terraform for $(PROVIDER)...$(NC)"
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt init
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/storage && terragrunt init || true
|
|
|
|
terraform-plan: terraform-init ## Plan infrastructure changes
|
|
@echo "$(GREEN)Planning infrastructure for $(PROVIDER)...$(NC)"
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt plan
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/storage && terragrunt plan || true
|
|
|
|
terraform-apply: terraform-init ## Apply infrastructure changes
|
|
@echo "$(GREEN)Applying infrastructure for $(PROVIDER)...$(NC)"
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/storage && terragrunt apply -auto-approve || true
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt apply -auto-approve
|
|
@echo "$(GREEN)✓ Infrastructure created$(NC)"
|
|
@echo "$(YELLOW)Waiting 30 seconds for server initialization...$(NC)"
|
|
@sleep 30
|
|
@$(MAKE) terraform-output
|
|
|
|
terraform-output: ## Display Terraform outputs
|
|
@echo "$(GREEN)Infrastructure outputs:$(NC)"
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output
|
|
|
|
terraform-destroy: ## Destroy infrastructure
|
|
@echo "$(RED)WARNING: This will destroy all infrastructure!$(NC)"
|
|
@read -p "Type 'yes' to confirm: " confirm && [ "$$confirm" = "yes" ] || exit 1
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt destroy -auto-approve
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/storage && terragrunt destroy -auto-approve || true
|
|
@echo "$(GREEN)Infrastructure destroyed$(NC)"
|
|
|
|
## Ansible Commands
|
|
ansible-ping: ssh-agent-check ## Test Ansible connection
|
|
@echo "$(GREEN)Testing Ansible connection...$(NC)"
|
|
@ansible -i $(INVENTORY) forgejo -m ping
|
|
|
|
ansible-setup: ssh-agent-check ## Run Ansible setup to gather facts
|
|
@echo "$(GREEN)Gathering system facts...$(NC)"
|
|
@ansible -i $(INVENTORY) forgejo -m setup
|
|
|
|
ansible-vault-create: ## Create new Ansible vault file
|
|
@echo "$(GREEN)Creating Ansible vault...$(NC)"
|
|
@ansible-vault create $(ANSIBLE_DIR)/playbooks/vars/secrets.yml
|
|
|
|
ansible-vault-edit: ## Edit Ansible vault file
|
|
@echo "$(GREEN)Editing Ansible vault...$(NC)"
|
|
@ansible-vault edit $(ANSIBLE_DIR)/playbooks/vars/secrets.yml
|
|
|
|
ansible-vault-encrypt: ## Encrypt an existing file
|
|
@echo "$(GREEN)Encrypting file...$(NC)"
|
|
@read -p "File to encrypt: " file && ansible-vault encrypt $$file
|
|
|
|
## Deployment Commands
|
|
deploy: check-deps ssh-agent-check ## Deploy Forgejo (full deployment)
|
|
@echo "$(GREEN)Deploying Forgejo...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/deploy.yml --ask-vault-pass
|
|
@echo "$(GREEN)✓ Deployment complete$(NC)"
|
|
|
|
deploy-quick: ssh-agent-check ## Quick deploy without dependency checks
|
|
@echo "$(GREEN)Quick deploying Forgejo...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/deploy.yml --ask-vault-pass
|
|
|
|
deploy-tags: ssh-agent-check ## Deploy specific tags (make deploy-tags TAGS=nginx,ssl)
|
|
@echo "$(GREEN)Deploying with tags: $(TAGS)$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/deploy.yml --ask-vault-pass --tags "$(TAGS)"
|
|
|
|
deploy-check: ssh-agent-check ## Dry-run deployment
|
|
@echo "$(GREEN)Checking deployment...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/deploy.yml --ask-vault-pass --check
|
|
|
|
## Update Commands
|
|
update: ssh-agent-check ## Update Forgejo to latest version
|
|
@echo "$(GREEN)Updating Forgejo...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/update.yml --ask-vault-pass
|
|
@echo "$(GREEN)✓ Update complete$(NC)"
|
|
|
|
update-no-backup: ssh-agent-check ## Update without creating backup
|
|
@echo "$(YELLOW)Updating without backup...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/update.yml --ask-vault-pass --extra-vars "skip_backup=true"
|
|
|
|
## Backup Commands
|
|
backup: ssh-agent-check ## Create backup of Forgejo
|
|
@echo "$(GREEN)Creating backup...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/backup.yml --ask-vault-pass
|
|
@echo "$(GREEN)✓ Backup complete$(NC)"
|
|
|
|
backup-cron: ## Create backup non-interactively (for cron jobs)
|
|
@test -f $(VAULT_PASSWORD_FILE) || { echo "$(RED)Error: Vault password file not found at $(VAULT_PASSWORD_FILE)$(NC)"; echo "Create it with: echo 'your-vault-password' > $(VAULT_PASSWORD_FILE) && chmod 600 $(VAULT_PASSWORD_FILE)"; exit 1; }
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/backup.yml --vault-password-file $(VAULT_PASSWORD_FILE)
|
|
|
|
backup-to-s3: ssh-agent-check ## Create backup and upload to S3
|
|
@echo "$(GREEN)Creating backup and uploading to S3...$(NC)"
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/backup.yml --ask-vault-pass --extra-vars "upload_to_s3=true"
|
|
|
|
backup-cron-s3: ## Create backup and upload to S3 (for cron jobs)
|
|
@test -f $(VAULT_PASSWORD_FILE) || { echo "$(RED)Error: Vault password file not found at $(VAULT_PASSWORD_FILE)$(NC)"; exit 1; }
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/backup.yml --vault-password-file $(VAULT_PASSWORD_FILE) --extra-vars "upload_to_s3=true"
|
|
|
|
## Restore Commands
|
|
restore: ssh-agent-check ## Restore Forgejo from backup
|
|
@echo "$(RED)WARNING: This will restore from backup$(NC)"
|
|
@read -p "Backup timestamp (e.g., 20240115T120000): " timestamp && \
|
|
ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/restore.yml --ask-vault-pass --extra-vars "backup_timestamp=$$timestamp"
|
|
|
|
restore-force: ssh-agent-check ## Force restore without confirmation
|
|
@read -p "Backup timestamp: " timestamp && \
|
|
ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/restore.yml --ask-vault-pass --extra-vars "backup_timestamp=$$timestamp force_restore=true"
|
|
|
|
restore-from-s3: ssh-agent-check ## Restore from S3 backup
|
|
@read -p "Backup timestamp: " timestamp && \
|
|
ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/restore.yml --ask-vault-pass --extra-vars "backup_timestamp=$$timestamp backup_source=s3"
|
|
|
|
## Maintenance Commands
|
|
logs: ssh-agent-check ## View Forgejo logs
|
|
@echo "$(GREEN)Fetching Forgejo logs...$(NC)"
|
|
@ssh -i $(SSH_KEY) $(ANSIBLE_USER)@$$(cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output -raw server_ipv4 2>/dev/null || terragrunt output -raw server_ip) "docker logs forgejo --tail 100 -f"
|
|
|
|
logs-caddy: ssh-agent-check ## View Caddy logs
|
|
@echo "$(GREEN)Fetching Caddy logs...$(NC)"
|
|
@ssh -i $(SSH_KEY) $(ANSIBLE_USER)@$$(cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output -raw server_ipv4 2>/dev/null || terragrunt output -raw server_ip) "tail -f /var/log/caddy/forgejo_access.log"
|
|
|
|
restart: ssh-agent-check ## Restart Forgejo service
|
|
@echo "$(GREEN)Restarting Forgejo...$(NC)"
|
|
@ssh -i $(SSH_KEY) $(ANSIBLE_USER)@$$(cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output -raw server_ipv4 2>/dev/null || terragrunt output -raw server_ip) "cd /opt/forgejo && docker compose restart"
|
|
@echo "$(GREEN)✓ Forgejo restarted$(NC)"
|
|
|
|
status: ssh-agent-check ## Check Forgejo status
|
|
@echo "$(GREEN)Checking Forgejo status...$(NC)"
|
|
@ssh -i $(SSH_KEY) $(ANSIBLE_USER)@$$(cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output -raw server_ipv4 2>/dev/null || terragrunt output -raw server_ip) "cd /opt/forgejo && docker compose ps"
|
|
|
|
health: ssh-agent-check ## Check Forgejo health
|
|
@echo "$(GREEN)Checking Forgejo health...$(NC)"
|
|
@ssh -i $(SSH_KEY) $(ANSIBLE_USER)@$$(cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt output -raw server_ipv4 2>/dev/null || terragrunt output -raw server_ip) "curl -s http://localhost:3000/api/healthz"
|
|
|
|
## Full Stack Commands
|
|
install: terraform-apply deploy ## Full installation (infrastructure + deployment)
|
|
@echo "$(GREEN)✓ Full installation complete!$(NC)"
|
|
|
|
rebuild: terraform-destroy install ## Rebuild everything from scratch
|
|
@echo "$(GREEN)✓ Rebuild complete!$(NC)"
|
|
|
|
## Utility Commands
|
|
clean: ## Clean local temporary files
|
|
@echo "$(GREEN)Cleaning temporary files...$(NC)"
|
|
@find . -type f -name "*.retry" -delete
|
|
@find . -type d -name ".terraform" -exec rm -rf {} + 2>/dev/null || true
|
|
@find . -type f -name "terraform.tfstate*" -delete 2>/dev/null || true
|
|
@echo "$(GREEN)✓ Cleaned$(NC)"
|
|
|
|
validate: check-deps ## Validate all configurations
|
|
@echo "$(GREEN)Validating configurations...$(NC)"
|
|
@cd $(TERRAFORM_DIR)/$(PROVIDER)/compute && terragrunt validate
|
|
@ansible-playbook -i $(INVENTORY) $(PLAYBOOK_DIR)/deploy.yml --syntax-check
|
|
@echo "$(GREEN)✓ All configurations valid$(NC)"
|
|
|
|
docs: ## Generate documentation
|
|
@echo "$(GREEN)Generating documentation...$(NC)"
|
|
@terraform-docs markdown $(TERRAFORM_DIR)/$(PROVIDER)/compute > $(TERRAFORM_DIR)/$(PROVIDER)/compute/README.md || true
|
|
@echo "$(GREEN)✓ Documentation generated$(NC)"
|
|
|
|
## Information Commands
|
|
info: ## Display project information
|
|
@echo "$(GREEN)Forgejo Self-Hosting Project$(NC)"
|
|
@echo ""
|
|
@echo "Provider: $(PROVIDER)"
|
|
@echo "Environment: $(ENVIRONMENT)"
|
|
@echo "Ansible User: $(ANSIBLE_USER)"
|
|
@echo "SSH Key: $(SSH_KEY)"
|
|
@echo "Inventory: $(INVENTORY)"
|
|
@echo ""
|
|
|
|
version: ## Display tool versions
|
|
@echo "$(GREEN)Tool Versions:$(NC)"
|
|
@echo "Terraform: $$(terraform version | head -1)"
|
|
@echo "Terragrunt: $$(terragrunt --version)"
|
|
@echo "Ansible: $$(ansible --version | head -1)"
|
|
@echo "Make: $$(make --version | head -1)"
|