puffin-app/DEPLOYMENT.md
Matt 1c9c570ece
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled
Add CI/CD pipeline with Gitea Actions and Portainer deployment
- Create Gitea Actions workflow for automated Docker builds on push to main
- Add docker-compose.portainer.yml for production Portainer deployment
- Create comprehensive DEPLOYMENT.md guide with step-by-step instructions
- Update CLAUDE.md with CI/CD pipeline documentation

Images are built and pushed to Gitea registry at:
code.puffinoffset.com/matt/puffin-app:latest
code.puffinoffset.com/matt/puffin-app:main-<sha>

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 13:31:04 +01:00

6.8 KiB

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-<commit-sha> - 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-<sha>

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:

# 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

  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-<commit-sha>
    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-<sha> 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:

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:

# 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-<previous-sha>
  4. Update the stack

Example:

# 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