Getting Started

Configuration

Environment variables and settings for the ZineCore2 server

This guide covers all configuration options for the ZineCore2 Django server, including environment variables, database settings, and deployment configurations.

Settings Modules

ZineCore2 uses Django's multiple settings pattern with three settings modules:

ModulePurposeUse When
zinecore.settings.developmentDevelopmentLocal development, DEBUG=True
zinecore.settings.productionProductionProduction deployment, DEBUG=False
zinecore.settings.testingTestingRunning test suite

Set via the DJANGO_SETTINGS_MODULE environment variable:

export DJANGO_SETTINGS_MODULE=zinecore.settings.development

Environment Variables

Required Variables

These variables must be set for the server to run:

DJANGO_SETTINGS_MODULE

Specifies which settings module to use.

# Development
export DJANGO_SETTINGS_MODULE=zinecore.settings.development

# Production
export DJANGO_SETTINGS_MODULE=zinecore.settings.production

DATABASE_URL

PostgreSQL database connection string.

# Format
DATABASE_URL=postgresql://USER:PASSWORD@HOST:PORT/DATABASE

# Examples
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/zinecore2
DATABASE_URL=postgresql://zinecore2:[email protected]:5432/zinecore2_prod

Parts:

  • USER — PostgreSQL username
  • PASSWORD — PostgreSQL password
  • HOST — Database host (localhost or server address)
  • PORT — PostgreSQL port (default: 5432, docker-compose uses 5433)
  • DATABASE — Database name

SECRET_KEY

Django secret key for cryptographic signing.

# Generate a secret key
python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())'

# Set it
export SECRET_KEY='django-insecure-abc123...'
Security: Never commit SECRET_KEY to version control. Generate a unique key for each environment.

Production Variables

These variables are required in production but optional in development:

DEBUG

Controls debug mode.

# Development (default: True)
DEBUG=True

# Production (MUST be False)
DEBUG=False
Never run production with DEBUG=True — it exposes sensitive information and is a security risk.

ALLOWED_HOSTS

Comma-separated list of allowed hostnames.

# Development (default: *, localhost, 127.0.0.1)
ALLOWED_HOSTS=*

# Production (specify exact domains)
ALLOWED_HOSTS=zinecore.example.com,api.zinecore.example.com

CORS_ALLOWED_ORIGINS

Comma-separated list of allowed CORS origins (for frontend apps).

# Allow frontend to access API
CORS_ALLOWED_ORIGINS=https://yourfrontend.com,https://www.yourfrontend.com

Optional Variables

CORS_ALLOW_ALL_ORIGINS

Allow all origins (development only).

# Development (convenient but insecure)
CORS_ALLOW_ALL_ORIGINS=True

# Production (DO NOT SET)

STATIC_ROOT

Directory for collected static files (production).

# Default: backend/staticfiles/
STATIC_ROOT=/var/www/zinecore2/static/

STATIC_URL

URL path for static files.

# Default: /static/
STATIC_URL=/static/

MEDIA_ROOT

Directory for user-uploaded files (if needed).

# Default: backend/media/
MEDIA_ROOT=/var/www/zinecore2/media/

Configuration Files

.env File

Create a .env file in backend/ directory for local development:

# backend/.env

# Core settings
DJANGO_SETTINGS_MODULE=zinecore.settings.development
DEBUG=True
SECRET_KEY=your-secret-key-here

# Database
DATABASE_URL=postgresql://zinecore2:password@localhost:5433/zinecore2

# Hosts
ALLOWED_HOSTS=localhost,127.0.0.1

# CORS (development)
CORS_ALLOW_ALL_ORIGINS=True

Django will automatically load variables from .env via python-decouple.

Important: Add .env to .gitignore to prevent committing secrets.

Database Configuration

Development Database

Default development configuration (from settings/development.py):

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'zinecore2',
        'USER': 'postgres',
        'PASSWORD': 'postgres',
        'HOST': 'localhost',
        'PORT': '5433',  # docker-compose PostgreSQL
    }
}

Override with DATABASE_URL environment variable.

Production Database

Use DATABASE_URL for production:

DATABASE_URL=postgresql://zinecore2:[email protected]:5432/zinecore2_prod

Best practices:

  • Use strong passwords (20+ characters)
  • Restrict database user permissions
  • Use SSL connections (?sslmode=require)
  • Regular backups

Example with SSL:

DATABASE_URL=postgresql://user:[email protected]:5432/zinecore2?sslmode=require

REST Framework Configuration

Configured in settings/base.py:

Pagination

REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE': 25,
}

Override page size per request:

curl "http://localhost:8000/api/zines/?page_size=50"

Permissions

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ],
}
  • Read operations (GET): Public, no auth required
  • Write operations (POST/PUT/PATCH/DELETE): Authentication required

Authentication

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework.authentication.TokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
    ],
}

Supports:

  • Token authentication (for API clients)
  • Session authentication (for browsable API)

CORS Configuration

Cross-Origin Resource Sharing settings (for frontend apps):

Development (Allow All)

# settings/development.py
CORS_ALLOW_ALL_ORIGINS = True

Production (Specific Origins)

# settings/production.py
CORS_ALLOWED_ORIGINS = [
    "https://yourfrontend.com",
    "https://www.yourfrontend.com",
]

CORS_ALLOW_CREDENTIALS = True

Static Files Configuration

Development

Static files served automatically by Django:

# settings/development.py
STATIC_URL = '/static/'

No collection needed for development.

Production

Collect static files for serving by nginx/Apache:

# Collect static files
python manage.py collectstatic --noinput

Serve with nginx:

location /static/ {
    alias /var/www/zinecore2/static/;
}

Logging Configuration

Configure logging in settings:

LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console': {
            'class': 'logging.StreamHandler',
        },
        'file': {
            'class': 'logging.FileHandler',
            'filename': 'zinecore2.log',
        },
    },
    'loggers': {
        'django': {
            'handlers': ['console', 'file'],
            'level': 'INFO',
        },
    },
}

Security Settings

Production Security Checklist

    • DEBUG = False
    • SECRET_KEY is unique and not committed
    • ALLOWED_HOSTS specifies exact domains
    • SECURE_SSL_REDIRECT = True (if using HTTPS)
    • SESSION_COOKIE_SECURE = True
    • CSRF_COOKIE_SECURE = True
    • Database password is strong (20+ characters)
    • Database user has minimal permissions
    • Static files served by nginx/Apache (not Django)

HTTPS Settings

If serving over HTTPS (recommended):

# settings/production.py
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000  # 1 year
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

Example Configurations

Development (.env)

DJANGO_SETTINGS_MODULE=zinecore.settings.development
DEBUG=True
SECRET_KEY=dev-insecure-key-change-in-production
DATABASE_URL=postgresql://postgres:postgres@localhost:5433/zinecore2
ALLOWED_HOSTS=localhost,127.0.0.1
CORS_ALLOW_ALL_ORIGINS=True

Production (Environment Variables)

DJANGO_SETTINGS_MODULE=zinecore.settings.production
DEBUG=False
SECRET_KEY=prod-strong-secret-key-40-characters-long
DATABASE_URL=postgresql://zinecore2:[email protected]:5432/zinecore2_prod?sslmode=require
ALLOWED_HOSTS=api.zinecore.example.com
CORS_ALLOWED_ORIGINS=https://zinecore.example.com
STATIC_ROOT=/var/www/zinecore2/static/

Docker Compose

# docker-compose.yml
version: '3.8'

services:
  db:
    image: postgres:16
    environment:
      POSTGRES_DB: zinecore2
      POSTGRES_USER: zinecore2
      POSTGRES_PASSWORD: password
    ports:
      - "5433:5432"

  web:
    build: .
    environment:
      DJANGO_SETTINGS_MODULE: zinecore.settings.production
      DATABASE_URL: postgresql://zinecore2:password@db:5432/zinecore2
      SECRET_KEY: ${SECRET_KEY}
      ALLOWED_HOSTS: localhost
    ports:
      - "8000:8000"
    depends_on:
      - db

Checking Configuration

Check Current Settings

# Show all settings (development only!)
python manage.py diffsettings

# Check if settings module loads
python manage.py check

Run System Checks

# Check for issues
python manage.py check --deploy

This command checks for common deployment issues.


Troubleshooting

"ImproperlyConfigured: Set the SECRET_KEY environment variable"

Solution: Set the SECRET_KEY environment variable:

export SECRET_KEY=$(python -c 'from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())')

"DisallowedHost at / Invalid HTTP_HOST header"

Solution: Add your hostname to ALLOWED_HOSTS:

export ALLOWED_HOSTS=yourdomain.com,www.yourdomain.com

CORS Errors in Browser

Solution: Add your frontend domain to CORS_ALLOWED_ORIGINS:

export CORS_ALLOWED_ORIGINS=https://yourfrontend.com

Database Connection Errors

Solution: Check DATABASE_URL format and that PostgreSQL is running:

# Test connection
psql "$DATABASE_URL"

Next Steps

Configuration complete! Your ZineCore2 server is properly configured. Continue to Architecture to understand the internals.
Copyright ©2026 ZineCore2 Contributors,