# Forgejo Self-Hosting Automation Makefile # Provides convenient commands for deployment, updates, backups, and maintenance .PHONY: help install deploy update backup 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)Forgejo Self-Hosting - Available Commands$(NC)" @echo "" @echo "$(YELLOW)First time? Run:$(NC) ./setup-wizard.sh" @echo "" @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf " $(YELLOW)%-20s$(NC) %s\n", $$1, $$2}' @echo "" @echo "$(GREEN)Examples:$(NC)" @echo " ./setup-wizard.sh # Interactive first-time setup" @echo " make check-deps # Check all dependencies" @echo " make terraform-apply # Create infrastructure" @echo " make deploy # Deploy Forgejo" @echo " make update # Update Forgejo" @echo " make backup # Create backup" @echo " make PROVIDER=hetzner deploy # Deploy on Hetzner" ## 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-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" ## 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)"