244 lines
6.8 KiB
Markdown
244 lines
6.8 KiB
Markdown
|
|
# 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:
|
||
|
|
|
||
|
|
```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-<commit-sha>`
|
||
|
|
```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-<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:**
|
||
|
|
```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-<previous-sha>`
|
||
|
|
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
|