This commit is contained in:
349
docs/SERVER_SETUP.md
Normal file
349
docs/SERVER_SETUP.md
Normal file
@@ -0,0 +1,349 @@
|
||||
# Server Setup Guide - KLZ Cables
|
||||
|
||||
This guide explains how to set up the production environment on the deployment server.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Server: `alpha.mintel.me`
|
||||
- User: `deploy` (with sudo access)
|
||||
- Docker and Docker Compose installed
|
||||
- Traefik reverse proxy running
|
||||
- External network `infra` created
|
||||
|
||||
## Initial Server Setup
|
||||
|
||||
### 1. Create Project Directory
|
||||
|
||||
```bash
|
||||
# SSH to the server as root or deploy user
|
||||
ssh root@alpha.mintel.me
|
||||
|
||||
# Create project directory
|
||||
mkdir -p /home/deploy/sites/klz-cables.com
|
||||
cd /home/deploy/sites/klz-cables.com
|
||||
```
|
||||
|
||||
### 2. Create Environment File
|
||||
|
||||
Create the `.env` file with production configuration:
|
||||
|
||||
```bash
|
||||
# Create .env file from template
|
||||
cat > /home/deploy/sites/klz-cables.com/.env << 'EOF'
|
||||
# ============================================================================
|
||||
# KLZ Cables - Production Environment Configuration
|
||||
# ============================================================================
|
||||
|
||||
# Application
|
||||
NODE_ENV=production
|
||||
NEXT_PUBLIC_BASE_URL=https://klz-cables.com
|
||||
|
||||
# Analytics (Umami)
|
||||
NEXT_PUBLIC_UMAMI_WEBSITE_ID=your-umami-website-id
|
||||
NEXT_PUBLIC_UMAMI_SCRIPT_URL=https://analytics.infra.mintel.me/script.js
|
||||
|
||||
# Error Tracking (GlitchTip/Sentry)
|
||||
SENTRY_DSN=https://your-sentry-dsn@errors.infra.mintel.me/project-id
|
||||
|
||||
# Email Configuration (Mailgun)
|
||||
MAIL_HOST=smtp.eu.mailgun.org
|
||||
MAIL_PORT=587
|
||||
MAIL_USERNAME=your-mailgun-username
|
||||
MAIL_PASSWORD=your-mailgun-password
|
||||
MAIL_FROM=KLZ Cables <noreply@klz-cables.com>
|
||||
MAIL_RECIPIENTS=info@klz-cables.com
|
||||
|
||||
# Redis Cache
|
||||
REDIS_URL=redis://redis:6379/2
|
||||
REDIS_KEY_PREFIX=klz:
|
||||
|
||||
# Varnish Cache Size
|
||||
VARNISH_CACHE_SIZE=256m
|
||||
EOF
|
||||
```
|
||||
|
||||
**Important**: Replace all placeholder values with actual production credentials.
|
||||
|
||||
### 3. Secure the Environment File
|
||||
|
||||
```bash
|
||||
# Set proper permissions (readable only by owner)
|
||||
chmod 600 /home/deploy/sites/klz-cables.com/.env
|
||||
|
||||
# Verify ownership
|
||||
chown deploy:deploy /home/deploy/sites/klz-cables.com/.env
|
||||
|
||||
# Verify permissions
|
||||
ls -la /home/deploy/sites/klz-cables.com/.env
|
||||
# Should show: -rw------- 1 deploy deploy
|
||||
```
|
||||
|
||||
### 4. Create Docker Compose File
|
||||
|
||||
```bash
|
||||
# Copy docker-compose.yml from repository
|
||||
# This should be done automatically by the deployment script
|
||||
# Or manually:
|
||||
cat > /home/deploy/sites/klz-cables.com/docker-compose.yml << 'EOF'
|
||||
services:
|
||||
varnish:
|
||||
image: varnish:7
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
depends_on:
|
||||
- app
|
||||
command: >-
|
||||
varnishd
|
||||
-F
|
||||
-f /etc/varnish/default.vcl
|
||||
-s malloc,${VARNISH_CACHE_SIZE:-256m}
|
||||
volumes:
|
||||
- ./varnish/default.vcl:/etc/varnish/default.vcl:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:80/health || wget --quiet --tries=1 --spider http://localhost:80/ || true"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 10s
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.klz-cables-web.rule=(Host(\`klz-cables.com\`) || Host(\`www.klz-cables.com\`) || Host(\`staging.klz-cables.com\`)) && !PathPrefix(\`/.well-known/acme-challenge/\`)"
|
||||
- "traefik.http.routers.klz-cables-web.entrypoints=web"
|
||||
- "traefik.http.routers.klz-cables-web.middlewares=redirect-https"
|
||||
- "traefik.http.routers.klz-cables.rule=Host(\`klz-cables.com\`) || Host(\`www.klz-cables.com\`) || Host(\`staging.klz-cables.com\`)"
|
||||
- "traefik.http.routers.klz-cables.entrypoints=websecure"
|
||||
- "traefik.http.routers.klz-cables.tls.certresolver=le"
|
||||
- "traefik.http.routers.klz-cables.tls=true"
|
||||
- "traefik.http.routers.klz-cables.service=klz-cables"
|
||||
- "traefik.http.services.klz-cables.loadbalancer.server.port=80"
|
||||
- "traefik.http.services.klz-cables.loadbalancer.server.scheme=http"
|
||||
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Proto=https"
|
||||
- "traefik.http.middlewares.klz-forward.headers.customrequestheaders.X-Forwarded-Ssl=on"
|
||||
- "traefik.http.routers.klz-cables.middlewares=klz-forward,compress"
|
||||
|
||||
app:
|
||||
image: registry.infra.mintel.me/mintel/klz-cables.com:latest
|
||||
restart: always
|
||||
networks:
|
||||
- infra
|
||||
env_file:
|
||||
- .env
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:3000/health || wget --quiet --tries=1 --spider http://localhost:3000/ || true"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
|
||||
networks:
|
||||
infra:
|
||||
external: true
|
||||
EOF
|
||||
```
|
||||
|
||||
### 5. Create Varnish Configuration
|
||||
|
||||
```bash
|
||||
# Create varnish directory
|
||||
mkdir -p /home/deploy/sites/klz-cables.com/varnish
|
||||
|
||||
# Copy varnish configuration from repository
|
||||
# This should be in the repository at varnish/default.vcl
|
||||
```
|
||||
|
||||
### 6. Create Deployment Script
|
||||
|
||||
```bash
|
||||
cat > /home/deploy/deploy.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
PROJECT_DIR="/home/deploy/sites/klz-cables.com"
|
||||
|
||||
echo "╔══════════════════════════════════════════════════════════════════════════════╗"
|
||||
echo "║ KLZ Cables - Deployment Script ║"
|
||||
echo "╚══════════════════════════════════════════════════════════════════════════════╝"
|
||||
echo ""
|
||||
|
||||
cd "$PROJECT_DIR"
|
||||
|
||||
# Check if .env file exists
|
||||
if [ ! -f .env ]; then
|
||||
echo "❌ ERROR: .env file not found at $PROJECT_DIR/.env"
|
||||
echo "Please create the .env file before deploying."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔐 Logging into Docker registry..."
|
||||
echo "$REGISTRY_PASS" | docker login registry.infra.mintel.me -u "$REGISTRY_USER" --password-stdin
|
||||
|
||||
echo "🔄 Pulling latest image..."
|
||||
docker pull registry.infra.mintel.me/mintel/klz-cables.com:latest
|
||||
|
||||
echo "🔄 Stopping existing containers..."
|
||||
docker-compose down
|
||||
|
||||
echo "🚀 Starting new containers..."
|
||||
docker-compose up -d
|
||||
|
||||
echo "⏳ Waiting for services to be healthy..."
|
||||
sleep 10
|
||||
|
||||
echo "🔍 Checking service status..."
|
||||
docker-compose ps
|
||||
|
||||
echo ""
|
||||
echo "✅ Deployment complete!"
|
||||
echo ""
|
||||
echo "📊 Service URLs:"
|
||||
echo " • Production: https://klz-cables.com"
|
||||
echo " • Staging: https://staging.klz-cables.com"
|
||||
echo ""
|
||||
EOF
|
||||
|
||||
# Make script executable
|
||||
chmod +x /home/deploy/deploy.sh
|
||||
```
|
||||
|
||||
### 7. Configure Docker Registry Access
|
||||
|
||||
The deployment script needs registry credentials. These are passed as environment variables from the CI/CD workflow:
|
||||
|
||||
```bash
|
||||
# The workflow passes these variables:
|
||||
# REGISTRY_USER - from Gitea secrets
|
||||
# REGISTRY_PASS - from Gitea secrets
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
### Check Environment File
|
||||
|
||||
```bash
|
||||
# Verify .env file exists and has correct permissions
|
||||
ls -la /home/deploy/sites/klz-cables.com/.env
|
||||
|
||||
# Check content (be careful not to expose secrets in logs)
|
||||
head -n 5 /home/deploy/sites/klz-cables.com/.env
|
||||
```
|
||||
|
||||
### Test Deployment Script
|
||||
|
||||
```bash
|
||||
# Run deployment script manually (requires registry credentials)
|
||||
REGISTRY_USER=your-user REGISTRY_PASS=your-pass /home/deploy/deploy.sh
|
||||
```
|
||||
|
||||
### Check Running Containers
|
||||
|
||||
```bash
|
||||
cd /home/deploy/sites/klz-cables.com
|
||||
docker-compose ps
|
||||
docker-compose logs -f app
|
||||
```
|
||||
|
||||
### Verify Environment Variables in Container
|
||||
|
||||
```bash
|
||||
# Check that environment variables are loaded
|
||||
docker-compose exec app env | grep -E "NODE_ENV|NEXT_PUBLIC|MAIL|REDIS"
|
||||
```
|
||||
|
||||
## Updating Environment Variables
|
||||
|
||||
When you need to update environment variables:
|
||||
|
||||
```bash
|
||||
# 1. SSH to the server
|
||||
ssh root@alpha.mintel.me
|
||||
|
||||
# 2. Edit the .env file
|
||||
nano /home/deploy/sites/klz-cables.com/.env
|
||||
|
||||
# 3. Restart the containers to pick up changes
|
||||
cd /home/deploy/sites/klz-cables.com
|
||||
docker-compose down
|
||||
docker-compose up -d
|
||||
|
||||
# 4. Verify the changes
|
||||
docker-compose logs -f app
|
||||
```
|
||||
|
||||
**Note**: Changes to `NEXT_PUBLIC_*` variables require rebuilding the Docker image, as they are baked into the client bundle at build time.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### .env File Not Found
|
||||
|
||||
```bash
|
||||
# Check if file exists
|
||||
ls -la /home/deploy/sites/klz-cables.com/.env
|
||||
|
||||
# If missing, create it from template
|
||||
cp .env.production /home/deploy/sites/klz-cables.com/.env
|
||||
# Then edit with actual values
|
||||
```
|
||||
|
||||
### Permission Denied
|
||||
|
||||
```bash
|
||||
# Fix ownership
|
||||
chown -R deploy:deploy /home/deploy/sites/klz-cables.com
|
||||
|
||||
# Fix .env permissions
|
||||
chmod 600 /home/deploy/sites/klz-cables.com/.env
|
||||
```
|
||||
|
||||
### Container Won't Start
|
||||
|
||||
```bash
|
||||
# Check logs
|
||||
docker-compose logs app
|
||||
|
||||
# Check if .env is loaded
|
||||
docker-compose config
|
||||
|
||||
# Verify environment variables
|
||||
docker-compose exec app env
|
||||
```
|
||||
|
||||
### Network Issues
|
||||
|
||||
```bash
|
||||
# Verify infra network exists
|
||||
docker network ls | grep infra
|
||||
|
||||
# If missing, create it
|
||||
docker network create infra
|
||||
```
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] `.env` file has `600` permissions (readable only by owner)
|
||||
- [ ] `.env` file is owned by `deploy:deploy`
|
||||
- [ ] `.env` file is NOT in git repository
|
||||
- [ ] All sensitive credentials are filled in
|
||||
- [ ] SSH keys are properly secured
|
||||
- [ ] Firewall rules are configured
|
||||
- [ ] HTTPS is enforced via Traefik
|
||||
- [ ] Regular backups of `.env` file are maintained
|
||||
|
||||
## Backup
|
||||
|
||||
Create a secure backup of the environment file:
|
||||
|
||||
```bash
|
||||
# Backup .env file
|
||||
cp /home/deploy/sites/klz-cables.com/.env \
|
||||
/home/deploy/backups/klz-cables.env.$(date +%Y%m%d)
|
||||
|
||||
# Set proper permissions on backup
|
||||
chmod 600 /home/deploy/backups/klz-cables.env.*
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- [Deployment Guide](./DEPLOYMENT.md)
|
||||
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
||||
- [Traefik Documentation](https://doc.traefik.io/traefik/)
|
||||
Reference in New Issue
Block a user