Some checks failed
Build & Deploy KLZ Cables / 🔍 Prepare Environment (push) Successful in 7s
Build & Deploy KLZ Cables / 🧪 Quality Assurance (push) Failing after 1m31s
Build & Deploy KLZ Cables / 🏗️ Build App (push) Successful in 3m51s
Build & Deploy KLZ Cables / 🚀 Deploy (push) Has been skipped
Build & Deploy KLZ Cables / ⚡ PageSpeed (push) Has been skipped
Build & Deploy KLZ Cables / 🔔 Notifications (push) Successful in 2s
295 lines
11 KiB
Markdown
295 lines
11 KiB
Markdown
# KLZ Cables - Deployment Guide
|
|
|
|
This document explains the deployment process and environment variable management for the KLZ Cables application.
|
|
|
|
## Table of Contents
|
|
|
|
- [Overview](#overview)
|
|
- [Environment Variables](#environment-variables)
|
|
- [Local Development](#local-development)
|
|
- [Production Deployment](#production-deployment)
|
|
- [Troubleshooting](#troubleshooting)
|
|
|
|
## Overview
|
|
|
|
The application uses a clean, robust, **fully automated** environment variable strategy:
|
|
|
|
- **Build-time variables**: Only `NEXT_PUBLIC_*` variables are baked into the client bundle
|
|
- **Runtime variables**: All other variables are loaded from `.env` file at runtime
|
|
- **Fully automated**: `.env` file is automatically generated from Gitea secrets on every deployment
|
|
- **No manual steps**: No need to manually create or update `.env` files on the server
|
|
- **No duplication**: Single source of truth for each environment
|
|
|
|
### Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ CI/CD Workflow (.gitea/workflows/deploy.yml) │
|
|
│ │
|
|
│ 1. Build Docker image with NEXT_PUBLIC_* build args │
|
|
│ 2. Push to registry │
|
|
│ 3. SSH to server and run deploy.sh │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
↓
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ Production Server (alpha.mintel.me) │
|
|
│ │
|
|
│ /home/deploy/sites/klz-cables.com/ │
|
|
│ ├── .env ← Runtime environment vars │
|
|
│ └── docker-compose.yml ← Loads .env file │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Environment Variables
|
|
|
|
### Build-Time Variables (NEXT*PUBLIC*\*)
|
|
|
|
These are embedded into the JavaScript bundle during build and are visible to the client:
|
|
|
|
| Variable | Required | Description |
|
|
| ---------------------- | -------- | ------------------------------------------------------------ |
|
|
| `NEXT_PUBLIC_BASE_URL` | ✅ Yes | Base URL of the application (e.g., `https://klz-cables.com`) |
|
|
| `UMAMI_WEBSITE_ID` | ❌ No | Umami analytics website ID (passed as prop) |
|
|
| `UMAMI_API_ENDPOINT` | ❌ No | Backend-only Umami analytics API target (internal) |
|
|
|
|
**Important**: These must be provided as `--build-arg` when building the Docker image.
|
|
|
|
### Runtime Variables
|
|
|
|
These are loaded from the `.env` file at runtime and are only available on the server:
|
|
|
|
| Variable | Required | Description |
|
|
| -------------------------- | -------- | ------------------------------------------------------ |
|
|
| `NODE_ENV` | ✅ Yes | Environment mode (`production`, `development`, `test`) |
|
|
| `SENTRY_DSN` | ❌ No | GlitchTip/Sentry error tracking DSN |
|
|
| `MAIL_HOST` | ❌ No | SMTP server hostname |
|
|
| `MAIL_PORT` | ❌ No | SMTP server port (default: `587`) |
|
|
| `MAIL_USERNAME` | ❌ No | SMTP authentication username |
|
|
| `MAIL_PASSWORD` | ❌ No | SMTP authentication password |
|
|
| `MAIL_FROM` | ❌ No | Email sender address |
|
|
| `MAIL_RECIPIENTS` | ❌ No | Comma-separated list of recipient emails |
|
|
| `REDIS_URL` | ❌ No | Redis connection URL (e.g., `redis://redis:6379/2`) |
|
|
| `REDIS_KEY_PREFIX` | ❌ No | Redis key prefix (default: `klz:`) |
|
|
| `STRAPI_DATABASE_NAME` | ✅ Yes | Strapi database name |
|
|
| `STRAPI_DATABASE_USERNAME` | ✅ Yes | Strapi database username |
|
|
| `STRAPI_DATABASE_PASSWORD` | ✅ Yes | Strapi database password |
|
|
| `STRAPI_URL` | ✅ Yes | URL of the Strapi CMS |
|
|
| `APP_KEYS` | ✅ Yes | Strapi application keys (comma-separated) |
|
|
| `API_TOKEN_SALT` | ✅ Yes | Strapi API token salt |
|
|
| `ADMIN_JWT_SECRET` | ✅ Yes | Strapi admin JWT secret |
|
|
| `TRANSFER_TOKEN_SALT` | ✅ Yes | Strapi transfer token salt |
|
|
| `JWT_SECRET` | ✅ Yes | Strapi JWT secret |
|
|
|
|
## Local Development
|
|
|
|
### Setup
|
|
|
|
1. Copy the example environment file:
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
```
|
|
|
|
2. Edit `.env` and fill in your local configuration:
|
|
|
|
```bash
|
|
NODE_ENV=development
|
|
NEXT_PUBLIC_BASE_URL=http://localhost:3000
|
|
# Add other variables as needed
|
|
```
|
|
|
|
3. Install dependencies:
|
|
|
|
```bash
|
|
npm install
|
|
```
|
|
|
|
4. Run the development server:
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
### Testing Docker Build Locally
|
|
|
|
```bash
|
|
# Build with build-time arguments
|
|
docker build \
|
|
--build-arg NEXT_PUBLIC_BASE_URL=http://localhost:3000 \
|
|
--build-arg UMAMI_WEBSITE_ID=your-id \
|
|
--build-arg UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me \
|
|
-t klz-cables:local .
|
|
|
|
# Run with runtime environment file
|
|
docker run --env-file .env -p 3000:3000 klz-cables:local
|
|
```
|
|
|
|
## Production Deployment
|
|
|
|
### Prerequisites
|
|
|
|
1. **Server Setup**: Ensure the production server has:
|
|
- Docker and Docker Compose installed
|
|
- Traefik reverse proxy running
|
|
- Network `infra` created
|
|
- Project directory exists: `/home/deploy/sites/klz-cables.com`
|
|
|
|
2. **Gitea Secrets**: Configure the following secrets in your Gitea repository:
|
|
|
|
**Registry Access:**
|
|
- `REGISTRY_USER` - Docker registry username
|
|
- `REGISTRY_PASS` - Docker registry password
|
|
|
|
**Build-Time Variables:**
|
|
- `NEXT_PUBLIC_BASE_URL` - Production URL (e.g., `https://klz-cables.com`)
|
|
- `UMAMI_WEBSITE_ID` - Umami analytics ID
|
|
- `UMAMI_API_ENDPOINT` - Umami API endpoint
|
|
|
|
**Runtime Variables:**
|
|
- `SENTRY_DSN` - Error tracking DSN
|
|
- `MAIL_HOST` - SMTP server
|
|
- `MAIL_PORT` - SMTP port
|
|
- `MAIL_USERNAME` - SMTP username
|
|
- `MAIL_PASSWORD` - SMTP password
|
|
- `MAIL_FROM` - Sender email
|
|
- `MAIL_RECIPIENTS` - Recipient emails (comma-separated)
|
|
- `REDIS_URL` - Redis connection URL
|
|
- `REDIS_KEY_PREFIX` - Redis key prefix
|
|
|
|
**Infrastructure:**
|
|
- `REGISTRY_USER` - Docker registry username
|
|
- `REGISTRY_PASS` - Docker registry password
|
|
- `ALPHA_SSH_KEY` - SSH private key for deployment server
|
|
|
|
**Notifications:**
|
|
- `GOTIFY_URL` - Gotify notification server URL
|
|
- `GOTIFY_TOKEN` - Gotify application token
|
|
|
|
### Deployment Process
|
|
|
|
The deployment is **fully automated** via Gitea Actions:
|
|
|
|
1. **Trigger**: Push to `main` branch
|
|
2. **Build**: Docker image is built with `NEXT_PUBLIC_*` build arguments
|
|
3. **Push**: Image is pushed to private registry
|
|
4. **Generate .env**: Workflow creates `.env` file from all Gitea secrets
|
|
5. **Upload .env**: File is uploaded to server via SCP and secured (600 permissions)
|
|
6. **Deploy**: SSH to server, pull image, and run docker-compose
|
|
7. **Notify**: Send success/failure notification via Gotify
|
|
|
|
**No manual steps required!** The `.env` file is automatically created and deployed on every push.
|
|
|
|
### Manual Deployment
|
|
|
|
If you need to deploy manually (not recommended - use the automated workflow):
|
|
|
|
```bash
|
|
# SSH to the server
|
|
ssh root@alpha.mintel.me
|
|
|
|
# Navigate to the project directory
|
|
cd /home/deploy/sites/klz-cables.com
|
|
|
|
# Ensure .env file exists (normally created by workflow)
|
|
# If missing, you'll need to create it from Gitea secrets
|
|
|
|
# Pull the latest image
|
|
docker pull registry.infra.mintel.me/mintel/klz-cables.com:latest
|
|
|
|
# Restart the services
|
|
docker-compose down
|
|
docker-compose up -d
|
|
|
|
# Check logs
|
|
docker-compose logs -f app
|
|
```
|
|
|
|
**Note**: Manual deployment requires the `.env` file to exist. The automated workflow creates this file from Gitea secrets. If deploying manually, you'll need to create it yourself using [`.env.production`](.env.production) as a template.
|
|
|
|
## Troubleshooting
|
|
|
|
### Build Failures
|
|
|
|
**Problem**: Build fails with "Environment validation failed"
|
|
|
|
**Solution**: Ensure all required `NEXT_PUBLIC_*` variables are provided as build arguments:
|
|
|
|
```bash
|
|
docker build \
|
|
--build-arg NEXT_PUBLIC_BASE_URL=https://klz-cables.com \
|
|
--build-arg UMAMI_WEBSITE_ID=your-id \
|
|
--build-arg UMAMI_API_ENDPOINT=https://analytics.infra.mintel.me \
|
|
-t klz-cables .
|
|
```
|
|
|
|
### Runtime Failures
|
|
|
|
**Problem**: Container starts but application crashes
|
|
|
|
**Solution**: Check that the `.env` file exists and contains all required runtime variables:
|
|
|
|
```bash
|
|
# On the server
|
|
cat /home/deploy/sites/klz-cables.com/.env
|
|
|
|
# Check container logs
|
|
docker-compose logs app
|
|
```
|
|
|
|
### Missing Environment Variables
|
|
|
|
**Problem**: Features not working (email, analytics, etc.)
|
|
|
|
**Solution**:
|
|
|
|
1. Check that the secret is configured in Gitea
|
|
2. Verify the workflow includes it in the `.env` generation (see `.gitea/workflows/deploy.yml`)
|
|
3. Redeploy to regenerate the `.env` file:
|
|
|
|
```bash
|
|
git commit --allow-empty -m "Trigger redeploy"
|
|
git push origin main
|
|
```
|
|
|
|
4. Check the variable is loaded on the server:
|
|
```bash
|
|
ssh root@alpha.mintel.me
|
|
cd /home/deploy/sites/klz-cables.com
|
|
docker-compose exec app env | grep VARIABLE_NAME
|
|
```
|
|
|
|
### Docker Compose Issues
|
|
|
|
**Problem**: `docker-compose up` fails with "env file not found"
|
|
|
|
**Solution**: The `.env` file should be automatically created by the workflow. If it's missing:
|
|
|
|
1. Check the workflow logs for errors in the "📝 Preparing environment configuration" step
|
|
2. Manually trigger a deployment by pushing to main
|
|
3. If still missing, check server permissions and disk space
|
|
|
|
### Network Issues
|
|
|
|
**Problem**: Container can't connect to Traefik
|
|
|
|
**Solution**: Verify the `infra` network exists:
|
|
|
|
```bash
|
|
docker network ls | grep infra
|
|
docker network inspect infra
|
|
```
|
|
|
|
## Security Best Practices
|
|
|
|
1. **Never commit `.env` files** with real credentials to git
|
|
2. **Use Gitea/GitHub secrets** for CI/CD workflows
|
|
3. **Restrict SSH key access** to deployment server
|
|
4. **Rotate credentials regularly** (SMTP passwords, API keys, etc.)
|
|
5. **Use HTTPS** for all production URLs
|
|
6. **Monitor logs** for suspicious activity
|
|
|
|
## Additional Resources
|
|
|
|
- [Next.js Environment Variables](https://nextjs.org/docs/basic-features/environment-variables)
|
|
- [Docker Compose Environment Variables](https://docs.docker.com/compose/environment-variables/)
|
|
- [Traefik Documentation](https://doc.traefik.io/traefik/)
|