# Puffin Offset - Deployment Guide This guide covers deploying the Puffin Offset application using Gitea Actions for automated builds and Portainer for container orchestration. ## Architecture Overview ``` Push to main → Gitea Actions → Build Docker Image → Push to Registry → Manual Deploy via Portainer ``` ## CI/CD Pipeline ### Automated Build Process When code is pushed to the `main` branch: 1. **Gitea Actions triggers** automatically 2. **Docker image is built** using the multi-stage Dockerfile 3. **Image is pushed** to Gitea's container registry with two tags: - `latest` - Always points to the most recent build - `main-` - Specific commit for rollback capability ### Registry Location Images are stored at: ``` code.puffinoffset.com/matt/puffin-app:latest code.puffinoffset.com/matt/puffin-app:main- ``` ## Portainer Deployment ### Prerequisites 1. **Portainer installed and accessible** 2. **Gitea registry credentials configured in Portainer** 3. **Environment variables prepared** (see below) ### Step 1: Configure Gitea Registry in Portainer 1. Navigate to **Portainer → Registries** 2. Click **"Add registry"** 3. Configure: - **Name**: `Gitea - code.puffinoffset.com` - **Registry URL**: `code.puffinoffset.com` - **Authentication**: Enabled - **Username**: Your Gitea username (e.g., `matt`) - **Password**: Gitea access token or password 4. Click **"Add registry"** ### Step 2: Prepare Environment Variables Create a `.env` file on your server with the required variables: ```bash # Example: /path/to/puffin-app/.env VITE_WREN_API_TOKEN=your-wren-api-token VITE_FORMSPREE_CONTACT_ID=your-formspree-contact-id VITE_FORMSPREE_OFFSET_ID=your-formspree-offset-id ``` **Note**: The env.sh script in the Docker image will inject these at runtime. ### Step 3: Create Portainer Stack #### Option A: Using Portainer UI 1. Navigate to **Portainer → Stacks** 2. Click **"Add stack"** 3. Configure: - **Name**: `puffin-app` - **Build method**: "Web editor" 4. Paste the contents of `docker-compose.portainer.yml` 5. In **Environment variables** section, add: - Name: `ENV_FILE_PATH` - Value: `/path/to/your/.env` 6. Click **"Deploy the stack"** #### Option B: Using Git Repository 1. Navigate to **Portainer → Stacks** 2. Click **"Add stack"** 3. Configure: - **Name**: `puffin-app` - **Build method**: "Repository" - **Repository URL**: `https://code.puffinoffset.com/matt/puffin-app.git` - **Repository reference**: `refs/heads/main` - **Compose path**: `docker-compose.portainer.yml` - **Authentication**: Configure with your Gitea credentials 4. Click **"Deploy the stack"** ### Step 4: Verify Deployment 1. Check that the container is running: - Navigate to **Portainer → Containers** - Look for `puffin-app-web-1` or similar - Status should be "running" 2. Test the application: - Access: `http://your-server:3800` - Or via your Nginx reverse proxy configuration 3. Check logs if needed: - Click on the container - Select **"Logs"** tab ## Updating to New Versions ### Method 1: Using Portainer UI (Recommended) 1. Navigate to **Portainer → Stacks** 2. Click on **puffin-app** stack 3. Click **"Update the stack"** 4. Enable **"Pull latest image version"** 5. Enable **"Re-pull image and redeploy"** 6. Click **"Update"** Portainer will: - Pull the latest image from Gitea registry - Recreate the container with the new image - Maintain your environment variables and configuration ### Method 2: Pull Specific Version To rollback or deploy a specific commit: 1. Edit the stack in Portainer 2. Change the image tag from `latest` to `main-` ```yaml image: code.puffinoffset.com/matt/puffin-app:main-abc1234 ``` 3. Update the stack ## Monitoring Build Status ### Check Gitea Actions 1. Go to your Gitea repository: `https://code.puffinoffset.com/matt/puffin-app` 2. Navigate to **"Actions"** tab 3. View recent workflow runs 4. Click on a run to see detailed logs ### Verify Image in Registry 1. In Gitea, navigate to **"Packages"** or **"Registry"** 2. Look for `puffin-app` images 3. Verify tags: `latest` and `main-` tags should be present ## Troubleshooting ### Build Failed in Gitea Actions **Check the workflow logs:** 1. Go to Gitea → puffin-app → Actions 2. Click on the failed run 3. Review error messages **Common issues:** - Registry authentication failed: Check secrets.GITHUB_TOKEN is available - Build errors: Review Dockerfile and build logs - Network issues: Check runner connectivity ### Image Pull Failed in Portainer **Error:** `unauthorized: authentication required` **Solution:** 1. Verify registry is configured in Portainer (Step 1) 2. Check credentials are correct 3. Ensure registry URL is `code.puffinoffset.com` (no `https://`) ### Container Won't Start **Check environment variables:** 1. Verify `.env` file exists on the host 2. Ensure volume mount path is correct in docker-compose.portainer.yml 3. Check container logs for missing env var errors **Check port conflicts:** 1. Ensure port 3800 is not already in use 2. Run `netstat -tuln | grep 3800` on the host ### Application Not Accessible **Verify container is running:** ```bash docker ps | grep puffin-app ``` **Check nginx reverse proxy:** - Review host Nginx configuration (`nginx-host.conf`) - Ensure proxy_pass points to correct container port - Test direct access: `http://server-ip:3800` **Check firewall:** ```bash # Example for ufw sudo ufw status sudo ufw allow 3800/tcp ``` ## Environment Variables Reference | Variable | Description | Required | |----------|-------------|----------| | `VITE_WREN_API_TOKEN` | Wren Climate API authentication token | Yes | | `VITE_FORMSPREE_CONTACT_ID` | Formspree contact form endpoint ID | Yes | | `VITE_FORMSPREE_OFFSET_ID` | Formspree offset order form endpoint ID | Yes | | `NODE_ENV` | Node environment (set to `production`) | Auto-set | ## Rollback Procedure To rollback to a previous version: 1. Find the commit SHA of the working version 2. In Portainer, edit the stack 3. Change image tag to `main-` 4. Update the stack Example: ```yaml # Before (current broken version) image: code.puffinoffset.com/matt/puffin-app:latest # After (rollback to specific commit) image: code.puffinoffset.com/matt/puffin-app:main-ab0dbbd ``` ## Security Best Practices 1. **Never commit `.env` file to git** (already in .gitignore) 2. **Use Gitea access tokens** instead of passwords for registry auth 3. **Restrict registry access** to necessary users 4. **Review Gitea Actions logs** for sensitive data exposure 5. **Keep base images updated** (node:20-alpine, nginx:alpine) ## Next Steps - Set up monitoring/alerting for failed builds - Configure automatic backups of `.env` file - Implement health checks in docker-compose - Set up SSL certificates via Let's Encrypt - Configure log aggregation for production debugging